添加系统管理、登录模块的接口、标准化开发流程
This commit is contained in:
277
src/components/system/dict/DictItemDrawer.vue
Normal file
277
src/components/system/dict/DictItemDrawer.vue
Normal file
@@ -0,0 +1,277 @@
|
||||
<template>
|
||||
<a-drawer
|
||||
:open="visible"
|
||||
:title="`字典项管理 - ${dictData?.name || ''}`"
|
||||
width="800"
|
||||
:destroyOnClose="true"
|
||||
@close="handleClose"
|
||||
>
|
||||
<div class="drawer-content">
|
||||
<!-- 字典项操作栏 -->
|
||||
<div class="item-toolbar">
|
||||
<a-button type="primary" @click="handleAddItem">
|
||||
<template #icon><PlusOutlined /></template>
|
||||
新增字典项
|
||||
</a-button>
|
||||
</div>
|
||||
|
||||
<!-- 字典项表格 -->
|
||||
<a-table
|
||||
:columns="columns"
|
||||
:data-source="tableData"
|
||||
:loading="loading"
|
||||
:pagination="false"
|
||||
row-key="id"
|
||||
size="small"
|
||||
>
|
||||
<template #bodyCell="{ column, record }">
|
||||
<template v-if="column.dataIndex === 'status'">
|
||||
<a-tag :color="record.status === 1 ? 'green' : 'red'" size="small">
|
||||
{{ record.status === 1 ? '正常' : '禁用' }}
|
||||
</a-tag>
|
||||
</template>
|
||||
<template v-if="column.dataIndex === 'isDefault'">
|
||||
<a-tag v-if="record.isDefault === 1" color="blue">是</a-tag>
|
||||
<span v-else class="text-muted">否</span>
|
||||
</template>
|
||||
<template v-if="column.dataIndex === 'action'">
|
||||
<a-space>
|
||||
<a-button type="link" size="small" @click="handleEditItem(record)">编辑</a-button>
|
||||
<a-popconfirm
|
||||
title="确定删除此字典项吗?"
|
||||
@confirm="handleDeleteItem(record.id)"
|
||||
>
|
||||
<a-button type="link" size="small" danger>删除</a-button>
|
||||
</a-popconfirm>
|
||||
</a-space>
|
||||
</template>
|
||||
</template>
|
||||
</a-table>
|
||||
</div>
|
||||
|
||||
<!-- 新增/编辑字典项弹窗 -->
|
||||
<a-modal
|
||||
v-model:open="itemModalVisible"
|
||||
:title="isEditItem ? '编辑字典项' : '新增字典项'"
|
||||
@ok="handleSubmitItem"
|
||||
:confirm-loading="submitLoading"
|
||||
>
|
||||
<a-form
|
||||
ref="formRef"
|
||||
:model="formData"
|
||||
:rules="formRules"
|
||||
:label-col="{ span: 6 }"
|
||||
:wrapper-col="{ span: 16 }"
|
||||
>
|
||||
<a-form-item label="字典项标签" name="label">
|
||||
<a-input v-model:value="formData.label" placeholder="请输入显示的文本" />
|
||||
</a-form-item>
|
||||
<a-form-item label="字典项值" name="value">
|
||||
<a-input v-model:value="formData.value" placeholder="请输入存储的值" />
|
||||
</a-form-item>
|
||||
<a-form-item label="排序" name="sort">
|
||||
<a-input-number v-model:value="formData.sort" :min="0" :max="999" style="width: 100%" />
|
||||
</a-form-item>
|
||||
<a-form-item label="是否默认" name="isDefault">
|
||||
<a-switch v-model:checked="formData.isDefault" :checked-value="1" :un-checked-value="0" />
|
||||
</a-form-item>
|
||||
<a-form-item label="状态" name="status">
|
||||
<a-radio-group v-model:value="formData.status">
|
||||
<a-radio :value="1">正常</a-radio>
|
||||
<a-radio :value="0">禁用</a-radio>
|
||||
</a-radio-group>
|
||||
</a-form-item>
|
||||
<a-form-item label="备注" name="remark">
|
||||
<a-textarea v-model:value="formData.remark" placeholder="请输入备注" :rows="2" />
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
</a-modal>
|
||||
</a-drawer>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, reactive, watch } from 'vue'
|
||||
import { message } from 'ant-design-vue'
|
||||
import { PlusOutlined } from '@ant-design/icons-vue'
|
||||
import type { FormInstance } from 'ant-design-vue'
|
||||
|
||||
// 类型定义
|
||||
interface DictRecord {
|
||||
id: number
|
||||
name: string
|
||||
code: string
|
||||
}
|
||||
|
||||
interface DictItemRecord {
|
||||
id?: number
|
||||
dictId?: number
|
||||
label: string
|
||||
value: string
|
||||
sort: number
|
||||
isDefault: number
|
||||
status: number
|
||||
remark?: string
|
||||
}
|
||||
|
||||
const props = defineProps<{
|
||||
visible: boolean
|
||||
dictData?: DictRecord | null
|
||||
}>()
|
||||
|
||||
const emit = defineEmits(['update:visible'])
|
||||
|
||||
// 表格
|
||||
const loading = ref(false)
|
||||
const tableData = ref<DictItemRecord[]>([])
|
||||
|
||||
const columns = [
|
||||
{ title: '标签', dataIndex: 'label', width: 120 },
|
||||
{ title: '值', dataIndex: 'value', width: 100 },
|
||||
{ title: '排序', dataIndex: 'sort', width: 70 },
|
||||
{ title: '默认', dataIndex: 'isDefault', width: 70 },
|
||||
{ title: '状态', dataIndex: 'status', width: 70 },
|
||||
{ title: '备注', dataIndex: 'remark', ellipsis: true },
|
||||
{ title: '操作', dataIndex: 'action', width: 120, fixed: 'right' }
|
||||
]
|
||||
|
||||
// 字典项表单
|
||||
const itemModalVisible = ref(false)
|
||||
const isEditItem = ref(false)
|
||||
const submitLoading = ref(false)
|
||||
const formRef = ref<FormInstance>()
|
||||
|
||||
const formData = reactive<DictItemRecord>({
|
||||
id: undefined,
|
||||
dictId: undefined,
|
||||
label: '',
|
||||
value: '',
|
||||
sort: 0,
|
||||
isDefault: 0,
|
||||
status: 1,
|
||||
remark: ''
|
||||
})
|
||||
|
||||
const formRules = {
|
||||
label: [{ required: true, message: '请输入字典项标签' }],
|
||||
value: [{ required: true, message: '请输入字典项值' }]
|
||||
}
|
||||
|
||||
// 监听 visible 变化,加载数据
|
||||
watch(
|
||||
() => props.visible,
|
||||
(val) => {
|
||||
if (val && props.dictData) {
|
||||
loadData(props.dictData.id)
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
function handleClose() {
|
||||
emit('update:visible', false)
|
||||
}
|
||||
|
||||
// 加载字典项数据
|
||||
async function loadData(dictId: number) {
|
||||
loading.value = true
|
||||
try {
|
||||
// TODO: 接入真实API
|
||||
// const res = await getDictItemList(dictId)
|
||||
// tableData.value = res.data.data
|
||||
|
||||
// 模拟数据
|
||||
if (dictId === 1) {
|
||||
tableData.value = [
|
||||
{ id: 1, dictId: 1, label: '男', value: '1', sort: 1, isDefault: 1, status: 1, remark: '' },
|
||||
{ id: 2, dictId: 1, label: '女', value: '2', sort: 2, isDefault: 0, status: 1, remark: '' },
|
||||
{ id: 3, dictId: 1, label: '未知', value: '0', sort: 3, isDefault: 0, status: 1, remark: '' }
|
||||
]
|
||||
} else if (dictId === 2) {
|
||||
tableData.value = [
|
||||
{ id: 4, dictId: 2, label: '正常', value: '1', sort: 1, isDefault: 1, status: 1, remark: '' },
|
||||
{ id: 5, dictId: 2, label: '禁用', value: '0', sort: 2, isDefault: 0, status: 1, remark: '' }
|
||||
]
|
||||
} else if (dictId === 3) {
|
||||
tableData.value = [
|
||||
{ id: 6, dictId: 3, label: '待审批', value: 'pending', sort: 1, isDefault: 1, status: 1, remark: '' },
|
||||
{ id: 7, dictId: 3, label: '已通过', value: 'approved', sort: 2, isDefault: 0, status: 1, remark: '' },
|
||||
{ id: 8, dictId: 3, label: '已驳回', value: 'rejected', sort: 3, isDefault: 0, status: 1, remark: '' }
|
||||
]
|
||||
} else {
|
||||
tableData.value = []
|
||||
}
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
function handleAddItem() {
|
||||
isEditItem.value = false
|
||||
formData.id = undefined
|
||||
formData.dictId = props.dictData?.id
|
||||
formData.label = ''
|
||||
formData.value = ''
|
||||
formData.sort = 0
|
||||
formData.isDefault = 0
|
||||
formData.status = 1
|
||||
formData.remark = ''
|
||||
itemModalVisible.value = true
|
||||
}
|
||||
|
||||
function handleEditItem(record: DictItemRecord) {
|
||||
isEditItem.value = true
|
||||
formData.id = record.id
|
||||
formData.dictId = record.dictId
|
||||
formData.label = record.label
|
||||
formData.value = record.value
|
||||
formData.sort = record.sort
|
||||
formData.isDefault = record.isDefault
|
||||
formData.status = record.status
|
||||
formData.remark = record.remark || ''
|
||||
itemModalVisible.value = true
|
||||
}
|
||||
|
||||
async function handleDeleteItem(id: number) {
|
||||
// TODO: 接入真实API
|
||||
// await deleteDictItem(id)
|
||||
message.success('删除成功')
|
||||
if (props.dictData) {
|
||||
loadData(props.dictData.id)
|
||||
}
|
||||
}
|
||||
|
||||
async function handleSubmitItem() {
|
||||
try {
|
||||
await formRef.value?.validate()
|
||||
submitLoading.value = true
|
||||
|
||||
// TODO: 接入真实API
|
||||
// if (isEditItem.value) {
|
||||
// await updateDictItem(formData)
|
||||
// } else {
|
||||
// await createDictItem(formData)
|
||||
// }
|
||||
|
||||
message.success(isEditItem.value ? '编辑成功' : '新增成功')
|
||||
itemModalVisible.value = false
|
||||
if (props.dictData) {
|
||||
loadData(props.dictData.id)
|
||||
}
|
||||
} catch (error) {
|
||||
// 验证失败
|
||||
} finally {
|
||||
submitLoading.value = false
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.drawer-content {
|
||||
height: 100%;
|
||||
}
|
||||
.item-toolbar {
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
.text-muted {
|
||||
color: #999;
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user