yyb
4 天以前 451c79860be3a1fca7270309831dc9c567a26b27
审批管理/审批流程
已修改2个文件
已添加4个文件
1120 ■■■■■ 文件已修改
src/api/cooperativeOffice/collaborativeApproval.js 111 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/pages.json 23 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/pages/cooperativeOffice/clientVisit/index.vue 51 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/pages/cooperativeOffice/collaborativeApproval/detail.vue 535 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/pages/cooperativeOffice/collaborativeApproval/index.vue 390 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/pages/index.vue 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
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,
  });
}
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": [
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>
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 {
        // æ›¿æ¢ä¸ºå®žé™…接口地址
        // 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>
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>
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}`,