|
|
@@ -1,342 +1,342 @@
|
|
|
-<template>
|
|
|
- <div class="dict-tab-panel">
|
|
|
- <div class="tip-banner">
|
|
|
- <i class="el-icon-info" />
|
|
|
- <span>可从「字典维护」勾选字典后点「导入到平台模板」,或在此从平台主库 / 租户库批量选取导入</span>
|
|
|
- </div>
|
|
|
-
|
|
|
- <el-card shadow="never" class="mb16 filter-card" v-show="showSearch">
|
|
|
- <el-form :model="queryParams" ref="queryForm" :inline="true" size="small" label-width="72px">
|
|
|
- <el-form-item label="字典名称" prop="dictName">
|
|
|
- <el-input v-model="queryParams.dictName" placeholder="请输入字典名称" clearable @keyup.enter.native="handleQuery" />
|
|
|
- </el-form-item>
|
|
|
- <el-form-item label="字典类型" prop="dictType">
|
|
|
- <el-input v-model="queryParams.dictType" placeholder="请输入字典类型" clearable @keyup.enter.native="handleQuery" />
|
|
|
- </el-form-item>
|
|
|
- <el-form-item>
|
|
|
- <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
|
|
|
- <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
|
|
|
- </el-form-item>
|
|
|
- </el-form>
|
|
|
- </el-card>
|
|
|
-
|
|
|
- <el-row :gutter="10" class="mb8 toolbar-row">
|
|
|
- <el-col :span="1.5">
|
|
|
- <el-button type="primary" plain icon="el-icon-download" size="mini" @click="openImportDialog" v-hasPermi="['tenant:dict:template:add']">从字典库导入</el-button>
|
|
|
- </el-col>
|
|
|
- <el-col :span="1.5">
|
|
|
- <el-button type="primary" plain icon="el-icon-plus" size="mini" @click="handleAdd" v-hasPermi="['tenant:dict:template:add']">手动新增</el-button>
|
|
|
- </el-col>
|
|
|
- <el-col :span="1.5">
|
|
|
- <el-button type="success" plain icon="el-icon-edit" size="mini" :disabled="single" @click="handleUpdate" v-hasPermi="['tenant:dict:template:edit']">修改</el-button>
|
|
|
- </el-col>
|
|
|
- <el-col :span="1.5">
|
|
|
- <el-button type="danger" plain icon="el-icon-delete" size="mini" :disabled="multiple" @click="handleDelete" v-hasPermi="['tenant:dict:template:remove']">删除</el-button>
|
|
|
- </el-col>
|
|
|
- <right-toolbar :showSearch.sync="showSearch" @queryTable="getList" />
|
|
|
- </el-row>
|
|
|
-
|
|
|
- <el-table v-loading="loading" :data="typeList" border size="small" @selection-change="handleSelectionChange" class="dict-table">
|
|
|
- <el-table-column type="selection" width="48" align="center" />
|
|
|
- <el-table-column label="编号" align="center" prop="dictId" width="76" />
|
|
|
- <el-table-column label="字典名称" align="center" prop="dictName" min-width="120" :show-overflow-tooltip="true" />
|
|
|
- <el-table-column label="字典类型" align="center" min-width="140">
|
|
|
- <template slot-scope="scope">
|
|
|
- <el-link type="primary" :underline="false" @click="openDataDrawer(scope.row)">{{ scope.row.dictType }}</el-link>
|
|
|
- </template>
|
|
|
- </el-table-column>
|
|
|
- <el-table-column label="平台管控" align="center" width="88">
|
|
|
- <template slot-scope="scope">
|
|
|
- <el-tag size="mini" :type="scope.row.isManaged === 1 ? 'danger' : 'info'">{{ scope.row.isManaged === 1 ? '是' : '否' }}</el-tag>
|
|
|
- </template>
|
|
|
- </el-table-column>
|
|
|
- <el-table-column label="默认同步模式" align="center" prop="syncMode" width="120">
|
|
|
- <template slot-scope="scope">
|
|
|
- <el-tag size="mini" type="info" effect="plain">{{ scope.row.syncMode }}</el-tag>
|
|
|
- </template>
|
|
|
- </el-table-column>
|
|
|
- <el-table-column label="状态" align="center" width="76">
|
|
|
- <template slot-scope="scope">
|
|
|
- <dict-tag :options="statusOptions" :value="scope.row.status"/>
|
|
|
- </template>
|
|
|
- </el-table-column>
|
|
|
- <el-table-column label="操作" align="center" width="200" fixed="right" class-name="small-padding fixed-width">
|
|
|
- <template slot-scope="scope">
|
|
|
- <el-button size="mini" type="text" icon="el-icon-view" @click="openDataDrawer(scope.row)">字典数据</el-button>
|
|
|
- <el-button size="mini" type="text" icon="el-icon-edit" @click="handleUpdate(scope.row)" v-hasPermi="['tenant:dict:template:edit']">修改</el-button>
|
|
|
- <el-button size="mini" type="text" icon="el-icon-delete" style="color:#f5222d" @click="handleDelete(scope.row)" v-hasPermi="['tenant:dict:template:remove']">删除</el-button>
|
|
|
- </template>
|
|
|
- </el-table-column>
|
|
|
- </el-table>
|
|
|
-
|
|
|
- <pagination v-show="total>0" :total="total" :page.sync="queryParams.pageNum" :limit.sync="queryParams.pageSize" @pagination="getList" />
|
|
|
-
|
|
|
- <el-drawer
|
|
|
- :title="'模板字典数据 · ' + (currentType.dictName || currentType.dictType || '')"
|
|
|
- :visible.sync="dataDrawerVisible"
|
|
|
- size="62%"
|
|
|
- append-to-body
|
|
|
- destroy-on-close
|
|
|
- custom-class="dict-data-drawer"
|
|
|
- >
|
|
|
- <div class="drawer-body-wrap" v-if="dataDrawerVisible && currentType.dictType">
|
|
|
- <div class="drawer-type-meta">
|
|
|
- <el-tag size="small" type="primary" effect="plain">{{ currentType.dictType }}</el-tag>
|
|
|
- </div>
|
|
|
- <template-data-panel :dict-type="currentType.dictType" />
|
|
|
- </div>
|
|
|
- </el-drawer>
|
|
|
-
|
|
|
- <el-dialog :title="title" :visible.sync="open" width="560px" append-to-body>
|
|
|
- <el-form ref="form" :model="form" :rules="rules" label-width="110px">
|
|
|
- <el-form-item label="字典名称" prop="dictName"><el-input v-model="form.dictName" /></el-form-item>
|
|
|
- <el-form-item label="字典类型" prop="dictType"><el-input v-model="form.dictType" :disabled="form.dictId != null" /></el-form-item>
|
|
|
- <el-form-item label="平台管控" prop="isManaged">
|
|
|
- <el-radio-group v-model="form.isManaged">
|
|
|
- <el-radio :label="1">是(同步时可覆盖)</el-radio>
|
|
|
- <el-radio :label="0">否(同步时仅追加)</el-radio>
|
|
|
- </el-radio-group>
|
|
|
- </el-form-item>
|
|
|
- <el-form-item label="默认同步模式" prop="syncMode">
|
|
|
- <el-select v-model="form.syncMode" style="width: 100%">
|
|
|
- <el-option label="MERGE - 合并更新" value="MERGE" />
|
|
|
- <el-option label="APPEND - 仅追加" value="APPEND" />
|
|
|
- <el-option label="OVERWRITE - 覆盖平台项" value="OVERWRITE" />
|
|
|
- </el-select>
|
|
|
- </el-form-item>
|
|
|
- <el-form-item label="状态" prop="status">
|
|
|
- <el-radio-group v-model="form.status">
|
|
|
- <el-radio v-for="dict in statusOptions" :key="dict.dictValue" :label="dict.dictValue">{{ dict.dictLabel }}</el-radio>
|
|
|
- </el-radio-group>
|
|
|
- </el-form-item>
|
|
|
- <el-form-item label="备注"><el-input v-model="form.remark" type="textarea" /></el-form-item>
|
|
|
- </el-form>
|
|
|
- <div slot="footer" class="dialog-footer">
|
|
|
- <el-button type="primary" @click="submitForm">确 定</el-button>
|
|
|
- <el-button @click="cancel">取 消</el-button>
|
|
|
- </div>
|
|
|
- </el-dialog>
|
|
|
-
|
|
|
- <el-dialog title="从字典库导入到平台模板" :visible.sync="importOpen" width="800px" append-to-body class="import-dialog">
|
|
|
- <el-tabs v-model="importTab" class="import-tabs">
|
|
|
- <el-tab-pane label="平台主库字典" name="platform">
|
|
|
- <el-table v-loading="importLoading" :data="platformDictList" @selection-change="s => importPlatformSelection = s" max-height="360" size="small" border>
|
|
|
- <el-table-column type="selection" width="45" />
|
|
|
- <el-table-column label="字典名称" prop="dictName" min-width="140" />
|
|
|
- <el-table-column label="字典类型" prop="dictType" min-width="160" />
|
|
|
- <el-table-column label="状态" prop="status" width="80" align="center" />
|
|
|
- </el-table>
|
|
|
- </el-tab-pane>
|
|
|
- <el-tab-pane label="租户字典" name="tenant">
|
|
|
- <el-card shadow="never" class="mb8 import-filter">
|
|
|
- <el-form inline size="small">
|
|
|
- <el-form-item label="租户">
|
|
|
- <inline-tenant-selector mode="admin" @change="onImportTenantChange" />
|
|
|
- </el-form-item>
|
|
|
- <el-form-item>
|
|
|
- <el-button type="primary" size="mini" icon="el-icon-search" @click="loadTenantDictList" :disabled="!importTenantId">加载字典</el-button>
|
|
|
- </el-form-item>
|
|
|
- </el-form>
|
|
|
- </el-card>
|
|
|
- <el-table v-loading="importLoading" :data="tenantDictList" @selection-change="s => importTenantSelection = s" max-height="300" size="small" border>
|
|
|
- <el-table-column type="selection" width="45" />
|
|
|
- <el-table-column label="字典名称" prop="dictName" min-width="140" />
|
|
|
- <el-table-column label="字典类型" prop="dictType" min-width="160" />
|
|
|
- <el-table-column label="来源" prop="dictSource" width="80" align="center" />
|
|
|
- </el-table>
|
|
|
- </el-tab-pane>
|
|
|
- </el-tabs>
|
|
|
- <div class="import-options">
|
|
|
- <el-checkbox v-model="importOverwrite">已存在同类型时覆盖更新(否则仅追加缺失项)</el-checkbox>
|
|
|
- </div>
|
|
|
- <div slot="footer" class="dialog-footer">
|
|
|
- <el-button type="primary" :loading="importSubmitting" icon="el-icon-upload2" @click="submitImport">导入选中</el-button>
|
|
|
- <el-button @click="importOpen = false">取 消</el-button>
|
|
|
- </div>
|
|
|
- </el-dialog>
|
|
|
- </div>
|
|
|
-</template>
|
|
|
-
|
|
|
-<script>
|
|
|
-import InlineTenantSelector from '@/components/InlineTenantSelector'
|
|
|
-import TemplateDataPanel from './TemplateDataPanel'
|
|
|
-import { listType } from '@/api/system/dict/type'
|
|
|
-import { listTenantDictType } from '@/api/tenant/dict'
|
|
|
-import {
|
|
|
- listTemplateDictType, getTemplateDictType, addTemplateDictType,
|
|
|
- updateTemplateDictType, delTemplateDictType,
|
|
|
- importTemplateFromPlatform, importTemplateFromTenant
|
|
|
-} from '@/api/tenant/dict'
|
|
|
-
|
|
|
-export default {
|
|
|
- name: 'TenantDictTemplate',
|
|
|
- components: { InlineTenantSelector, TemplateDataPanel },
|
|
|
- data() {
|
|
|
- return {
|
|
|
- loading: true, ids: [], single: true, multiple: true, showSearch: true, total: 0, typeList: [],
|
|
|
- title: '', open: false, statusOptions: [],
|
|
|
- queryParams: { pageNum: 1, pageSize: 10, dictName: undefined, dictType: undefined },
|
|
|
- form: {},
|
|
|
- rules: {
|
|
|
- dictName: [{ required: true, message: '字典名称不能为空', trigger: 'blur' }],
|
|
|
- dictType: [{ required: true, message: '字典类型不能为空', trigger: 'blur' }],
|
|
|
- syncMode: [{ required: true, message: '请选择同步模式', trigger: 'change' }]
|
|
|
- },
|
|
|
- dataDrawerVisible: false,
|
|
|
- currentType: {},
|
|
|
- importOpen: false,
|
|
|
- importTab: 'platform',
|
|
|
- importLoading: false,
|
|
|
- importSubmitting: false,
|
|
|
- importOverwrite: false,
|
|
|
- platformDictList: [],
|
|
|
- importPlatformSelection: [],
|
|
|
- importTenantId: null,
|
|
|
- tenantDictList: [],
|
|
|
- importTenantSelection: []
|
|
|
- }
|
|
|
- },
|
|
|
- created() {
|
|
|
- this.getList()
|
|
|
- this.getDicts('sys_normal_disable').then(r => { this.statusOptions = r.data })
|
|
|
- },
|
|
|
- methods: {
|
|
|
- getList() {
|
|
|
- this.loading = true
|
|
|
- listTemplateDictType(this.queryParams).then(r => {
|
|
|
- this.typeList = r.rows; this.total = r.total; this.loading = false
|
|
|
- }).catch(() => { this.loading = false })
|
|
|
- },
|
|
|
- openDataDrawer(row) {
|
|
|
- this.currentType = { dictId: row.dictId, dictType: row.dictType, dictName: row.dictName }
|
|
|
- this.dataDrawerVisible = true
|
|
|
- },
|
|
|
- openImportDialog() {
|
|
|
- this.importOpen = true
|
|
|
- this.importTab = 'platform'
|
|
|
- this.loadPlatformDictList()
|
|
|
- },
|
|
|
- loadPlatformDictList() {
|
|
|
- this.importLoading = true
|
|
|
- listType({ pageNum: 1, pageSize: 500 }).then(r => {
|
|
|
- this.platformDictList = r.rows || []
|
|
|
- this.importLoading = false
|
|
|
- }).catch(() => { this.importLoading = false })
|
|
|
- },
|
|
|
- onImportTenantChange(val) {
|
|
|
- this.importTenantId = val || null
|
|
|
- this.tenantDictList = []
|
|
|
- this.importTenantSelection = []
|
|
|
- },
|
|
|
- loadTenantDictList() {
|
|
|
- if (!this.importTenantId) return
|
|
|
- this.importLoading = true
|
|
|
- listTenantDictType(this.importTenantId, { pageNum: 1, pageSize: 500 }).then(r => {
|
|
|
- this.tenantDictList = r.rows || []
|
|
|
- this.importLoading = false
|
|
|
- }).catch(() => { this.importLoading = false })
|
|
|
- },
|
|
|
- submitImport() {
|
|
|
- const overwriteExisting = this.importOverwrite
|
|
|
- if (this.importTab === 'platform') {
|
|
|
- if (!this.importPlatformSelection.length) {
|
|
|
- this.$message.warning('请选择要导入的平台字典')
|
|
|
- return
|
|
|
- }
|
|
|
- this.importSubmitting = true
|
|
|
- importTemplateFromPlatform({
|
|
|
- dictIds: this.importPlatformSelection.map(i => i.dictId),
|
|
|
- overwriteExisting
|
|
|
- }).then(r => {
|
|
|
- this.$message.success(r.data.message || '导入成功')
|
|
|
- this.importOpen = false
|
|
|
- this.getList()
|
|
|
- }).finally(() => { this.importSubmitting = false })
|
|
|
- } else {
|
|
|
- if (!this.importTenantId || !this.importTenantSelection.length) {
|
|
|
- this.$message.warning('请选择租户并勾选字典')
|
|
|
- return
|
|
|
- }
|
|
|
- this.importSubmitting = true
|
|
|
- importTemplateFromTenant({
|
|
|
- tenantId: this.importTenantId,
|
|
|
- dictTypes: this.importTenantSelection.map(i => i.dictType),
|
|
|
- overwriteExisting
|
|
|
- }).then(r => {
|
|
|
- this.$message.success(r.data.message || '导入成功')
|
|
|
- this.importOpen = false
|
|
|
- this.getList()
|
|
|
- }).finally(() => { this.importSubmitting = false })
|
|
|
- }
|
|
|
- },
|
|
|
- cancel() { this.open = false; this.reset() },
|
|
|
- reset() {
|
|
|
- this.form = { dictId: undefined, dictName: undefined, dictType: undefined, status: '0', isManaged: 0, syncMode: 'MERGE', remark: undefined }
|
|
|
- this.resetForm('form')
|
|
|
- },
|
|
|
- handleQuery() { this.queryParams.pageNum = 1; this.getList() },
|
|
|
- resetQuery() { this.resetForm('queryForm'); this.handleQuery() },
|
|
|
- handleAdd() { this.reset(); this.open = true; this.title = '添加模板字典类型' },
|
|
|
- handleSelectionChange(s) { this.ids = s.map(i => i.dictId); this.single = s.length !== 1; this.multiple = !s.length },
|
|
|
- handleUpdate(row) {
|
|
|
- this.reset()
|
|
|
- getTemplateDictType(row.dictId || this.ids[0]).then(r => { this.form = r.data; this.open = true; this.title = '修改模板字典类型' })
|
|
|
- },
|
|
|
- submitForm() {
|
|
|
- this.$refs['form'].validate(valid => {
|
|
|
- if (!valid) return
|
|
|
- const req = this.form.dictId != null ? updateTemplateDictType(this.form) : addTemplateDictType(this.form)
|
|
|
- req.then(() => { this.msgSuccess('保存成功'); this.open = false; this.getList() })
|
|
|
- })
|
|
|
- },
|
|
|
- handleDelete(row) {
|
|
|
- const ids = row.dictId || this.ids.join(',')
|
|
|
- this.$confirm('确认删除?', '警告', { type: 'warning' }).then(() => delTemplateDictType(ids))
|
|
|
- .then(() => { this.getList(); this.msgSuccess('删除成功') }).catch(() => {})
|
|
|
- }
|
|
|
- }
|
|
|
-}
|
|
|
-</script>
|
|
|
-
|
|
|
-<style scoped>
|
|
|
-.tip-banner {
|
|
|
- display: flex;
|
|
|
- align-items: flex-start;
|
|
|
- gap: 8px;
|
|
|
- padding: 10px 14px;
|
|
|
- margin-bottom: 16px;
|
|
|
- background: #fdf6ec;
|
|
|
- border: 1px solid #faecd8;
|
|
|
- border-radius: 8px;
|
|
|
- font-size: 13px;
|
|
|
- color: #e6a23c;
|
|
|
- line-height: 1.5;
|
|
|
-}
|
|
|
-.tip-banner i { font-size: 16px; margin-top: 1px; }
|
|
|
-.mb8 { margin-bottom: 8px; }
|
|
|
-.mb16 { margin-bottom: 16px; }
|
|
|
-.filter-card { padding-bottom: 0; }
|
|
|
-.toolbar-row { display: flex; flex-wrap: wrap; align-items: center; }
|
|
|
-.dict-table { width: 100%; }
|
|
|
-.drawer-body-wrap { padding: 0 20px 20px; }
|
|
|
-.drawer-type-meta { margin-bottom: 12px; }
|
|
|
-.import-filter { padding-bottom: 0; background: #fafafa; }
|
|
|
-.import-options {
|
|
|
- margin-top: 16px;
|
|
|
- padding: 12px 14px;
|
|
|
- background: #f5f7fa;
|
|
|
- border-radius: 6px;
|
|
|
-}
|
|
|
-</style>
|
|
|
-
|
|
|
-<style>
|
|
|
-.dict-data-drawer .el-drawer__header {
|
|
|
- margin-bottom: 8px;
|
|
|
- padding-bottom: 16px;
|
|
|
- border-bottom: 1px solid #ebeef5;
|
|
|
- font-weight: 600;
|
|
|
- color: #303133;
|
|
|
-}
|
|
|
-.dict-data-drawer .el-drawer__body { padding-top: 0; }
|
|
|
-</style>
|
|
|
-
|
|
|
+<template>
|
|
|
+ <div class="dict-tab-panel">
|
|
|
+ <div class="tip-banner">
|
|
|
+ <i class="el-icon-info" />
|
|
|
+ <span>可从「字典维护」勾选字典后点「导入到平台模板」,或在此从平台主库 / 租户库批量选取导入</span>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <el-card shadow="never" class="mb16 filter-card" v-show="showSearch">
|
|
|
+ <el-form :model="queryParams" ref="queryForm" :inline="true" size="small" label-width="72px">
|
|
|
+ <el-form-item label="字典名称" prop="dictName">
|
|
|
+ <el-input v-model="queryParams.dictName" placeholder="请输入字典名称" clearable @keyup.enter.native="handleQuery" />
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item label="字典类型" prop="dictType">
|
|
|
+ <el-input v-model="queryParams.dictType" placeholder="请输入字典类型" clearable @keyup.enter.native="handleQuery" />
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item>
|
|
|
+ <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
|
|
|
+ <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
|
|
|
+ </el-form-item>
|
|
|
+ </el-form>
|
|
|
+ </el-card>
|
|
|
+
|
|
|
+ <el-row :gutter="10" class="mb8 toolbar-row">
|
|
|
+ <el-col :span="1.5">
|
|
|
+ <el-button type="primary" plain icon="el-icon-download" size="mini" @click="openImportDialog" v-hasPermi="['tenant:dict:template:add']">从字典库导入</el-button>
|
|
|
+ </el-col>
|
|
|
+ <el-col :span="1.5">
|
|
|
+ <el-button type="primary" plain icon="el-icon-plus" size="mini" @click="handleAdd" v-hasPermi="['tenant:dict:template:add']">手动新增</el-button>
|
|
|
+ </el-col>
|
|
|
+ <el-col :span="1.5">
|
|
|
+ <el-button type="success" plain icon="el-icon-edit" size="mini" :disabled="single" @click="handleUpdate" v-hasPermi="['tenant:dict:template:edit']">修改</el-button>
|
|
|
+ </el-col>
|
|
|
+ <el-col :span="1.5">
|
|
|
+ <el-button type="danger" plain icon="el-icon-delete" size="mini" :disabled="multiple" @click="handleDelete" v-hasPermi="['tenant:dict:template:remove']">删除</el-button>
|
|
|
+ </el-col>
|
|
|
+ <right-toolbar :showSearch.sync="showSearch" @queryTable="getList" />
|
|
|
+ </el-row>
|
|
|
+
|
|
|
+ <el-table v-loading="loading" :data="typeList" border size="small" @selection-change="handleSelectionChange" class="dict-table">
|
|
|
+ <el-table-column type="selection" width="48" align="center" />
|
|
|
+ <el-table-column label="编号" align="center" prop="dictId" width="76" />
|
|
|
+ <el-table-column label="字典名称" align="center" prop="dictName" min-width="120" :show-overflow-tooltip="true" />
|
|
|
+ <el-table-column label="字典类型" align="center" min-width="140">
|
|
|
+ <template slot-scope="scope">
|
|
|
+ <el-link type="primary" :underline="false" @click="openDataDrawer(scope.row)">{{ scope.row.dictType }}</el-link>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column label="平台管控" align="center" width="88">
|
|
|
+ <template slot-scope="scope">
|
|
|
+ <el-tag size="mini" :type="scope.row.isManaged === 1 ? 'danger' : 'info'">{{ scope.row.isManaged === 1 ? '是' : '否' }}</el-tag>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column label="默认同步模式" align="center" prop="syncMode" width="120">
|
|
|
+ <template slot-scope="scope">
|
|
|
+ <el-tag size="mini" type="info" effect="plain">{{ scope.row.syncMode }}</el-tag>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column label="状态" align="center" width="76">
|
|
|
+ <template slot-scope="scope">
|
|
|
+ <dict-tag :options="statusOptions" :value="scope.row.status"/>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column label="操作" align="center" width="200" fixed="right" class-name="small-padding fixed-width">
|
|
|
+ <template slot-scope="scope">
|
|
|
+ <el-button size="mini" type="text" icon="el-icon-view" @click="openDataDrawer(scope.row)">字典数据</el-button>
|
|
|
+ <el-button size="mini" type="text" icon="el-icon-edit" @click="handleUpdate(scope.row)" v-hasPermi="['tenant:dict:template:edit']">修改</el-button>
|
|
|
+ <el-button size="mini" type="text" icon="el-icon-delete" style="color:#f5222d" @click="handleDelete(scope.row)" v-hasPermi="['tenant:dict:template:remove']">删除</el-button>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ </el-table>
|
|
|
+
|
|
|
+ <pagination v-show="total>0" :total="total" :page.sync="queryParams.pageNum" :limit.sync="queryParams.pageSize" @pagination="getList" />
|
|
|
+
|
|
|
+ <el-drawer
|
|
|
+ :title="'模板字典数据 · ' + (currentType.dictName || currentType.dictType || '')"
|
|
|
+ :visible.sync="dataDrawerVisible"
|
|
|
+ size="62%"
|
|
|
+ append-to-body
|
|
|
+ destroy-on-close
|
|
|
+ custom-class="dict-data-drawer"
|
|
|
+ >
|
|
|
+ <div class="drawer-body-wrap" v-if="dataDrawerVisible && currentType.dictType">
|
|
|
+ <div class="drawer-type-meta">
|
|
|
+ <el-tag size="small" type="primary" effect="plain">{{ currentType.dictType }}</el-tag>
|
|
|
+ </div>
|
|
|
+ <template-data-panel :dict-type="currentType.dictType" />
|
|
|
+ </div>
|
|
|
+ </el-drawer>
|
|
|
+
|
|
|
+ <el-dialog :title="title" :visible.sync="open" width="560px" append-to-body>
|
|
|
+ <el-form ref="form" :model="form" :rules="rules" label-width="110px">
|
|
|
+ <el-form-item label="字典名称" prop="dictName"><el-input v-model="form.dictName" /></el-form-item>
|
|
|
+ <el-form-item label="字典类型" prop="dictType"><el-input v-model="form.dictType" :disabled="form.dictId != null" /></el-form-item>
|
|
|
+ <el-form-item label="平台管控" prop="isManaged">
|
|
|
+ <el-radio-group v-model="form.isManaged">
|
|
|
+ <el-radio :label="1">是(同步时可覆盖)</el-radio>
|
|
|
+ <el-radio :label="0">否(同步时仅追加)</el-radio>
|
|
|
+ </el-radio-group>
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item label="默认同步模式" prop="syncMode">
|
|
|
+ <el-select v-model="form.syncMode" style="width: 100%">
|
|
|
+ <el-option label="MERGE - 合并更新" value="MERGE" />
|
|
|
+ <el-option label="APPEND - 仅追加" value="APPEND" />
|
|
|
+ <el-option label="OVERWRITE - 覆盖平台项" value="OVERWRITE" />
|
|
|
+ </el-select>
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item label="状态" prop="status">
|
|
|
+ <el-radio-group v-model="form.status">
|
|
|
+ <el-radio v-for="dict in statusOptions" :key="dict.dictValue" :label="dict.dictValue">{{ dict.dictLabel }}</el-radio>
|
|
|
+ </el-radio-group>
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item label="备注"><el-input v-model="form.remark" type="textarea" /></el-form-item>
|
|
|
+ </el-form>
|
|
|
+ <div slot="footer" class="dialog-footer">
|
|
|
+ <el-button type="primary" @click="submitForm">确 定</el-button>
|
|
|
+ <el-button @click="cancel">取 消</el-button>
|
|
|
+ </div>
|
|
|
+ </el-dialog>
|
|
|
+
|
|
|
+ <el-dialog title="从字典库导入到平台模板" :visible.sync="importOpen" width="800px" append-to-body class="import-dialog">
|
|
|
+ <el-tabs v-model="importTab" class="import-tabs">
|
|
|
+ <el-tab-pane label="平台主库字典" name="platform">
|
|
|
+ <el-table v-loading="importLoading" :data="platformDictList" @selection-change="s => importPlatformSelection = s" max-height="360" size="small" border>
|
|
|
+ <el-table-column type="selection" width="45" />
|
|
|
+ <el-table-column label="字典名称" prop="dictName" min-width="140" />
|
|
|
+ <el-table-column label="字典类型" prop="dictType" min-width="160" />
|
|
|
+ <el-table-column label="状态" prop="status" width="80" align="center" />
|
|
|
+ </el-table>
|
|
|
+ </el-tab-pane>
|
|
|
+ <el-tab-pane label="租户字典" name="tenant">
|
|
|
+ <el-card shadow="never" class="mb8 import-filter">
|
|
|
+ <el-form inline size="small">
|
|
|
+ <el-form-item label="租户">
|
|
|
+ <inline-tenant-selector mode="admin" @change="onImportTenantChange" />
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item>
|
|
|
+ <el-button type="primary" size="mini" icon="el-icon-search" @click="loadTenantDictList" :disabled="!importTenantId">加载字典</el-button>
|
|
|
+ </el-form-item>
|
|
|
+ </el-form>
|
|
|
+ </el-card>
|
|
|
+ <el-table v-loading="importLoading" :data="tenantDictList" @selection-change="s => importTenantSelection = s" max-height="300" size="small" border>
|
|
|
+ <el-table-column type="selection" width="45" />
|
|
|
+ <el-table-column label="字典名称" prop="dictName" min-width="140" />
|
|
|
+ <el-table-column label="字典类型" prop="dictType" min-width="160" />
|
|
|
+ <el-table-column label="来源" prop="dictSource" width="80" align="center" />
|
|
|
+ </el-table>
|
|
|
+ </el-tab-pane>
|
|
|
+ </el-tabs>
|
|
|
+ <div class="import-options">
|
|
|
+ <el-checkbox v-model="importOverwrite">已存在同类型时覆盖更新(否则仅追加缺失项)</el-checkbox>
|
|
|
+ </div>
|
|
|
+ <div slot="footer" class="dialog-footer">
|
|
|
+ <el-button type="primary" :loading="importSubmitting" icon="el-icon-upload2" @click="submitImport">导入选中</el-button>
|
|
|
+ <el-button @click="importOpen = false">取 消</el-button>
|
|
|
+ </div>
|
|
|
+ </el-dialog>
|
|
|
+ </div>
|
|
|
+</template>
|
|
|
+
|
|
|
+<script>
|
|
|
+import InlineTenantSelector from '@/components/InlineTenantSelector'
|
|
|
+import TemplateDataPanel from './TemplateDataPanel'
|
|
|
+import { listType } from '@/api/system/dict/type'
|
|
|
+import { listTenantDictType } from '@/api/tenant/dict'
|
|
|
+import {
|
|
|
+ listTemplateDictType, getTemplateDictType, addTemplateDictType,
|
|
|
+ updateTemplateDictType, delTemplateDictType,
|
|
|
+ importTemplateFromPlatform, importTemplateFromTenant
|
|
|
+} from '@/api/tenant/dict'
|
|
|
+
|
|
|
+export default {
|
|
|
+ name: 'TenantDictTemplate',
|
|
|
+ components: { InlineTenantSelector, TemplateDataPanel },
|
|
|
+ data() {
|
|
|
+ return {
|
|
|
+ loading: true, ids: [], single: true, multiple: true, showSearch: true, total: 0, typeList: [],
|
|
|
+ title: '', open: false, statusOptions: [],
|
|
|
+ queryParams: { pageNum: 1, pageSize: 10, dictName: undefined, dictType: undefined },
|
|
|
+ form: {},
|
|
|
+ rules: {
|
|
|
+ dictName: [{ required: true, message: '字典名称不能为空', trigger: 'blur' }],
|
|
|
+ dictType: [{ required: true, message: '字典类型不能为空', trigger: 'blur' }],
|
|
|
+ syncMode: [{ required: true, message: '请选择同步模式', trigger: 'change' }]
|
|
|
+ },
|
|
|
+ dataDrawerVisible: false,
|
|
|
+ currentType: {},
|
|
|
+ importOpen: false,
|
|
|
+ importTab: 'platform',
|
|
|
+ importLoading: false,
|
|
|
+ importSubmitting: false,
|
|
|
+ importOverwrite: false,
|
|
|
+ platformDictList: [],
|
|
|
+ importPlatformSelection: [],
|
|
|
+ importTenantId: null,
|
|
|
+ tenantDictList: [],
|
|
|
+ importTenantSelection: []
|
|
|
+ }
|
|
|
+ },
|
|
|
+ created() {
|
|
|
+ this.getList()
|
|
|
+ this.getDicts('sys_normal_disable').then(r => { this.statusOptions = r.data })
|
|
|
+ },
|
|
|
+ methods: {
|
|
|
+ getList() {
|
|
|
+ this.loading = true
|
|
|
+ listTemplateDictType(this.queryParams).then(r => {
|
|
|
+ this.typeList = r.rows; this.total = r.total; this.loading = false
|
|
|
+ }).catch(() => { this.loading = false })
|
|
|
+ },
|
|
|
+ openDataDrawer(row) {
|
|
|
+ this.currentType = { dictId: row.dictId, dictType: row.dictType, dictName: row.dictName }
|
|
|
+ this.dataDrawerVisible = true
|
|
|
+ },
|
|
|
+ openImportDialog() {
|
|
|
+ this.importOpen = true
|
|
|
+ this.importTab = 'platform'
|
|
|
+ this.loadPlatformDictList()
|
|
|
+ },
|
|
|
+ loadPlatformDictList() {
|
|
|
+ this.importLoading = true
|
|
|
+ listType({ pageNum: 1, pageSize: 500 }).then(r => {
|
|
|
+ this.platformDictList = r.rows || []
|
|
|
+ this.importLoading = false
|
|
|
+ }).catch(() => { this.importLoading = false })
|
|
|
+ },
|
|
|
+ onImportTenantChange(val) {
|
|
|
+ this.importTenantId = val || null
|
|
|
+ this.tenantDictList = []
|
|
|
+ this.importTenantSelection = []
|
|
|
+ },
|
|
|
+ loadTenantDictList() {
|
|
|
+ if (!this.importTenantId) return
|
|
|
+ this.importLoading = true
|
|
|
+ listTenantDictType(this.importTenantId, { pageNum: 1, pageSize: 500 }).then(r => {
|
|
|
+ this.tenantDictList = r.rows || []
|
|
|
+ this.importLoading = false
|
|
|
+ }).catch(() => { this.importLoading = false })
|
|
|
+ },
|
|
|
+ submitImport() {
|
|
|
+ const overwriteExisting = this.importOverwrite
|
|
|
+ if (this.importTab === 'platform') {
|
|
|
+ if (!this.importPlatformSelection.length) {
|
|
|
+ this.$message.warning('请选择要导入的平台字典')
|
|
|
+ return
|
|
|
+ }
|
|
|
+ this.importSubmitting = true
|
|
|
+ importTemplateFromPlatform({
|
|
|
+ dictIds: this.importPlatformSelection.map(i => i.dictId),
|
|
|
+ overwriteExisting
|
|
|
+ }).then(r => {
|
|
|
+ this.$message.success(r.data.message || '导入成功')
|
|
|
+ this.importOpen = false
|
|
|
+ this.getList()
|
|
|
+ }).finally(() => { this.importSubmitting = false })
|
|
|
+ } else {
|
|
|
+ if (!this.importTenantId || !this.importTenantSelection.length) {
|
|
|
+ this.$message.warning('请选择租户并勾选字典')
|
|
|
+ return
|
|
|
+ }
|
|
|
+ this.importSubmitting = true
|
|
|
+ importTemplateFromTenant({
|
|
|
+ tenantId: this.importTenantId,
|
|
|
+ dictTypes: this.importTenantSelection.map(i => i.dictType),
|
|
|
+ overwriteExisting
|
|
|
+ }).then(r => {
|
|
|
+ this.$message.success(r.data.message || '导入成功')
|
|
|
+ this.importOpen = false
|
|
|
+ this.getList()
|
|
|
+ }).finally(() => { this.importSubmitting = false })
|
|
|
+ }
|
|
|
+ },
|
|
|
+ cancel() { this.open = false; this.reset() },
|
|
|
+ reset() {
|
|
|
+ this.form = { dictId: undefined, dictName: undefined, dictType: undefined, status: '0', isManaged: 0, syncMode: 'MERGE', remark: undefined }
|
|
|
+ this.resetForm('form')
|
|
|
+ },
|
|
|
+ handleQuery() { this.queryParams.pageNum = 1; this.getList() },
|
|
|
+ resetQuery() { this.resetForm('queryForm'); this.handleQuery() },
|
|
|
+ handleAdd() { this.reset(); this.open = true; this.title = '添加模板字典类型' },
|
|
|
+ handleSelectionChange(s) { this.ids = s.map(i => i.dictId); this.single = s.length !== 1; this.multiple = !s.length },
|
|
|
+ handleUpdate(row) {
|
|
|
+ this.reset()
|
|
|
+ getTemplateDictType(row.dictId || this.ids[0]).then(r => { this.form = r.data; this.open = true; this.title = '修改模板字典类型' })
|
|
|
+ },
|
|
|
+ submitForm() {
|
|
|
+ this.$refs['form'].validate(valid => {
|
|
|
+ if (!valid) return
|
|
|
+ const req = this.form.dictId != null ? updateTemplateDictType(this.form) : addTemplateDictType(this.form)
|
|
|
+ req.then(() => { this.msgSuccess('保存成功'); this.open = false; this.getList() })
|
|
|
+ })
|
|
|
+ },
|
|
|
+ handleDelete(row) {
|
|
|
+ const ids = row.dictId || this.ids.join(',')
|
|
|
+ this.$confirm('确认删除?', '警告', { type: 'warning' }).then(() => delTemplateDictType(ids))
|
|
|
+ .then(() => { this.getList(); this.msgSuccess('删除成功') }).catch(() => {})
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+</script>
|
|
|
+
|
|
|
+<style scoped>
|
|
|
+.tip-banner {
|
|
|
+ display: flex;
|
|
|
+ align-items: flex-start;
|
|
|
+ gap: 8px;
|
|
|
+ padding: 10px 14px;
|
|
|
+ margin-bottom: 16px;
|
|
|
+ background: #fdf6ec;
|
|
|
+ border: 1px solid #faecd8;
|
|
|
+ border-radius: 8px;
|
|
|
+ font-size: 13px;
|
|
|
+ color: #e6a23c;
|
|
|
+ line-height: 1.5;
|
|
|
+}
|
|
|
+.tip-banner i { font-size: 16px; margin-top: 1px; }
|
|
|
+.mb8 { margin-bottom: 8px; }
|
|
|
+.mb16 { margin-bottom: 16px; }
|
|
|
+.filter-card { padding-bottom: 0; }
|
|
|
+.toolbar-row { display: flex; flex-wrap: wrap; align-items: center; }
|
|
|
+.dict-table { width: 100%; }
|
|
|
+.drawer-body-wrap { padding: 0 20px 20px; }
|
|
|
+.drawer-type-meta { margin-bottom: 12px; }
|
|
|
+.import-filter { padding-bottom: 0; background: #fafafa; }
|
|
|
+.import-options {
|
|
|
+ margin-top: 16px;
|
|
|
+ padding: 12px 14px;
|
|
|
+ background: #f5f7fa;
|
|
|
+ border-radius: 6px;
|
|
|
+}
|
|
|
+</style>
|
|
|
+
|
|
|
+<style>
|
|
|
+.dict-data-drawer .el-drawer__header {
|
|
|
+ margin-bottom: 8px;
|
|
|
+ padding-bottom: 16px;
|
|
|
+ border-bottom: 1px solid #ebeef5;
|
|
|
+ font-weight: 600;
|
|
|
+ color: #303133;
|
|
|
+}
|
|
|
+.dict-data-drawer .el-drawer__body { padding-top: 0; }
|
|
|
+</style>
|
|
|
+
|