- 新增 utils/formDataGroups.ts:groups 顺序展示、schema 外字段归「其他信息」、无 schema 回落按 key - ApplyDetail 改用详情出参 formSchemaJson(删除再调 /api/apply/item 取 schema 的旁路);ApplyVo 类型补 formSchemaJson - 顺带入库 hall 动态表单修复(就地写 reactive + 内联 validate,2026-09-17 会话)
This commit is contained in:
+31
-2
@@ -14,9 +14,9 @@ import { computed, onMounted, reactive, ref } from "vue";
|
||||
import { useRoute, useRouter } from "vue-router";
|
||||
import { Message } from "view-ui-plus";
|
||||
import { applyApi } from "@/api/module/svc";
|
||||
import type { ApplyAttachmentItem } from "@/types/svc";
|
||||
import { useSite } from "@/utils/site";
|
||||
import DynamicForm from "@/components/DynamicForm.vue";
|
||||
|
||||
const route = useRoute();
|
||||
const router = useRouter();
|
||||
const { resolveSite, rememberItem } = useSite();
|
||||
@@ -31,6 +31,7 @@ const item = ref<Record<string, any> | null>(null);
|
||||
const loadError = ref("");
|
||||
const siteCode = ref("");
|
||||
const formData = reactive<Record<string, any>>({});
|
||||
const dynFormRef = ref<InstanceType<typeof DynamicForm> | null>(null); // DynamicForm.validate()
|
||||
|
||||
const schemaJson = computed(() => (item.value?.schemaJson as string) || "");
|
||||
|
||||
@@ -56,6 +57,30 @@ async function load() {
|
||||
|
||||
const sleep = (ms: number) => new Promise(resolve => setTimeout(resolve, ms));
|
||||
|
||||
/**
|
||||
* 从 formData 提取附件行(upload/image 字段值为 /api/file/upload 返回体数组,
|
||||
* 每项含附件行 id):后端 submit 依据 attachments 做办件材料绑定(bindApply),
|
||||
* 不传则附件行永远未落 topic,表现为「附件传了但提交后无效」。
|
||||
*/
|
||||
function collectAttachments(): ApplyAttachmentItem[] {
|
||||
const out: ApplyAttachmentItem[] = [];
|
||||
try {
|
||||
const groups = JSON.parse(schemaJson.value || "{}").groups || [];
|
||||
for (const g of groups) {
|
||||
for (const f of g.fields || []) {
|
||||
if (f.type !== "upload" && f.type !== "image") continue;
|
||||
const list = formData[f.key];
|
||||
for (const it of Array.isArray(list) ? list : []) {
|
||||
if (it && it.id != null) out.push({ fieldKey: f.key, attachmentId: it.id });
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch {
|
||||
// schema 解析失败时只丢附件绑定,不阻断提交
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
/** 轮询办件状态直到离开 PENDING;超时返回最后一次看到的办件(可能仍是待提交) */
|
||||
async function awaitFlowStart(applyId: number, first: any) {
|
||||
let latest = first;
|
||||
@@ -75,6 +100,9 @@ async function awaitFlowStart(applyId: number, first: any) {
|
||||
|
||||
async function submit() {
|
||||
if (!item.value) return;
|
||||
// 前端先按 schema 校验(字段下方内联红字 + 滚到第一个错误),不再把"必填项未填写"
|
||||
// 这类校验留给后端弹 Message——后端强校验仍保留作兜底
|
||||
if (dynFormRef.value && !dynFormRef.value.validate()) return;
|
||||
submitting.value = true;
|
||||
try {
|
||||
const apply: any = await applyApi
|
||||
@@ -82,6 +110,7 @@ async function submit() {
|
||||
siteCode: siteCode.value,
|
||||
itemCode: String(route.query.itemCode),
|
||||
formData: Object.keys(formData).length ? JSON.stringify(formData) : undefined,
|
||||
attachments: collectAttachments(),
|
||||
})
|
||||
.send();
|
||||
|
||||
@@ -121,7 +150,7 @@ onMounted(load);
|
||||
</div>
|
||||
</div>
|
||||
<Divider v-if="schemaJson" orientation="left">申请表单</Divider>
|
||||
<DynamicForm v-if="schemaJson" :schema-json="schemaJson" v-model:form-data="formData" />
|
||||
<DynamicForm v-if="schemaJson" ref="dynFormRef" :schema-json="schemaJson" :form-data="formData" />
|
||||
<div v-else class="no-form">该事项无需填写表单,提交后由办理部门联系确认。</div>
|
||||
<div class="actions">
|
||||
<Button class="sh-btn-primary" type="primary" :loading="submitting" @click="submit">
|
||||
|
||||
Reference in New Issue
Block a user