From dab13c9a8b0b850d47c59b6a4bd725aefa2298fd Mon Sep 17 00:00:00 2001
From: tuqin <tuqin@tuqin.cn>
Date: 星期二, 13 十月 2026 18:33:41 +0800
Subject: [PATCH] feat(hrm): 员工合同「下载合同模板」新增退休返聘合同

---
 src/views/aftersales/problem/modules/form.vue |  139 ++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 139 insertions(+), 0 deletions(-)

diff --git a/src/views/aftersales/problem/modules/form.vue b/src/views/aftersales/problem/modules/form.vue
new file mode 100644
index 0000000..37ec0ec
--- /dev/null
+++ b/src/views/aftersales/problem/modules/form.vue
@@ -0,0 +1,139 @@
+<script lang="ts" setup>
+import type { ProblemFormType } from '../data';
+
+import type { AftersalesProblemApi } from '#/api/aftersales/problem';
+
+import { computed, ref } from 'vue';
+
+import { useVbenModal } from '@vben/common-ui';
+import { Button, message } from 'ant-design-vue';
+
+import { useVbenForm } from '#/adapter/form';
+import {
+  createProblem,
+  getProblem,
+  updateProblem,
+} from '#/api/aftersales/problem';
+
+import { useProblemFormSchema } from '../data';
+
+defineOptions({ name: 'AftersalesProblemForm' });
+
+const emit = defineEmits(['success']);
+
+const formType = ref<ProblemFormType>('create');
+const id = ref<number>();
+const submitting = ref(false);
+
+const isEdit = computed(() => formType.value !== 'detail');
+const title = computed(() => {
+  if (formType.value === 'detail') return '鏌ョ湅鍞悗闂';
+  if (id.value) return '缂栬緫鍞悗闂';
+  return '鏂板鍞悗闂';
+});
+
+// 涓昏〃鍗�
+const [Form, formApi] = useVbenForm({
+  commonConfig: { componentProps: { class: 'w-full' }, formItemClass: 'col-span-1', labelWidth: 100 },
+  layout: 'horizontal',
+  schema: [],
+  showDefaultActions: false,
+  wrapperClass: 'grid-cols-2',
+});
+
+/** 鎶婇棶棰樺璞℃槧灏勬垚琛ㄥ崟鍊硷紙闄勪欢杞负 FileUpload 缁撴瀯锛� */
+function problemToForm(p: AftersalesProblemApi.Problem): Record<string, unknown> {
+  const form: Record<string, unknown> = { ...p };
+  if (p.attachmentList?.length) {
+    form.blobIds = p.attachmentList.map((item) => ({
+      uid: String(item.id),
+      name: item.name || '',
+      url: item.url || '',
+      status: 'done',
+      id: item.id,
+    }));
+  }
+  return form;
+}
+
+/** 鎶婅〃鍗曢噷鐨勯檮浠跺�艰鏁存垚 blobId 鏁扮粍 */
+function normalizeBlobIds(value: unknown): number[] {
+  const arr = Array.isArray(value) ? value : [];
+  return arr
+    .map((x) =>
+      typeof x === 'number'
+        ? x
+        : x && typeof x === 'object' && 'id' in (x as Record<string, unknown>)
+          ? Number((x as Record<string, unknown>).id)
+          : Number(x),
+    )
+    .filter((n) => Number.isFinite(n));
+}
+
+// Modal
+const [Modal, modalApi] = useVbenModal({
+  async onOpenChange(isOpen: boolean) {
+    if (!isOpen) {
+      id.value = undefined;
+      return;
+    }
+    const data = modalApi.getData<{ formType: ProblemFormType; id?: number }>();
+    formType.value = data.formType;
+    id.value = data.id;
+    formApi.setState({ schema: useProblemFormSchema(formType.value) });
+    formApi.setDisabled(formType.value === 'detail');
+    if (data.id) {
+      modalApi.lock();
+      try {
+        const detail = await getProblem(data.id);
+        await formApi.setValues(problemToForm(detail));
+      } finally {
+        modalApi.unlock();
+      }
+    } else {
+      await formApi.resetForm();
+    }
+  },
+});
+
+async function handleSubmit() {
+  const { valid } = await formApi.validate();
+  if (!valid) {
+    return;
+  }
+  submitting.value = true;
+  try {
+    const data = (await formApi.getValues()) as Record<string, unknown>;
+    const blobIds = normalizeBlobIds(data.blobIds);
+    const payload = { ...data, blobIds } as AftersalesProblemApi.Problem;
+    if (id.value) {
+      await updateProblem({ ...payload, id: id.value });
+    } else {
+      await createProblem(payload);
+    }
+    message.success('鎿嶄綔鎴愬姛');
+    await modalApi.close();
+    emit('success');
+  } catch (e: unknown) {
+    message.error((e as Error).message || '鎻愪氦澶辫触');
+  } finally {
+    submitting.value = false;
+  }
+}
+</script>
+
+<template>
+  <Modal :title="title" class="w-2/3">
+    <Form class="mx-4" />
+
+    <template #footer>
+      <div class="flex justify-end gap-2">
+        <Button @click="modalApi.close()">鍙栨秷</Button>
+        <Button v-if="isEdit" type="primary" :loading="submitting" @click="handleSubmit">
+          纭
+        </Button>
+        <Button v-else type="primary" @click="modalApi.close()">鍏抽棴</Button>
+      </div>
+    </template>
+  </Modal>
+</template>

--
Gitblit v1.9.3