From 42a1a434f77154746038c476ef70ca9be0b8e4e0 Mon Sep 17 00:00:00 2001
From: spring <2396852758@qq.com>
Date: 星期一, 19 一月 2026 18:02:46 +0800
Subject: [PATCH] fix: 完成资金管理,财务对账

---
 src/api/financialManagement/fundsManagement.js                             |   37 ++
 src/views/collaborativeApproval/rulesRegulationsManagement/index.vue       |   80 -----
 src/api/collaborativeApproval/knowledgeBase.js                             |   55 +++
 src/views/financialManagement/fundsManagement/index.vue                    |  298 ++++++++++++++++++
 src/api/collaborativeApproval/sealManagement.js                            |  116 +++++++
 src/api/financialManagement/financialReconciliation.js                     |   37 ++
 src/views/financialManagement/financialReconciliation/index.vue            |  291 ++++++++++++++++++
 src/views/inventoryManagement/stockManagement/components/FormDiaManual.vue |    2 
 8 files changed, 835 insertions(+), 81 deletions(-)

diff --git a/src/api/collaborativeApproval/knowledgeBase.js b/src/api/collaborativeApproval/knowledgeBase.js
new file mode 100644
index 0000000..b195525
--- /dev/null
+++ b/src/api/collaborativeApproval/knowledgeBase.js
@@ -0,0 +1,55 @@
+import request from "@/utils/request";
+
+// 鏌ヨ鐭ヨ瘑搴撳垪琛�
+export function listKnowledgeBase(query) {
+  return request({
+    url: "/knowledgeBase/getList",
+    method: "get",
+    params: query,
+  });
+}
+
+// 鏌ヨ鐭ヨ瘑搴撹缁�
+// export function getKnowledgeBase(knowledgeBaseId) {
+//   return request({
+//     url: "/collaborativeApproval/knowledgeBase/" + knowledgeBaseId,
+//     method: "get",
+//   });
+// }
+
+// 鏂板鐭ヨ瘑搴�
+export function addKnowledgeBase(data) {
+  return request({
+    url: "/knowledgeBase/add",
+    method: "post",
+    data: data,
+  });
+}
+
+// 淇敼鐭ヨ瘑搴�
+export function updateKnowledgeBase(data) {
+  return request({
+    url: "/knowledgeBase/update",
+    method: "post",
+    data: data,
+  });
+}
+
+// 鍒犻櫎鐭ヨ瘑搴�
+export function delKnowledgeBase(query) {
+  return request({
+    url: "/knowledgeBase/delete",
+    method: "delete",
+    data: query,
+  });
+}
+
+// 鎵归噺鍒犻櫎鐭ヨ瘑搴�
+export function delKnowledgeBaseBatch(knowledgeBaseIds) {
+  return request({
+    url: "/knowledgeBase/batch",
+    method: "delete",
+    data: knowledgeBaseIds,
+  });
+}
+
diff --git a/src/api/collaborativeApproval/sealManagement.js b/src/api/collaborativeApproval/sealManagement.js
new file mode 100644
index 0000000..cb990b3
--- /dev/null
+++ b/src/api/collaborativeApproval/sealManagement.js
@@ -0,0 +1,116 @@
+import request from "@/utils/request";
+
+// 鏌ヨ鍗扮珷鐢宠鍒楄〃
+export function listSealApplication(page,query) {
+  return request({
+    url: "/sealApplicationManagement/getList",
+    method: "get",
+    params: {
+      ...page,
+      ...query},
+  });
+}
+// 鏌ヨ瑙勭珷鍒跺害鍒楄〃
+export function listRuleManagement(page,query) {
+  return request({
+    url: "/rulesRegulationsManagement/getList",
+    method: "get",
+    params: {
+      ...page,
+      ...query},
+  });
+}
+// 鏌ヨ闃呰鐘舵�佸垪琛�
+export function getReadingStatusList(page,query) {
+  return request({
+    url: "/rulesRegulationsManagement/getReadingStatusList",
+    method: "get",
+    params: {
+      ...page,
+      ...query},
+  });
+}
+// 鏍规嵁瑙勫垯id鏌ヨ闃呰鐘舵�佸垪琛�
+export function getReadingStatusByRuleId(id) {
+  return request({
+    url: "/rulesRegulationsManagement/getReadingStatusByRuleId/"+id,
+    method: "get"
+  });
+}
+
+// 鏂板鍗扮珷鐢宠
+export function addSealApplication(data) {
+  return request({
+    url: "/sealApplicationManagement/add",
+    method: "post",
+    data: data,
+  });
+}
+// 鏂板瑙勭珷鍒跺害
+export function addRuleManagement(data) {
+  return request({
+    url: "/rulesRegulationsManagement/add",
+    method: "post",
+    data: data,
+  });
+}
+// 鏂板闃呰鐘舵��
+export function addReadingStatus(data) {
+  return request({
+    url: "/rulesRegulationsManagement/addReadingStatus",
+    method: "post",
+    data: data,
+  });
+}
+
+// 淇敼鍗扮珷鐢宠
+export function updateSealApplication(data) {
+  return request({
+    url: "/sealApplicationManagement/update",
+    method: "post",
+    data: data,
+  });
+}
+// 淇敼瑙勭珷鍒跺害
+export function updateRuleManagement(data) {
+  return request({
+    url: "/rulesRegulationsManagement/update",
+    method: "post",
+    data: data,
+  });
+}
+// 淇敼闃呰鐘舵��
+export function updateReadingStatus(data) {
+  return request({
+    url: "/rulesRegulationsManagement/updateReadingStatus",
+    method: "post",
+    data: data,
+  });
+}
+
+// 鍒犻櫎鍗扮珷鐢宠
+export function delSealApplication(query) {
+  return request({
+    url: "/sealApplicationManagement/delete",
+    method: "delete",
+    data: query,
+  });
+}
+// 鍒犻櫎瑙勭珷鍒跺害
+export function delRuleManagement(query) {
+  return request({
+    url: "/rulesRegulationsManagement/delete",
+    method: "delete",
+    data: query,
+  });
+}
+
+// 鎵归噺鍒犻櫎鐭ヨ瘑搴�
+export function delKnowledgeBaseBatch(knowledgeBaseIds) {
+  return request({
+    url: "/knowledgeBase/batch",
+    method: "delete",
+    data: knowledgeBaseIds,
+  });
+}
+
diff --git a/src/api/financialManagement/financialReconciliation.js b/src/api/financialManagement/financialReconciliation.js
new file mode 100644
index 0000000..d2c08d1
--- /dev/null
+++ b/src/api/financialManagement/financialReconciliation.js
@@ -0,0 +1,37 @@
+import request from "@/utils/request";
+
+// 鍒嗛〉鏌ヨ璐㈠姟瀵硅处鍙拌处
+export const getReconciliationPage = (params) => {
+  return request({
+    url: "/finance/reconciliation/page",
+    method: "get",
+    params,
+  });
+};
+
+// 鏂板瀵硅处璁板綍
+export const addReconciliation = (data) => {
+  return request({
+    url: "/finance/reconciliation",
+    method: "post",
+    data,
+  });
+};
+
+// 鏇存柊瀵硅处璁板綍
+export const updateReconciliation = (data) => {
+  return request({
+    url: "/finance/reconciliation",
+    method: "put",
+    data,
+  });
+};
+
+// 鍒犻櫎瀵硅处璁板綍锛堟敮鎸佹壒閲忥級
+export const deleteReconciliation = (ids) => {
+  return request({
+    url: "/finance/reconciliation",
+    method: "delete",
+    data: ids,
+  });
+};
diff --git a/src/api/financialManagement/fundsManagement.js b/src/api/financialManagement/fundsManagement.js
new file mode 100644
index 0000000..a970638
--- /dev/null
+++ b/src/api/financialManagement/fundsManagement.js
@@ -0,0 +1,37 @@
+import request from "@/utils/request";
+
+// 鍒嗛〉鏌ヨ璧勯噾绠$悊鍙拌处
+export const getFundsPage = (params) => {
+  return request({
+    url: "/finance/funds/page",
+    method: "get",
+    params,
+  });
+};
+
+// 鏂板璧勯噾璁板綍
+export const addFunds = (data) => {
+  return request({
+    url: "/finance/funds",
+    method: "post",
+    data,
+  });
+};
+
+// 鏇存柊璧勯噾璁板綍
+export const updateFunds = (data) => {
+  return request({
+    url: "/finance/funds",
+    method: "put",
+    data,
+  });
+};
+
+// 鍒犻櫎璧勯噾璁板綍锛堟敮鎸佹壒閲忥級
+export const deleteFunds = (ids) => {
+  return request({
+    url: "/finance/funds",
+    method: "delete",
+    data: ids,
+  });
+};
diff --git a/src/views/collaborativeApproval/rulesRegulationsManagement/index.vue b/src/views/collaborativeApproval/rulesRegulationsManagement/index.vue
index 91a6468..b0f8a90 100644
--- a/src/views/collaborativeApproval/rulesRegulationsManagement/index.vue
+++ b/src/views/collaborativeApproval/rulesRegulationsManagement/index.vue
@@ -59,7 +59,6 @@
                     <el-button link type="danger" @click="repealEdit(scope.row)">搴熷純</el-button>
                     <el-button link type="success" @click="viewVersionHistory(scope.row)">鐗堟湰鍘嗗彶</el-button>
                     <el-button link type="warning" @click="viewReadStatus(scope.row)">闃呰鐘舵��</el-button>
-                    <el-button link type="primary" @click="openFileDialog(scope.row)">闄勪欢</el-button>
                   </template>
                 </el-table-column>
               </el-table>
@@ -174,16 +173,6 @@
       </el-table>
     </el-dialog>
 
-    <FileListDialog
-      ref="fileListDialogRef"
-      v-model="fileDialogVisible"
-      :show-upload-button="true"
-      :show-delete-button="true"
-      :delete-method="handleAttachmentDelete"
-      :rules-regulations-management-id="currentFileRuleId"
-      :name-column-label="'闄勪欢鍚嶇О'"
-      @upload="handleAttachmentUpload"
-    />
   </div>
 </template>
 
@@ -191,8 +180,6 @@
 import { ref, reactive, onMounted, getCurrentInstance } from 'vue'
 import { ElMessage, ElMessageBox } from 'element-plus'
 import { listRuleManagement,addRuleManagement,updateRuleManagement,delRuleManagement,getReadingStatusByRuleId,addReadingStatus,updateReadingStatus  } from '@/api/collaborativeApproval/sealManagement.js'
-import FileListDialog from '@/components/Dialog/FileListDialog.vue'
-import { listRuleFiles, delRuleFile, addRuleFile } from '@/api/collaborativeApproval/rulesRegulationsManagementFile.js'
 
 // 鍝嶅簲寮忔暟鎹�
 const operationType = ref('add')
@@ -200,15 +187,6 @@
 const tableLoading = ref(false)
 // 鍒嗛〉鍙傛暟
 const page = reactive({
-  current: 1,
-  size: 10,
-  total: 0
-})
-// 闄勪欢寮圭獥
-const fileDialogVisible = ref(false)
-const fileListDialogRef = ref(null)
-const currentFileRuleId = ref(null)
-const filePage = reactive({
   current: 1,
   size: 10,
   total: 0
@@ -457,64 +435,6 @@
 const { proxy } = getCurrentInstance()
 const handleExport = () => {
   proxy.download('/rulesRegulationsManagement/export', { ...regulationSearchForm }, '瑙勭珷鍒跺害.xlsx')
-}
-
-// 闄勪欢锛氭煡璇�
-const fetchRuleFiles = async (rulesRegulationsManagementId) => {
-  const params = {
-    current: filePage.current,
-    size: filePage.size,
-    rulesRegulationsManagementId
-  }
-  const res = await listRuleFiles(params)
-  const records = res?.data?.records || []
-  filePage.total = res?.data?.total || records.length
-  const mapped = records.map(item => ({
-    id: item.id,
-    name: item.fileName || item.name,
-    url: item.fileUrl || item.url,
-    raw: item
-  }))
-  fileListDialogRef.value?.setList(mapped)
-}
-
-// 鎵撳紑闄勪欢寮圭獥
-const openFileDialog = async (row) => {
-  currentFileRuleId.value = row.id
-  fileDialogVisible.value = true
-  await fetchRuleFiles(row.id)
-}
-
-// 鍒锋柊闄勪欢鍒楄〃
-const refreshFileList = async () => {
-  if (!currentFileRuleId.value) return
-  await fetchRuleFiles(currentFileRuleId.value)
-}
-
-// 涓婁紶闄勪欢锛堢敱瀛愮粍浠惰Е鍙戯級
-const handleAttachmentUpload = async (filePayload) => {
-  if (!currentFileRuleId.value) return
-  const payload = {
-    name: filePayload?.fileName || filePayload?.name,
-    url: filePayload?.fileUrl || filePayload?.url,
-    rulesRegulationsManagementId: currentFileRuleId.value
-  }
-  await addRuleFile(payload)
-  ElMessage.success('鏂囦欢涓婁紶鎴愬姛')
-  await refreshFileList()
-}
-
-// 鍒犻櫎闄勪欢
-const handleAttachmentDelete = async (row) => {
-  if (!row?.id) return false
-  try {
-    await ElMessageBox.confirm('纭鍒犻櫎璇ラ檮浠讹紵', '鎻愮ず', { type: 'warning' })
-  } catch {
-    return false
-  }
-  await delRuleFile([row.id])
-  ElMessage.success('鍒犻櫎鎴愬姛')
-  await refreshFileList()
 }
 
 // 鑾峰彇瑙勭珷鍒跺害鍒楄〃鏁版嵁
diff --git a/src/views/financialManagement/financialReconciliation/index.vue b/src/views/financialManagement/financialReconciliation/index.vue
new file mode 100644
index 0000000..fa4db0a
--- /dev/null
+++ b/src/views/financialManagement/financialReconciliation/index.vue
@@ -0,0 +1,291 @@
+<template>
+  <div class="app-container">
+    <!-- 鎼滅储鍖� -->
+    <div class="search_form">
+      <el-form :inline="true" :model="searchForm">
+        <el-form-item label="寰�鏉ュ崟浣嶏細">
+          <el-input v-model="searchForm.counterparty" placeholder="璇疯緭鍏ュ線鏉ュ崟浣�" clearable style="width: 180px" />
+        </el-form-item>
+        <el-form-item label="瀵硅处鐘舵�侊細">
+          <el-select v-model="searchForm.status" placeholder="璇烽�夋嫨" clearable style="width: 150px">
+            <el-option label="鏈璐�" value="pending" />
+            <el-option label="瀵硅处涓�" value="processing" />
+            <el-option label="宸插畬鎴�" value="done" />
+          </el-select>
+        </el-form-item>
+        <!-- <el-form-item label="鏃ユ湡锛�">
+          <el-date-picker
+            v-model="searchForm.dateRange"
+            type="daterange"
+            range-separator="鑷�"
+            start-placeholder="寮�濮嬫棩鏈�"
+            end-placeholder="缁撴潫鏃ユ湡"
+            value-format="YYYY-MM-DD"
+            format="YYYY-MM-DD"
+            clearable
+          />
+        </el-form-item> -->
+        <el-form-item>
+          <el-button type="primary" @click="handleQuery">鎼滅储</el-button>
+          <el-button @click="resetQuery">閲嶇疆</el-button>
+        </el-form-item>
+      </el-form>
+    </div>
+
+    <!-- 鎿嶄綔鍖� -->
+    <div class="actions">
+      <el-button type="primary" @click="openDialog('add')">鏂板</el-button>
+      <el-button type="danger" plain @click="handleDelete">鍒犻櫎</el-button>
+    </div>
+
+    <!-- 琛ㄦ牸 -->
+    <el-table
+      :data="tableData"
+      border
+      v-loading="tableLoading"
+      @selection-change="handleSelectionChange"
+      style="width: 100%"
+      height="calc(100vh - 280px)"
+      :row-key="row => row.id"
+    >
+      <el-table-column type="selection" width="55" align="center" />
+      <el-table-column type="index" label="搴忓彿" width="60" align="center" />
+      <el-table-column prop="accountDate" label="瀵硅处鏃ユ湡" width="130" show-overflow-tooltip />
+      <el-table-column prop="counterparty" label="寰�鏉ュ崟浣�" width="180" show-overflow-tooltip />
+      <el-table-column prop="amount" label="瀵硅处閲戦(鍏�)" width="140" show-overflow-tooltip />
+      <el-table-column prop="statusText" label="鐘舵��" width="120" show-overflow-tooltip />
+      <el-table-column prop="remark" label="澶囨敞" show-overflow-tooltip />
+      <el-table-column fixed="right" label="鎿嶄綔" width="150" align="center">
+        <template #default="scope">
+          <el-button link type="primary" size="small" @click="openDialog('edit', scope.row)">缂栬緫</el-button>
+        </template>
+      </el-table-column>
+    </el-table>
+
+    <pagination
+      v-show="total > 0"
+      :total="total"
+      layout="total, sizes, prev, pager, next, jumper"
+      :page="page.current"
+      :limit="page.size"
+      @pagination="paginationChange"
+    />
+
+    <!-- 寮圭獥 -->
+    <el-dialog v-model="dialogVisible" :title="dialogTitle" width="520px" @close="resetForm">
+      <el-form :model="form" :rules="rules" ref="formRef" label-width="120px">
+        <el-form-item label="瀵硅处鏃ユ湡锛�" prop="accountDate">
+          <el-date-picker v-model="form.accountDate" type="date" value-format="YYYY-MM-DD" format="YYYY-MM-DD" style="width: 100%" />
+        </el-form-item>
+        <el-form-item label="寰�鏉ュ崟浣嶏細" prop="counterparty">
+          <el-input v-model="form.counterparty" placeholder="璇疯緭鍏ュ線鏉ュ崟浣�" />
+        </el-form-item>
+        <el-form-item label="瀵硅处閲戦(鍏�)锛�" prop="amount">
+          <el-input-number v-model="form.amount" :min="0" :precision="2" :step="100" style="width: 100%" />
+        </el-form-item>
+        <el-form-item label="鐘舵�侊細" prop="status">
+          <el-select v-model="form.status" placeholder="璇烽�夋嫨" style="width: 100%">
+            <el-option label="鏈璐�" value="pending" />
+            <el-option label="瀵硅处涓�" value="processing" />
+            <el-option label="宸插畬鎴�" value="done" />
+          </el-select>
+        </el-form-item>
+        <el-form-item label="澶囨敞锛�">
+          <el-input v-model="form.remark" type="textarea" :rows="3" placeholder="璇疯緭鍏ュ娉�" />
+        </el-form-item>
+      </el-form>
+      <template #footer>
+        <div class="dialog-footer">
+          <el-button @click="dialogVisible = false">鍙栨秷</el-button>
+          <el-button type="primary" @click="submitForm">纭</el-button>
+        </div>
+      </template>
+    </el-dialog>
+  </div>
+</template>
+
+<script setup>
+import { ref, reactive, onMounted } from 'vue'
+import { ElMessage, ElMessageBox } from 'element-plus'
+import pagination from '@/components/PIMTable/Pagination.vue'
+import {
+  getReconciliationPage,
+  addReconciliation,
+  updateReconciliation,
+  deleteReconciliation
+} from '@/api/financialManagement/financialReconciliation.js'
+
+const tableData = ref([])
+const tableLoading = ref(false)
+const selectedRows = ref([])
+const dialogVisible = ref(false)
+const dialogTitle = ref('鏂板')
+const formRef = ref(null)
+
+const page = reactive({
+  current: 1,
+  size: 100
+})
+const total = ref(0)
+
+const searchForm = reactive({
+  counterparty: '',
+  status: '',
+  dateRange: []
+})
+
+const form = reactive({
+  id: null,
+  accountDate: '',
+  counterparty: '',
+  amount: null,
+  status: '',
+  remark: ''
+})
+
+const rules = {
+  accountDate: [{ required: true, message: '璇烽�夋嫨瀵硅处鏃ユ湡', trigger: 'change' }],
+  counterparty: [{ required: true, message: '璇疯緭鍏ュ線鏉ュ崟浣�', trigger: 'blur' }],
+  amount: [{ required: true, message: '璇疯緭鍏ュ璐﹂噾棰�', trigger: 'blur' }],
+  status: [{ required: true, message: '璇烽�夋嫨鐘舵��', trigger: 'change' }]
+}
+
+const statusTextMap = {
+  pending: '鏈璐�',
+  processing: '瀵硅处涓�',
+  done: '宸插畬鎴�'
+}
+
+// 鑾峰彇鍒楄〃
+const getList = () => {
+  tableLoading.value = true
+  const params = {
+    ...searchForm,
+    current: page.current,
+    size: page.size
+  }
+  if (params.dateRange && params.dateRange.length === 2) {
+    params.beginDate = params.dateRange[0]
+    params.endDate = params.dateRange[1]
+  }
+  delete params.dateRange
+
+  getReconciliationPage(params)
+    .then(res => {
+      if (res.code === 200) {
+        tableData.value = (res.data?.records || []).map(item => ({
+          ...item,
+          statusText: statusTextMap[item.status] || item.status
+        }))
+        total.value = res.data?.total || 0
+      }
+    })
+    .finally(() => {
+      tableLoading.value = false
+    })
+}
+
+const handleQuery = () => {
+  page.current = 1
+  getList()
+}
+const resetQuery = () => {
+  searchForm.counterparty = ''
+  searchForm.status = ''
+  searchForm.dateRange = []
+  handleQuery()
+}
+const paginationChange = (obj) => {
+  page.current = obj.page
+  page.size = obj.limit
+  getList()
+}
+
+const handleSelectionChange = (rows) => {
+  selectedRows.value = rows
+}
+
+const openDialog = (type, row) => {
+  dialogTitle.value = type === 'add' ? '鏂板瀵硅处璁板綍' : '缂栬緫瀵硅处璁板綍'
+  if (type === 'edit' && row) {
+    Object.assign(form, row)
+  } else {
+    resetForm()
+  }
+  dialogVisible.value = true
+}
+
+const resetForm = () => {
+  Object.assign(form, {
+    id: null,
+    date: '',
+    counterparty: '',
+    amount: null,
+    status: '',
+    remark: ''
+  })
+}
+
+const submitForm = () => {
+  formRef.value?.validate(valid => {
+    if (!valid) return
+    const payload = { ...form }
+    const request = payload.id ? updateReconciliation(payload) : addReconciliation(payload)
+    request
+      .then(res => {
+        if (res.code === 200) {
+          ElMessage.success('鎻愪氦鎴愬姛')
+          dialogVisible.value = false
+          getList()
+        }
+      })
+      .catch(err => {
+        ElMessage.error(err.msg || '鎻愪氦澶辫触')
+      })
+  })
+}
+
+const handleDelete = () => {
+  if (!selectedRows.value.length) {
+    ElMessage.warning('璇烽�夋嫨瑕佸垹闄ょ殑璁板綍')
+    return
+  }
+  ElMessageBox.confirm('纭鍒犻櫎閫変腑璁板綍鍚楋紵', '鎻愮ず', {
+    confirmButtonText: '纭',
+    cancelButtonText: '鍙栨秷',
+    type: 'warning'
+  }).then(() => {
+    const ids = selectedRows.value.map(r => r.id)
+    deleteReconciliation(ids).then(res => {
+      if (res.code === 200) {
+        ElMessage.success('鍒犻櫎鎴愬姛')
+        getList()
+        selectedRows.value = []
+      }
+    }).catch(err => {
+      ElMessage.error(err.msg || '鍒犻櫎澶辫触')
+    })
+  }).catch(() => {})
+}
+
+onMounted(() => {
+  getList()
+})
+</script>
+
+<style scoped lang="scss">
+.app-container {
+  padding: 20px;
+
+  .search_form {
+    background: #fff;
+    padding: 16px;
+    border-radius: 6px;
+    margin-bottom: 16px;
+  }
+
+  .actions {
+    margin-bottom: 12px;
+  }
+}
+</style>
diff --git a/src/views/financialManagement/fundsManagement/index.vue b/src/views/financialManagement/fundsManagement/index.vue
new file mode 100644
index 0000000..845dc52
--- /dev/null
+++ b/src/views/financialManagement/fundsManagement/index.vue
@@ -0,0 +1,298 @@
+<template>
+  <div class="app-container">
+    <!-- 鎼滅储鍖� -->
+    <div class="search_form">
+      <el-form :inline="true" :model="searchForm">
+        <el-form-item label="璧勯噾绫诲瀷锛�">
+          <el-select v-model="searchForm.typeText" placeholder="璇烽�夋嫨" clearable style="width: 150px">
+            <el-option label="鏀跺叆" value="鏀跺叆" />
+            <el-option label="鏀嚭" value="鏀嚭" />
+            <el-option label="鍐呴儴杞处" value="鍐呴儴杞处" />
+          </el-select>
+        </el-form-item>
+        <el-form-item label="璐︽埛锛�">
+          <el-input v-model="searchForm.account" placeholder="璇疯緭鍏ヨ处鎴�" clearable style="width: 160px" />
+        </el-form-item>
+        <!-- <el-form-item label="鏃ユ湡锛�">
+          <el-date-picker
+            v-model="searchForm.dateRange"
+            type="daterange"
+            range-separator="鑷�"
+            start-placeholder="寮�濮嬫棩鏈�"
+            end-placeholder="缁撴潫鏃ユ湡"
+            value-format="YYYY-MM-DD"
+            format="YYYY-MM-DD"
+            clearable
+          />
+        </el-form-item> -->
+        <el-form-item>
+          <el-button type="primary" @click="handleQuery">鎼滅储</el-button>
+          <el-button @click="resetQuery">閲嶇疆</el-button>
+        </el-form-item>
+      </el-form>
+    </div>
+
+    <!-- 鎿嶄綔鍖� -->
+    <div class="actions">
+      <el-button type="primary" @click="openDialog('add')">鏂板</el-button>
+      <el-button type="danger" plain @click="handleDelete">鍒犻櫎</el-button>
+    </div>
+
+    <!-- 琛ㄦ牸 -->
+    <el-table
+      :data="tableData"
+      border
+      v-loading="tableLoading"
+      @selection-change="handleSelectionChange"
+      style="width: 100%"
+      height="calc(100vh - 280px)"
+      :row-key="row => row.id"
+    >
+      <el-table-column type="selection" width="55" align="center" />
+      <el-table-column type="index" label="搴忓彿" width="60" align="center" />
+      <el-table-column prop="accountDate" label="鏃ユ湡" width="130" show-overflow-tooltip />
+      <el-table-column prop="typeText" label="璧勯噾绫诲瀷" width="120" show-overflow-tooltip />
+      <el-table-column prop="amount" label="閲戦(鍏�)" width="120" show-overflow-tooltip />
+      <el-table-column prop="account" label="璐︽埛" width="160" show-overflow-tooltip />
+      <el-table-column prop="counterparty" label="寰�鏉ュ崟浣�" width="180" show-overflow-tooltip />
+      <el-table-column prop="remark" label="澶囨敞" show-overflow-tooltip />
+      <el-table-column fixed="right" label="鎿嶄綔" width="150" align="center">
+        <template #default="scope">
+          <el-button link type="primary" size="small" @click="openDialog('edit', scope.row)">缂栬緫</el-button>
+        </template>
+      </el-table-column>
+    </el-table>
+
+    <pagination
+      v-show="total > 0"
+      :total="total"
+      layout="total, sizes, prev, pager, next, jumper"
+      :page="page.current"
+      :limit="page.size"
+      @pagination="paginationChange"
+    />
+
+    <!-- 寮圭獥 -->
+    <el-dialog v-model="dialogVisible" :title="dialogTitle" width="520px" @close="resetForm">
+      <el-form :model="form" :rules="rules" ref="formRef" label-width="120px">
+        <el-form-item label="鏃ユ湡锛�" prop="accountDate">
+          <el-date-picker v-model="form.accountDate" type="date" value-format="YYYY-MM-DD" format="YYYY-MM-DD" style="width: 100%" />
+        </el-form-item>
+        <el-form-item label="璧勯噾绫诲瀷锛�" prop="typeText">
+          <el-select v-model="form.typeText" placeholder="璇烽�夋嫨" style="width: 100%">
+            <el-option label="鏀跺叆" value="鏀跺叆" />
+            <el-option label="鏀嚭" value="鏀嚭" />
+            <el-option label="鍐呴儴杞处" value="鍐呴儴杞处" />
+          </el-select>
+        </el-form-item>
+        <el-form-item label="閲戦(鍏�)锛�" prop="amount">
+          <el-input-number v-model="form.amount" :min="0" :precision="2" :step="100" style="width: 100%" />
+        </el-form-item>
+        <el-form-item label="璐︽埛锛�" prop="account">
+          <el-input v-model="form.account" placeholder="璇疯緭鍏ヨ处鎴�" />
+        </el-form-item>
+        <el-form-item label="寰�鏉ュ崟浣嶏細" prop="counterparty">
+          <el-input v-model="form.counterparty" placeholder="璇疯緭鍏ュ線鏉ュ崟浣�" />
+        </el-form-item>
+        <el-form-item label="澶囨敞锛�">
+          <el-input v-model="form.remark" type="textarea" :rows="3" placeholder="璇疯緭鍏ュ娉�" />
+        </el-form-item>
+      </el-form>
+      <template #footer>
+        <div class="dialog-footer">
+          <el-button @click="dialogVisible = false">鍙栨秷</el-button>
+          <el-button type="primary" @click="submitForm">纭</el-button>
+        </div>
+      </template>
+    </el-dialog>
+  </div>
+</template>
+
+<script setup>
+import { ref, reactive, onMounted } from 'vue'
+import { ElMessage, ElMessageBox } from 'element-plus'
+import pagination from '@/components/PIMTable/Pagination.vue'
+import {
+  getFundsPage,
+  addFunds,
+  updateFunds,
+  deleteFunds
+} from '@/api/financialManagement/fundsManagement.js'
+
+const tableData = ref([])
+const tableLoading = ref(false)
+const selectedRows = ref([])
+const dialogVisible = ref(false)
+const dialogTitle = ref('鏂板')
+const formRef = ref(null)
+
+const page = reactive({
+  current: 1,
+  size: 100
+})
+const total = ref(0)
+
+const searchForm = reactive({
+  typeText: '',
+  account: '',
+  dateRange: []
+})
+
+const form = reactive({
+  id: null,
+  accountDate: '',
+  typeText: '',
+  amount: null,
+  account: '',
+  counterparty: '',
+  remark: ''
+})
+
+const rules = {
+  accountDate: [{ required: true, message: '璇烽�夋嫨鏃ユ湡', trigger: 'change' }],
+  typeText: [{ required: true, message: '璇烽�夋嫨璧勯噾绫诲瀷', trigger: 'change' }],
+  amount: [{ required: true, message: '璇疯緭鍏ラ噾棰�', trigger: 'blur' }],
+  account: [{ required: true, message: '璇疯緭鍏ヨ处鎴�', trigger: 'blur' }]
+}
+
+const typeTextMap = {
+  income: '鏀跺叆',
+  expense: '鏀嚭',
+  transfer: '鍐呴儴杞处'
+}
+
+// 鑾峰彇鍒楄〃
+const getList = () => {
+  tableLoading.value = true
+  const params = {
+    ...searchForm,
+    current: page.current,
+    size: page.size
+  }
+  // 鍏煎鍚庣瀛楁锛氳嫢鍚庣浣跨敤 typeText锛岃鐩存帴浼犻�掞紱鑻ヤ娇鐢� type锛岃涓庡悗绔榻�
+  if (params.dateRange && params.dateRange.length === 2) {
+    params.beginDate = params.dateRange[0]
+    params.endDate = params.dateRange[1]
+  }
+  delete params.dateRange
+
+  getFundsPage(params)
+    .then(res => {
+      if (res.code === 200) {
+        tableData.value = (res.data?.records || []).map(item => ({
+          ...item,
+          typeText: item.typeText || typeTextMap[item.typeText] || item.typeText
+        }))
+        total.value = res.data?.total || 0
+      }
+    })
+    .finally(() => {
+      tableLoading.value = false
+    })
+}
+
+const handleQuery = () => {
+  page.current = 1
+  getList()
+}
+const resetQuery = () => {
+  searchForm.typeText = ''
+  searchForm.account = ''
+  searchForm.dateRange = []
+  handleQuery()
+}
+const paginationChange = (obj) => {
+  page.current = obj.page
+  page.size = obj.limit
+  getList()
+}
+
+const handleSelectionChange = (rows) => {
+  selectedRows.value = rows
+}
+
+const openDialog = (type, row) => {
+  dialogTitle.value = type === 'add' ? '鏂板璧勯噾璁板綍' : '缂栬緫璧勯噾璁板綍'
+  if (type === 'edit' && row) {
+    Object.assign(form, row)
+  } else {
+    resetForm()
+  }
+  dialogVisible.value = true
+}
+
+const resetForm = () => {
+  Object.assign(form, {
+    id: null,
+    accountDate: '',
+    typeText: '',
+    amount: null,
+    account: '',
+    counterparty: '',
+    remark: ''
+  })
+}
+
+const submitForm = () => {
+  formRef.value?.validate(valid => {
+    if (!valid) return
+    const payload = { ...form }
+    const request = payload.id ? updateFunds(payload) : addFunds(payload)
+    request
+      .then(res => {
+        if (res.code === 200) {
+          ElMessage.success('鎻愪氦鎴愬姛')
+          dialogVisible.value = false
+          getList()
+        }
+      })
+      .catch(err => {
+        ElMessage.error(err.msg || '鎻愪氦澶辫触')
+      })
+  })
+}
+
+const handleDelete = () => {
+  if (!selectedRows.value.length) {
+    ElMessage.warning('璇烽�夋嫨瑕佸垹闄ょ殑璁板綍')
+    return
+  }
+  ElMessageBox.confirm('纭鍒犻櫎閫変腑璁板綍鍚楋紵', '鎻愮ず', {
+    confirmButtonText: '纭',
+    cancelButtonText: '鍙栨秷',
+    type: 'warning'
+  }).then(() => {
+    const ids = selectedRows.value.map(r => r.id)
+    deleteFunds(ids).then(res => {
+      if (res.code === 200) {
+        ElMessage.success('鍒犻櫎鎴愬姛')
+        getList()
+        selectedRows.value = []
+      }
+    }).catch(err => {
+      ElMessage.error(err.msg || '鍒犻櫎澶辫触')
+    })
+  }).catch(() => {})
+}
+
+onMounted(() => {
+  getList()
+})
+</script>
+
+<style scoped lang="scss">
+.app-container {
+  padding: 20px;
+
+  .search_form {
+    background: #fff;
+    padding: 16px;
+    border-radius: 6px;
+    margin-bottom: 16px;
+  }
+
+  .actions {
+    margin-bottom: 12px;
+  }
+}
+</style>
diff --git a/src/views/inventoryManagement/stockManagement/components/FormDiaManual.vue b/src/views/inventoryManagement/stockManagement/components/FormDiaManual.vue
index 818fd0d..fcbfd77 100644
--- a/src/views/inventoryManagement/stockManagement/components/FormDiaManual.vue
+++ b/src/views/inventoryManagement/stockManagement/components/FormDiaManual.vue
@@ -42,7 +42,7 @@
       <el-row :gutter="30">
         <el-col :span="12">
           <el-form-item label="棰勮鍊硷細" prop="warnNum">
-            <el-input v-model="form.warnNum" placeholder="璇疯緭鍏ラ璀﹀��" clearable />
+            <el-input-number v-model="form.warnNum" placeholder="璇疯緭鍏ラ璀﹀��" clearable min="0" />
           </el-form-item>
         </el-col>
       </el-row>

--
Gitblit v1.9.3