t1: 定义编辑器接表单中心绑定(表单选择与版本坐标)
build / build (push) Successful in 1m36s

This commit is contained in:
chenxing
2026-10-22 10:03:34 +08:00
parent 5534cd107a
commit cdea9c559b
2 changed files with 78 additions and 1 deletions
+23 -1
View File
@@ -144,7 +144,29 @@ class FlowApi {
defGet(id: number | string) { defGet(id: number | string) {
return get(`${ROOT}/admin/def/get`, { id }); return get(`${ROOT}/admin/def/get`, { id });
} }
defSave(body: { id?: number; code: string; name: string; contentJson: string; baseGuid?: string; appKey?: string; changeLog?: string }) { /**
* 表单中心目录(v3/TASK_1):编辑器"关联表单"选择器的数据源。
* 走本应用同源代理,浏览器不持 appKey/secret、也不出现 form-center 地址;
* **没有 schId 入参**——管理域由后端从 CAS 会话派生,这是有意的,别"顺手加一个"。
*/
formCenterForms(params: { keyword?: string; page?: number; pageSize?: number } = {}) {
return get<{ items: any[]; total: number }>(`${ROOT}/admin/form-center/forms`, params);
}
/**
* 保存定义。`formUuid`/`formVersion`(v3)是**行字段**、不进 contentJson:
* 成对提交(后端单传一个即拒);`formUuid=""`=取消关联并同时清空版本;不传=保持原关联。
*/
defSave(body: {
id?: number;
code: string;
name: string;
contentJson: string;
baseGuid?: string;
appKey?: string;
changeLog?: string;
formUuid?: string;
formVersion?: number;
}) {
return post(`${ROOT}/admin/def/save`, body); return post(`${ROOT}/admin/def/save`, body);
} }
/** 元数据原地编辑(2026-10-10 议题2):只改 name/appKey 不升版本;已发布亦可 */ /** 元数据原地编辑(2026-10-10 议题2):只改 name/appKey 不升版本;已发布亦可 */
+55
View File
@@ -61,6 +61,15 @@ const sourceFlowGuid = ref("");
const appKey = ref(""); const appKey = ref("");
/** 应用清单下拉(应用设置白名单 flw_app enabled=1,显示应用名),拉取失败降级为仅当前值 */ /** 应用清单下拉(应用设置白名单 flw_app enabled=1,显示应用名),拉取失败降级为仅当前值 */
const appOptions = ref<{ appKey: string; appName: string }[]>([]); const appOptions = ref<{ appKey: string; appName: string }[]>([]);
/**
* 关联表单坐标(flw_def.form_uuid / form_version,v3/TASK_1):行字段、不进 contentJson。
* 版本由选中时那一条目录行带出(中心当前发布版),不给手填——存的就是服务端核验过的坐标。
*/
const formUuid = ref("");
const formVersion = ref<number | undefined>(undefined);
/** 表单中心目录(同源代理);拉不到时选择器禁用并说明原因,不假装"这所学校没有表单" */
const formOptions = ref<any[]>([]);
const formCenterError = ref("");
const model = reactive<EditorModel>(createEmptyModel()); const model = reactive<EditorModel>(createEmptyModel());
/** 科室列表(deptList 聚合行):仅用于下拉选项与"无启用人员"提示 */ /** 科室列表(deptList 聚合行):仅用于下拉选项与"无启用人员"提示 */
@@ -249,6 +258,15 @@ async function load(): Promise<void> {
} catch { } catch {
appOptions.value = []; appOptions.value = [];
} }
// 表单中心目录:授权没配/中心不可达时选择器禁用并说明原因(空列表 ≠ "没有可用表单")
try {
const page: any = await flowApi.formCenterForms({ page: 1, pageSize: 100 }).send();
formOptions.value = page?.items || [];
formCenterError.value = "";
} catch (e: any) {
formOptions.value = [];
formCenterError.value = String(e?.message || e || "表单中心目录不可达");
}
const queryId = route.query.id ? Number(route.query.id) : null; const queryId = route.query.id ? Number(route.query.id) : null;
const queryGuid = (route.query.baseGuid as string) || ""; const queryGuid = (route.query.baseGuid as string) || "";
@@ -273,6 +291,8 @@ async function load(): Promise<void> {
model.code = d?.code || ""; model.code = d?.code || "";
model.name = d?.name || ""; model.name = d?.name || "";
appKey.value = d?.appKey || ""; appKey.value = d?.appKey || "";
formUuid.value = d?.formUuid || "";
formVersion.value = d?.formVersion == null ? undefined : Number(d.formVersion);
try { try {
applyParsed(fromContentJson(JSON.parse(d?.contentJson || "{}"))); applyParsed(fromContentJson(JSON.parse(d?.contentJson || "{}")));
} catch (e: any) { } catch (e: any) {
@@ -430,6 +450,16 @@ function onJsonApplied(p: ParsedDef): void {
applyParsed(p); applyParsed(p);
} }
/**
* 选表=成对记下 uuid 与中心当时发布版;清空则两列一起清(后端要求成对,半个坐标存不下)。
* 版本号一律取自目录行,页面不提供手填——填一个中心没有的版本,只会在发布期撞"坐标不符"。
*/
function onFormChange(uuid: string): void {
const hit = uuid ? formOptions.value.find((f) => f.formUuid === uuid) : null;
formUuid.value = hit ? hit.formUuid : "";
formVersion.value = hit ? Number(hit.version) : undefined;
}
async function onSave(): Promise<void> { async function onSave(): Promise<void> {
if (!model.name.trim()) { if (!model.name.trim()) {
Message.warning("请填写流程名称"); Message.warning("请填写流程名称");
@@ -445,6 +475,11 @@ async function onSave(): Promise<void> {
Message.warning("请选择归属应用(应用需先在 流程管理 > 应用设置 中开启)"); Message.warning("请选择归属应用(应用需先在 流程管理 > 应用设置 中开启)");
return; return;
} }
// 关联表单必须成对:改造前只有关联、没有版本号的存量行,重新选一次才能保存(后端同样会拒)
if (formUuid.value && !formVersion.value) {
Message.warning("该流程关联的表单还没有确切版本号,请在「关联表单」里重新选择一次(版本由表单中心给出,不可手填)");
return;
}
const errors = countErrors(issues.value); const errors = countErrors(issues.value);
if (errors.length) { if (errors.length) {
Message.error(`校验未通过:${errors[0].text}`); Message.error(`校验未通过:${errors[0].text}`);
@@ -503,6 +538,9 @@ async function submitSave(changeLog?: string): Promise<void> {
baseGuid: baseGuid.value || undefined, baseGuid: baseGuid.value || undefined,
appKey: (appKey.value || "").trim() || undefined, appKey: (appKey.value || "").trim() || undefined,
changeLog: changeLog || undefined, changeLog: changeLog || undefined,
// 关联表单成对提交:空串=显式取消关联(后端同时清空版本),有值=uuid + 中心当时发布版
formUuid: formUuid.value,
formVersion: formUuid.value ? formVersion.value : undefined,
}).send(); }).send();
savedSnapshot.value = currentSnapshot.value; savedSnapshot.value = currentSnapshot.value;
Message.success(willCreateVersion() Message.success(willCreateVersion()
@@ -617,6 +655,23 @@ onUnmounted(() => window.removeEventListener("beforeunload", onBeforeUnload));
<Option v-for="a in appOptions" :key="a.appKey" :value="a.appKey">{{ a.appName }}</Option> <Option v-for="a in appOptions" :key="a.appKey" :value="a.appKey">{{ a.appName }}</Option>
</Select> </Select>
</div> </div>
<div class="ip-fld">
<label>关联表单<span class="ip-mini">表单中心 · 成对存版本</span></label>
<Select :value="formUuid" clearable filterable placeholder="不关联(原生办理)"
:disabled="!!formCenterError" @on-change="onFormChange">
<Option v-for="f in formOptions" :key="f.formUuid" :value="f.formUuid">
{{ f.name }}({{ f.appCode }}/{{ f.code }} · v{{ f.version }})
</Option>
</Select>
<div v-if="formCenterError" class="ip-mini" style="color: #ed4014">
{{ formCenterError }}
</div>
<div v-else-if="formUuid && !formVersion" class="ip-mini" style="color: #ed4014">
历史关联缺版本号,请重新选择表单后再保存
</div>
<div v-else-if="formUuid" class="ip-mini">已绑定 v{{ formVersion }}(发布时按这组坐标核验快照)</div>
<div v-else class="ip-mini">目录只列中心已发布、且已授权给本应用的表单</div>
</div>
</section> </section>
<section class="ip-sec"> <section class="ip-sec">