feat: 办事大厅前端源码首次入库(事项列表/详情/申报/管理端)
build / build (push) Successful in 1m55s

This commit is contained in:
chenxing
2026-09-15 11:00:57 +08:00
parent 7a2ea27f1e
commit 22dfb70377
328 changed files with 26089 additions and 0 deletions
+131
View File
@@ -0,0 +1,131 @@
<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>