From b337be5073334334962e873c1a980968ad2cf068 Mon Sep 17 00:00:00 2001
From: liu <2021943741@qq.com>
Date: 星期二, 27 十月 2026 18:06:37 +0800
Subject: [PATCH] feat(research): 课题申报成员新增成员类型并调整成员表列

---
 src/views/research/application/data.ts                             |   12 +-
 src/api/research/application/index.ts                              |   16 ++-
 src/views/research/application/modules/member-table.vue            |  126 +++++++++++++-----------------
 src/views/research/application/modules/member-statistics-modal.vue |   15 ++-
 src/views/research/application/detail/approve/index.vue            |   13 +-
 5 files changed, 85 insertions(+), 97 deletions(-)

diff --git a/src/api/research/application/index.ts b/src/api/research/application/index.ts
index 5a2f91d..a2de159 100644
--- a/src/api/research/application/index.ts
+++ b/src/api/research/application/index.ts
@@ -10,19 +10,21 @@
     id?: number;
     applicationId?: number;
     name: string; // 鎴愬憳濮撳悕
-    contactPhone?: string; // 鑱旂郴鐢佃瘽
-    workUnit?: string; // 鎵�灞炲崟浣�
-    jobTitle?: string; // 鑱岀О/鑱屽姟
-    memberRole?: string; // 鎴愬憳瑙掕壊锛氫富鎸佷汉/鏍稿績鎴愬憳/鍙備笌浜�
-    sortNo?: number; // 鎺掑簭鍙�
+    memberType?: string; // 鎴愬憳绫诲瀷锛氭暀甯�/瀛︾敓/鏍″浜哄憳
+    contactPhone?: string; // 鑱旂郴鐢佃瘽锛堝巻鍙插瓧娈碉紝涓嶅啀褰曞叆锛�
+    workUnit?: string; // 鎵�灞為儴闂�
+    jobTitle?: string; // 鑱岀О
+    memberRole?: string; // 鎴愬憳瑙掕壊锛堝巻鍙插瓧娈碉紝涓嶅啀褰曞叆锛�
+    sortNo?: number; // 缃插悕椤哄簭
   }
 
   /** 鎴愬憳缁村害缁熻 */
   export interface MemberStatistics {
     name: string; // 鎴愬憳濮撳悕
+    memberTypes?: string; // 鎴愬憳绫诲瀷锛堝涓互椤垮彿鍒嗛殧锛�
     contactPhone?: string; // 鑱旂郴鐢佃瘽
-    workUnit?: string; // 鎵�灞炲崟浣�
-    jobTitle?: string; // 鑱岀О/鑱屽姟
+    workUnit?: string; // 鎵�灞為儴闂�
+    jobTitle?: string; // 鑱岀О
     memberRoles?: string; // 鎴愬憳瑙掕壊锛堝涓互椤垮彿鍒嗛殧锛�
     projectCount?: number; // 鍙備笌璇鹃鏁�
     projectTitles?: string; // 鍙備笌璇鹃鍚嶇О锛堝垎鍙峰垎闅旓級
diff --git a/src/views/research/application/data.ts b/src/views/research/application/data.ts
index fd50bee..835b0a0 100644
--- a/src/views/research/application/data.ts
+++ b/src/views/research/application/data.ts
@@ -20,22 +20,24 @@
 /** 琛ㄥ崟绫诲瀷 */
 export type FormType = 'create' | 'detail' | 'edit';
 
-/** 璇鹃缁勬垚鍛樿鑹查�夐」 */
-export const MEMBER_ROLE_OPTIONS = [
-  { label: '涓绘寔浜�', value: '涓绘寔浜�' },
-  { label: '鏍稿績鎴愬憳', value: '鏍稿績鎴愬憳' },
-  { label: '鍙備笌浜�', value: '鍙備笌浜�' },
+/** 璇鹃缁勬垚鍛樼被鍨嬮�夐」锛堝榻愬鏍$増鎴愬憳琛級 */
+export const MEMBER_TYPE_OPTIONS = [
+  { label: '鏁欏笀', value: '鏁欏笀' },
+  { label: '瀛︾敓', value: '瀛︾敓' },
+  { label: '鏍″浜哄憳', value: '鏍″浜哄憳' },
 ];
 
 /**
  * 鎴愬憳琛屾姇褰变负鍙彁浜ゅ璞★細鍙繚鐣欏悗绔帴鍙楃殑瀛楁锛�
  * 涓嶅甫 id / applicationId锛岄伩鍏嶄笌銆屽厛鍒犲悗澧炪�嶇殑杞垹琛屼富閿啿绐併��
+ * 鑱旂郴鐢佃瘽銆佹垚鍛樿鑹插凡涓嶅湪琛ㄥ崟褰曞叆锛屼絾鍘嗗彶琛屽師鍊肩户缁�忎紶锛岄伩鍏嶇紪杈戞椂琚竻绌恒��
  */
 export function toSubmitMembers(
   members?: ResearchApplicationApi.ApplicationMember[],
 ): ResearchApplicationApi.ApplicationMember[] {
   return (members ?? []).map((member) => ({
     name: member.name,
+    memberType: member.memberType,
     contactPhone: member.contactPhone,
     workUnit: member.workUnit,
     jobTitle: member.jobTitle,
diff --git a/src/views/research/application/detail/approve/index.vue b/src/views/research/application/detail/approve/index.vue
index 6dfee12..9a1765a 100644
--- a/src/views/research/application/detail/approve/index.vue
+++ b/src/views/research/application/detail/approve/index.vue
@@ -38,14 +38,13 @@
   return val === 0 || val ? String(val) : '-';
 }
 
-/** 璇鹃缁勬垚鍛樺彧璇诲垪 */
+/** 璇鹃缁勬垚鍛樺彧璇诲垪锛堝榻愬鏍$増鎴愬憳琛級 */
 const memberColumns = [
-  { title: '濮撳悕', dataIndex: 'name', key: 'name', width: 110 },
-  { title: '鑱旂郴鐢佃瘽', dataIndex: 'contactPhone', key: 'contactPhone', width: 130 },
-  { title: '鎵�灞炲崟浣�', dataIndex: 'workUnit', key: 'workUnit' },
-  { title: '鑱岀О/鑱屽姟', dataIndex: 'jobTitle', key: 'jobTitle', width: 120 },
-  { title: '鎴愬憳瑙掕壊', dataIndex: 'memberRole', key: 'memberRole', width: 110 },
-  { title: '鎺掑簭', dataIndex: 'sortNo', key: 'sortNo', width: 70 },
+  { title: '缃插悕椤哄簭', dataIndex: 'sortNo', key: 'sortNo', width: 100 },
+  { title: '鎴愬憳绫诲瀷', dataIndex: 'memberType', key: 'memberType', width: 120 },
+  { title: '鎴愬憳濮撳悕', dataIndex: 'name', key: 'name', width: 120 },
+  { title: '鎵�灞為儴闂�', dataIndex: 'workUnit', key: 'workUnit' },
+  { title: '鑱岀О', dataIndex: 'jobTitle', key: 'jobTitle', width: 120 },
 ];
 
 /** 閲戦瀛楁绌哄�煎崰浣� */
diff --git a/src/views/research/application/modules/member-statistics-modal.vue b/src/views/research/application/modules/member-statistics-modal.vue
index 8e7452b..688ae36 100644
--- a/src/views/research/application/modules/member-statistics-modal.vue
+++ b/src/views/research/application/modules/member-statistics-modal.vue
@@ -39,10 +39,9 @@
 
 const columns: TableColumnsType<ResearchApplicationApi.MemberStatistics> = [
   { title: '鎴愬憳濮撳悕', dataIndex: 'name', key: 'name', width: 110, fixed: 'left' },
-  { title: '鑱旂郴鐢佃瘽', dataIndex: 'contactPhone', key: 'contactPhone', width: 130 },
-  { title: '鎵�灞炲崟浣�', dataIndex: 'workUnit', key: 'workUnit', width: 180 },
-  { title: '鑱岀О/鑱屽姟', dataIndex: 'jobTitle', key: 'jobTitle', width: 120 },
-  { title: '鎴愬憳瑙掕壊', dataIndex: 'memberRoles', key: 'memberRoles', width: 140 },
+  { title: '鎴愬憳绫诲瀷', dataIndex: 'memberTypes', key: 'memberTypes', width: 120 },
+  { title: '鎵�灞為儴闂�', dataIndex: 'workUnit', key: 'workUnit', width: 200 },
+  { title: '鑱岀О', dataIndex: 'jobTitle', key: 'jobTitle', width: 110 },
   { title: '鍙備笌璇鹃鏁�', dataIndex: 'projectCount', key: 'projectCount', width: 110 },
   { title: '鍙備笌璇鹃', dataIndex: 'projectTitles', key: 'projectTitles', ellipsis: true },
 ];
@@ -79,7 +78,9 @@
 function buildPublishText() {
   const lines = ['銆愯棰樻垚鍛樺悕鍗曘��'];
   rows.value.forEach((row, index) => {
-    const meta = [row.workUnit, row.jobTitle].filter(Boolean).join('/');
+    const meta = [row.memberTypes, row.workUnit, row.jobTitle]
+      .filter(Boolean)
+      .join('/');
     const metaText = meta ? `锛�${meta}锛塦 : '';
     const roles = row.memberRoles ? `锛�${row.memberRoles}锛絗 : '';
     const projects = row.projectTitles ? `锛�${row.projectTitles}` : '';
@@ -122,7 +123,7 @@
     <div class="mb-3 flex flex-wrap items-center gap-2">
       <Input
         v-model:value="keyword"
-        placeholder="濮撳悕 / 鐢佃瘽 / 鍗曚綅"
+        placeholder="濮撳悕 / 鎵�灞為儴闂�"
         allow-clear
         style="width: 220px"
         @press-enter="loadData"
@@ -152,7 +153,7 @@
     />
 
     <div class="mt-2 text-xs text-gray-400">
-      缁熻鍙e緞锛氬悓涓�銆屽鍚� + 鐢佃瘽 + 鍗曚綅銆嶈涓哄悓涓�鎴愬憳锛涘弬涓庤棰樻暟鎸変笉閲嶅璇鹃璁℃暟銆�
+      缁熻鍙e緞锛氬悓涓�銆屽鍚� + 鎵�灞為儴闂ㄣ�嶈涓哄悓涓�鎴愬憳锛涘弬涓庤棰樻暟鎸変笉閲嶅璇鹃璁℃暟銆�
     </div>
   </Modal>
 </template>
diff --git a/src/views/research/application/modules/member-table.vue b/src/views/research/application/modules/member-table.vue
index 6b44423..0e21315 100644
--- a/src/views/research/application/modules/member-table.vue
+++ b/src/views/research/application/modules/member-table.vue
@@ -9,7 +9,7 @@
 import { ACTION_ICON, TableAction, useVbenVxeGrid } from '#/adapter/vxe-table';
 import { $t } from '#/locales';
 
-import { MEMBER_ROLE_OPTIONS, toSubmitMembers } from '../data';
+import { MEMBER_TYPE_OPTIONS, toSubmitMembers } from '../data';
 
 const props = withDefaults(
   defineProps<{
@@ -29,42 +29,35 @@
 const [Grid, gridApi] = useVbenVxeGrid({
   gridOptions: {
     columns: [
-      { type: 'seq', title: '搴忓彿', width: 55, fixed: 'left' },
+      {
+        field: 'sortNo',
+        title: '缃插悕椤哄簭',
+        width: 110,
+        slots: { default: 'sortNo' },
+      },
+      {
+        field: 'memberType',
+        title: '鎴愬憳绫诲瀷',
+        width: 130,
+        slots: { default: 'memberType' },
+      },
       {
         field: 'name',
-        title: '濮撳悕',
-        minWidth: 110,
+        title: '鎴愬憳濮撳悕',
+        minWidth: 120,
         slots: { default: 'name' },
       },
       {
-        field: 'contactPhone',
-        title: '鑱旂郴鐢佃瘽',
-        minWidth: 140,
-        slots: { default: 'contactPhone' },
-      },
-      {
         field: 'workUnit',
-        title: '鎵�灞炲崟浣�',
-        minWidth: 180,
+        title: '鎵�灞為儴闂�',
+        minWidth: 220,
         slots: { default: 'workUnit' },
       },
       {
         field: 'jobTitle',
-        title: '鑱岀О/鑱屽姟',
-        minWidth: 120,
-        slots: { default: 'jobTitle' },
-      },
-      {
-        field: 'memberRole',
-        title: '鎴愬憳瑙掕壊',
+        title: '鑱岀О',
         minWidth: 130,
-        slots: { default: 'memberRole' },
-      },
-      {
-        field: 'sortNo',
-        title: '鎺掑簭',
-        width: 90,
-        slots: { default: 'sortNo' },
+        slots: { default: 'jobTitle' },
       },
       {
         title: '鎿嶄綔',
@@ -113,7 +106,7 @@
 async function handleAdd() {
   await gridApi.grid.insertAt(
     {
-      memberRole: '鍙備笌浜�',
+      memberType: '鏁欏笀',
       sortNo: collectMembers().length + 1,
     } as unknown as ResearchApplicationApi.ApplicationMember,
     -1,
@@ -133,7 +126,7 @@
   for (let i = 0; i < rows.length; i++) {
     const row = rows[i];
     if (!row?.name || String(row.name).trim() === '') {
-      throw new Error(`绗� ${i + 1} 琛屾垚鍛橈細璇峰~鍐欏鍚峘);
+      throw new Error(`绗� ${i + 1} 琛屾垚鍛橈細璇峰~鍐欐垚鍛樺鍚峘);
     }
     const phone = row.contactPhone ? String(row.contactPhone).trim() : '';
     if (phone !== '' && !/^1[3-9]\d{9}$/.test(phone)) {
@@ -165,49 +158,6 @@
 
 <template>
   <Grid class="w-full">
-    <template #name="{ row }">
-      <Input
-        v-model:value="row.name"
-        :disabled="disabled"
-        placeholder="璇疯緭鍏ュ鍚�"
-        @change="() => recalc()"
-      />
-    </template>
-    <template #contactPhone="{ row }">
-      <Input
-        v-model:value="row.contactPhone"
-        :disabled="disabled"
-        :maxlength="11"
-        placeholder="11 浣嶆墜鏈哄彿锛堥�夊~锛�"
-        @change="() => recalc()"
-      />
-    </template>
-    <template #workUnit="{ row }">
-      <Input
-        v-model:value="row.workUnit"
-        :disabled="disabled"
-        placeholder="璇疯緭鍏ユ墍灞炲崟浣�"
-        @change="() => recalc()"
-      />
-    </template>
-    <template #jobTitle="{ row }">
-      <Input
-        v-model:value="row.jobTitle"
-        :disabled="disabled"
-        placeholder="璇疯緭鍏ヨ亴绉�/鑱屽姟"
-        @change="() => recalc()"
-      />
-    </template>
-    <template #memberRole="{ row }">
-      <Select
-        v-model:value="row.memberRole"
-        :disabled="disabled"
-        :options="MEMBER_ROLE_OPTIONS"
-        placeholder="璇烽�夋嫨瑙掕壊"
-        allow-clear
-        @change="() => recalc()"
-      />
-    </template>
     <template #sortNo="{ row }">
       <InputNumber
         v-model:value="row.sortNo"
@@ -218,6 +168,40 @@
         @change="() => recalc()"
       />
     </template>
+    <template #memberType="{ row }">
+      <Select
+        v-model:value="row.memberType"
+        :disabled="disabled"
+        :options="MEMBER_TYPE_OPTIONS"
+        placeholder="璇烽�夋嫨鎴愬憳绫诲瀷"
+        allow-clear
+        @change="() => recalc()"
+      />
+    </template>
+    <template #name="{ row }">
+      <Input
+        v-model:value="row.name"
+        :disabled="disabled"
+        placeholder="璇疯緭鍏ユ垚鍛樺鍚�"
+        @change="() => recalc()"
+      />
+    </template>
+    <template #workUnit="{ row }">
+      <Input
+        v-model:value="row.workUnit"
+        :disabled="disabled"
+        placeholder="璇疯緭鍏ユ墍灞為儴闂�"
+        @change="() => recalc()"
+      />
+    </template>
+    <template #jobTitle="{ row }">
+      <Input
+        v-model:value="row.jobTitle"
+        :disabled="disabled"
+        placeholder="璇疯緭鍏ヨ亴绉�"
+        @change="() => recalc()"
+      />
+    </template>
     <template #actions="{ row }">
       <TableAction
         :actions="[

--
Gitblit v1.9.3