From fe2d6627b8f1002af7a31b08f6f43bec034d04ee Mon Sep 17 00:00:00 2001
From: liu <2021943741@qq.com>
Date: 星期三, 21 十月 2026 18:29:07 +0800
Subject: [PATCH] feat: 完善课题、会员、财务、企微页面并新增资产/用车/采购

---
 src/views/finance/reimbursement/modules/item-form.vue |   58 +++++++++++++++++++++++++++++++++++++++++++++++++++++-----
 1 files changed, 53 insertions(+), 5 deletions(-)

diff --git a/src/views/finance/reimbursement/modules/item-form.vue b/src/views/finance/reimbursement/modules/item-form.vue
index 3c852a4..c87f1f5 100644
--- a/src/views/finance/reimbursement/modules/item-form.vue
+++ b/src/views/finance/reimbursement/modules/item-form.vue
@@ -1,21 +1,35 @@
 <script lang="ts" setup>
 import type { VxeTableGridOptions } from '#/adapter/vxe-table';
+import type { FinanceReimbursementAiApi } from '#/api/finance/reimbursement/ai';
 import type { FinanceReimbursementApi } from '#/api/finance/reimbursement';
+import type { SystemStorageApi } from '#/api/system/storage';
 
 import type { DefaultOptionType } from 'ant-design-vue/es/select';
 
-import { nextTick, watch } from 'vue';
+import { nextTick, ref, watch } from 'vue';
 
 import { DICT_TYPE } from '@vben/constants';
 import { getDictOptions } from '@vben/hooks';
 import { erpPriceInputFormatter } from '@vben/utils';
 
-import { Button, DatePicker, Input, InputNumber, Select } from 'ant-design-vue';
+import {
+  Button,
+  DatePicker,
+  Input,
+  InputNumber,
+  Select,
+  message,
+} from 'ant-design-vue';
 
 import { ACTION_ICON, TableAction, useVbenVxeGrid } from '#/adapter/vxe-table';
 import { $t } from '#/locales';
 
-import { toSubmitItems, useItemColumns } from '../data';
+import {
+  INVOICE_TYPE_OPTIONS,
+  toSubmitItems,
+  useItemColumns,
+} from '../data';
+import OcrUpload from './ocr-upload.vue';
 
 const props = withDefaults(
   defineProps<{
@@ -28,7 +42,13 @@
   },
 );
 
-const emit = defineEmits(['update:items', 'update:totalAmount']);
+const emit = defineEmits<{
+  'ocr-blobs': [blobs: SystemStorageApi.StorageBlob[]];
+  'update:items': [items: FinanceReimbursementApi.ReimbursementItem[]];
+  'update:totalAmount': [totalAmount: number];
+}>();
+
+const ocrUploadRef = ref<InstanceType<typeof OcrUpload>>();
 
 const expenseTypeOptions = getDictOptions(
   DICT_TYPE.FINANCE_EXPENSE_TYPE,
@@ -101,6 +121,22 @@
   recalc();
 }
 
+/** OCR 璇嗗埆缁撴灉锛氳拷鍔犱负鏄庣粏琛岋紝骞舵妸鍙戠エ鏂囦欢鍚屾缁欎富琛ㄩ檮浠� */
+async function handleOcrSuccess(
+  payload: FinanceReimbursementAiApi.OcrImportPayload,
+) {
+  for (const item of payload.items) {
+    await gridApi.grid.insertAt(item, -1);
+  }
+  recalc();
+  message.success(
+    `宸插~鍏� ${payload.items.length} 鏉″彂绁ㄦ槑缁嗭紝璇疯ˉ鍏呰垂鐢ㄧ被鍨嬪悗鎻愪氦`,
+  );
+  if (payload.blobs.length > 0) {
+    emit('ocr-blobs', payload.blobs);
+  }
+}
+
 /** 鍒犻櫎鏄庣粏琛� */
 async function handleDelete(row: FinanceReimbursementApi.ReimbursementItem) {
   await gridApi.grid.remove(row);
@@ -146,6 +182,7 @@
 </script>
 
 <template>
+  <OcrUpload ref="ocrUploadRef" @success="handleOcrSuccess" />
   <Grid class="w-full">
     <template #expenseType="{ row }">
       <Select
@@ -153,6 +190,16 @@
         :disabled="disabled"
         :options="expenseTypeOptions"
         placeholder="璇烽�夋嫨璐圭敤绫诲瀷"
+        allow-clear
+        @change="() => recalc()"
+      />
+    </template>
+    <template #invoiceType="{ row }">
+      <Select
+        v-model:value="row.invoiceType"
+        :disabled="disabled"
+        :options="INVOICE_TYPE_OPTIONS"
+        placeholder="璇烽�夋嫨鍙戠エ绫诲瀷"
         allow-clear
         @change="() => recalc()"
       />
@@ -217,7 +264,8 @@
       />
     </template>
   </Grid>
-  <div v-if="!disabled" class="-mt-4 flex justify-center">
+  <div v-if="!disabled" class="-mt-4 flex justify-center gap-2">
+    <Button @click="ocrUploadRef?.open()">OCR 璇嗗埆鍙戠エ</Button>
     <Button type="primary" ghost @click="handleAdd"> 娣诲姞鎶ラ攢鏄庣粏 </Button>
   </div>
 </template>

--
Gitblit v1.9.3