|
|
<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>
|