mirror of
https://github.com/continew-org/continew-admin-ui.git
synced 2025-09-08 22:57:11 +08:00
feat: 新增字典管理
This commit is contained in:
54
src/apis/system/dict.ts
Normal file
54
src/apis/system/dict.ts
Normal file
@@ -0,0 +1,54 @@
|
||||
import http from '@/utils/http'
|
||||
import type * as System from './type'
|
||||
|
||||
const BASE_URL = '/system/dict'
|
||||
|
||||
/** @desc 查询字典列表 */
|
||||
export function listDict(query: System.DictQuery) {
|
||||
return http.get<PageRes<System.DictResp[]>>(`${BASE_URL}`, query)
|
||||
}
|
||||
|
||||
/** @desc 查询字典详情 */
|
||||
export function getDict(id: string) {
|
||||
return http.get<System.DictResp>(`${BASE_URL}/${id}`)
|
||||
}
|
||||
|
||||
/** @desc 新增字典 */
|
||||
export function addDict(data: any) {
|
||||
return http.post(`${BASE_URL}`, data)
|
||||
}
|
||||
|
||||
/** @desc 修改字典 */
|
||||
export function updateDict(data: any, id: string) {
|
||||
return http.put(`${BASE_URL}/${id}`, data)
|
||||
}
|
||||
|
||||
/** @desc 删除字典 */
|
||||
export function deleteDict(id: string) {
|
||||
return http.del(`${BASE_URL}/${id}`)
|
||||
}
|
||||
|
||||
/** @desc 查询字典项列表 */
|
||||
export function listDictItem(query: System.DictItemQuery) {
|
||||
return http.get<PageRes<System.DictItemResp[]>>(`${BASE_URL}/item`, query)
|
||||
}
|
||||
|
||||
/** @desc 查询字典项详情 */
|
||||
export function getDictItem(id: string) {
|
||||
return http.get<System.DictItemResp>(`${BASE_URL}/item/${id}`)
|
||||
}
|
||||
|
||||
/** @desc 新增字典项 */
|
||||
export function addDictItem(data: any) {
|
||||
return http.post(`${BASE_URL}/item`, data)
|
||||
}
|
||||
|
||||
/** @desc 修改字典项 */
|
||||
export function updateDictItem(data: any, id: string) {
|
||||
return http.put(`${BASE_URL}/item/${id}`, data)
|
||||
}
|
||||
|
||||
/** @desc 删除字典项 */
|
||||
export function deleteDictItem(id: string) {
|
||||
return http.del(`${BASE_URL}/item/${id}`)
|
||||
}
|
@@ -1,3 +1,4 @@
|
||||
export * from './dept'
|
||||
export * from './log'
|
||||
export * from './dict'
|
||||
export * from './storage'
|
||||
|
@@ -56,6 +56,41 @@ export interface LogQuery{
|
||||
status?: number
|
||||
}
|
||||
|
||||
/** 系统字典类型 */
|
||||
export interface DictResp {
|
||||
id: string
|
||||
name: string
|
||||
code: string
|
||||
isSystem: boolean
|
||||
description: string
|
||||
createUserString: string
|
||||
createTime: string
|
||||
updateUserString: string
|
||||
updateTime: string
|
||||
}
|
||||
export interface DictQuery extends PageQuery {
|
||||
description?: string
|
||||
}
|
||||
export type DictItemResp = {
|
||||
id: string
|
||||
label: string
|
||||
value: string
|
||||
color: string
|
||||
sort: number
|
||||
description: string
|
||||
status: 1 | 2
|
||||
dictId: number
|
||||
createUserString: string
|
||||
createTime: string
|
||||
updateUserString: string
|
||||
updateTime: string
|
||||
}
|
||||
export interface DictItemQuery extends PageQuery {
|
||||
description?: string
|
||||
status?: number
|
||||
dictId: string
|
||||
}
|
||||
|
||||
/** 系统存储类型 */
|
||||
export type StorageResp = {
|
||||
id: string
|
||||
|
99
src/views/system/dict/AddDictModal.vue
Normal file
99
src/views/system/dict/AddDictModal.vue
Normal file
@@ -0,0 +1,99 @@
|
||||
<template>
|
||||
<a-modal
|
||||
v-model:visible="visible"
|
||||
:title="title"
|
||||
:mask-closable="false"
|
||||
:esc-to-close="false"
|
||||
:modal-style="{ maxWidth: '520px' }"
|
||||
width="90%"
|
||||
@before-ok="save"
|
||||
@close="reset"
|
||||
>
|
||||
<GiForm ref="formRef" v-model="form" :options="options" :columns="columns" />
|
||||
</a-modal>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { getDict, addDict, updateDict } from '@/apis'
|
||||
import { Message } from '@arco-design/web-vue'
|
||||
import { GiForm, type Columns } from '@/components/GiForm'
|
||||
import { useForm } from '@/hooks'
|
||||
|
||||
const dataId = ref('')
|
||||
const isUpdate = computed(() => !!dataId.value)
|
||||
const title = computed(() => (isUpdate.value ? '修改字典' : '新增字典'))
|
||||
const formRef = ref<InstanceType<typeof GiForm>>()
|
||||
|
||||
const options: Options = {
|
||||
form: {},
|
||||
col: { xs: 24, sm: 24, md: 24, lg: 24, xl: 24, xxl: 24 },
|
||||
btns: { hide: true }
|
||||
}
|
||||
|
||||
const columns: Columns = [
|
||||
{ label: '名称', field: 'name', type: 'input', rules: [{ required: true, message: '请输入名称' }] },
|
||||
{ label: '编码', field: 'code', type: 'input', rules: [{ required: true, message: '请输入编码' }] },
|
||||
{
|
||||
label: '描述',
|
||||
field: 'description',
|
||||
type: 'textarea',
|
||||
props: {
|
||||
maxLength: 200,
|
||||
autoSize: { minRows: 3, maxRows: 5 }
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
const { form, resetForm } = useForm({
|
||||
name: '',
|
||||
code: ''
|
||||
})
|
||||
|
||||
// 重置
|
||||
const reset = () => {
|
||||
formRef.value?.formRef?.resetFields()
|
||||
resetForm()
|
||||
}
|
||||
|
||||
const visible = ref(false)
|
||||
// 新增
|
||||
const onAdd = () => {
|
||||
reset()
|
||||
dataId.value = ''
|
||||
visible.value = true
|
||||
}
|
||||
|
||||
// 修改
|
||||
const onUpdate = async (id: string) => {
|
||||
reset()
|
||||
dataId.value = id
|
||||
const res = await getDict(id)
|
||||
Object.assign(form, res.data)
|
||||
visible.value = true
|
||||
}
|
||||
|
||||
// 保存
|
||||
const save = async () => {
|
||||
try {
|
||||
const isInvalid = await formRef.value?.formRef?.validate()
|
||||
if (isInvalid) return false
|
||||
if (isUpdate.value) {
|
||||
await updateDict(form, dataId.value)
|
||||
Message.success('修改成功')
|
||||
} else {
|
||||
await addDict(form)
|
||||
Message.success('新增成功')
|
||||
}
|
||||
emit('save-success')
|
||||
return true
|
||||
} catch (error) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
const emit = defineEmits<{
|
||||
(e: 'save-success'): void
|
||||
}>()
|
||||
|
||||
defineExpose({ onAdd, onUpdate })
|
||||
</script>
|
127
src/views/system/dict/index.vue
Normal file
127
src/views/system/dict/index.vue
Normal file
@@ -0,0 +1,127 @@
|
||||
<template>
|
||||
<div class="gi_page">
|
||||
<a-card title="字典管理" class="general-card">
|
||||
<GiTable
|
||||
ref="tableRef"
|
||||
row-key="id"
|
||||
:data="dataList"
|
||||
:columns="columns"
|
||||
:loading="loading"
|
||||
:scroll="{ x: '100%', y: '100%', minWidth: 1000 }"
|
||||
:pagination="pagination"
|
||||
:disabledColumnKeys="['name']"
|
||||
@refresh="search"
|
||||
>
|
||||
<template #custom-left>
|
||||
<a-button type="primary" @click="onAdd">
|
||||
<template #icon><icon-plus /></template>
|
||||
<span>新增</span>
|
||||
</a-button>
|
||||
</template>
|
||||
<template #custom-right>
|
||||
<a-input v-model="queryForm.description" placeholder="请输入关键词" allow-clear @change="search">
|
||||
<template #prefix><icon-search /></template>
|
||||
</a-input>
|
||||
<a-button @click="reset">重置</a-button>
|
||||
</template>
|
||||
<template #isSystem="{ record }">
|
||||
<a-tag v-if="record.isSystem" color="red">是</a-tag>
|
||||
<a-tag v-else color="arcoblue">否</a-tag>
|
||||
</template>
|
||||
<template #action="{ record }">
|
||||
<a-space>
|
||||
<template #split>
|
||||
<a-divider direction="vertical" :margin="0" />
|
||||
</template>
|
||||
<a-link @click="onViewDictItem(record)">管理</a-link>
|
||||
<a-link @click="onUpdate(record)">修改</a-link>
|
||||
<a-link
|
||||
status="danger"
|
||||
:title="record.isSystem ? '系统内置数据不能删除' : '删除'"
|
||||
:disabled="record.disabled"
|
||||
@click="onDelete(record)"
|
||||
>
|
||||
删除
|
||||
</a-link>
|
||||
</a-space>
|
||||
</template>
|
||||
</GiTable>
|
||||
</a-card>
|
||||
|
||||
<AddDictModal ref="AddDictModalRef" @save-success="search" />
|
||||
<DictItemModal ref="DictItemModalRef" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { listDict, deleteDict, type DictResp } from '@/apis'
|
||||
import type { TableInstance } from '@arco-design/web-vue'
|
||||
import AddDictModal from './AddDictModal.vue'
|
||||
import DictItemModal from '@/views/system/dict/item/index.vue'
|
||||
import { useTable } from '@/hooks'
|
||||
import { isMobile } from '@/utils'
|
||||
|
||||
defineOptions({ name: 'Dict' })
|
||||
|
||||
const columns: TableInstance['columns'] = [
|
||||
{
|
||||
title: '序号',
|
||||
width: 66,
|
||||
align: 'center',
|
||||
render: ({ rowIndex }) => h('span', {}, rowIndex + 1 + (pagination.current - 1) * pagination.pageSize)
|
||||
},
|
||||
{ title: '名称', dataIndex: 'name', ellipsis: true, tooltip: true },
|
||||
{ title: '编码', dataIndex: 'code', width: 170, ellipsis: true, tooltip: true },
|
||||
{ title: '系统内置', slotName: 'isSystem', align: 'center', show: false },
|
||||
{ title: '描述', dataIndex: 'description', ellipsis: true, tooltip: true },
|
||||
{ title: '创建人', dataIndex: 'createUserString', show: false, ellipsis: true, tooltip: true },
|
||||
{ title: '创建时间', dataIndex: 'createTime', width: 180 },
|
||||
{ title: '修改人', dataIndex: 'updateUserString', show: false, ellipsis: true, tooltip: true },
|
||||
{ title: '修改时间', dataIndex: 'updateTime', width: 180, show: false },
|
||||
{ title: '操作', slotName: 'action', width: 200, align: 'center', fixed: !isMobile() ? 'right' : undefined }
|
||||
]
|
||||
|
||||
const queryForm = reactive({
|
||||
description: undefined,
|
||||
sort: ['createTime,desc']
|
||||
})
|
||||
|
||||
const {
|
||||
tableData: dataList,
|
||||
loading,
|
||||
pagination,
|
||||
search,
|
||||
handleDelete
|
||||
} = useTable((p) => listDict({ ...queryForm, page: p.page, size: p.size }), { immediate: true })
|
||||
|
||||
// 重置
|
||||
const reset = () => {
|
||||
queryForm.description = undefined
|
||||
queryForm.status = undefined
|
||||
search()
|
||||
}
|
||||
|
||||
// 删除
|
||||
const onDelete = (item: DictResp) => {
|
||||
return handleDelete(() => deleteDict(item.id), { content: `是否确定删除字典 [${item.name}]?`, showModal: true })
|
||||
}
|
||||
|
||||
const AddDictModalRef = ref<InstanceType<typeof AddDictModal>>()
|
||||
// 新增
|
||||
const onAdd = () => {
|
||||
AddDictModalRef.value?.onAdd()
|
||||
}
|
||||
|
||||
// 修改
|
||||
const onUpdate = (item: DictResp) => {
|
||||
AddDictModalRef.value?.onUpdate(item.id)
|
||||
}
|
||||
|
||||
const DictItemModalRef = ref<InstanceType<typeof DictItemModal>>()
|
||||
// 查看字典项
|
||||
const onViewDictItem = (item: DictResp) => {
|
||||
DictItemModalRef.value?.open(item.id, item.code)
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped></style>
|
134
src/views/system/dict/item/AddDictItemModal.vue
Normal file
134
src/views/system/dict/item/AddDictItemModal.vue
Normal file
@@ -0,0 +1,134 @@
|
||||
<template>
|
||||
<a-modal
|
||||
v-model:visible="visible"
|
||||
:title="title"
|
||||
:mask-closable="false"
|
||||
:esc-to-close="false"
|
||||
:modal-style="{ maxWidth: '520px' }"
|
||||
width="90%"
|
||||
@before-ok="save"
|
||||
@close="reset"
|
||||
>
|
||||
<GiForm ref="formRef" v-model="form" :options="options" :columns="columns">
|
||||
<template #color>
|
||||
<a-input v-model="form.color" placeholder="请选择或输入标签颜色" allow-clear>
|
||||
<template #suffix>
|
||||
<a-color-picker v-model="form.color" />
|
||||
</template>
|
||||
</a-input>
|
||||
</template>
|
||||
</GiForm>
|
||||
</a-modal>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { getDictItem, addDictItem, updateDictItem } from '@/apis'
|
||||
import { Message } from '@arco-design/web-vue'
|
||||
import { GiForm, type Columns } from '@/components/GiForm'
|
||||
import { useForm } from '@/hooks'
|
||||
|
||||
const dictId = ref('')
|
||||
const dataId = ref('')
|
||||
const isUpdate = computed(() => !!dataId.value)
|
||||
const title = computed(() => (isUpdate.value ? '修改字典项' : '新增字典项'))
|
||||
const formRef = ref<InstanceType<typeof GiForm>>()
|
||||
|
||||
const options: Options = {
|
||||
form: {},
|
||||
col: { xs: 24, sm: 24, md: 24, lg: 24, xl: 24, xxl: 24 },
|
||||
btns: { hide: true }
|
||||
}
|
||||
|
||||
const columns: Columns = [
|
||||
{ label: '标签', field: 'label', type: 'input', rules: [{ required: true, message: '请输入标签' }] },
|
||||
{ label: '值', field: 'value', type: 'input', rules: [{ required: true, message: '请输入值' }] },
|
||||
{ label: '标签颜色', field: 'color', type: 'input' },
|
||||
{
|
||||
label: '排序',
|
||||
field: 'sort',
|
||||
type: 'input-number',
|
||||
props: {
|
||||
min: 1,
|
||||
mode: 'button'
|
||||
}
|
||||
},
|
||||
{
|
||||
label: '描述',
|
||||
field: 'description',
|
||||
type: 'textarea',
|
||||
props: {
|
||||
maxLength: 200,
|
||||
autoSize: { minRows: 3, maxRows: 5 }
|
||||
}
|
||||
},
|
||||
{
|
||||
label: '状态',
|
||||
field: 'status',
|
||||
type: 'switch',
|
||||
props: {
|
||||
type: 'round',
|
||||
checkedValue: 1,
|
||||
uncheckedValue: 2,
|
||||
checkedText: '启用',
|
||||
uncheckedText: '禁用'
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
const { form, resetForm } = useForm({
|
||||
label: '',
|
||||
value: '',
|
||||
color: '',
|
||||
sort: 999,
|
||||
status: 1
|
||||
})
|
||||
|
||||
// 重置
|
||||
const reset = () => {
|
||||
formRef.value?.formRef?.resetFields()
|
||||
resetForm()
|
||||
}
|
||||
|
||||
const visible = ref(false)
|
||||
// 新增
|
||||
const onAdd = (id: string) => {
|
||||
reset()
|
||||
dictId.value = id
|
||||
dataId.value = ''
|
||||
visible.value = true
|
||||
}
|
||||
|
||||
// 修改
|
||||
const onUpdate = async (id: string) => {
|
||||
reset()
|
||||
dataId.value = id
|
||||
const res = await getDictItem(id)
|
||||
Object.assign(form, res.data)
|
||||
visible.value = true
|
||||
}
|
||||
|
||||
// 保存
|
||||
const save = async () => {
|
||||
try {
|
||||
const isInvalid = await formRef.value?.formRef?.validate()
|
||||
if (isInvalid) return false
|
||||
if (isUpdate.value) {
|
||||
await updateDictItem(form, dataId.value)
|
||||
Message.success('修改成功')
|
||||
} else {
|
||||
await addDictItem({ ...form, dictId: dictId.value })
|
||||
Message.success('新增成功')
|
||||
}
|
||||
emit('save-success')
|
||||
return true
|
||||
} catch (error) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
const emit = defineEmits<{
|
||||
(e: 'save-success'): void
|
||||
}>()
|
||||
|
||||
defineExpose({ onAdd, onUpdate })
|
||||
</script>
|
143
src/views/system/dict/item/index.vue
Normal file
143
src/views/system/dict/item/index.vue
Normal file
@@ -0,0 +1,143 @@
|
||||
<template>
|
||||
<a-modal
|
||||
v-model:visible="visible"
|
||||
:title="'字典项管理(' + dictCode + ')'"
|
||||
title-align="start"
|
||||
:mask-closable="false"
|
||||
:esc-to-close="false"
|
||||
:modal-style="{ maxWidth: '780px' }"
|
||||
width="90%"
|
||||
ok-text="关闭"
|
||||
hide-cancel
|
||||
>
|
||||
<GiTable
|
||||
ref="tableRef"
|
||||
row-key="id"
|
||||
:data="dataList"
|
||||
:columns="columns"
|
||||
:loading="loading"
|
||||
:scroll="{ x: '100%', y: '100%', minWidth: 780 }"
|
||||
:pagination="pagination"
|
||||
:disabledColumnKeys="['label']"
|
||||
@refresh="search"
|
||||
>
|
||||
<template #custom-left>
|
||||
<a-button type="primary" @click="onAdd">
|
||||
<template #icon><icon-plus /></template>
|
||||
<span>新增</span>
|
||||
</a-button>
|
||||
</template>
|
||||
<template #custom-right>
|
||||
<a-input v-model="queryForm.description" placeholder="请输入关键词" allow-clear @change="search">
|
||||
<template #prefix><icon-search /></template>
|
||||
</a-input>
|
||||
<a-button @click="reset">重置</a-button>
|
||||
</template>
|
||||
<template #label="{ record }">
|
||||
<a-tag :color="record.color">{{ record.label }}</a-tag>
|
||||
</template>
|
||||
<template #status="{ record }">
|
||||
<GiCellStatus :status="record.status" />
|
||||
</template>
|
||||
<template #action="{ record }">
|
||||
<a-space>
|
||||
<template #split>
|
||||
<a-divider direction="vertical" :margin="0" />
|
||||
</template>
|
||||
<a-link @click="onUpdate(record)">修改</a-link>
|
||||
<a-popconfirm
|
||||
type="warning"
|
||||
content="是否确定删除该条数据?"
|
||||
:ok-button-props="{ status: 'danger' }"
|
||||
@ok="onDelete(record)"
|
||||
>
|
||||
<a-link status="danger">删除</a-link>
|
||||
</a-popconfirm>
|
||||
</a-space>
|
||||
</template>
|
||||
</GiTable>
|
||||
|
||||
<AddDictItemModal ref="AddDictItemModalRef" @save-success="search" />
|
||||
</a-modal>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { listDictItem, deleteDictItem, type DictItemResp } from '@/apis'
|
||||
import type { TableInstance } from '@arco-design/web-vue'
|
||||
import AddDictItemModal from './AddDictItemModal.vue'
|
||||
import { useTable } from '@/hooks'
|
||||
import { isMobile } from '@/utils'
|
||||
|
||||
const columns: TableInstance['columns'] = [
|
||||
{
|
||||
title: '序号',
|
||||
width: 66,
|
||||
align: 'center',
|
||||
render: ({ rowIndex }) => h('span', {}, rowIndex + 1 + (pagination.current - 1) * pagination.pageSize)
|
||||
},
|
||||
{ title: '标签', dataIndex: 'label', slotName: 'label' },
|
||||
{ title: '值', dataIndex: 'value', ellipsis: true, tooltip: true },
|
||||
{ title: '状态', slotName: 'status', align: 'center' },
|
||||
{ title: '排序', dataIndex: 'sort', show: false },
|
||||
{ title: '描述', dataIndex: 'description', ellipsis: true, tooltip: true },
|
||||
{ title: '创建人', dataIndex: 'createUserString', show: false, ellipsis: true, tooltip: true },
|
||||
{ title: '创建时间', dataIndex: 'createTime', width: 180 },
|
||||
{ title: '修改人', dataIndex: 'updateUserString', show: false, ellipsis: true, tooltip: true },
|
||||
{ title: '修改时间', dataIndex: 'updateTime', width: 180, show: false },
|
||||
{ title: '操作', slotName: 'action', width: 130, align: 'center', fixed: !isMobile() ? 'right' : undefined }
|
||||
]
|
||||
|
||||
const queryForm = reactive({
|
||||
description: undefined,
|
||||
status: undefined,
|
||||
sort: ['createTime,desc']
|
||||
})
|
||||
|
||||
const dictId = ref('')
|
||||
const dictCode = ref('')
|
||||
const visible = ref(false)
|
||||
// 打开
|
||||
const open = (id: string, code: string) => {
|
||||
dataList.value = []
|
||||
dictId.value = id
|
||||
dictCode.value = code
|
||||
visible.value = true
|
||||
search()
|
||||
}
|
||||
defineExpose({ open })
|
||||
|
||||
const {
|
||||
tableData: dataList,
|
||||
loading,
|
||||
pagination,
|
||||
search,
|
||||
handleDelete
|
||||
} = useTable((p) => listDictItem({ ...queryForm, dictId: dictId.value, page: p.page, size: p.size }), {
|
||||
immediate: true
|
||||
})
|
||||
|
||||
// 重置
|
||||
const reset = () => {
|
||||
queryForm.description = undefined
|
||||
queryForm.status = undefined
|
||||
search()
|
||||
}
|
||||
|
||||
// 删除
|
||||
const onDelete = (item: DictItemResp) => {
|
||||
return handleDelete(() => deleteDictItem(item.id), { content: `是否确定删除 [${item.label}]?`, showModal: false })
|
||||
}
|
||||
|
||||
const AddDictItemModalRef = ref<InstanceType<typeof AddDictItemModal>>()
|
||||
// 新增
|
||||
const onAdd = () => {
|
||||
AddDictItemModalRef.value?.onAdd(dictId.value)
|
||||
}
|
||||
|
||||
// 修改
|
||||
const onUpdate = (item: DictItemResp) => {
|
||||
AddDictItemModalRef.value?.onUpdate(item.id)
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped></style>
|
Reference in New Issue
Block a user