357 lines
9.5 KiB
Vue
357 lines
9.5 KiB
Vue
<template>
|
|
<!-- 面包屑 -->
|
|
<el-breadcrumb>
|
|
<el-breadcrumb-item>系统管理</el-breadcrumb-item>
|
|
<el-breadcrumb-item to="/system/dictionary">数据字典</el-breadcrumb-item>
|
|
</el-breadcrumb>
|
|
<el-row :gutter="20">
|
|
<el-col :span="12">
|
|
<template v-if="checkData.length">
|
|
<el-button type="danger" @click="handleCheckDeleteClick">
|
|
批量删除
|
|
</el-button>
|
|
</template>
|
|
<el-input v-model="filterText" placeholder="搜索数据字典" />
|
|
<el-row style="margin: 15px 0;">
|
|
<!-- 导入 -->
|
|
<el-upload class="upload-demo" :action="importExcel" :headers="headers" :on-success="handleExcelSuccess"
|
|
:on-progress="uploadLoading" :on-error="closeUploadLoading" style="margin-left: 10px" :show-file-list="false">
|
|
<el-button type="primary">导入</el-button>
|
|
</el-upload>
|
|
<!-- 下载导入模板 -->
|
|
<el-button style="margin-left: 10px" icon="ElIconDownload" @click="downloadTemplate()">下载导入模板</el-button>
|
|
</el-row>
|
|
|
|
<el-tree
|
|
ref="treeRef"
|
|
:filter-node-method="filterNode"
|
|
:data="treeData"
|
|
show-checkbox
|
|
draggable
|
|
:default-expanded-keys="treeExpandData"
|
|
:highlight-current="true"
|
|
:expand-on-click-node="true"
|
|
node-key="id"
|
|
@node-drop="handleDrop"
|
|
@check="handleCheck"
|
|
>
|
|
<template #default="{ node, data }">
|
|
<span class="custom-tree-node">
|
|
<span>{{ node.label }}</span>
|
|
<span>
|
|
<a @click="handleTreeClick('create', data)"> 添加 </a>
|
|
<a v-if="data.allow == 1" @click="handleTreeClick('edit', data)">
|
|
编辑
|
|
</a>
|
|
</span>
|
|
</span>
|
|
</template>
|
|
</el-tree>
|
|
</el-col>
|
|
<el-col :span="12">
|
|
<div v-if="model.dictionary_guid">
|
|
<el-form ref="formRef" :model="model" :rules="rules">
|
|
<el-form-item label="名称" prop="dictionary_name">
|
|
<el-input v-model="model.dictionary_name" type="text"></el-input>
|
|
</el-form-item>
|
|
<el-form-item label="值" prop="dictionary_value">
|
|
<el-input v-model="model.dictionary_value" type="text"></el-input>
|
|
</el-form-item>
|
|
<el-form-item label="排序" prop="dictionary_order">
|
|
<el-input v-model="model.dictionary_order" type="number"></el-input>
|
|
</el-form-item>
|
|
<el-form-item label="状态" prop="dictionary_status">
|
|
<el-switch
|
|
v-model="model.dictionary_status"
|
|
active-text="启用"
|
|
inactive-text="停用"
|
|
/>
|
|
</el-form-item>
|
|
<el-form-item label="允许更新" prop="dictionary_allow_update">
|
|
<el-switch
|
|
v-model="model.dictionary_allow_update"
|
|
active-text="启用"
|
|
inactive-text="停用"
|
|
/>
|
|
</el-form-item>
|
|
<el-form-item label="回显样式" prop="dictionary_list_class">
|
|
<el-select v-model="model.dictionary_list_class">
|
|
<el-option
|
|
v-for="item in listClassOptions"
|
|
:key="item.value"
|
|
:label="item.label + '(' + item.value + ')'"
|
|
:value="item.value"></el-option>
|
|
</el-select>
|
|
</el-form-item>
|
|
<el-form-item>
|
|
<el-button type="primary" @click="handleSaveClick">
|
|
保存
|
|
</el-button>
|
|
<el-button
|
|
v-if="model.dictionary_guid && model.dictionary_guid != 'create'"
|
|
type="danger"
|
|
@click="handleDeleteClick"
|
|
>
|
|
删除
|
|
</el-button>
|
|
</el-form-item>
|
|
</el-form>
|
|
</div>
|
|
<div v-else>
|
|
<el-empty description="请选择字典" />
|
|
</div>
|
|
</el-col>
|
|
</el-row>
|
|
</template>
|
|
<script setup>
|
|
import { ref, reactive, watch } from 'vue';
|
|
import {
|
|
getDictionaryTree,
|
|
addDictionary,
|
|
updateDictionary,
|
|
deleteDictionary,
|
|
downloadTemplate,
|
|
importExcel
|
|
} from '~/service/dictionary';
|
|
import { useLoginStore } from "~/store";
|
|
|
|
const store = useLoginStore();
|
|
const headers = {
|
|
Accept: "application/json",
|
|
...store.headers,
|
|
};
|
|
|
|
const formRef = ref();
|
|
const treeRef = ref();
|
|
const filterText = ref('');
|
|
const treeData = ref([]);
|
|
const treeExpandData = ref([]);
|
|
const checkData = ref([]);
|
|
const model = reactive({
|
|
dictionary_guid: '',
|
|
dictionary_parent_guid: '',
|
|
dictionary_name: '',
|
|
dictionary_value: '',
|
|
dictionary_status: true,
|
|
dictionary_index: 0,
|
|
dictionary_order: 0,
|
|
dictionary_allow_update: 0,
|
|
dictionary_list_class: 'default',
|
|
});
|
|
// 数据标签回显样式
|
|
const listClassOptions = ref([
|
|
{
|
|
value: 'default',
|
|
label: '默认'
|
|
},
|
|
{
|
|
value: 'primary',
|
|
label: '主要'
|
|
},
|
|
{
|
|
value: 'success',
|
|
label: '成功'
|
|
},
|
|
{
|
|
value: 'info',
|
|
label: '信息'
|
|
},
|
|
{
|
|
value: 'warning',
|
|
label: '警告'
|
|
},
|
|
{
|
|
value: 'danger',
|
|
label: '危险'
|
|
}
|
|
])
|
|
|
|
const rules = {
|
|
dictionary_name: [
|
|
{
|
|
required: true,
|
|
message: '请输入字典名称'
|
|
}
|
|
],
|
|
dictionary_order: [
|
|
{
|
|
required: true,
|
|
message: '请输入字典排序'
|
|
}
|
|
]
|
|
};
|
|
|
|
const loadTree = async () => {
|
|
const { code, data } = await getDictionaryTree();
|
|
if (code == 0) {
|
|
treeData.value = data;
|
|
data.forEach(element => {
|
|
treeExpandData.value.push("0")
|
|
});
|
|
}
|
|
};
|
|
|
|
loadTree();
|
|
|
|
watch(filterText, v => {
|
|
treeRef.value.filter(v);
|
|
});
|
|
// 搜索树组件
|
|
const filterNode = (value, data) => {
|
|
if (!value) return true;
|
|
return data.label.indexOf(value) !== -1;
|
|
};
|
|
// 拖拽排序
|
|
const handleDrop = async (current, to, action) => {
|
|
const currentData = current.data;
|
|
const toData = to.data;
|
|
console.log({
|
|
current: currentData,
|
|
to: toData,
|
|
action
|
|
});
|
|
const data = {
|
|
dictionary_guid: current.data.id,
|
|
dictionary_parent_guid: '',
|
|
dictionary_index: '',
|
|
dictionary_order: ''
|
|
};
|
|
switch (action) {
|
|
case 'before':
|
|
data.dictionary_parent_guid = toData.parent_id;
|
|
data.dictionary_index = toData.index;
|
|
data.dictionary_order = toData.order + 1;
|
|
break;
|
|
case 'after':
|
|
data.dictionary_parent_guid = toData.parent_id;
|
|
data.dictionary_index = toData.index;
|
|
data.dictionary_order = toData.order - 1;
|
|
break;
|
|
case 'inner':
|
|
data.dictionary_parent_guid = toData.id;
|
|
data.dictionary_index = toData.index + 1;
|
|
data.dictionary_order = 0;
|
|
break;
|
|
}
|
|
const { code } = await updateDictionary(data);
|
|
if (code == 0) {
|
|
loadTree();
|
|
}
|
|
};
|
|
// 选中菜单
|
|
const handleCheck = (_, { checkedKeys }) => {
|
|
checkData.value = checkedKeys;
|
|
};
|
|
// 表单提交
|
|
const handleSaveClick = async () => {
|
|
try {
|
|
await formRef.value.validate();
|
|
const data = {
|
|
...model,
|
|
dictionary_status: model.dictionary_status ? 1 : 2,
|
|
dictionary_allow_update: model.dictionary_allow_update ? 1 : 2
|
|
};
|
|
if (model.dictionary_guid === 'create') {
|
|
const { code } = await addDictionary(data);
|
|
if (code == 0) {
|
|
loadTree();
|
|
}
|
|
model.dictionary_guid = '';
|
|
} else {
|
|
const { code } = await updateDictionary(data);
|
|
if (code == 0) {
|
|
loadTree();
|
|
model.dictionary_guid = '';
|
|
}
|
|
}
|
|
} catch (error) {}
|
|
};
|
|
// 批量删除
|
|
const handleCheckDeleteClick = () => {
|
|
ElMessageBox.alert('您确定要删除该字典吗?', '删除字典', {
|
|
confirmButtonText: '确定'
|
|
}).then(async () => {
|
|
const { code } = await deleteDictionary({
|
|
dictionary_guid: checkData.value.join()
|
|
});
|
|
if (code == 0) {
|
|
loadTree();
|
|
checkData.value = [];
|
|
}
|
|
});
|
|
};
|
|
// 删除字典
|
|
const handleDeleteClick = () => {
|
|
ElMessageBox.alert('您确定要删除该字典吗?', '删除字典', {
|
|
confirmButtonText: '确定'
|
|
}).then(async () => {
|
|
const { code } = await deleteDictionary(model);
|
|
if (code == 0) {
|
|
loadTree();
|
|
model.dictionary_guid = '';
|
|
}
|
|
});
|
|
};
|
|
|
|
const handleTreeClick = (type, data) => {
|
|
switch (type) {
|
|
case 'create':
|
|
model.dictionary_guid = 'create';
|
|
model.dictionary_parent_guid = data.id;
|
|
model.dictionary_index = data.index + 1;
|
|
model.dictionary_name = '';
|
|
model.dictionary_value = '';
|
|
model.dictionary_order = 0;
|
|
model.dictionary_status = true;
|
|
model.dictionary_allow_update = true;
|
|
model.dictionary_list_class = "default";
|
|
break;
|
|
case 'edit':
|
|
model.dictionary_guid = data.id;
|
|
model.dictionary_parent_guid = data.parent_id;
|
|
model.dictionary_index = data.index;
|
|
model.dictionary_name = data.label;
|
|
model.dictionary_value = data.value;
|
|
model.dictionary_order = data.order;
|
|
model.dictionary_status = data.status == 1;
|
|
model.dictionary_allow_update = data.allow == 1;
|
|
model.dictionary_list_class = data.list_class;
|
|
break;
|
|
}
|
|
};
|
|
|
|
let loading = null;
|
|
const uploadLoading = () => {
|
|
loading = ElLoading.service({
|
|
lock: true,
|
|
text: "正在导入中...",
|
|
background: "rgba(255, 255, 255, 0.7)",
|
|
});
|
|
};
|
|
const closeUploadLoading = () => loading.close();
|
|
const handleExcelSuccess = (value) => {
|
|
if (value.code == 0) {
|
|
ElMessageBox.alert(value.msg, "导入信息", {
|
|
dangerouslyUseHTMLString: true,
|
|
confirmButtonText: "确定",
|
|
});
|
|
} else {
|
|
ElMessage.error(value.msg);
|
|
}
|
|
closeUploadLoading();
|
|
treeRef.value.reload();
|
|
};
|
|
|
|
|
|
</script>
|
|
<style scoped>
|
|
.custom-tree-node {
|
|
flex: 1;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: space-between;
|
|
font-size: 14px;
|
|
padding-right: 8px;
|
|
}
|
|
</style>
|