You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

621 lines
22 KiB

<template>
<div class="customer-css">
<!-- 查询条件 -->
<el-form :inline="true" label-position="top" class="pi-search-form">
<el-form-item label="字典名称">
<el-input v-model="typeSearch.dictName" clearable placeholder="字典名称" style="width:160px" @keyup.enter.native="loadTypeList" />
</el-form-item>
<el-form-item label="字典类型">
<el-input v-model="typeSearch.dictType" clearable placeholder="字典类型" style="width:200px" @keyup.enter.native="loadTypeList" />
</el-form-item>
<el-form-item label="状态">
<el-select v-model="typeSearch.status" clearable placeholder="请选择" style="width:100px">
<el-option label="全部" value="" />
<el-option label="启用" value="Y" />
<el-option label="停用" value="N" />
</el-select>
</el-form-item>
<el-form-item label=" ">
<el-button type="primary" class="customer-bun-min" @click="loadTypeList">查询</el-button>
</el-form-item>
</el-form>
<!-- 主表:字典类型(系统配置,只读) -->
<el-table
ref="typeTable"
:data="typeList"
:height="tableHeight"
border
highlight-current-row
v-loading="typeLoading"
style="width:100%"
@row-click="selectDictType">
<!-- <el-table-column prop="dictType" label="字典类型" min-width="120" header-align="center" align="left" show-overflow-tooltip />-->
<el-table-column prop="dictName" label="字典名称" min-width="120" header-align="center" align="left" show-overflow-tooltip />
<el-table-column prop="status" label="状态" width="80" header-align="center" align="center">
<template slot-scope="scope">
{{ scope.row.status === 'Y' ? '启用' : '停用' }}
</template>
</el-table-column>
<el-table-column label="操作" width="70" fixed="right" header-align="center" align="center">
<template slot-scope="scope">
<el-link
v-if="canDeleteType(scope.row)"
style="cursor:pointer"
@click.stop="handleDeleteType(scope.row)">删除</el-link>
<span v-else>-</span>
</template>
</el-table-column>
<el-table-column prop="remark" label="备注" min-width="300" header-align="center" align="left" show-overflow-tooltip />
<!-- <el-table-column prop="createBy" label="创建人" width="100" header-align="center" align="center" />-->
<!-- <el-table-column prop="createDate" label="创建时间" min-width="140" header-align="center" align="center" />-->
</el-table>
<el-pagination
style="margin-top:5px"
@size-change="typeSizeChange"
@current-change="typePageChange"
:current-page="typePageIndex"
:page-sizes="[20, 50, 100]"
:page-size="typePageSize"
:total="typeTotal"
layout="total, sizes, prev, pager, next, jumper" />
<!-- 子表:字典明细 -->
<div class="sub-title">
字典明细列表
<el-button
type="primary"
class="customer-bun-min"
style="margin-left:10px"
:disabled="!currentType.dictType"
@click="openDataDialog()">
新增明细
</el-button>
</div>
<el-form :inline="true" label-position="top" class="pi-search-form" style="margin-top:0">
<el-form-item label="字典标签">
<el-input v-model="dataSearch.dictLabel" clearable placeholder="标签" style="width:160px" @keyup.enter.native="loadDataList" />
</el-form-item>
<el-form-item label="作用范围">
<el-select v-model="dataSearch.scope" clearable placeholder="请选择" style="width:120px" @change="applyDataFilterAndPage">
<el-option label="全部" value="" />
<el-option label="所有工厂" value="all" />
<el-option label="当前工厂" value="current" />
</el-select>
</el-form-item>
<el-form-item label="状态">
<el-select v-model="dataSearch.status" clearable placeholder="请选择" style="width:100px">
<el-option label="全部" value="" />
<el-option label="启用" value="Y" />
<el-option label="停用" value="N" />
</el-select>
</el-form-item>
<el-form-item label=" ">
<el-button type="primary" class="customer-bun-min" :disabled="!currentType.dictType" @click="loadDataList">查询</el-button>
</el-form-item>
</el-form>
<el-table
:data="dataList"
:height="subTableHeight"
border
v-loading="dataLoading"
style="width:100%">
<el-table-column fixed="right" label="操作" header-align="center" align="center" width="160">
<template slot-scope="scope">
<el-link style="cursor:pointer" @click="openDataDialog(scope.row)">编辑 |</el-link>
<el-link style="cursor:pointer" @click="handleDeleteData(scope.row)">删除 |</el-link>
<el-link style="cursor:pointer" @click="handleDisableData(scope.row)">停用</el-link>
</template>
</el-table-column>
<el-table-column prop="dictLabel" label="字典标签" min-width="120" header-align="center" align="left" show-overflow-tooltip />
<el-table-column prop="dictValue" label="字典键值" min-width="120" header-align="center" align="left" show-overflow-tooltip />
<el-table-column label="作用范围" width="80" header-align="center" align="center">
<template slot-scope="scope">
{{ formatDataScope(scope.row.site) }}
</template>
</el-table-column>
<el-table-column prop="dictSort" label="排序" width="60" header-align="center" align="center" />
<el-table-column prop="status" label="状态" width="80" header-align="center" align="center">
<template slot-scope="scope">
{{ scope.row.status === 'Y' ? '启用' : '停用' }}
</template>
</el-table-column>
<el-table-column prop="isDefault" label="默认" width="70" header-align="center" align="center">
<template slot-scope="scope">
{{ scope.row.isDefault === 'Y' ? '是' : '否' }}
</template>
</el-table-column>
<el-table-column prop="remark" label="备注" min-width="300" header-align="center" align="left" show-overflow-tooltip />
<el-table-column prop="createBy" label="创建人" width="100" header-align="center" align="center" />
<el-table-column prop="createDate" label="创建时间" min-width="140" header-align="center" align="center" />
</el-table>
<el-pagination
style="margin-top:5px"
@size-change="dataSizeChange"
@current-change="dataPageChange"
:current-page="dataPageIndex"
:page-sizes="[20, 50, 100, 200]"
:page-size="dataPageSize"
:total="dataTotal"
layout="total, sizes, prev, pager, next, jumper" />
<div v-if="dataList.length === 0 && !dataLoading" style="margin-top:8px;color:#909399;font-size:12px;text-align:center">
{{ currentType.dictType ? '暂无字典明细' : '请点击上方字典类型查看明细' }}
</div>
<!-- 字典明细弹窗 -->
<el-dialog
:title="dataDialogTitle"
:visible.sync="dataDialogVisible"
width="420px"
:close-on-click-modal="false"
append-to-body
v-drag
@close="resetDataForm">
<el-form ref="dataFormRef" label-position="top" :model="dataForm" :rules="dataRules">
<el-form-item label="字典类型">
<el-input v-model="dataForm.dictType" disabled />
</el-form-item>
<el-form-item label="作用范围" prop="dataScope">
<el-select v-model="dataForm.dataScope" :disabled="dataEditMode" placeholder="请选择" style="width:100%">
<el-option label="所有工厂" value="all" />
<el-option label="当前工厂" value="current" />
</el-select>
</el-form-item>
<el-form-item label="字典标签" prop="dictLabel">
<el-input v-model="dataForm.dictLabel" @blur="dictLabel()" maxlength="255" />
</el-form-item>
<el-form-item label="字典键值" prop="dictValue">
<el-input v-model="dataForm.dictValue" :disabled="dataEditMode" maxlength="255" />
</el-form-item>
<el-form-item label="排序" prop="dictSort">
<el-input-number v-model="dataForm.dictSort" :min="0" :controls="false" style="width:100%" />
</el-form-item>
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="状态" prop="status">
<el-radio-group v-model="dataForm.status">
<el-radio label="Y">启用</el-radio>
<el-radio label="N">停用</el-radio>
</el-radio-group>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label=" ">
<el-checkbox v-model="dataForm.isDefault" true-label="Y" false-label="N">默认</el-checkbox>
</el-form-item>
</el-col>
</el-row>
<el-form-item label="备注">
<el-input v-model="dataForm.remark" type="textarea" :rows="2" />
</el-form-item>
</el-form>
<el-footer style="height:30px;margin-top: 30px;text-align:center">
<el-button type="primary" :loading="dataSubmitLoading" @click="submitDataForm">保存</el-button>
<el-button @click="dataDialogVisible = false">取消</el-button>
</el-footer>
</el-dialog>
</div>
</template>
<script>
import {
listDictMaintenanceType,
listDictMaintenanceData,
saveDictMaintenanceData,
updateDictMaintenanceData,
deleteDictMaintenanceData,
disableDictMaintenanceData,
deleteDictMaintenanceType
} from '@/api/base/dictMaintenance'
const ALL_SITE = '*'
export default {
name: 'DictMaintenance',
data () {
const userSite = this.$store.state.user.site
return {
userSite,
tableHeight: 200,
subTableHeight: 200,
typeLoading: false,
dataLoading: false,
dataSubmitLoading: false,
typeList: [],
dataList: [],
dataListAll: [],
typePageIndex: 1,
typePageSize: 20,
typeTotal: 0,
dataPageIndex: 1,
dataPageSize: 20,
dataTotal: 0,
typeSearch: {
dictName: '',
dictType: '',
status: ''
},
dataSearch: {
dictLabel: '',
scope: '',
status: ''
},
currentType: {},
dataDialogVisible: false,
dataDialogTitle: '新增字典明细',
dataEditMode: false,
dataForm: this.buildEmptyDataForm(),
dataRules: {
dataScope: [{ required: true, message: ' ', trigger: 'change' }],
dictLabel: [{ required: true, message: ' ', trigger: 'blur' }],
dictValue: [{ required: true, message: ' ', trigger: 'blur' }],
dictSort: [{ required: true, type: 'number', message: ' ', trigger: 'blur' }],
status: [{ required: true, message: ' ', trigger: 'change' }]
}
}
},
mounted () {
this.calcHeight()
window.addEventListener('resize', this.calcHeight)
this.loadTypeList()
},
beforeDestroy () {
window.removeEventListener('resize', this.calcHeight)
},
methods: {
buildEmptyDataForm () {
return {
dictCode: undefined,
dictLabel: '',
dictValue: '',
dictType: '',
dictSort: 1,
isDefault: 'N',
status: 'Y',
remark: '',
site: ALL_SITE,
dataScope: 'all',
createBy: this.$store.state.user.name,
updateBy: this.$store.state.user.name
}
},
formatDataScope (site) {
return site === ALL_SITE ? '所有工厂' : '当前工厂'
},
resolveDataSite (scope) {
return scope === 'current' ? this.userSite : ALL_SITE
},
buildQueryParams (extra = {}) {
return {
site: this.userSite,
...extra
}
},
applyDataFilterAndPage () {
let rows = [...this.dataListAll]
if (this.dataSearch.scope === 'all') {
rows = rows.filter(r => r.site === ALL_SITE)
} else if (this.dataSearch.scope === 'current') {
rows = rows.filter(r => r.site === this.userSite)
}
rows.sort((a, b) => (a.dictSort || 0) - (b.dictSort || 0))
this.dataTotal = rows.length
const start = (this.dataPageIndex - 1) * this.dataPageSize
this.dataList = rows.slice(start, start + this.dataPageSize)
},
calcHeight () {
this.$nextTick(() => {
const h = (window.innerHeight - 320) / 2
this.tableHeight = h > 180 ? h : 180
this.subTableHeight = h > 180 ? h : 180
})
},
loadTypeList () {
this.typeLoading = true
listDictMaintenanceType(this.buildQueryParams({
dictName: this.typeSearch.dictName,
dictType: this.typeSearch.dictType,
status: this.typeSearch.status
})).then(({ data }) => {
if (data && data.code === 0) {
const rows = this.normalizeTypeRows(data.rows || [])
this.applyTypeListResult(rows, rows.length)
} else {
this.$message.error((data && data.msg) || '查询字典类型失败')
}
}).catch(() => {
this.$message.error('查询字典类型失败')
}).finally(() => {
this.typeLoading = false
})
},
applyTypeListResult (rows, total) {
const start = (this.typePageIndex - 1) * this.typePageSize
this.typeList = rows.slice(start, start + this.typePageSize)
this.typeTotal = total
if (this.typeList.length > 0) {
const currentId = this.currentType.dictId
const matched = currentId ? this.typeList.find(r => r.dictId === currentId) : null
const row = matched || this.typeList[0]
this.$nextTick(() => {
this.$refs.typeTable && this.$refs.typeTable.setCurrentRow(row)
})
this.selectDictType(row)
} else {
this.currentType = {}
this.dataList = []
this.dataTotal = 0
}
},
dictLabel(){
this.dataForm.dictValue = JSON.parse(JSON.stringify(this.dataForm.dictLabel));
},
normalizeTypeRows (rows) {
if (!Array.isArray(rows)) {
return []
}
return rows.map(row => this.normalizeTypeRow(row))
},
normalizeTypeRow (row) {
const normalized = { ...(row || {}) }
normalized.dictId = normalized.dictId != null ? normalized.dictId : normalized.dict_id
normalized.dictType = this.firstText(
normalized.dictType,
normalized.dict_type
)
normalized.status = this.normalizeStatus(
this.firstText(normalized.status, normalized.STATUS, normalized.active)
)
normalized.createBy = this.firstText(normalized.createBy, normalized.create_by)
normalized.site = this.firstText(normalized.site, normalized.SITE)
normalized.remark = this.firstText(normalized.remark)
normalized.dictName = this.resolveTypeDisplayName(normalized)
return normalized
},
resolveTypeDisplayName (row) {
const direct = this.firstText(row && row.dictName, row && row.dict_name)
if (direct && !this.isStatusText(direct)) {
return direct
}
const remark = this.firstText(row && row.remark)
if (remark) {
const sep = remark.indexOf('-')
if (sep > 0) {
const prefix = remark.substring(0, sep).trim()
if (prefix && !this.isStatusText(prefix)) {
return prefix
}
}
if (!this.isStatusText(remark)) {
return remark
}
}
return this.firstText(row && row.dictType, row && row.dict_type)
},
normalizeStatus (raw) {
const text = this.firstText(raw)
if (!text) {
return ''
}
const upper = text.toUpperCase()
if (upper === 'Y' || text === '启用') {
return 'Y'
}
if (upper === 'N' || text === '停用') {
return 'N'
}
return text
},
isStatusText (text) {
const val = this.firstText(text)
if (!val) {
return false
}
const upper = val.toUpperCase()
return upper === 'Y' || upper === 'N' || val === '启用' || val === '停用'
},
firstText (...vals) {
for (const val of vals) {
if (val === null || val === undefined) {
continue
}
const text = String(val).trim()
if (text) {
return text
}
}
return ''
},
selectDictType (row) {
if (!row || !row.dictType) return
this.currentType = { ...row }
this.dataPageIndex = 1
this.loadDataList()
},
loadDataList () {
if (!this.currentType.dictType) {
this.dataList = []
this.dataListAll = []
this.dataTotal = 0
return
}
this.dataLoading = true
listDictMaintenanceData(this.buildQueryParams({
dictType: this.currentType.dictType,
dictLabel: this.dataSearch.dictLabel,
status: this.dataSearch.status
})).then(({ data }) => {
if (data && data.code === 0) {
this.dataListAll = data.rows || []
this.dataPageIndex = 1
this.applyDataFilterAndPage()
} else {
this.$message.error((data && data.msg) || '查询字典明细失败')
}
}).catch(() => {
this.$message.error('查询字典明细失败')
}).finally(() => {
this.dataLoading = false
})
},
canDeleteType (row) {
return !!(row && row.createBy === '订单扩展字段')
},
handleDeleteType (row) {
if (!row || !row.dictType) {
return
}
if (!this.canDeleteType(row)) {
this.$message.warning('仅支持删除“订单扩展字段”自动维护的字典类型')
return
}
const label = row.dictName || row.dictType
this.$confirm('确定删除字典类型「' + label + '」及其明细数据吗?', '提示', { type: 'warning' }).then(() => {
deleteDictMaintenanceType({
dictId: row.dictId,
dictType: row.dictType,
site: row.site
}).then(({ data }) => {
if (data && data.code === 0) {
this.$message.success(data.msg || '删除成功')
this.currentType = {}
this.dataList = []
this.dataListAll = []
this.dataTotal = 0
this.loadTypeList()
} else {
this.$message.error((data && data.msg) || '删除失败')
}
}).catch(err => {
this.$message.error((err && err.message) || '删除失败')
})
}).catch(() => {})
},
typeSizeChange (val) {
this.typePageSize = val
this.typePageIndex = 1
this.loadTypeList()
},
typePageChange (val) {
this.typePageIndex = val
this.loadTypeList()
},
dataSizeChange (val) {
this.dataPageSize = val
this.dataPageIndex = 1
this.applyDataFilterAndPage()
},
dataPageChange (val) {
this.dataPageIndex = val
this.applyDataFilterAndPage()
},
openDataDialog (row) {
if (!this.currentType.dictType) {
this.$message.warning('请先选择字典类型')
return
}
if (row) {
this.dataEditMode = true
this.dataDialogTitle = '编辑字典明细'
this.dataForm = {
...row,
dataScope: row.site === ALL_SITE ? 'all' : 'current',
updateBy: this.$store.state.user.name
}
} else {
this.dataEditMode = false
this.dataDialogTitle = '新增字典明细'
this.dataForm = {
...this.buildEmptyDataForm(),
dictType: this.currentType.dictType,
dictSort: (this.dataListAll.length + 1) || 1
}
}
this.dataDialogVisible = true
},
resetDataForm () {
this.$refs.dataFormRef && this.$refs.dataFormRef.resetFields()
this.dataForm = this.buildEmptyDataForm()
},
submitDataForm () {
this.$refs.dataFormRef.validate(valid => {
if (!valid) {
this.$message.warning('请填写完整字典明细信息')
return
}
this.dataForm.site = this.resolveDataSite(this.dataForm.dataScope)
this.dataSubmitLoading = true
const api = this.dataEditMode ? updateDictMaintenanceData : saveDictMaintenanceData
api(this.dataForm).then(({ data }) => {
if (data && data.code === 0) {
this.$message.success(data.msg || '保存成功')
this.dataDialogVisible = false
this.loadDataList()
} else {
this.$message.error((data && data.msg) || '保存失败')
}
}).catch(err => {
this.$message.error(err.message || '保存失败')
}).finally(() => {
this.dataSubmitLoading = false
})
})
},
handleDeleteData (row) {
if (row.isSystem === 'Y') {
this.$message.warning('系统字典不可删除')
return
}
this.$confirm('确定删除字典明细「' + row.dictLabel + '」吗?', '提示', { type: 'warning' }).then(() => {
deleteDictMaintenanceData(row).then(({ data }) => {
if (data && data.code === 0) {
this.$message.success(data.msg || '删除成功')
this.loadDataList()
} else {
this.$message.error((data && data.msg) || '删除失败')
}
})
}).catch(() => {})
},
handleDisableData (row) {
if (row.isSystem === 'Y') {
this.$message.warning('系统字典不可停用')
return
}
this.$confirm('确定停用字典明细「' + row.dictLabel + '」吗?', '提示', { type: 'warning' }).then(() => {
disableDictMaintenanceData(row).then(({ data }) => {
if (data && data.code === 0) {
this.$message.success(data.msg || '操作成功')
this.loadDataList()
} else {
this.$message.error((data && data.msg) || '操作失败')
}
})
}).catch(() => {})
}
}
}
</script>
<style scoped>
.pi-search-form { margin-top: 0; }
.sub-title {
font-weight: 600;
margin: 16px 0 8px 0;
padding-left: 4px;
border-left: 4px solid #409eff;
line-height: 1.2;
color: #303133;
}
.customer-bun-min {
margin-right: 8px;
}
.dialog-footer {
text-align: center;
}
</style>