refactor(core): 重构数据字典组件

- 将 AppDictionary 组件拆分为 dictList 和 DictDetail 两个子组件
-优化数据字典列表的渲染逻辑
This commit is contained in:
aixianling
2024-12-18 15:08:55 +08:00
parent d40830188d
commit 31c874e1ba
4 changed files with 150 additions and 132 deletions

View File

@@ -1,151 +1,27 @@
<template> <template>
<section class="AppDictionary"> <section class="AppDictionary">
<ai-list v-if="!showDetail"> <component :is="currentPage" v-bind="$props"/>
<ai-title slot="title" title="数据字典" isShowBottomBorder/>
<template #content>
<ai-search-bar>
<template #left>
<el-button type="primary" size="small" icon="iconfont iconAdd" @click="addDict"
v-if="$permissions('admin_sysdictionary_add')">添加
</el-button>
</template>
<template #right>
<el-input size="small" v-model="search.condition" placeholder="数据项" clearable
@change="page.current=1,getDicts()" prefix-icon="iconfont iconSearch"/>
<el-button type="primary" size="small" icon="iconfont iconSearch"
@click="page.current=1,getDicts()">查询
</el-button>
<el-button size="small" icon="el-icon-refresh-right" @click="resetSearch">重置</el-button>
</template>
</ai-search-bar>
<el-table size="mini" :data="dictList" header-cell-class-name="table-header" tooltip-effect="light"
row-class-name="table-row" cell-class-name="table-cell" @expand-change="getDictInfo">
<el-table-column type="expand">
<el-row slot-scope="{row}" type="flex" align="middle" style="flex-wrap: wrap">
<el-tag v-for="(op,i) in row.detail||[]" :key="i" style="margin: 4px">{{ op.dictValue }}{{ op.dictName }}
{{ op.dictColor ? '| ' + op.dictColor : '' }}
</el-tag>
</el-row>
</el-table-column>
<el-table-column align="center" label="数据项" prop="code"/>
<el-table-column align="center" label="数据项名称" prop="name"/>
<el-table-column align="center" label="操作">
<div slot-scope="{row}">
<el-button type="text" @click="openDetail(row.id)" v-text="'编辑'"
v-if="$permissions('admin_sysdictionary_edit')"/>
<el-button type="text" @click="handleDelete(row.id)" v-text="'删除'"
v-if="$permissions('admin_sysdictionary_del')"/>
</div>
</el-table-column>
<div slot="empty" class="no-data"></div>
</el-table>
<div class="pagination">
<el-pagination background :current-page.sync="page.current" :total="page.total"
layout="total,prev, pager, next,sizes, jumper"
@size-change="handleSizeChange"
:page-size="page.size"
:page-sizes="[10, 20, 50, 100,200]"
@current-change="getDicts"/>
</div>
</template>
</ai-list>
<dict-detail v-else :instance="instance" :permissions="permissions"/>
</section> </section>
</template> </template>
<script> <script>
import DictDetail from "./dictDetail"; import DictDetail from "./dictDetail";
import DictList from "@project/xumu/AppDictionary/dictList.vue";
export default { export default {
name: "AppDictionary", name: "AppDictionary",
components: {DictDetail},
label: "数据字典", label: "数据字典",
props: { props: {
instance: Function, instance: Function,
dict: Object,
permissions: Function permissions: Function
}, },
computed: { computed: {
showDetail() { currentPage() {
return this.$route.hash == "#add" let {hash} = this.$route
return hash == "#add" ? DictDetail : DictList
} }
}, },
data() {
return {
page: {
current: 1,
total: 0,
size: 10
},
search: {
condition: ""
},
dictList: [],
id: ''
}
},
methods: {
resetSearch() {
this.page.current = 1;
this.search.condition = '';
this.getDicts();
},
getDicts() {
this.instance.post("/admin/dictionary/queryDictList", null, {
params: {
...this.page,
name: this.search.condition
}
}).then(res => {
this.dictList = res.data.records.map(e => {
return {...e, detail: []}
})
this.page.total = res.data.total
})
},
addDict() {
this.$router.push({hash: "#add"})
},
handleDelete(id) {
this.$confirm("确定要删除该数据项吗?", {
type: "error"
}).then(() => {
this.instance.post("/admin/dictionary/deleteDict", null, {
params: {id}
}).then(res => {
if (res?.code == 0) {
this.getDicts();
this.$message.success("删除成功!")
}
})
}).catch(() => 0)
},
openDetail(id) {
this.$router.push({query: {id}, hash: "#add"})
},
handleSizeChange(val) {
this.page.size = val;
this.getDicts();
},
getDictInfo(row) {
if (row.detail.length) {
row.detail = []
} else {
this.getDict(row.id).then(res => {
if (res && res.data) {
row.detail = res.data.dictionaryDetails || []
}
})
}
},
getDict(dictionaryId) {
return this.instance.post("/admin/dictionary/queryDictDetail", null, {
params: {dictionaryId}
})
},
},
created() {
this.getDicts()
},
} }
</script> </script>

View File

@@ -0,0 +1,142 @@
<script>
const columns = [
{slot: "expand"},
{label: "数据项", prop: "code"},
{label: "数据项名称", prop: "name"},
]
export default {
name: "dictList",
props: {
instance: Function,
dict: Object,
permissions: Function
},
data() {
return {
columns,
page: {
current: 1,
total: 0,
size: 10
},
search: {
condition: ""
},
dictList: [],
id: ''
}
},
methods: {
resetSearch() {
this.page.current = 1;
this.search.condition = '';
this.getDicts();
},
getDicts() {
this.instance.post("/admin/dictionary/queryDictList", null, {
params: {
...this.page,
name: this.search.condition
}
}).then(res => {
this.dictList = res.data.records.map(e => {
return {...e, detail: []}
})
this.page.total = res.data.total
})
},
addDict() {
this.$router.push({hash: "#add"})
},
handleDelete(id) {
this.$confirm("确定要删除该数据项吗?", {
type: "error"
}).then(() => {
this.instance.post("/admin/dictionary/deleteDict", null, {
params: {id}
}).then(res => {
if (res?.code == 0) {
this.getDicts();
this.$message.success("删除成功!")
}
})
}).catch(() => 0)
},
openDetail(id) {
this.$router.push({query: {id}, hash: "#add"})
},
handleSizeChange(val) {
this.page.size = val;
this.getDicts();
},
getDictInfo(row) {
if (row.detail.length) {
row.detail = []
} else {
this.getDict(row.id).then(res => {
if (res && res.data) {
row.detail = res.data.dictionaryDetails || []
}
})
}
},
getDict(dictionaryId) {
return this.instance.post("/admin/dictionary/queryDictDetail", null, {
params: {dictionaryId}
})
},
},
created() {
this.getDicts()
},
}
</script>
<template>
<section class="dictList">
<ai-list>
<ai-title slot="title" title="数据字典" isShowBottomBorder/>
<template #content>
<ai-search-bar>
<template #left>
<el-button type="primary" size="small" icon="iconfont iconAdd" @click="addDict"
v-if="$permissions('admin_sysdictionary_add')">添加
</el-button>
</template>
<template #right>
<el-input size="small" v-model="search.condition" placeholder="数据项" clearable
@change="page.current=1,getDicts()" prefix-icon="iconfont iconSearch"/>
<el-button type="primary" size="small" icon="iconfont iconSearch"
@click="page.current=1,getDicts()">查询
</el-button>
<el-button size="small" icon="el-icon-refresh-right" @click="resetSearch">重置</el-button>
</template>
</ai-search-bar>
<ai-table :tableData="dictList" :colConfigs="columns" :dict="dict" @getList="getDicts"
:total="page.total" :current.sync="page.current" :size.sync="page.size" :page-sizes="[10, 20, 50, 100,200]"
@expand-change="getDictInfo">
<el-table-column slot="expand" type="expand">
<template slot-scope="{row}">
<div class="flex" style="gap:4px">
<el-tag v-for="(op,i) in row.detail||[]" :key="i">{{ [op.dictValue, op.dictName, op.dictColor].filter(Boolean).join("") }}</el-tag>
</div>
</template>
</el-table-column>
<el-table-column slot="options" label="操作" fixed="right" align="center">
<template slot-scope="{row}">
<div class="table-options">
<el-button type="text" @click="openDetail(row.id)" v-if="$permissions('admin_sysdictionary_edit')">编辑</el-button>
<el-button type="text" @click="handleDelete(row.id)" v-if="$permissions('admin_sysdictionary_del')">删除</el-button>
</div>
</template>
</el-table-column>
</ai-table>
</template>
</ai-list>
</section>
</template>
<style scoped lang="scss">
.dictList {
height: 100%;
}
</style>

View File

@@ -357,7 +357,7 @@ div[flex], .flex {
display: grid; display: grid;
gap: 8px; gap: 8px;
grid-template-columns: repeat(2, 1fr); grid-template-columns: repeat(2, 1fr);
@for $i from 2 through 5 { @for $i from 2 through 10 {
&.c-#{$i} { &.c-#{$i} {
grid-template-columns: repeat($i, 1fr); grid-template-columns: repeat($i, 1fr);
} }

View File

@@ -15,7 +15,7 @@ export default {
<slot v-if="$slots.title" name="title"/> <slot v-if="$slots.title" name="title"/>
<ai-title v-else-if="$attrs.title" :title="$attrs.title" isShowBottomBorder/> <ai-title v-else-if="$attrs.title" :title="$attrs.title" isShowBottomBorder/>
<div class="fill main"> <div class="fill main">
<div class="left"> <div v-if="$slots.left" class="left">
<slot name="left"/> <slot name="left"/>
</div> </div>
<div class="fill" :class="[contentString]"> <div class="fill" :class="[contentString]">