132 lines
4.6 KiB
Vue
132 lines
4.6 KiB
Vue
<script setup lang="ts">
|
||
/** 服务字典管理(modId 24):object/category 双 Tab,引用守护。 */
|
||
import { onMounted, ref } from "vue";
|
||
import { Message, Modal } from "view-ui-plus";
|
||
import { svcDictApi } from "@/api/module/svc";
|
||
import type { SvcDictVo } from "@/types/svc";
|
||
import { useSite } from "@/utils/site";
|
||
|
||
const { currentSiteCode, sites, loadSites, setSite } = useSite();
|
||
const tab = ref<"object" | "category">("object");
|
||
const loading = ref(false);
|
||
const list = ref<SvcDictVo[]>([]);
|
||
const modal = ref(false);
|
||
const saving = ref(false);
|
||
const form = ref<any>({});
|
||
|
||
const cols = [
|
||
{ title: "键", key: "dictKey", width: 160 },
|
||
{ title: "名称", key: "dictName", minWidth: 160 },
|
||
{ title: "排序", key: "sortNo", width: 80 },
|
||
{ title: "被引用", key: "referenced", width: 90 },
|
||
{ title: "状态", slot: "status", width: 90 },
|
||
{ title: "操作", slot: "action", width: 140 },
|
||
];
|
||
|
||
async function load() {
|
||
if (!currentSiteCode.value) return;
|
||
loading.value = true;
|
||
try {
|
||
list.value = (await svcDictApi.list(currentSiteCode.value, tab.value).send()) || [];
|
||
} finally {
|
||
loading.value = false;
|
||
}
|
||
}
|
||
|
||
function open(row?: SvcDictVo) {
|
||
form.value = row
|
||
? { ...row }
|
||
: { siteCode: currentSiteCode.value, dictType: tab.value, dictKey: "", dictName: "", sortNo: 0, status: 1 };
|
||
modal.value = true;
|
||
}
|
||
|
||
async function save() {
|
||
saving.value = true;
|
||
try {
|
||
await svcDictApi.save(form.value).send();
|
||
Message.success("已保存");
|
||
modal.value = false;
|
||
load();
|
||
} finally {
|
||
saving.value = false;
|
||
}
|
||
}
|
||
|
||
function remove(row: SvcDictVo) {
|
||
Modal.confirm({
|
||
title: "删除确认",
|
||
content: `确定删除字典「${row.dictName}」吗?被引用的删除会被拒绝。`,
|
||
onOk: async () => {
|
||
await svcDictApi.delete(currentSiteCode.value, row.id).send();
|
||
Message.success("已删除");
|
||
load();
|
||
},
|
||
});
|
||
}
|
||
|
||
onMounted(async () => {
|
||
await loadSites();
|
||
load();
|
||
});
|
||
</script>
|
||
|
||
<template>
|
||
<div class="page">
|
||
<Card :bordered="false" dis-hover>
|
||
<div class="bar">
|
||
<Select :model-value="currentSiteCode" style="width: 240px" @on-change="(c: string) => { setSite(c); load(); }">
|
||
<Option v-for="s in sites" :key="s.siteCode" :value="s.siteCode">{{ s.name }}({{ s.siteCode }})</Option>
|
||
</Select>
|
||
<Button type="primary" @click="open()">新建{{ tab === "object" ? "服务对象" : "事项类别" }}</Button>
|
||
</div>
|
||
<Tabs v-model="tab" @on-click="() => load()">
|
||
<TabPane label="服务对象" name="object" />
|
||
<TabPane label="事项类别" name="category" />
|
||
</Tabs>
|
||
<Table :loading="loading" :columns="cols" :data="list">
|
||
<template #status="{ row }">
|
||
<Tag :color="row.status === 1 ? 'success' : 'default'">{{ row.status === 1 ? "启用" : "停用" }}</Tag>
|
||
</template>
|
||
<template #action="{ row }">
|
||
<Button size="small" type="text" @click="open(row)">编辑</Button>
|
||
<Button size="small" type="text" style="color: #ed4014" @click="remove(row)">删除</Button>
|
||
</template>
|
||
</Table>
|
||
</Card>
|
||
|
||
<Modal v-model="modal" :title="form.id ? '编辑字典' : '新建字典'">
|
||
<Form :label-width="90">
|
||
<FormItem label="字典键" required>
|
||
<Input v-model="form.dictKey" :disabled="!!form.id && (form.referenced || 0) > 0" placeholder="字母/数字/下划线" />
|
||
<div v-if="(form.referenced || 0) > 0" class="tip">已被 {{ form.referenced }} 个事项引用,仅可改名称</div>
|
||
</FormItem>
|
||
<FormItem label="名称" required>
|
||
<Input v-model="form.dictName" :maxlength="128" />
|
||
</FormItem>
|
||
<FormItem label="排序">
|
||
<InputNumber v-model="form.sortNo" style="width: 100%" />
|
||
</FormItem>
|
||
<FormItem label="状态">
|
||
<Switch v-model="form.status" :true-value="1" :false-value="0" />
|
||
</FormItem>
|
||
</Form>
|
||
<template #footer>
|
||
<Button @click="modal = false">取消</Button>
|
||
<Button type="primary" :loading="saving" @click="save">保存</Button>
|
||
</template>
|
||
</Modal>
|
||
</div>
|
||
</template>
|
||
|
||
<style scoped>
|
||
.bar {
|
||
display: flex;
|
||
gap: 8px;
|
||
margin-bottom: 8px;
|
||
}
|
||
.tip {
|
||
font-size: 12px;
|
||
color: #999;
|
||
}
|
||
</style>
|