From 451c79860be3a1fca7270309831dc9c567a26b27 Mon Sep 17 00:00:00 2001
From: yyb <995253665@qq.com>
Date: 星期二, 19 八月 2025 09:13:09 +0800
Subject: [PATCH] 审批管理/审批流程

---
 src/pages/index.vue                                          |   10 
 src/pages.json                                               |   23 +
 src/pages/cooperativeOffice/collaborativeApproval/index.vue  |  390 ++++++++++++++++++++
 src/api/cooperativeOffice/collaborativeApproval.js           |  111 +++++
 src/pages/cooperativeOffice/collaborativeApproval/detail.vue |  535 ++++++++++++++++++++++++++++
 src/pages/cooperativeOffice/clientVisit/index.vue            |   51 ++
 6 files changed, 1,120 insertions(+), 0 deletions(-)

diff --git a/src/api/cooperativeOffice/collaborativeApproval.js b/src/api/cooperativeOffice/collaborativeApproval.js
new file mode 100644
index 0000000..3a2fa22
--- /dev/null
+++ b/src/api/cooperativeOffice/collaborativeApproval.js
@@ -0,0 +1,111 @@
+// 閿�鍞彴璐﹂〉闈㈡帴鍙�
+import request from "@/utils/request";
+
+// 鍒嗛〉鏌ヨ
+export function ledgerList(query) {
+  return request({
+    url: "/sales/ledger/list",
+    method: "get",
+    params: query,
+  });
+}
+// 瀛愯〃鏍兼煡璇�
+export function productList(query) {
+  return request({
+    url: "/sales/product/list",
+    method: "get",
+    params: query,
+  });
+}
+// 鏌ヨ瀹㈡埛鍚嶇О鍒楄〃
+export function customerList(query) {
+  return request({
+    url: "/basic/customer/customerList",
+    method: "get",
+    params: query,
+  });
+}
+// 鏂板銆佷慨鏀归攢鍞彴璐�
+export function addOrUpdateSalesLedger(query) {
+  return request({
+    url: "/sales/ledger/addOrUpdateSalesLedger",
+    method: "post",
+    data: query,
+  });
+}
+// 鍒犻櫎閿�鍞彴璐�
+export function delLedger(query) {
+  return request({
+    url: "/sales/ledger/delLedger",
+    method: "delete",
+    data: query,
+  });
+}
+// 鏌ヨ閿�鍞彴璐﹁鎯�
+export function getSalesLedgerWithProducts(query) {
+  return request({
+    url: "/sales/ledger/getSalesLedgerWithProducts",
+    method: "get",
+    params: query,
+  });
+}
+// 瀹炴椂淇敼浜у搧淇℃伅
+export function addOrUpdateSalesLedgerProduct(query) {
+  return request({
+    url: "/sales/product/addOrUpdateSalesLedgerProduct",
+    method: "post",
+    data: query,
+  });
+}
+// 鍒犻櫎浜у搧
+export function delProduct(query) {
+  return request({
+    url: "/sales/product/delProduct",
+    method: "delete",
+    data: query,
+  });
+}
+// 涓婁紶闄勪欢
+export function upload(query) {
+  return request({
+    url: "/file/upload",
+    method: "post",
+    data: query,
+    responseType: "blob",
+  });
+}
+// 缂栬緫鏃跺垹闄ら檮浠�
+export function delLedgerFile(query) {
+  return request({
+    url: "/sales/ledger/delLedgerFile",
+    method: "delete",
+    data: query,
+  });
+}
+
+// 閿�鍞笉鍒嗛〉鏌ヨ
+export function ledgerListNoPage(query) {
+  return request({
+    url: "/sales/ledger/listNoPage",
+    method: "get",
+    params: query,
+  });
+}
+
+// 鍒嗛〉鏌ヨ
+export function ledgerListPage(query) {
+  return request({
+    url: "/sales/ledger/listPage",
+    method: "get",
+    params: query,
+  });
+}
+
+// 鏍规嵁閿�鍞悎鍚屽彿鏌ヤ骇鍝佷俊鎭�
+export function getProductInfoByContractNo(query) {
+  return request({
+    url: "/purchase/ledger/getProductBySalesNo",
+    method: "get",
+    params: query,
+  });
+}
diff --git a/src/pages.json b/src/pages.json
index ef5ee74..2427323 100644
--- a/src/pages.json
+++ b/src/pages.json
@@ -74,6 +74,29 @@
       "style": {
         "navigationBarTitleText": "娴忚鏂囨湰"
       }
+    },
+    //鍗忓悓瀹℃壒
+    {
+      "path": "pages/cooperativeOffice/collaborativeApproval/index",
+      "style": {
+        "navigationBarTitleText": "瀹℃壒绠$悊",
+        "navigationStyle": "custom"
+      }
+    },
+    {
+      "path": "pages/cooperativeOffice/collaborativeApproval/detail",
+      "style": {
+        "navigationBarTitleText": "瀹℃壒娴佺▼",
+        "navigationStyle": "custom"
+      }
+    },
+    //瀹㈡埛鎷滆
+    {
+      "path": "pages/cooperativeOffice/clientVisit/index",
+      "style": {
+        "navigationBarTitleText": "瀹㈡埛鎷滆",
+        "navigationStyle": "custom"
+      }
     }
   ],
   "subPackages": [
diff --git a/src/pages/cooperativeOffice/clientVisit/index.vue b/src/pages/cooperativeOffice/clientVisit/index.vue
new file mode 100644
index 0000000..f83d156
--- /dev/null
+++ b/src/pages/cooperativeOffice/clientVisit/index.vue
@@ -0,0 +1,51 @@
+// 瀹㈡埛鎷滆
+<template>
+  <view>
+    <view class="page-header">
+      <view class="header-left">
+        <up-icon name="arrow-left" size="20" color="#333" @click="goBack"></up-icon>
+      </view>
+      <view class="header-center">
+        <text class="page-title">瀹㈡埛鎷滆</text>
+      </view>
+    </view>
+  </view>
+</template>
+<script>
+export default {
+  data() {
+    return {
+      title: '瀹㈡埛鎷滆'
+    }
+  },
+  methods: {
+    goBack() {
+      uni.navigateBack({
+        delta: 1
+      })
+    }
+  }
+}
+</script>
+<style>
+.page-header {
+  display: flex;
+  align-items: center;
+  justify-content: space-between;
+  padding: 10px 20px;
+  background-color: #f5f5f5;
+}
+.header-left {
+  display: flex;
+  align-items: center;
+}
+.header-center {
+  flex: 1;
+  text-align: center;
+}
+.page-title {
+  font-size: 18px;
+  font-weight: bold;
+}
+</style>
+
diff --git a/src/pages/cooperativeOffice/collaborativeApproval/detail.vue b/src/pages/cooperativeOffice/collaborativeApproval/detail.vue
new file mode 100644
index 0000000..362b237
--- /dev/null
+++ b/src/pages/cooperativeOffice/collaborativeApproval/detail.vue
@@ -0,0 +1,535 @@
+<template>
+  <view class="account-detail">
+    <!-- 椤堕儴鏍囬鏍� -->
+    <view class="header">
+      <up-icon name="arrow-left" size="20" color="#333" @click="goBack" />
+      <text class="title">瀹℃壒娴佺▼</text>
+    </view>
+
+    <!-- 琛ㄥ崟鍖哄煙 -->
+    <view class="form-section">
+      <van-form ref="formRef" @submit="submitForm" :rules="rules" input-align="right">
+        <van-cell-group inset style="height:auto">
+          <van-field
+            v-model="taxPrice"
+            name="taxPrice"
+            label="濮撳悕"
+            placeholder="璇疯緭鍏ュ鍚�"
+            :rules="[{ required: true, message: '濮撳悕涓嶈兘涓虹┖' }]"
+            required
+            readonly
+          />
+          <van-field
+            v-model="result"
+            readonly
+            name="picker"
+            label="鐢宠閮ㄩ棬"
+            placeholder="璇烽�夋嫨鐢宠閮ㄩ棬"
+            :rules="[{ required: true, message: '璇烽�夋嫨鐢宠閮ㄩ棬' }]"
+            @click="showPicker = true"
+            required
+          />
+          <van-popup
+            v-model:show="showPicker"
+            destroy-on-close
+            position="bottom"
+          >
+            <van-picker
+              :columns="columns"
+              :model-value="pickerValue"
+              @confirm="onConfirm"
+              @cancel="showPicker = false"
+            />
+          </van-popup>
+          <van-field
+            v-model="message"
+            name="message"
+            rows="1"
+            autosize
+            label="鐢宠浜嬬敱"
+            type="textarea"
+            placeholder="璇疯緭鍏ョ敵璇蜂簨鐢�"
+            height="100"
+            :rules="[{ required: true, message: '鐢宠浜嬬敱涓嶈兘涓虹┖' }]"
+            required
+          />
+        </van-cell-group>
+      </van-form>
+    </view>
+    <!-- 瀹℃牳娴佺▼鍖哄煙 -->
+    <view class="approval-process">
+      <view class="approval-header">
+        <text class="approval-title">瀹℃牳娴佺▼</text>
+        <text class="approval-desc">宸茬敱绠$悊鍛橀璁句笉鍙慨鏀�</text>
+      </view>
+
+      <view class="approval-steps">
+        <view v-for="(step, stepIndex) in approvalSteps" :key="stepIndex" class="approval-step">
+          <view class="step-title">
+            <text>瀹℃壒浜�</text>
+          </view>
+          <view class="approvers-container">
+            <view v-for="(approver, approverIndex) in step.approvers" :key="approverIndex" class="approver-item">
+              <view class="approver-avatar"></view>
+              <text class="approver-name">{{ approver.name }}</text>
+              <view class="delete-approver-btn" @click="removeApprover(stepIndex, approverIndex)">脳</view>
+            </view>
+            <view class="add-approver-btn" @click="addApprover(stepIndex)">+
+            </view>
+          </view>
+          <view class="step-line" v-if="stepIndex < approvalSteps.length - 1"></view>
+          <view class="delete-step-btn" @click="removeApprovalStep(stepIndex)">鍒犻櫎鑺傜偣</view>
+        </view>
+      </view>
+
+      <view class="add-step-btn" @click="addApprovalStep">
+        <text>鏂板鑺傜偣瀹℃牳浜�</text>
+      </view>
+    </view>
+
+    <!-- 搴曢儴鎸夐挳 -->
+    <view class="footer-btns">
+      <van-button class="cancel-btn" @click="goBack">鍙栨秷</van-button>
+      <van-button class="save-btn" @click="submitForm">淇濆瓨</van-button>
+    </view>
+  </view>
+</template>
+
+<script>
+import { ref, onMounted } from "vue";
+
+export default {
+  setup() {
+    const rules = ref({
+
+  taxPrice: {
+    rules: [{ required: true, errorMessage: '濮撳悕涓嶈兘涓虹┖' }]
+  },
+  result: {
+    rules: [{ required: true, errorMessage: '璇烽�夋嫨鐢宠閮ㄩ棬' }]
+  },
+  message: {
+    rules: [{ required: true, errorMessage: '鐢宠浜嬬敱涓嶈兘涓虹┖' }]
+  },
+});
+    const result = ref("");
+    const pickerValue = ref([]);
+    const showPicker = ref(false);
+    const columns = ref([]);
+    onMounted(async () => {
+      try {
+        // 鏇挎崲涓哄疄闄呮帴鍙e湴鍧�
+        // const response = await axios.get('/api/getDepartments');
+        columns.value = [
+          {
+            text: "鏉窞",
+            value: "Hangzhou",
+          },
+          {
+            text: "瀹佹尝",
+            value: "Ningbo",
+          },
+          {
+            text: "娓╁窞",
+            value: "Wenzhou",
+          },
+          {
+            text: "缁嶅叴",
+            value: "Shaoxing",
+          },
+          {
+            text: "婀栧窞",
+            value: "Huzhou",
+          },
+        ];
+      } catch (error) {
+        console.error("鑾峰彇閮ㄩ棬鏁版嵁澶辫触:", error);
+      }
+    });
+    const onConfirm = ({ selectedValues, selectedOptions }) => {
+      result.value = selectedOptions[0]?.text;
+      pickerValue.value = selectedValues;
+      showPicker.value = false;
+    };
+    const taxPrice = ref("");
+    const contractAmount = ref("");
+    const approvalSteps = ref([
+      { approvers: [{ name: '鍗㈠皬鏁�' }, { name: '鍗㈠皬鏁�' }] },
+      { approvers: [{ name: '鍗㈠皬鏁�' }] },
+      { approvers: [{ name: '鍗㈠皬鏁�' }] },
+      { approvers: [{ name: '鍗㈠皬鏁�' }] }
+    ]);
+
+    const goBack = () => {
+    	uni.navigateBack();
+    };
+
+    const formRef = ref(null);
+
+    const submitForm = () => {
+      formRef.value.validate().then(() => {
+        // 琛ㄥ崟鏍¢獙閫氳繃锛屽彲浠ユ彁浜ゆ暟鎹�
+        console.log("琛ㄥ崟鏁版嵁:", {
+          taxPrice: taxPrice.value,
+          department: result.value,
+          message: message.value,
+          approvalSteps: approvalSteps.value
+        });
+
+        uni.showToast({
+          title: "淇濆瓨鎴愬姛",
+          icon: "success",
+        });
+      }).catch((error) => {
+        console.error("琛ㄥ崟鏍¢獙澶辫触:", error);
+        // 鏄剧ず鍏蜂綋鐨勯敊璇俊鎭�
+        if (error.length > 0) {
+          const firstError = error[0];
+          uni.showToast({
+            title: firstError.message || '琛ㄥ崟鏍¢獙澶辫触',
+            icon: 'none'
+          });
+        } else {
+          uni.showToast({
+            title: '琛ㄥ崟鏍¢獙澶辫触锛岃妫�鏌ュ繀濉」',
+            icon: 'none'
+          });
+        }
+      });
+    };
+
+    const message = ref("");
+
+    const addApprover = (stepIndex) => {
+      // 鍦ㄦ寚瀹氬鎵规楠ゆ坊鍔犳柊鐨勫鎵逛汉
+      approvalSteps.value[stepIndex].approvers.push({ name: '鍗㈠皬鏁�' });
+    };
+
+    const addApprovalStep = () => {
+      // 娣诲姞鏂扮殑瀹℃壒姝ラ
+      approvalSteps.value.push({ approvers: [{ name: '鍗㈠皬鏁�' }] });
+    };
+
+    const removeApprover = (stepIndex, approverIndex) => {
+      // 纭繚姣忎釜姝ラ鑷冲皯淇濈暀涓�涓鎵逛汉
+      if (approvalSteps.value[stepIndex].approvers.length > 1) {
+        approvalSteps.value[stepIndex].approvers.splice(approverIndex, 1);
+      } else {
+        uni.showToast({
+          title: '姣忎釜姝ラ鑷冲皯闇�瑕佷竴涓鎵逛汉',
+          icon: 'none'
+        });
+      }
+    };
+
+    const removeApprovalStep = (stepIndex) => {
+      // 纭繚鑷冲皯淇濈暀涓�涓鎵规楠�
+      if (approvalSteps.value.length > 1) {
+        approvalSteps.value.splice(stepIndex, 1);
+      } else {
+        uni.showToast({
+          title: '鑷冲皯闇�瑕佷竴涓鎵规楠�',
+          icon: 'none'
+        });
+      }
+    };
+
+    return {
+      rules,
+      removeApprovalStep,
+    removeApprover,
+      result,
+      pickerValue,
+      columns,
+      onConfirm,
+      showPicker,
+      taxPrice,
+      contractAmount,
+      goBack,
+      submitForm,
+      approvalSteps,
+      addApprover,
+      addApprovalStep,
+      formRef,
+      message
+    };
+  },
+};
+</script>
+
+<style scoped lang="scss">
+.account-detail {
+  min-height: 100vh;
+  background: #f8f9fa;
+  padding-bottom: 80px;
+}
+
+.header {
+  display: flex;
+  align-items: center;
+  background: #fff;
+  padding: 16px 20px;
+  border-bottom: 1px solid #f0f0f0;
+  position: sticky;
+  top: 0;
+  z-index: 100;
+}
+
+.title {
+  flex: 1;
+  text-align: center;
+  font-size: 18px;
+  font-weight: 600;
+  color: #333;
+}
+
+.form-section {
+  margin-top: 16px;
+}
+
+.van-field {
+  height: 56px;
+  line-height: 36px;
+}
+
+.product-section {
+  background: #fff;
+  margin: 16px;
+  border-radius: 16px;
+  padding: 20px 16px 8px 16px;
+  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.04);
+}
+
+.section-header {
+  display: flex;
+  align-items: center;
+  justify-content: space-between;
+  margin-bottom: 12px;
+}
+
+.section-title {
+  font-size: 16px;
+  font-weight: 600;
+  color: #333;
+}
+
+.add-btn {
+  background: #2979ff;
+  color: #fff;
+  border-radius: 8px;
+  padding: 4px 16px;
+  font-size: 14px;
+}
+
+.product-card {
+  background: #f8f9fa;
+  border-radius: 12px;
+  padding: 12px;
+  margin-bottom: 16px;
+  box-shadow: 0 1px 4px rgba(41, 121, 255, 0.06);
+  position: relative;
+}
+
+.product-row {
+  display: flex;
+  align-items: center;
+  margin-bottom: 8px;
+}
+
+.product-label {
+  min-width: 60px;
+  color: #888;
+  font-size: 13px;
+}
+
+.del-row {
+  justify-content: flex-end;
+}
+
+.del-btn {
+  background: #ff4d4f;
+  color: #fff;
+  border-radius: 8px;
+  padding: 4px 16px;
+  font-size: 13px;
+  margin-top: 4px;
+}
+
+.approval-process {
+  background: #fff;
+  margin: 16px;
+  border-radius: 16px;
+  padding: 16px;
+  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.04);
+}
+
+.approval-header {
+  margin-bottom: 16px;
+}
+
+.approval-title {
+  font-size: 16px;
+  font-weight: 600;
+  color: #333;
+  display: block;
+  margin-bottom: 4px;
+}
+
+.approval-desc {
+  font-size: 12px;
+  color: #999;
+}
+
+.approval-steps {
+  padding-left: 16px;
+  position: relative;
+}
+
+.approval-step {
+  position: relative;
+  margin-bottom: 20px;
+}
+
+.step-title {
+  margin-bottom: 12px;
+}
+
+.step-title text {
+  font-size: 14px;
+  color: #666;
+  background: #f0f0f0;
+  padding: 2px 8px;
+  border-radius: 4px;
+}
+
+.approvers-container {
+  display: flex;
+  flex-wrap: wrap;
+  gap: 12px;
+  margin-bottom: 8px;
+}
+
+.approver-item {
+  display: flex;
+  flex-direction: column;
+  align-items: center;
+  width: 60px;
+}
+
+.approver-avatar {
+  width: 40px;
+  height: 40px;
+  background: #e6f7ff;
+  border-radius: 50%;
+  margin-bottom: 4px;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+}
+
+.approver-avatar::after {
+  content: '馃懁';
+  font-size: 20px;
+}
+
+.approver-name {
+  font-size: 12px;
+  color: #333;
+  text-align: center;
+  white-space: nowrap;
+  overflow: hidden;
+  text-overflow: ellipsis;
+  margin-bottom: 2px;
+}
+
+.delete-approver-btn {
+  font-size: 12px;
+  color: #ff4d4f;
+  background: rgba(255, 77, 79, 0.1);
+  width: 16px;
+  height: 16px;
+  border-radius: 50%;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  margin-top: 2px;
+}
+
+.delete-step-btn {
+  margin-top: 8px;
+  color: #ff4d4f;
+  font-size: 12px;
+  background: rgba(255, 77, 79, 0.1);
+  padding: 2px 8px;
+  border-radius: 4px;
+  display: inline-block;
+  }
+
+.add-approver-btn {
+  width: 40px;
+  height: 40px;
+  border: 1px dashed #ccc;
+  border-radius: 50%;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  font-size: 20px;
+  color: #999;
+  margin-top: 8px;
+}
+
+.step-line {
+  position: absolute;
+  left: 20px;
+  top: 100%;
+  width: 1px;
+  height: 30px;
+  background: #e0e0e0;
+}
+
+.add-step-btn {
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  margin-top: 16px;
+  color: #006cfb;
+  font-size: 14px;
+  padding: 8px 0;
+  border: 1px dashed #006cfb;
+  border-radius: 8px;
+}
+
+.footer-btns {
+  position: fixed;
+  left: 0;
+  right: 0;
+  bottom: 0;
+  background: #fff;
+  display: flex;
+  justify-content: space-around;
+  align-items: center;
+  padding: 12px 0;
+  box-shadow: 0 -2px 8px rgba(0, 0, 0, 0.05);
+  z-index: 1000;
+}
+
+.cancel-btn {
+  font-weight: 400;
+  font-size: 16px;
+  color: #ffffff;
+  width: 102px;
+  background: #c7c9cc;
+  box-shadow: 0px 4px 10px 0px rgba(3, 88, 185, 0.2);
+  border-radius: 40px 40px 40px 40px;
+}
+
+.save-btn {
+  font-weight: 400;
+  font-size: 16px;
+  color: #ffffff;
+  width: 224px;
+  background: linear-gradient(140deg, #00baff 0%, #006cfb 100%);
+  box-shadow: 0px 4px 10px 0px rgba(3, 88, 185, 0.2);
+  border-radius: 40px 40px 40px 40px;
+}
+</style>
\ No newline at end of file
diff --git a/src/pages/cooperativeOffice/collaborativeApproval/index.vue b/src/pages/cooperativeOffice/collaborativeApproval/index.vue
new file mode 100644
index 0000000..69dc26d
--- /dev/null
+++ b/src/pages/cooperativeOffice/collaborativeApproval/index.vue
@@ -0,0 +1,390 @@
+// 瀹℃壒绠$悊涓婚〉闈�
+<template>
+	<view class="sales-account">
+		<!-- 椤甸潰澶撮儴 -->
+		<view class="page-header">
+			<view class="header-left">
+				<up-icon name="arrow-left" size="20" color="#333" @click="goBack"></up-icon>
+			</view>
+			<view class="header-center">
+				<text class="page-title">瀹℃壒绠$悊</text>
+			</view>
+		</view>
+
+		<!-- 鎼滅储鍜岀瓫閫夊尯鍩� -->
+		<view class="search-filter-section">
+			<view class="search-bar">
+				<view class="search-input">
+					<u-input placeholder="璇疯緭鍏ラ噰璐悎鍚屽彿" class="search-text" v-model="searchKeyword">
+						<template #suffix>
+							<up-icon name="search" size="24" color="#999" @click="getList"></up-icon>
+						</template>
+					</u-input>
+				</view>
+				<view class="filter-button" @click="showFilterOptions">
+					<van-icon name="filter-o" size="24" color="#999"></van-icon>
+				</view>
+			</view>
+		</view>
+
+		<!-- 閿�鍞彴璐︾�戝竷娴� -->
+		<view class="ledger-list" v-if="total > 0">
+			<view v-for="(item, index) in ledgerList" :key="index">
+				<view class="ledger-item" @click="handleItemClick(item)">
+					<view class="item-header">
+						<view class="item-left">
+							<view class="document-icon">
+								<up-icon name="file-text" size="16" color="#ffffff"></up-icon>
+							</view>
+							<text class="item-id">{{ item.salesContractNo }}</text>
+						</view>
+					</view>
+					<up-divider></up-divider>
+
+					<view class="item-details">
+						<view class="detail-info">
+							<view class="detail-row">
+								<text class="detail-label">鐢宠浜�</text>
+								<text class="detail-value">{{ item.entryPersonName }}</text>
+							</view>
+							<view class="detail-row">
+								<text class="detail-label">鐢宠鏃ユ湡</text>
+								<text class="detail-value highlightBlue">{{ item.entryDate }}</text>
+							</view>
+						</view>
+						<view class="detail-info">
+							<view class="detail-row">
+								<text class="detail-label">鐢宠閮ㄩ棬</text>
+								<text class="detail-value">{{ item.entryPersonName }}</text>
+							</view>
+							<view class="detail-row">
+								<text class="detail-label">瀹℃壒鐘舵��</text>
+								<text class="detail-value highlightYellow">{{ item.entryDate }}</text>
+							</view>
+						</view>
+					</view>
+				</view>
+			</view>
+		</view>
+		<view v-else class="no-data">
+			<text>鏆傛棤瀹℃壒鏁版嵁</text>
+		</view>
+
+		<!-- 娴姩鎿嶄綔鎸夐挳 -->
+		<view class="fab-button" @click="handleAdd">
+			<up-icon name="plus" size="24" color="#ffffff"></up-icon>
+		</view>
+	</view>
+</template>
+
+<script setup>
+	import {
+		ref,
+		reactive,
+		onMounted
+	} from "vue";
+	import {
+		ledgerListPage
+	} from "@/api/cooperativeOffice/collaborativeApproval";
+
+	// 鎼滅储鍏抽敭璇�
+	const searchKeyword = ref("");
+
+	// 閿�鍞彴璐︽暟鎹�
+	const ledgerList = ref([]);
+	const total = ref(0);
+
+	// 杩斿洖涓婁竴椤�
+	const goBack = () => {
+		uni.navigateBack();
+	};
+	// 鏌ヨ鍒楄〃
+	const getList = () => {
+		const page = {
+			current: -1,
+			size: -1,
+		};
+		ledgerListPage({
+				...page
+			})
+			.then((res) => {
+				ledgerList.value = res.records;
+				total.value = res.total;
+			})
+			.catch(() => {
+				// tableLoading.value = false;
+			});
+	};
+	// 鏄剧ず绛涢�夐�夐」
+	const showFilterOptions = () => {
+		uni.showActionSheet({
+			itemList: ["鎸夋棩鏈熺瓫閫�", "鎸夌姸鎬佺瓫閫�", "鎸夐噾棰濈瓫閫�"],
+			success: (res) => {
+				console.log("閫夋嫨浜嗙瓫閫夐�夐」:", res.tapIndex);
+			},
+		});
+	};
+
+	// 鐐瑰嚮鍒楄〃椤�
+	const handleItemClick = (item) => {
+		uni.showToast({
+			title: `鏌ョ湅鍚堝悓: ${item.contractId}`,
+			icon: "none",
+		});
+	};
+
+	// 娣诲姞鏂拌褰�
+	const handleAdd = () => {
+		uni.navigateTo({
+			url: "/pages/cooperativeOffice/collaborativeApproval/detail",
+		});
+	};
+
+	onMounted(() => {
+		// 椤甸潰鍔犺浇瀹屾垚鍚庣殑鍒濆鍖栭�昏緫
+		getList();
+	});
+</script>
+
+<style scoped lang="scss">
+	.u-divider {
+		margin: 0 !important;
+	}
+
+	.sales-account {
+		min-height: 100vh;
+		background: #f8f9fa;
+		position: relative;
+	}
+
+	.page-header {
+		background: #ffffff;
+		padding: 16px 20px;
+		display: flex;
+		align-items: center;
+		justify-content: space-between;
+		border-bottom: 1px solid #f0f0f0;
+		position: sticky;
+		/* 鍏煎 iOS 鍒樻捣/鐏靛姩宀涘畨鍏ㄥ尯 */
+		padding-top: env(safe-area-inset-top);
+		top: 0;
+		z-index: 100;
+	}
+
+	.header-left {
+		display: flex;
+		align-items: center;
+		gap: 8px;
+	}
+
+	.nav-icon {
+		width: 24px;
+		height: 24px;
+		background: #2979ff;
+		border-radius: 4px;
+		display: flex;
+		align-items: center;
+		justify-content: center;
+	}
+
+	.nav-text {
+		font-size: 14px;
+		color: #2979ff;
+		font-weight: 500;
+	}
+
+	.header-center {
+		flex: 1;
+		text-align: center;
+	}
+
+	.page-title {
+		font-size: 18px;
+		font-weight: 600;
+		color: #333;
+	}
+
+	.header-right {
+		display: flex;
+		align-items: center;
+	}
+
+	.status-bar {
+		display: flex;
+		align-items: center;
+		gap: 4px;
+	}
+
+	.signal,
+	.wifi,
+	.battery {
+		width: 16px;
+		height: 8px;
+		background: #333;
+		border-radius: 2px;
+	}
+
+	.search-filter-section {
+		padding: 10px 20px;
+		background: #ffffff;
+	}
+
+	.search-bar {
+		display: flex;
+		align-items: center;
+		gap: 12px;
+	}
+
+	.search-input {
+		flex: 1;
+		background: #f5f5f5;
+		border-radius: 24px;
+		padding: 4px 16px;
+		display: flex;
+		align-items: center;
+		gap: 8px;
+	}
+
+	.search-text {
+		flex: 1;
+		font-size: 14px;
+		color: #333;
+		background: transparent;
+		border: none;
+		outline: none;
+	}
+
+	.search-text::placeholder {
+		color: #999;
+	}
+
+	.filter-button {
+		width: 40px;
+		height: 40px;
+		border-radius: 8px;
+		display: flex;
+		align-items: center;
+		justify-content: center;
+	}
+
+	.ledger-list {
+		padding: 20px;
+	}
+
+	.ledger-item {
+		background: #ffffff;
+		border-radius: 12px;
+		margin-bottom: 16px;
+		overflow: hidden;
+		box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05);
+		padding: 0 16px;
+	}
+
+	.item-header {
+		padding: 16px 0;
+		display: flex;
+		align-items: center;
+		justify-content: space-between;
+	}
+
+	.item-left {
+		display: flex;
+		align-items: center;
+		gap: 8px;
+	}
+
+	.document-icon {
+		width: 24px;
+		height: 24px;
+		background: #ed8d05;
+		border-radius: 4px;
+		display: flex;
+		align-items: center;
+		justify-content: center;
+	}
+
+	.item-id {
+		font-size: 14px;
+		color: #333;
+		font-weight: 500;
+	}
+
+	.item-tag {
+		background: #4caf50;
+		border-radius: 4px;
+		padding: 2px 4px;
+	}
+
+	.tag-text {
+		font-size: 11px;
+		color: #ffffff;
+		font-weight: 500;
+	}
+
+	.item-details {
+		padding: 16px 0;
+	}
+
+	.detail-row {
+		display: flex;
+		align-items: flex-end;
+		justify-content: space-between;
+		margin-bottom: 8px;
+
+		&:last-child {
+			margin-bottom: 0;
+		}
+	}
+
+	.detail-info {
+		margin-top: 10px;
+		display: flex;
+		align-items: flex-start;
+		justify-content: space-between;
+	}
+
+	.detail-label {
+		font-size: 12px;
+		color: #777777;
+		min-width: 60px;
+	}
+
+	.detail-value {
+		font-size: 12px;
+		color: #000000;
+		text-align: right;
+		flex: 1;
+		margin-left: 16px;
+	}
+
+	.detail-value.highlightBlue {
+		color: #2979ff;
+		font-weight: 500;
+	}
+
+	.detail-value.highlightYellow {
+		color: #ed8d05;
+		font-weight: 500;
+	}
+
+	.no-data {
+		padding: 40px 0;
+		text-align: center;
+		color: #999;
+	}
+
+	.fab-button {
+		position: fixed;
+		bottom: 30px;
+		right: 30px;
+		width: 56px;
+		height: 56px;
+		background: #ed8d05;
+		border-radius: 50%;
+		display: flex;
+		align-items: center;
+		justify-content: center;
+		box-shadow: 0 4px 16px rgba(41, 121, 255, 0.3);
+		z-index: 1000;
+	}
+</style>
\ No newline at end of file
diff --git a/src/pages/index.vue b/src/pages/index.vue
index e35f5e3..1e51897 100644
--- a/src/pages/index.vue
+++ b/src/pages/index.vue
@@ -293,6 +293,16 @@
 				url: '/pages/sales/salesAccount/index'
 			});
 			break;
+		case '鍗忓悓瀹℃壒':
+			uni.navigateTo({
+				url: '/pages/cooperativeOffice/collaborativeApproval/index'
+			});
+			break;
+					case '瀹㈡埛鎷滆':
+			uni.navigateTo({
+				url: '/pages/cooperativeOffice/clientVisit/index'
+			});
+			break;
 		default:
 			uni.showToast({
 				title: `鐐瑰嚮浜�${item.label}`,

--
Gitblit v1.9.3