fix 更新依赖,修改字典页面布局

This commit is contained in:
yxh 2025-06-10 09:59:54 +08:00
parent 8addeaf491
commit bb39c4bfd9
9 changed files with 652 additions and 478 deletions

644
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -14,7 +14,7 @@
"@codemirror/lang-javascript": "^6.1.1", "@codemirror/lang-javascript": "^6.1.1",
"@codemirror/theme-one-dark": "^6.1.0", "@codemirror/theme-one-dark": "^6.1.0",
"@element-plus/icons-vue": "^2.3.1", "@element-plus/icons-vue": "^2.3.1",
"axios": "1.7.4", "axios": "1.8.2",
"codemirror": "^6.0.1", "codemirror": "^6.0.1",
"countup.js": "^2.8.0", "countup.js": "^2.8.0",
"cropperjs": "^1.6.0", "cropperjs": "^1.6.0",
@ -40,7 +40,7 @@
"vue-codemirror": "^6.1.1", "vue-codemirror": "^6.1.1",
"vue-demi": "^0.14.7", "vue-demi": "^0.14.7",
"vue-grid-layout": "^3.0.0-beta1", "vue-grid-layout": "^3.0.0-beta1",
"vue-i18n": "^9.10.2", "vue-i18n": "11.1.2",
"vue-router": "^4.3.0", "vue-router": "^4.3.0",
"vue-simple-uploader": "^1.0.0-beta.5", "vue-simple-uploader": "^1.0.0-beta.5",
"vue-ueditor-wrap": "^3.0.8" "vue-ueditor-wrap": "^3.0.8"
@ -60,7 +60,7 @@
"sass": "^1.80.7", "sass": "^1.80.7",
"sass-loader": "^16.0.3", "sass-loader": "^16.0.3",
"typescript": "^5.4.2", "typescript": "^5.4.2",
"vite": "5.4.6", "vite": "6.3.4",
"vite-plugin-cdn-import": "^0.3.5", "vite-plugin-cdn-import": "^0.3.5",
"vite-plugin-compression": "^0.5.1", "vite-plugin-compression": "^0.5.1",
"vite-plugin-vue-setup-extend-plus": "^0.1.0", "vite-plugin-vue-setup-extend-plus": "^0.1.0",

View File

@ -43,10 +43,11 @@ export function deleteType(dictIds:number[]) {
// 获取字典选择框列表 // 获取字典选择框列表
export function optionselect() { export function optionselect(all?:boolean) {
return request({ return request({
url: '/api/v1/system/dict/type/optionSelect', url: '/api/v1/system/dict/type/optionSelect',
method: 'get' method: 'get',
params:{all}
}) })
} }

View File

@ -2,6 +2,9 @@
<div class="system-edit-dic-container"> <div class="system-edit-dic-container">
<el-dialog :title="(ruleForm.dictId!==0?'修改':'添加')+'字典'" v-model="isShowDialog" width="769px"> <el-dialog :title="(ruleForm.dictId!==0?'修改':'添加')+'字典'" v-model="isShowDialog" width="769px">
<el-form :model="ruleForm" ref="formRef" :rules="rules" size="default" label-width="90px"> <el-form :model="ruleForm" ref="formRef" :rules="rules" size="default" label-width="90px">
<el-form-item label="上级" prop="pid">
<el-cascader v-model="ruleForm.pid" :options="dictTypeOpt" :props="typeProps" clearable />
</el-form-item>
<el-form-item label="字典名称" prop="dictName"> <el-form-item label="字典名称" prop="dictName">
<el-input v-model="ruleForm.dictName" placeholder="请输入字典名称" /> <el-input v-model="ruleForm.dictName" placeholder="请输入字典名称" />
</el-form-item> </el-form-item>
@ -29,11 +32,12 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { reactive, toRefs, defineComponent,ref, unref } from 'vue'; import { reactive, toRefs, ref, unref, getCurrentInstance } from 'vue';
import { getType,addType,editType } from '/@/api/system/dict/type'; import { getType, addType, editType, optionselect } from '/@/api/system/dict/type';
import {ElMessage} from "element-plus"; import {ElMessage} from "element-plus";
interface RuleFormState { interface RuleFormState {
dictId:number; dictId:number;
pid:number;
dictName:string; dictName:string;
dictType:string; dictType:string;
status:number; status:number;
@ -45,12 +49,22 @@ interface DicState {
rules:{} rules:{}
} }
defineOptions({ name: "systemEditDic"}) defineOptions({ name: "systemEditDic"})
const {proxy} = getCurrentInstance() as any;
const emit = defineEmits(['typeList']); const emit = defineEmits(['typeList']);
const formRef = ref<HTMLElement | null>(null); const formRef = ref<HTMLElement | null>(null);
const dictTypeOpt = ref<RuleFormState>()
const typeProps = ref({
value: 'dictId',
label: 'dictName',
children: 'children',
checkStrictly:true,
emitPath: false
})
const state = reactive<DicState>({ const state = reactive<DicState>({
isShowDialog: false, isShowDialog: false,
ruleForm: { ruleForm: {
dictId:0, dictId:0,
pid:0,
dictName:'', dictName:'',
dictType:'', dictType:'',
status:1, status:1,
@ -66,9 +80,16 @@ const state = reactive<DicState>({
} }
}); });
const { isShowDialog,ruleForm,rules } = toRefs(state); const { isShowDialog,ruleForm,rules } = toRefs(state);
const getParent = () => {
optionselect(true).then((res:any)=>{
const data = res.data.dictType??[]
dictTypeOpt.value = proxy.handleTree(data, 'dictId', 'pid', 'children', true)
})
}
// //
const openDialog = (row: RuleFormState|null) => { const openDialog = (row: RuleFormState|null) => {
resetForm(); resetForm();
getParent();
if (row){ if (row){
getType(row.dictId).then((res:any)=>{ getType(row.dictId).then((res:any)=>{
state.ruleForm = res.data.dictType state.ruleForm = res.data.dictType
@ -81,6 +102,7 @@ defineExpose({ openDialog})
const resetForm = ()=>{ const resetForm = ()=>{
state.ruleForm = { state.ruleForm = {
dictId:0, dictId:0,
pid:0,
dictName:'', dictName:'',
dictType:'', dictType:'',
status:1, status:1,

View File

@ -64,7 +64,7 @@
<el-table-column label="字典标签" align="center" prop="dictLabel" /> <el-table-column label="字典标签" align="center" prop="dictLabel" />
<el-table-column label="字典键值" align="center" prop="dictValue" /> <el-table-column label="字典键值" align="center" prop="dictValue" />
<el-table-column label="字典排序" align="center" prop="dictSort" /> <el-table-column label="字典排序" align="center" prop="dictSort" />
<el-table-column label="备注" align="center" prop="remark" :show-overflow-tooltip="true" /> <el-table-column label="字典类型" align="center" prop="dictType" />
<el-table-column label="创建时间" align="center" prop="createdAt" width="180"/> <el-table-column label="创建时间" align="center" prop="createdAt" width="180"/>
<el-table-column prop="status" label="字典状态" show-overflow-tooltip> <el-table-column prop="status" label="字典状态" show-overflow-tooltip>
<template #default="scope"> <template #default="scope">
@ -92,7 +92,7 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { toRefs, reactive, onMounted, ref, defineComponent } from 'vue'; import { toRefs, reactive, onMounted, ref } from 'vue';
import { ElMessageBox, ElMessage,FormInstance} from 'element-plus'; import { ElMessageBox, ElMessage,FormInstance} from 'element-plus';
import EditDic from '/@/views/system/dict/component/editDicData.vue'; import EditDic from '/@/views/system/dict/component/editDicData.vue';
import {getDataList,deleteData} from "/@/api/system/dict/data"; import {getDataList,deleteData} from "/@/api/system/dict/data";
@ -121,12 +121,12 @@ interface TableDataState {
dictType: string; dictType: string;
dictLabel:string; dictLabel:string;
status: string; status: string;
typeId:number;
}; };
}; };
} }
defineOptions({ name: "apiV1SystemDictDataList"}) defineOptions({ name: "apiV1SystemDictDataList"})
const route = useRoute(); const route = useRoute();
const addDicRef = ref();
const editDicRef = ref(); const editDicRef = ref();
const queryRef = ref(); const queryRef = ref();
const state = reactive<TableDataState>({ const state = reactive<TableDataState>({
@ -140,13 +140,15 @@ const state = reactive<TableDataState>({
pageSize: 10, pageSize: 10,
dictLabel:'', dictLabel:'',
dictType:'', dictType:'',
status:'' status:'',
typeId:0
}, },
}, },
}); });
const { tableData } = toRefs(state); const { tableData } = toRefs(state);
// //
const initTableData = () => { const initTableData = (typeId?: number) => {
state.tableData.param.typeId = typeId as number;
dataList() dataList()
}; };
const dataList=()=>{ const dataList=()=>{
@ -206,4 +208,5 @@ const resetQuery = (formEl: FormInstance | undefined) => {
const handleSelectionChange = (selection:TableDataRow[])=> { const handleSelectionChange = (selection:TableDataRow[])=> {
state.ids = selection.map(item => item.dictCode) state.ids = selection.map(item => item.dictCode)
}; };
defineExpose({initTableData})
</script> </script>

View File

@ -0,0 +1,186 @@
<template>
<div class="system-dic-container">
<el-row :gutter="10" style="width: 100%;">
<el-col :span="5">
<el-card shadow="hover">
<el-aside style="width: 100%;">
<el-scrollbar>
<div class="act-btn">
<el-button size="default" type="success" class="ml10 btm8" @click="onOpenAddDic">
<el-icon>
<ele-FolderAdd />
</el-icon>
新增
</el-button>
<el-button size="default" type="primary" class="ml10 btm8" @click="onOpenEditDic" :disabled="selectedNode===null">
<el-icon>
<ele-Edit />
</el-icon>
编辑
</el-button>
<el-button size="default" type="danger" class="ml10 btm8" @click="onRowDel(null)" :disabled="checkedNodes.length===0">
<el-icon>
<ele-Delete />
</el-icon>
删除
</el-button>
<el-button size="default" type="warning" class="ml10 btm8" @click="expandedOn">
<el-icon>
<ele-DCaret />
</el-icon>
{{expanded?'收起':'展开'}}
</el-button>
</div>
<el-divider />
<el-input :prefix-icon="search" v-model="filterText" placeholder="请输入部门名称" clearable style="margin-bottom: 8px;"/>
<el-tree
ref="treeRef"
class="filter-tree"
:data="dictTypeData"
:props="treeProps"
:filter-node-method="filterNode"
@node-click="handleNodeClick"
show-checkbox
@check-change="handleCheckChange"
node-key="dictId"
/>
</el-scrollbar>
</el-aside>
</el-card>
</el-col>
<el-col :span="19">
<apiV1SystemDictDataList ref="dataViewRef"></apiV1SystemDictDataList>
</el-col>
</el-row>
<EditDic ref="editDicRef" @typeList="getTypeData"/>
</div>
</template>
<script setup lang="ts">
import { onMounted, ref, getCurrentInstance, watch } from 'vue';
import { ElMessageBox, ElMessage, ElTree } from 'element-plus';
import EditDic from '/@/views/system/dict/component/editDic.vue';
import { deleteType, optionselect } from '/@/api/system/dict/type';
import { Search } from '@element-plus/icons-vue'
import apiV1SystemDictDataList from '/@/views/system/dict/dataList.vue'
//
interface TableDataRow {
dictId:number;
pid:number;
dictName: string;
dictType: string;
status: number;
remark:string;
createdAt:string;
}
defineOptions({ name: "apiV1SystemDictTypeList"})
const search = Search
const filterText = ref('');
const treeRef = ref()
const {proxy} = getCurrentInstance() as any;
const editDicRef = ref();
const dictTypeData = ref([])
const selectedNode = ref<TableDataRow|null>(null)
const checkedNodes = ref<TableDataRow[]>([])
const expanded = ref<boolean>(false)
const dataViewRef = ref()
const treeProps = ref({
value: 'dictId',
label: 'dictName',
children: 'children',
checkStrictly:true,
emitPath: false
})
const getTypeData = () => {
optionselect(true).then((res:any)=>{
const data = res.data.dictType??[]
dictTypeData.value = proxy.handleTree(data, 'dictId', 'pid', 'children', true)
})
}
//
const initTableData = () => {
getTypeData()
};
//
const onOpenAddDic = () => {
editDicRef.value.openDialog();
};
//
const onOpenEditDic = () => {
const row = selectedNode.value;
editDicRef.value.openDialog(row);
};
//
const onRowDel = (row: TableDataRow|null) => {
let msg = '你确定要删除所选数据?';
let ids:number[] = [] ;
if(row){
msg = `此操作将永久删除用户:“${row.dictName}”,是否继续?`
ids = [row.dictId]
}else{
checkedNodes.value.forEach(item=>{
ids.push(item.dictId);
})
}
if(ids.length===0){
ElMessage.error('请选择要删除的数据。');
return
}
ElMessageBox.confirm(msg, '提示', {
confirmButtonText: '确认',
cancelButtonText: '取消',
type: 'warning',
})
.then(() => {
deleteType(ids).then(()=>{
ElMessage.success('删除成功');
getTypeData()
checkedNodes.value = []
})
})
.catch(() => {});
};
//
onMounted(() => {
initTableData();
});
const filterNode = (value: string, data:any) => {
if (!value) return true;
return data.dictName.includes(value)
};
//
const handleNodeClick = (data:TableDataRow) => {
selectedNode.value = data
dataViewRef.value.initTableData(data.dictId)
};
const handleCheckChange = (
data: TableDataRow,
checked: boolean,
) => {
if(checked){
checkedNodes.value.push(data)
}else{
checkedNodes.value = checkedNodes.value.filter((item:TableDataRow) => {
if(item.dictId!==data.dictId){
return true
}
return false
})
}
}
const expandedOn = ()=>{
expanded.value = !expanded.value
let treeList = dictTypeData.value as Array<TableDataRow>;
for (let i = 0; i < treeList.length; i++) {
treeRef.value.store.nodesMap[treeList[i].dictId].expanded = expanded.value;
}
}
watch(filterText, (val) => {
treeRef.value!.filter(val)
});
</script>
<style scoped lang="scss">
.btm8{margin-bottom: 8px;}
</style>

View File

@ -1,225 +0,0 @@
<template>
<div class="system-dic-container">
<el-card shadow="hover">
<div class="system-user-search mb15">
<el-form :model="tableData.param" ref="queryRef" :inline="true" label-width="68px">
<el-form-item label="字典名称" prop="dictName">
<el-input
v-model="tableData.param.dictName"
placeholder="请输入字典名称"
clearable
style="width: 240px"
@keyup.enter.native="typeList"
/>
</el-form-item>
<el-form-item label="字典类型" prop="dictType">
<el-input
v-model="tableData.param.dictType"
placeholder="请输入字典类型"
clearable
style="width: 240px"
@keyup.enter.native="typeList"
/>
</el-form-item>
<el-form-item label="状态" prop="status" style="width: 200px;">
<el-select
v-model="tableData.param.status"
placeholder="字典状态"
clearable
style="width: 240px"
>
<el-option label="启用" :value="1"/>
<el-option label="禁用" :value="0"/>
</el-select>
</el-form-item>
<el-form-item label="创建时间" prop="dateRange">
<el-date-picker
v-model="tableData.param.dateRange"
style="width: 240px"
value-format="YYYY-MM-DD"
type="daterange"
range-separator="-"
start-placeholder="开始日期"
end-placeholder="结束日期"
></el-date-picker>
</el-form-item>
<el-form-item>
<el-button size="default" type="primary" class="ml10" @click="typeList">
<el-icon>
<ele-Search />
</el-icon>
查询
</el-button>
<el-button size="default" @click="resetQuery(queryRef)">
<el-icon>
<ele-Refresh />
</el-icon>
重置
</el-button>
<el-button size="default" type="success" class="ml10" @click="onOpenAddDic">
<el-icon>
<ele-FolderAdd />
</el-icon>
新增字典
</el-button>
<el-button size="default" type="danger" class="ml10" @click="onRowDel(null)">
<el-icon>
<ele-Delete />
</el-icon>
删除字典
</el-button>
</el-form-item>
</el-form>
</div>
<el-table :data="tableData.data" style="width: 100%" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" align="center" />
<el-table-column label="字典ID" align="center" prop="dictId" width="120"/>
<el-table-column label="字典名称" align="center" prop="dictName" :show-overflow-tooltip="true" />
<el-table-column label="字典类型" align="center" :show-overflow-tooltip="true">
<template #default="scope">
<router-link :to="'/system/dict/data/list/' + scope.row.dictType" class="link-type">
<span>{{ scope.row.dictType }}</span>
</router-link>
</template>
</el-table-column>
<el-table-column prop="status" label="字典状态" show-overflow-tooltip>
<template #default="scope">
<el-tag type="success" v-if="scope.row.status">启用</el-tag>
<el-tag type="info" v-else>禁用</el-tag>
</template>
</el-table-column>
<el-table-column prop="remark" label="字典描述" show-overflow-tooltip></el-table-column>
<el-table-column prop="createdAt" label="创建时间" show-overflow-tooltip width="180"></el-table-column>
<el-table-column label="操作" width="200">
<template #default="scope">
<el-button size="small" text type="primary" @click="onOpenEditDic(scope.row)">修改</el-button>
<el-button size="small" text type="primary" @click="onRowDel(scope.row)">删除</el-button>
</template>
</el-table-column>
</el-table>
<pagination
v-show="tableData.total>0"
:total="tableData.total"
v-model:page="tableData.param.pageNum"
v-model:limit="tableData.param.pageSize"
@pagination="typeList"
/>
</el-card>
<EditDic ref="editDicRef" @typeList="typeList"/>
</div>
</template>
<script setup lang="ts">
import { toRefs, reactive, onMounted, ref, defineComponent } from 'vue';
import { ElMessageBox, ElMessage,FormInstance} from 'element-plus';
import EditDic from '/@/views/system/dict/component/editDic.vue';
import {deleteType, getTypeList} from "/@/api/system/dict/type";
//
interface TableDataRow {
dictId:number;
dictName: string;
dictType: string;
status: number;
remark:string;
createdAt:string;
}
interface TableDataState {
ids:number[];
tableData: {
data: Array<TableDataRow>;
total: number;
loading: boolean;
param: {
pageNum: number;
pageSize: number;
dictName: string;
dictType: string;
status: string;
dateRange:string[];
};
};
}
defineOptions({ name: "systemDic"})
const addDicRef = ref();
const editDicRef = ref();
const queryRef = ref();
const state = reactive<TableDataState>({
ids:[],
tableData: {
data: [],
total: 0,
loading: false,
param: {
pageNum: 1,
pageSize: 10,
dictName:'',
dictType:'',
status:'',
dateRange:[],
},
},
});
const { tableData } = toRefs(state);
//
const initTableData = () => {
typeList()
};
const typeList=()=>{
getTypeList(state.tableData.param).then((res:any)=>{
state.tableData.data = res.data.dictTypeList;
state.tableData.total = res.data.total;
});
};
//
const onOpenAddDic = () => {
editDicRef.value.openDialog();
};
//
const onOpenEditDic = (row: TableDataRow) => {
editDicRef.value.openDialog(row);
};
//
const onRowDel = (row: TableDataRow|null) => {
let msg = '你确定要删除所选数据?';
let ids:number[] = [] ;
if(row){
msg = `此操作将永久删除用户:“${row.dictName}”,是否继续?`
ids = [row.dictId]
}else{
ids = state.ids
}
if(ids.length===0){
ElMessage.error('请选择要删除的数据。');
return
}
ElMessageBox.confirm(msg, '提示', {
confirmButtonText: '确认',
cancelButtonText: '取消',
type: 'warning',
})
.then(() => {
deleteType(ids).then(()=>{
ElMessage.success('删除成功');
typeList();
})
})
.catch(() => {});
};
//
onMounted(() => {
initTableData();
});
/** 重置按钮操作 */
const resetQuery = (formEl: FormInstance | undefined) => {
if (!formEl) return
formEl.resetFields()
typeList()
};
//
const handleSelectionChange = (selection:TableDataRow[])=> {
state.ids = selection.map(item => item.dictId)
};
</script>

View File

@ -172,12 +172,7 @@
</el-table-column> </el-table-column>
<el-table-column label="字典类型" width="160"> <el-table-column label="字典类型" width="160">
<template #default="scope"> <template #default="scope">
<el-select v-model="scope.row.dictType" clearable filterable placeholder="请选择"> <el-cascader v-model="scope.row.dictType" :options="dictOptions" :props="typeProps" clearable :show-all-levels="false"/>
<el-option v-for="dict in dictOptions" :key="dict.dictType" :label="dict.dictName" :value="dict.dictType">
<span style="float: left">{{ dict.dictName }}</span>
<span style="float: right; color: #8492a6; font-size: 13px">{{ dict.dictType }}</span>
</el-option>
</el-select>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column label="关联表" width="160"> <el-table-column label="关联表" width="160">
@ -205,23 +200,31 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { inject, onBeforeMount, ref} from 'vue'; import { getCurrentInstance, inject, onBeforeMount, ref } from 'vue';
import type { FormInstance } from 'element-plus'; import type { FormInstance } from 'element-plus';
import {DictOpt, TableColumns, TableDataInfo} from '/@/views/system/tools/gen/component/model'; import {DictOpt, TableColumns} from '/@/views/system/tools/gen/component/model';
import {optionselect} from "/@/api/system/dict/type"; import {optionselect} from "/@/api/system/dict/type";
import RelationTable from "/@/views/system/tools/gen/component/relationTable.vue"; import RelationTable from "/@/views/system/tools/gen/component/relationTable.vue";
import _ from "lodash"; import _ from "lodash";
defineOptions({ name: "genTableColumns"}) defineOptions({ name: "genTableColumns"})
const {proxy} = getCurrentInstance() as any;
const relationTableRef = ref(); const relationTableRef = ref();
const tableColumnsRef = ref<FormInstance>(); const tableColumnsRef = ref<FormInstance>();
const info = inject<any>('tableData'); const info = inject<any>('tableData');
// //
const tableHeight = ref(document.documentElement.scrollHeight - 300 + 'px'); const tableHeight = ref(document.documentElement.scrollHeight - 300 + 'px');
const dictOptions = ref(<DictOpt[]>[]) const dictOptions = ref(<DictOpt[]>[])
const typeProps = ref({
value: 'dictType',
label: 'dictName',
children: 'children',
emitPath: false
})
onBeforeMount(()=>{ onBeforeMount(()=>{
// //
optionselect().then((res:any)=>{ optionselect().then((res:any)=>{
dictOptions.value = res.data.dictType??[] const data = res.data.dictType??[]
dictOptions.value = proxy.handleTree(data, 'dictId', 'pid', 'children', true)
}) })
}) })
const handleChangeConfig = (row:TableColumns)=>{ const handleChangeConfig = (row:TableColumns)=>{

View File

@ -102,7 +102,7 @@
<script setup lang="ts"> <script setup lang="ts">
import {toRefs, reactive, onMounted, ref, watch, getCurrentInstance} from 'vue'; import {toRefs, reactive, onMounted, ref, watch, getCurrentInstance} from 'vue';
import {ElTree,FormInstance} from 'element-plus'; import {ElTree,FormInstance} from 'element-plus';
import { Search } from '@element-plus/icons-vue' import { Search } from '@element-plus/icons-vue'
import UserList from '/@/views/system/user/component/userList.vue'; import UserList from '/@/views/system/user/component/userList.vue';
import {getDeptTree} from '/@/api/system/user'; import {getDeptTree} from '/@/api/system/user';