t1: 事项编辑接表单中心绑定(表单目录选择/设计器对齐svc模型)
build / build (push) Successful in 1m38s

This commit is contained in:
chenxing
2026-10-22 10:03:15 +08:00
parent 54813134ae
commit 509fc6d20c
4 changed files with 193 additions and 352 deletions
+48 -14
View File
@@ -10,7 +10,7 @@ import {
svcFormApi,
svcItemApi,
} from "@/api/module/svc";
import type { SvcDeptVo, SvcFormVo, SvcItemAttachmentVo, SvcItemSaveRequest } from "@/types/svc";
import type { FcFormCatalogItem, SvcDeptVo, SvcItemAttachmentVo, SvcItemSaveRequest } from "@/types/svc";
import { useSite } from "@/utils/site";
import RichTextEditor from "@/components/RichTextEditor.vue";
@@ -43,7 +43,10 @@ const form = ref<SvcItemSaveRequest>({
const objects = ref<{ dictKey: string; dictName: string }[]>([]);
const categories = ref<{ dictKey: string; dictName: string }[]>([]);
const depts = ref<SvcDeptVo[]>([]);
const forms = ref<SvcFormVo[]>([]);
/** 表单中心目录(v3/TASK_1:办理表单只能从这里选;本地表单定义已停写) */
const fcForms = ref<FcFormCatalogItem[]>([]);
const fcFormsDisabled = ref(false);
const fcFormsReason = ref("");
const flows = ref<{ flowGuid: string; name: string; version: number }[]>([]);
const flowDisabled = ref(false);
const flowDisabledReason = ref("");
@@ -53,11 +56,22 @@ const uploadingCover = ref(false);
const editing = computed(() => !!route.query.id);
const pageTitle = computed(() => (editing.value ? "编辑事项" : "新建事项"));
/** 选中表单的最新版本是否为草稿/停用(草稿可先绑,但发起页要等发布才生效) */
const selectedFormDraft = computed(() => {
if (!form.value.formCode) return false;
const f = forms.value.find((x) => x.code === form.value.formCode);
return !!f && f.status !== 1;
/**
* 选中即成对存 uuid + 中心当时的发布版(v3 §4:只保存服务器验证过的坐标,不接受手填版本)。
* 清空=两列一起清——后端要求成对,留一个没人认领的版本号没有意义。
*/
function onFcFormChange(uuid?: string) {
const hit = uuid ? fcForms.value.find((f) => f.formUuid === uuid) : undefined;
form.value.fcFormUuid = hit ? hit.formUuid : undefined;
form.value.fcFormVersion = hit ? hit.version : undefined;
}
/** 绑定回显:存的是当时核验过的版本,中心又发新版时页面要点出来(不自动改绑) */
const fcBinding = computed(() => {
if (!form.value.fcFormUuid) return "";
const newest = fcForms.value.find((f) => f.formUuid === form.value.fcFormUuid)?.version;
const base = `已绑定 ${form.value.fcFormUuid} v${form.value.fcFormVersion}`;
return newest && newest !== form.value.fcFormVersion ? `${base}(中心最新已发布 v${newest},需换版请重新选择)` : base;
});
/** 部门树扁平化(缩进展示,承袭 CMS flattenDepts) */
@@ -84,7 +98,20 @@ async function loadAll() {
objects.value = ((await svcDictApi.list(siteCode, "object").send()) as any[]) || [];
categories.value = ((await svcDictApi.list(siteCode, "category").send()) as any[]) || [];
depts.value = (await svcDictApi.deptTree(siteCode).send()) || [];
forms.value = ((await svcFormApi.list(siteCode).send()) as SvcFormVo[]) || [];
// 表单中心目录(同源代理):授权没配/中心不可达时降级为"选不了",不阻塞事项其余字段的编辑
try {
const page = await svcFormApi.centerForms(siteCode, { page: 1, pageSize: 100 }).send();
fcForms.value = page?.items || [];
fcFormsDisabled.value = false;
fcFormsReason.value = "";
} catch (e: any) {
fcForms.value = [];
fcFormsDisabled.value = true;
const msg = String(e?.message || e || "");
fcFormsReason.value = msg.includes("不可达") || msg.includes("返回空")
? msg
: `表单中心目录获取失败:${msg}`;
}
try {
flows.value = ((await svcFlowApi.list(siteCode).send()) as any[]) || [];
flowDisabled.value = false;
@@ -312,15 +339,22 @@ onMounted(loadAll);
</Col>
<Col span="12">
<FormItem label="办理表单">
<Select v-model="form.formCode" clearable placeholder="该事项发起时填写的自定义表单">
<Option v-for="f in forms" :key="f.code" :value="f.code">
{{ f.name }}{{ f.status !== 1 ? `(${f.status === 2 ? "已停用" : "草稿"})` : "" }}
<Select :value="form.fcFormUuid" clearable placeholder="从表单中心选择已发布表单"
:disabled="fcFormsDisabled" @on-change="onFcFormChange">
<Option v-for="f in fcForms" :key="f.formUuid" :value="f.formUuid">
{{ f.name }}({{ f.appCode }}/{{ f.code }} · v{{ f.version }})
</Option>
</Select>
<div v-if="selectedFormDraft" class="tip" style="color: #ed4014">
该表单尚未发布,发布后才能在发起页实际填写;请到「表单管理」发布。
<div v-if="fcFormsDisabled" class="tip" style="color: #ed4014">
{{ fcFormsReason || "表单中心目录不可达" }}
</div>
<div v-else-if="fcBinding" class="tip">{{ fcBinding }}</div>
<div v-else class="tip">
目录只列中心已发布、且已授权给本应用的表单;保存时服务端会再向中心核验一次坐标
</div>
<div v-if="form.formCode" class="tip" style="color: #ed4014">
历史本地表单「{{ form.formCode }}」只读保留(本地表单定义已停用,改绑请选表单中心的表)
</div>
<div v-else class="tip">发起页按表单编码取最新已发布版本渲染</div>
</FormItem>
</Col>
<Col span="24">