之前公司有维护过一个内部的字典平台,基本步骤和页面如下
添加字典属性弹窗
import { defineStore } from 'pinia'
export const useDictionary = defineStore('dictionary', {
state: () => ({
dict: [],
dictObj: {},
}),
actions: {
setDict(data, type) {
let init = this.dictObj[type] || []
this.dictObj[type] = [...init, ...data]
},
setDictContent(data, type) {
let initData = JSON.parse(JSON.stringify(data))
this.dictObj[type] = initData.list || []
this.dict.push(initData)
},
},
getters: {
getDict(type) {
return this.dictObj[type]
},
getDictList() {
return this.dict
},
},
})
主页面代码
<template>
<div class="main flex_c">
<div class="m8_b">
<el-button type="primary" @click="addDict">添加字典</el-button>
</div>
<div class="flex_r dict">
<div class="dict_left">
<el-table :data="dictList" border @row-click="rowClick">
<el-table-column
label="字典名称"
prop="label"
></el-table-column>
<el-table-column
label="字典key"
prop="key"
></el-table-column>
<el-table-column label="启用状态">
<template #default="scope">
<span>{{ scope.row.flag ? '禁用' : '启用' }}</span>
</template>
</el-table-column>
</el-table>
</div>
<div class="dict_right">
<div class="m8_b">
<el-button
type="primary"
@click="addItem"
:disabled="disabledAdd"
>添加枚举值</el-button
>
</div>
<el-table :data="dictItemList" border>
<el-table-column label="序号" prop="desc"></el-table-column>
<el-table-column
label="枚举名称"
prop="label"
></el-table-column>
<el-table-column
label="枚举值"
prop="value"
></el-table-column>
</el-table>
</div>
</div>
<dictForm v-model="dictFlag" />
<dictContent
v-model="dictContentFlag"
ref="dictContents"
@submitItem="submitItem"
/>
</div>
</template>
<script setup>
import { useDictionary } from '@/stores/dictionary';
import { computed, watch } from 'vue';
import dictContent from './components/dictContent.vue';
import dictForm from './components/dictForm.vue';
const dictFlag = ref(false) // 字典列表
const dictContentFlag = ref(false) // 字典详情
const dictContents = ref(null)
const keyType = ref('')
const store = useDictionary()
const dictList = computed(() => {
return store.dict
})
watch(dictList, (newValue) => {
console.log(newValue, '>><<<')
})
const addDict = () => {
dictFlag.value = !dictFlag.value
}
const disabledAdd = computed(() => {
return !keyType.value
})
const dictItemList = computed(() => {
return store.dictObj[keyType.value]
})
// 点击某一行
const rowClick = (row, column, event) => {
// dictContents.value.addRef(row.key)
keyType.value = row.key
}
const addItem = () => {
dictContentFlag.value = !dictContentFlag.value
}
const submitItem = (val) => {
store.setDict([val], keyType.value)
}
</script>
<style lang="scss" scoped>
.main {
width: 100%;
height: 100%;
}
.dict {
width: 100%;
height: 100%;
.dict_left {
flex: 2;
border: 1px solid #eee;
border-radius: 4px;
box-shadow: 0px 2px 2px 2px #eee;
margin-right: 8px;
}
.dict_right {
flex: 1;
}
}
</style>
字典弹窗代码
<template>
<div>
<el-dialog v-model="centerDialogVisible" title="新增" width="50%" align-center @close="close">
<div>
<el-form :model="addForm" ref="addFroms" :rules="rules">
<el-row :gutter="24">
<el-col :span="12">
<el-form-item label="字典名称" prop="label">
<el-input v-model="addForm.label" placeholder="请输字典名称"></el-input>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="字典key" prop="key">
<el-input v-model="addForm.key" placeholder="请输入字典key"></el-input>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="排序顺序" prop="desc">
<el-input v-model.number="addForm.desc" placeholder="请输入排序顺序"></el-input>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="是否禁用" prop="flag">
<el-radio-group v-model="addForm.flag" class="ml-4">
<el-radio :label="false" size="large">
启用</el-radio>
<el-radio :label="true" size="large">禁用</el-radio>
</el-radio-group>
</el-form-item>
</el-col>
</el-row>
</el-form>
</div>
<template #footer>
<span class="dialog-footer">
<el-button @click="close">取消</el-button>
<el-button type="primary" @click="addConfirm">
确定
</el-button>
</span>
</template>
</el-dialog>
</div>
</template>
<script setup>
import { useDictionary } from '@/stores/dictionary';
import { reactive } from "vue";
// import { storeToRefs } from 'pinia'
const store = useDictionary()
const props = defineProps({
modelValue: {
type: Boolean,
default: false
}
})
const addForm = reactive({
key: '',
label: '',
desc: '',
flag: false,
list: []
})
const rules = {
key: [{ required: true, message: '请输入字典key', target: 'blur' }],
label: [{ required: true, message: '请输入字典名称', target: 'blur' }],
desc: [{ required: false, message: '' }],
flag: [{ required: false }]
}
const addFroms = ref(null)
const emit = defineEmits(['update:modelValue'])
const centerDialogVisible = computed({
get() {
return props.modelValue
},
set(val) {
emit('update:modelValue', val)
}
})
const addRef = (value) => {
// console.log(value, '我是父组件传值过来的')
}
const close = () => {
emit('update:modelValue', false)
addFroms.value.resetFields()
}
// 确认
const addConfirm = () => {
addFroms.value.validate((valid) => {
if (valid) {
store.setDictContent(addForm, addForm.key)
close()
}
})
}
defineExpose({
centerDialogVisible,
addRef
})
</script>
枚举值弹窗代码
<template>
<div>
<el-dialog
v-model="centerDialogVisible"
title="新增"
width="50%"
align-center
@close="close"
>
<div>
<el-form :model="addForm" ref="addFroms">
<el-row :gutter="24">
<el-col :span="12">
<el-form-item label="枚举名称" prop="label">
<el-input
v-model="addForm.label"
placeholder="请输入枚举名称"
></el-input>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="枚举值" prop="value">
<el-input
v-model="addForm.value"
placeholder="请输入枚举值"
></el-input>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="排序顺序" prop="desc">
<el-input
v-model.number="addForm.desc"
placeholder="请输入排序顺序"
></el-input>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="是否禁用" prop="flag">
<el-radio-group
v-model="addForm.flag"
class="ml-4"
>
<el-radio :label="false" size="large">
启用</el-radio
>
<el-radio :label="true" size="large"
>禁用</el-radio
>
</el-radio-group>
</el-form-item>
</el-col>
</el-row>
</el-form>
</div>
<template #footer>
<span class="dialog-footer">
<el-button @click="close">取消</el-button>
<el-button type="primary" @click="addConfirm">
确定
</el-button>
</span>
</template>
</el-dialog>
</div>
</template>
<script setup>
import { reactive, ref } from "vue";
const props = defineProps({
modelValue: {
type: Boolean,
default: false
}
})
const addFroms = ref(null)
const addForm = reactive({
value: '',
label: '',
desc: '',
flag: false
})
const emit = defineEmits(['update:modelValue', 'submitItem'])
const centerDialogVisible = computed({
get () {
return props.modelValue
},
set (val) {
emit('update:modelValue', val)
}
})
const addRef = (value) => {
console.log(value, '我是父组件传值过来的')
}
const close = () => {
emit('update:modelValue', false)
addFroms.value.resetFields()
}
// 确认
const addConfirm = () => {
let form = JSON.parse(JSON.stringify(addForm))
emit('submitItem', form)
close()
}
defineExpose({
centerDialogVisible,
addRef
})
</script>
一个简单版的字典服务排序和删除的暂时没有做 思路大概是这个样子