gaoluyang
2026-04-28 2082dea4977d47618c8d7ad4dd9bb847f5cf1b17
升级apppro
1.迁移档案管理功能
已添加9个文件
已修改3个文件
1743 ■■■■■ 文件已修改
src/api/fileManagement/bookshelf.js 129 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/fileManagement/borrow.js 47 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/fileManagement/document.js 189 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/fileManagement/return.js 61 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/fileManagement/statistics.js 75 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/pages.json 28 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/pages/fileManagement/borrow/edit.vue 333 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/pages/fileManagement/borrow/index.vue 262 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/pages/fileManagement/return/edit.vue 313 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/pages/fileManagement/return/index.vue 262 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/pages/works.vue 38 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/utils/versionUpgrade.js 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/fileManagement/bookshelf.js
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,129 @@
import request from "@/utils/request";
/**
 * ä¹¦æž¶ç®¡ç†ç›¸å…³API接口
 * åŒ…含仓库管理、货架管理、图书管理等功能的接口
 */
/**
 * èŽ·å–ä»“åº“åˆ—è¡¨
 * @description èŽ·å–æ‰€æœ‰ä»“åº“çš„åŸºæœ¬ä¿¡æ¯åˆ—è¡¨
 * @returns {Promise} è¿”回仓库列表数据
 */
export function getWarehouseList() {
  return request({
    url: "/warehouse/tree",
    method: "get",
  });
}
/**
 * æ–°å¢žä»“库
 * @description åˆ›å»ºæ–°çš„仓库记录
 * @param {Object} data ä»“库信息对象,包含仓库名称等字段
 * @returns {Promise} è¿”回新增结果
 */
export function addWarehouse(data) {
  return request({
    url: "/warehouse/add",
    method: "post",
    data,
  });
}
/**
 * æ›´æ–°ä»“库信息
 * @description ä¿®æ”¹çŽ°æœ‰ä»“åº“çš„åŸºæœ¬ä¿¡æ¯
 * @param {Object} data ä»“库信息对象,必须包含仓库ID
 * @returns {Promise} è¿”回更新结果
 */
export function updateWarehouse(data) {
  return request({
    url: "/warehouse/update",
    method: "put",
    data,
  });
}
/**
 * åˆ é™¤ä»“库
 * @description æ ¹æ®ä»“库ID删除指定的仓库记录
 * @param {string|number} id ä»“库ID
 * @returns {Promise} è¿”回删除结果
 */
export function deleteWarehouse(data) {
  return request({
    url: `/warehouse/delete/`,
    method: "delete",
    data,
  });
}
/**
 * èŽ·å–è´§æž¶åˆ—è¡¨
 * @description æ ¹æ®ä»“库ID获取该仓库下的所有货架信息
 * @param {string|number} warehouseId ä»“库ID
 * @returns {Promise} è¿”回货架列表数据
 */
export function getShelfList(warehouseId) {
  return request({
    url: `/shelf/list/${warehouseId}`,
    method: "get",
  });
}
/**
 * æ–°å¢žè´§æž¶
 * @description åœ¨æŒ‡å®šä»“库下创建新的货架记录
 * @param {Object} data è´§æž¶ä¿¡æ¯å¯¹è±¡ï¼ŒåŒ…含货架名称、层数、列数等字段
 * @returns {Promise} è¿”回新增结果
 */
export function addShelf(data) {
  return request({
    url: "/warehouse/goodsShelves/add",
    method: "post",
    data,
  });
}
/**
 * æ›´æ–°è´§æž¶ä¿¡æ¯
 * @description ä¿®æ”¹çŽ°æœ‰è´§æž¶çš„åŸºæœ¬ä¿¡æ¯
 * @param {Object} data è´§æž¶ä¿¡æ¯å¯¹è±¡ï¼Œå¿…须包含货架ID
 * @returns {Promise} è¿”回更新结果
 */
export function updateShelf(data) {
  return request({
    url: "/warehouse/goodsShelves/update",
    method: "put",
    data,
  });
}
/**
 * åˆ é™¤è´§æž¶
 * @description æ ¹æ®è´§æž¶ID删除指定的货架记录,后端要求传入 ID æ•°ç»„(支持批量)
 * @param {Array<string|number>} data è´§æž¶ID数组
 * @returns {Promise} è¿”回删除结果
 */
export function deleteShelf(data) {
  return request({
    url: `/warehouse/goodsShelves/delete/`,
    method: "delete",
    data,
  });
}
/**
 * èŽ·å–ä»“åº“ç»“æž„
 * @description èŽ·å–æŒ‡å®šä»“åº“çš„å®Œæ•´ç»“æž„ä¿¡æ¯ï¼ŒåŒ…æ‹¬è´§æž¶ã€å±‚æ•°ã€åˆ—æ•°ç­‰
 * @param {string|number} warehouseId ä»“库ID
 * @returns {Promise} è¿”回仓库的完整结构数据
 */
export function getWarehouseStructure(data) {
  return request({
    url: `/warehouse/goodsShelvesRowcol/list`,
    method: "get",
    params: data,
  });
}
src/api/fileManagement/borrow.js
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,47 @@
import request from "@/utils/request";
// æ–‡æ¡£å€Ÿé˜…管理相关接口
// èŽ·å–æ–‡æ¡£åˆ—è¡¨ï¼ˆç”¨äºŽå€Ÿé˜…ä¹¦ç±é€‰æ‹©ï¼‰
export function getDocumentList() {
  return request({
    url: "/documentation/list",
    method: "get",
  });
}
// å€Ÿé˜…分页查询
export function getBorrowList(params) {
  return request({
    url: "/documentationBorrowManagement/listPage",
    method: "get",
    params: params,
  });
}
// æ–°å¢žå€Ÿé˜…
export function addBorrow(data) {
  return request({
    url: "/documentationBorrowManagement/add",
    method: "post",
    data: data,
  });
}
// æ›´æ–°å€Ÿé˜…
export function updateBorrow(data) {
  return request({
    url: "/documentationBorrowManagement/update",
    method: "put",
    data: data,
  });
}
// åˆ é™¤å€Ÿé˜…
export function deleteBorrow(ids) {
  return request({
    url: "/documentationBorrowManagement/delete",
    method: "delete",
    data: ids,
  });
}
src/api/fileManagement/document.js
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,189 @@
import request from "@/utils/request";
// èŽ·å–åˆ†ç±»æ ‘
export function getCategoryTree() {
  return request({
    url: "/warehouse/documentClassification/getList",
    method: "get",
  });
}
// æ–°å¢žåˆ†ç±»
export function addCategory(data) {
  return request({
    url: "/warehouse/documentClassification/add",
    method: "post",
    data: {
      category: data.category,
      parentId: data.parentId,
    },
  });
}
// ä¿®æ”¹åˆ†ç±»
export function updateCategory(data) {
  return request({
    url: "/warehouse/documentClassification/update",
    method: "put",
    data: {
      id: data.id,
      category: data.category,
    },
  });
}
// åˆ é™¤åˆ†ç±»
export function deleteCategory(ids) {
  return request({
    url: "/warehouse/documentClassification/delete",
    method: "delete",
    data: ids,
  });
}
// èŽ·å–æ–‡æ¡£åˆ—è¡¨ï¼ˆåˆ†é¡µï¼‰
export function getDocumentList(query) {
  return request({
    url: "/documentation/listPage",
    method: "get",
    params: query,
  });
}
// æ–°å¢žæ–‡æ¡£
export function addDocument(data) {
  return request({
    url: "/documentation/add",
    method: "post",
    data: data,
  });
}
// ä¿®æ”¹æ–‡æ¡£
export function updateDocument(data) {
  return request({
    url: "/documentation/update",
    method: "put",
    data: data,
  });
}
// åˆ é™¤æ–‡æ¡£
export function deleteDocument(ids) {
  return request({
    url: "/documentation/delete",
    method: "delete",
    data: ids,
  });
}
// èŽ·å–æ–‡æ¡£è¯¦æƒ…
export function getDocumentDetail(id) {
  return request({
    url: "/document/" + id,
    method: "get",
  });
}
// æœç´¢æ–‡æ¡£
export function searchDocument(query) {
  return request({
    url: "/document/search",
    method: "get",
    params: query,
  });
}
// èŽ·å–ä»“åº“ç»“æž„
export function getWarehouseStructure() {
  return request({
    url: "/document/warehouse/structure",
    method: "get",
  });
}
// é™„件管理相关接口
// æ·»åР附件
export function addDocumentationFile(data) {
  return request({
    url: "/documentation/documentationFile/add",
    method: "post",
    data: data,
  });
}
// èŽ·å–é™„ä»¶åˆ—è¡¨
export function getDocumentationFileList(params) {
  return request({
    url: "/documentation/documentationFile/listPage",
    method: "get",
    params: params,
  });
}
// åˆ é™¤é™„ä»¶
export function deleteDocumentationFile(ids) {
  return request({
    url: "/documentation/documentationFile/del",
    method: "delete",
    data: ids,
  });
}
// æ–‡æ¡£å€Ÿé˜…管理相关接口
export function getBorrowList(params) {
  return request({
    url: "/documentationBorrowManagement/listPage",
    method: "get",
    params: params,
  });
}
export function addBorrow(data) {
  return request({
    url: "/documentationBorrowManagement/add",
    method: "post",
    data: data,
  });
}
export function updateBorrow(data) {
  return request({
    url: "/documentationBorrowManagement/update",
    method: "put",
    data: data,
  });
}
export function deleteBorrow(ids) {
  return request({
    url: "/documentationBorrowManagement/delete",
    method: "delete",
    data: ids,
  });
}
// ç»Ÿè®¡ç›¸å…³æŽ¥å£
// èŽ·å–æ€»ä½“ç»Ÿè®¡æ•°æ®
export function getDocumentationOverview() {
  return request({
    url: "/documentation/overview",
    method: "get",
  });
}
// èŽ·å–åˆ†ç±»ç»Ÿè®¡æ•°æ®
export function getDocumentationCategoryStats() {
  return request({
    url: "/documentation/category",
    method: "get",
  });
}
// èŽ·å–çŠ¶æ€ç»Ÿè®¡æ•°æ®
export function getDocumentationStatusStats() {
  return request({
    url: "/documentation/status",
    method: "get",
  });
}
src/api/fileManagement/return.js
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,61 @@
import request from "@/utils/request";
// åˆ†é¡µæŸ¥è¯¢å½’还记录
export function getReturnListPage(query) {
  return request({
    url: "/documentationBorrowManagement/listPageReturn",
    method: "get",
    params: query,
  });
}
// å½’还操作
export function returnDocument(data) {
  return request({
    url: "/documentationBorrowManagement/revent",
    method: "put",
    data: data,
  });
}
// åˆ é™¤å½’还记录
export function deleteReturn(ids) {
  return request({
    url: "/documentationBorrowManagement/reventDelete",
    method: "delete",
    data: ids,
  });
}
//根据书籍id查询借阅记录
export function getBorrowListByDocumentationId(id) {
  return request({
    url: "/documentationBorrowManagement/getByDocumentationId/"+id,
    method: "get"
  });
}
// æ›´æ–°å€Ÿé˜…记录
export function updateBorrow(data) {
  return request({
    url: "/documentationBorrowManagement/update",
    method: "put",
    data: data,
  });
}
// å½’还更新
export function reventUpdate(data) {
  return request({
    url: "/documentationBorrowManagement/reventUpdate",
    method: "put",
    data: data,
  });
}
// èŽ·å–æ–‡æ¡£åˆ—è¡¨
export function getDocumentList() {
  return request({
    url: "/documentationBorrowManagement/list",
    method: "get",
  });
}
src/api/fileManagement/statistics.js
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,75 @@
import request from "@/utils/request";
// èŽ·å–æ¡£æ¡ˆæ€»ä½“ç»Ÿè®¡
export function getDocumentStatistics() {
  return request({
    url: "/fileManagement/statistics/overview",
    method: "get",
  });
}
// èŽ·å–æ¡£æ¡ˆåˆ†ç±»ç»Ÿè®¡
export function getCategoryStatistics() {
  return request({
    url: "/fileManagement/statistics/category",
    method: "get",
  });
}
// èŽ·å–æ¡£æ¡ˆçŠ¶æ€ç»Ÿè®¡
export function getStatusStatistics() {
  return request({
    url: "/fileManagement/statistics/status",
    method: "get",
  });
}
// èŽ·å–æ¡£æ¡ˆå€Ÿé˜…ç»Ÿè®¡
export function getBorrowStatistics() {
  return request({
    url: "/fileManagement/statistics/borrow",
    method: "get",
  });
}
// èŽ·å–æ¡£æ¡ˆå¹´åº¦ç»Ÿè®¡
export function getYearStatistics() {
  return request({
    url: "/fileManagement/statistics/year",
    method: "get",
  });
}
// èŽ·å–æ¡£æ¡ˆä½ç½®ç»Ÿè®¡
export function getLocationStatistics() {
  return request({
    url: "/fileManagement/statistics/location",
    method: "get",
  });
}
// èŽ·å–æ¡£æ¡ˆè¶‹åŠ¿ç»Ÿè®¡
export function getTrendStatistics(params) {
  return request({
    url: "/fileManagement/statistics/trend",
    method: "get",
    params: params,
  });
}
// èŽ·å–æ¡£æ¡ˆå€Ÿé˜…æŽ’è¡Œ
export function getBorrowRanking() {
  return request({
    url: "/fileManagement/statistics/borrowRanking",
    method: "get",
  });
}
// èŽ·å–æ¡£æ¡ˆåˆ†ç±»è¯¦æƒ…ç»Ÿè®¡
export function getCategoryDetailStatistics(categoryId) {
  return request({
    url: `/fileManagement/statistics/categoryDetail/${categoryId}`,
    method: "get",
  });
}
src/pages.json
@@ -1143,6 +1143,34 @@
      "style": {
        "navigationBarTitleText": "消息中心"
      }
    },
    {
      "path": "pages/fileManagement/borrow/index",
      "style": {
        "navigationBarTitleText": "借阅管理",
        "navigationStyle": "custom"
      }
    },
    {
      "path": "pages/fileManagement/borrow/edit",
      "style": {
        "navigationBarTitleText": "借阅登记",
        "navigationStyle": "custom"
      }
    },
    {
      "path": "pages/fileManagement/return/index",
      "style": {
        "navigationBarTitleText": "归还管理",
        "navigationStyle": "custom"
      }
    },
    {
      "path": "pages/fileManagement/return/edit",
      "style": {
        "navigationBarTitleText": "归还登记",
        "navigationStyle": "custom"
      }
    }
  ],
  "subPackages": [
src/pages/fileManagement/borrow/edit.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,333 @@
<template>
  <view class="borrow-edit">
    <PageHeader :title="pageTitle" @back="goBack" />
    <up-form
      ref="formRef"
      :model="form"
      :rules="rules"
      label-width="110"
    >
      <up-form-item label="借阅人" prop="borrower" required>
        <up-input
          v-model="form.borrower"
          placeholder="请输入借阅人"
          clearable
          :disabled="isReturned"
        />
      </up-form-item>
      <up-form-item label="借阅书籍" prop="documentationId" required>
        <up-input
          v-model="displayDocName"
          placeholder="请选择借阅书籍"
          readonly
          :disabled="isEdit"
          @click="!isEdit && (showDocPicker = true)"
        />
        <template #right>
          <up-icon v-if="!isEdit" name="arrow-right" @click="showDocPicker = true"></up-icon>
        </template>
      </up-form-item>
      <up-form-item label="借阅日期" prop="borrowDate" required>
        <up-input
          v-model="form.borrowDate"
          placeholder="请选择借阅日期"
          readonly
          @click="!isReturned && (showBorrowDatePicker = true)"
          :disabled="isReturned"
        />
        <template #right>
          <up-icon name="arrow-right" @click="!isReturned && (showBorrowDatePicker = true)"></up-icon>
        </template>
      </up-form-item>
      <up-form-item label="应归还日期" prop="dueReturnDate" required>
        <up-input
          v-model="form.dueReturnDate"
          placeholder="请选择应归还日期"
          readonly
          @click="!isReturned && (showDueDatePicker = true)"
          :disabled="isReturned"
        />
        <template #right>
          <up-icon name="arrow-right" @click="!isReturned && (showDueDatePicker = true)"></up-icon>
        </template>
      </up-form-item>
      <up-form-item label="借阅目的" prop="borrowPurpose" required>
        <up-input
          v-model="form.borrowPurpose"
          placeholder="请输入借阅目的"
          clearable
          :disabled="isReturned"
        />
      </up-form-item>
      <up-form-item label="备注">
        <up-textarea
          v-model="form.remark"
          placeholder="请输入备注信息"
          height="80"
          border="none"
          :disabled="isReturned"
        />
      </up-form-item>
    </up-form>
    <FooterButtons
      v-if="!isReturned"
      :loading="loading"
      :confirmText="isEdit ? '保存' : '新增'"
      @cancel="goBack"
      @confirm="handleSubmit"
    />
    <!-- å€Ÿé˜…日期选择器 -->
    <up-popup :show="showBorrowDatePicker" mode="bottom" @close="showBorrowDatePicker = false">
      <up-datetime-picker
        :show="true"
        v-model="borrowDateValue"
        @confirm="onBorrowDateConfirm"
        @cancel="showBorrowDatePicker = false"
        mode="date"
      />
    </up-popup>
    <!-- åº”归还日期选择器 -->
    <up-popup :show="showDueDatePicker" mode="bottom" @close="showDueDatePicker = false">
      <up-datetime-picker
        :show="true"
        v-model="dueReturnDateValue"
        @confirm="onDueDateConfirm"
        @cancel="showDueDatePicker = false"
        mode="date"
      />
    </up-popup>
    <!-- æ–‡æ¡£é€‰æ‹©å™¨ -->
    <up-action-sheet
      :show="showDocPicker"
      :actions="documentOptions"
      title="选择借阅书籍"
      @select="onDocSelect"
      @close="showDocPicker = false"
    />
  </view>
</template>
<script setup>
import { ref, computed, onMounted } from "vue";
import { onLoad } from "@dcloudio/uni-app";
import PageHeader from "@/components/PageHeader.vue";
import FooterButtons from "@/components/FooterButtons.vue";
import { addBorrow, updateBorrow, getDocumentList } from "@/api/fileManagement/borrow";
const formRef = ref();
const loading = ref(false);
const borrowId = ref("");
const isEdit = ref(false);
// å¼¹çª—显示状态
const showDocPicker = ref(false);
const showBorrowDatePicker = ref(false);
const showDueDatePicker = ref(false);
// æ•°æ®
const documentList = ref([]);
const borrowDateValue = ref(Date.now());
const dueReturnDateValue = ref(Date.now());
const displayDocName = ref(""); // ç”¨äºŽæ˜¾ç¤ºçš„æ–‡æ¡£åç§°
const form = ref({
  id: "",
  documentationId: "",
  borrower: "",
  borrowPurpose: "",
  borrowDate: "",
  dueReturnDate: "",
  remark: "",
  borrowStatus: "",
});
const rules = {
  borrower: [{ required: true, message: "请输入借阅人", trigger: "blur" }],
  documentationId: [{ required: true, message: "请选择借阅书籍", trigger: "change" }],
  borrowPurpose: [{ required: true, message: "请输入借阅目的", trigger: "blur" }],
  borrowDate: [{ required: true, message: "请选择借阅日期", trigger: "change" }],
  dueReturnDate: [{ required: true, message: "请选择应归还日期", trigger: "change" }],
};
// é¡µé¢æ ‡é¢˜
const pageTitle = computed(() => {
  if (isEdit.value) {
    return form.value.borrowStatus === "归还" ? "借阅详情" : "编辑借阅";
  }
  return "新增借阅";
});
// æ˜¯å¦å·²å½’还
const isReturned = computed(() => {
  return form.value.borrowStatus === "归还";
});
// æ–‡æ¡£é€‰é¡¹ï¼ˆä»…新增模式使用)
const documentOptions = computed(() => {
  return documentList.value.map((item) => ({
    name: item.docName || item.name,
    id: item.id,
  }));
});
// è¿”回上一页
const goBack = () => {
  uni.removeStorageSync("borrowEditData");
  uni.navigateBack();
};
// åŠ è½½æ–‡æ¡£åˆ—è¡¨ï¼ˆä»…æ–°å¢žæ¨¡å¼éœ€è¦ï¼‰
const loadDocumentList = async () => {
  try {
    const res = await getDocumentList();
    if (res.code === 200) {
      documentList.value = res.data || [];
    }
  } catch (error) {
    console.error("获取文档列表失败", error);
  }
};
// æ–‡æ¡£é€‰æ‹©ç¡®è®¤
const onDocSelect = (e) => {
  form.value.documentationId = e.id;
  displayDocName.value = e.name;
  showDocPicker.value = false;
};
// å€Ÿé˜…日期确认
const onBorrowDateConfirm = (e) => {
  const date = new Date(e.value);
  form.value.borrowDate = formatDate(date);
  showBorrowDatePicker.value = false;
};
// åº”归还日期确认
const onDueDateConfirm = (e) => {
  const date = new Date(e.value);
  form.value.dueReturnDate = formatDate(date);
  showDueDatePicker.value = false;
};
// æ ¼å¼åŒ–日期
const formatDate = (date) => {
  const year = date.getFullYear();
  const month = String(date.getMonth() + 1).padStart(2, "0");
  const day = String(date.getDate()).padStart(2, "0");
  return `${year}-${month}-${day}`;
};
// æäº¤è¡¨å•
const handleSubmit = () => {
  // å¦‚果已归还,禁止提交
  if (isReturned.value) {
    uni.showToast({ title: "已归还的借阅记录不能编辑", icon: "none" });
    return;
  }
  formRef.value
    .validate()
    .then(async () => {
      try {
        loading.value = true;
        if (isEdit.value) {
          // ç¼–辑模式
          const res = await updateBorrow({
            id: form.value.id,
            borrower: form.value.borrower,
            borrowPurpose: form.value.borrowPurpose,
            borrowDate: form.value.borrowDate,
            dueReturnDate: form.value.dueReturnDate,
            remark: form.value.remark,
          });
          if (res.code === 200) {
            uni.showToast({ title: "编辑成功", icon: "success" });
            setTimeout(() => {
              goBack();
            }, 1500);
          } else {
            uni.showToast({ title: res.msg || "编辑失败", icon: "none" });
          }
        } else {
          // æ–°å¢žæ¨¡å¼
          const res = await addBorrow({
            documentationId: form.value.documentationId,
            borrower: form.value.borrower,
            borrowPurpose: form.value.borrowPurpose,
            borrowDate: form.value.borrowDate,
            dueReturnDate: form.value.dueReturnDate,
            borrowStatus: "借阅",
            remark: form.value.remark,
          });
          if (res.code === 200) {
            uni.showToast({ title: "新增成功", icon: "success" });
            setTimeout(() => {
              goBack();
            }, 1500);
          } else {
            uni.showToast({ title: res.msg || "新增失败", icon: "none" });
          }
        }
      } catch (error) {
        uni.showToast({ title: "操作失败", icon: "none" });
      } finally {
        loading.value = false;
      }
    })
    .catch(() => {
      // éªŒè¯å¤±è´¥
    });
};
// é¡µé¢åŠ è½½
onLoad((options) => {
  if (options.id) {
    // ç¼–辑模式
    isEdit.value = true;
    borrowId.value = options.id;
    // ä»Ž storage èŽ·å–ç¼–è¾‘æ•°æ®
    const editDataStr = uni.getStorageSync("borrowEditData");
    if (editDataStr) {
      try {
        const data = JSON.parse(editDataStr);
        Object.assign(form.value, data);
        borrowDateValue.value = new Date(data.borrowDate).getTime();
        dueReturnDateValue.value = new Date(data.dueReturnDate).getTime();
        // ç›´æŽ¥ä½¿ç”¨ä¼ é€’的文档名称显示,尝试多个可能的字段名
        displayDocName.value = data.docName || data.documentationName || data.fileName || data.name || "";
      } catch (e) {
        console.error("解析编辑数据失败", e);
      }
    }
  } else {
    // æ–°å¢žæ¨¡å¼ï¼ŒåŠ è½½æ–‡æ¡£åˆ—è¡¨å¹¶è®¾ç½®é»˜è®¤æ—¥æœŸ
    loadDocumentList();
    const today = new Date();
    form.value.borrowDate = formatDate(today);
    borrowDateValue.value = today.getTime();
  }
});
</script>
<style lang="scss">
@import "@/static/scss/form-common.scss";
.borrow-edit {
  min-height: 100vh;
  background: #f5f5f5;
}
</style>
src/pages/fileManagement/borrow/index.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,262 @@
<template>
  <view class="sales-account">
    <!-- ä½¿ç”¨é€šç”¨é¡µé¢å¤´éƒ¨ç»„ä»¶ -->
    <PageHeader title="借阅管理" @back="goBack" />
    <!-- æœç´¢å’Œç­›é€‰åŒºåŸŸ -->
    <view class="search-section">
      <view class="search-bar">
        <view class="search-input">
          <up-input
            class="search-text"
            placeholder="请输入借阅人搜索"
            v-model="searchForm.borrower"
            @change="getList"
            clearable
          />
        </view>
        <view class="filter-button" @click="getList">
          <up-icon name="search" size="24" color="#999"></up-icon>
        </view>
      </view>
    </view>
    <!-- å€Ÿé˜…列表 -->
    <view class="ledger-list" v-if="borrowList.length > 0">
      <view v-for="(item, index) in borrowList" :key="index">
        <view class="ledger-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.docName || '-' }}</text>
            </view>
            <view class="item-tag" :class="getStatusClass(item.borrowStatus)">
              <text class="tag-text">{{ item.borrowStatus }}</text>
            </view>
          </view>
          <up-divider></up-divider>
          <view class="item-details">
            <view class="detail-row">
              <text class="detail-label">借阅人</text>
              <text class="detail-value">{{ item.borrower || '-' }}</text>
            </view>
            <view class="detail-row">
              <text class="detail-label">借阅目的</text>
              <text class="detail-value">{{ item.borrowPurpose || '-' }}</text>
            </view>
            <view class="detail-row">
              <text class="detail-label">借阅日期</text>
              <text class="detail-value">{{ item.borrowDate || '-' }}</text>
            </view>
            <view class="detail-row">
              <text class="detail-label">应归还日期</text>
              <text class="detail-value">{{ item.dueReturnDate || '-' }}</text>
            </view>
            <view class="detail-row" v-if="item.remark">
              <text class="detail-label">备注</text>
              <text class="detail-value">{{ item.remark }}</text>
            </view>
          </view>
          <up-divider></up-divider>
          <view class="detail-buttons">
            <u-button
              v-if="item.borrowStatus !== '归还'"
              class="detail-button"
              size="small"
              type="primary"
              @click.stop="goEdit(item)"
            >
              ç¼–辑
            </u-button>
            <u-button
              v-if="item.borrowStatus !== '归还'"
              class="detail-button"
              size="small"
              type="error"
              plain
              @click.stop="handleDelete(item)"
            >
              åˆ é™¤
            </u-button>
            <u-button
              v-if="item.borrowStatus === '归还'"
              class="detail-button"
              size="small"
              type="primary"
              plain
              @click.stop="goView(item)"
            >
              æŸ¥çœ‹
            </u-button>
          </view>
        </view>
      </view>
    </view>
    <view v-else class="no-data">
      <text>暂无借阅记录</text>
    </view>
    <!-- æµ®åŠ¨æ“ä½œæŒ‰é’® -->
    <view class="fab-button" @click="goAdd">
      <up-icon name="plus" size="24" color="#ffffff"></up-icon>
    </view>
  </view>
</template>
<script setup>
import { ref, reactive } from "vue";
import { onShow } from "@dcloudio/uni-app";
import PageHeader from "@/components/PageHeader.vue";
import { getBorrowList, deleteBorrow } from "@/api/fileManagement/borrow";
// æŸ¥è¯¢è¡¨å•
const searchForm = reactive({
  borrower: "",
});
// å€Ÿé˜…列表数据
const borrowList = ref([]);
// åˆ†é¡µç›¸å…³
const pagination = reactive({
  currentPage: 1,
  pageSize: 10,
  total: 0,
});
// è¿”回上一页
const goBack = () => {
  uni.navigateBack();
};
// èŽ·å–çŠ¶æ€æ ·å¼ç±»
const getStatusClass = (status) => {
  if (status === "归还") return "tag-success";
  if (status === "借阅") return "tag-warning";
  return "tag-default";
};
// åŠ è½½å€Ÿé˜…åˆ—è¡¨
const getList = async () => {
  uni.showLoading({ title: "加载中...", mask: true });
  const query = {
    page: -1,
    size: -1,
    borrower: searchForm.borrower || undefined,
  };
  try {
    const res = await getBorrowList(query);
    if (res.code === 200) {
      borrowList.value = res.data.records || [];
      pagination.total = res.data.total || 0;
    } else {
      uni.showToast({ title: res.msg || "获取借阅列表失败", icon: "none" });
      borrowList.value = [];
    }
  } catch (error) {
    uni.showToast({ title: "获取借阅列表失败", icon: "none" });
    borrowList.value = [];
  } finally {
    uni.hideLoading();
  }
};
// è·³è½¬åˆ°æ–°å¢žé¡µé¢
const goAdd = () => {
  uni.navigateTo({
    url: "/pages/fileManagement/borrow/edit",
  });
};
// è·³è½¬åˆ°ç¼–辑页面
const goEdit = (item) => {
  uni.setStorageSync("borrowEditData", JSON.stringify(item));
  uni.navigateTo({
    url: `/pages/fileManagement/borrow/edit?id=${item.id}`,
  });
};
// è·³è½¬åˆ°æŸ¥çœ‹é¡µé¢ï¼ˆå·²å½’还记录)
const goView = (item) => {
  uni.setStorageSync("borrowEditData", JSON.stringify(item));
  uni.navigateTo({
    url: `/pages/fileManagement/borrow/edit?id=${item.id}`,
  });
};
// åˆ é™¤
const handleDelete = (row) => {
  uni.showModal({
    title: "删除确认",
    content: "选中的内容将被删除,是否确认删除?",
    confirmText: "确认",
    cancelText: "取消",
    success: async (res) => {
      if (res.confirm) {
        try {
          uni.showLoading({ title: "删除中...", mask: true });
          const result = await deleteBorrow([row.id]);
          if (result.code === 200) {
            uni.showToast({ title: "删除成功", icon: "success" });
            getList();
          } else {
            uni.showToast({ title: result.msg || "删除失败", icon: "none" });
          }
        } catch (error) {
          uni.showToast({ title: "删除失败", icon: "none" });
        } finally {
          uni.hideLoading();
        }
      }
    },
  });
};
onShow(() => {
  getList();
});
</script>
<style scoped lang="scss">
@import "@/styles/sales-common.scss";
// æ ‡ç­¾æ ·å¼
.item-tag {
  border-radius: 4px;
  padding: 2px 8px;
  &.tag-success {
    background: #4caf50;
  }
  &.tag-warning {
    background: #ff9800;
  }
  &.tag-default {
    background: #9e9e9e;
  }
}
.tag-text {
  font-size: 11px;
  color: #ffffff;
  font-weight: 500;
}
// æŒ‰é’®æ ·å¼
.detail-buttons {
  padding: 12px 0;
  display: flex;
  gap: 12px;
}
.detail-button {
  flex: 1;
}
</style>
src/pages/fileManagement/return/edit.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,313 @@
<template>
  <view class="return-edit">
    <PageHeader :title="pageTitle" @back="goBack" />
    <up-form
      ref="formRef"
      :model="form"
      :rules="rules"
      label-width="110"
    >
      <up-form-item label="文档" prop="borrowId" required>
        <up-input
          v-model="displayDocName"
          placeholder="请选择文档"
          readonly
          :disabled="isEdit"
          @click="!isEdit && (showDocPicker = true)"
        />
        <template #right>
          <up-icon v-if="!isEdit" name="arrow-right" @click="showDocPicker = true"></up-icon>
        </template>
      </up-form-item>
      <up-form-item label="借阅人" prop="borrower">
        <up-input
          v-model="form.borrower"
          placeholder="选择文档后自动带出"
          disabled
        />
      </up-form-item>
      <up-form-item label="归还人" prop="returner" required>
        <up-input
          v-model="form.returner"
          placeholder="请输入归还人"
          clearable
          :disabled="isReturned"
        />
      </up-form-item>
      <up-form-item label="归还日期" prop="returnDate" required>
        <up-input
          v-model="form.returnDate"
          placeholder="请选择归还日期"
          readonly
          @click="!isReturned && (showReturnDatePicker = true)"
          :disabled="isReturned"
        />
        <template #right>
          <up-icon name="arrow-right" @click="!isReturned && (showReturnDatePicker = true)"></up-icon>
        </template>
      </up-form-item>
      <up-form-item label="应归还日期" prop="dueReturnDate">
        <up-input
          v-model="form.dueReturnDate"
          placeholder="选择文档后自动带出"
          disabled
        />
      </up-form-item>
      <up-form-item label="备注说明" prop="remark">
        <up-textarea
          v-model="form.remark"
          placeholder="请输入备注说明"
          height="80"
          border="none"
          :disabled="isReturned"
        />
      </up-form-item>
    </up-form>
    <FooterButtons
      v-if="!isReturned"
      :loading="loading"
      :confirmText="isEdit ? '保存' : '新增'"
      @cancel="goBack"
      @confirm="handleSubmit"
    />
    <!-- æ–‡æ¡£é€‰æ‹©å™¨ -->
    <up-action-sheet
      :show="showDocPicker"
      :actions="documentOptions"
      title="选择文档"
      @select="onDocSelect"
      @close="showDocPicker = false"
    />
    <!-- å½’还日期选择器 -->
    <up-popup :show="showReturnDatePicker" mode="bottom" @close="showReturnDatePicker = false">
      <up-datetime-picker
        :show="true"
        v-model="returnDateValue"
        @confirm="onReturnDateConfirm"
        @cancel="showReturnDatePicker = false"
        mode="date"
      />
    </up-popup>
  </view>
</template>
<script setup>
import { ref, computed, onMounted } from "vue";
import { onLoad } from "@dcloudio/uni-app";
import PageHeader from "@/components/PageHeader.vue";
import FooterButtons from "@/components/FooterButtons.vue";
import { returnDocument, reventUpdate, getDocumentList } from "@/api/fileManagement/return";
const formRef = ref();
const loading = ref(false);
const returnId = ref("");
const isEdit = ref(false);
// å¼¹çª—显示状态
const showDocPicker = ref(false);
const showReturnDatePicker = ref(false);
// æ•°æ®
const documentList = ref([]);
const returnDateValue = ref(Date.now());
const displayDocName = ref(""); // ç”¨äºŽæ˜¾ç¤ºçš„æ–‡æ¡£åç§°
const form = ref({
  id: "",
  borrowId: "",
  documentationId: "",
  borrower: "",
  returner: "",
  borrowStatus: "",
  returnDate: "",
  dueReturnDate: "",
  remark: "",
});
const rules = {
  borrowId: [{ required: true, message: "请选择文档", trigger: "change" }],
  returner: [{ required: true, message: "请输入归还人", trigger: "blur" }],
  returnDate: [{ required: true, message: "请选择归还日期", trigger: "change" }],
};
// é¡µé¢æ ‡é¢˜
const pageTitle = computed(() => {
  if (isEdit.value) {
    return form.value.borrowStatus === "归还" ? "归还详情" : "编辑归还";
  }
  return "新增归还";
});
// æ˜¯å¦å·²å½’还
const isReturned = computed(() => {
  return form.value.borrowStatus === "归还";
});
// æ–‡æ¡£é€‰é¡¹ï¼ˆä»…新增模式使用)
const documentOptions = computed(() => {
  return documentList.value.map((item) => ({
    name: item.docName || item.name,
    id: item.id,
    borrower: item.borrower,
    dueReturnDate: item.dueReturnDate,
  }));
});
// è¿”回上一页
const goBack = () => {
  uni.removeStorageSync("returnEditData");
  uni.navigateBack();
};
// åŠ è½½æ–‡æ¡£åˆ—è¡¨ï¼ˆä»…æ–°å¢žæ¨¡å¼éœ€è¦ï¼‰
const loadDocumentList = async () => {
  try {
    const res = await getDocumentList();
    if (res.code === 200) {
      documentList.value = res.data || [];
    }
  } catch (error) {
    console.error("获取文档列表失败", error);
  }
};
// æ–‡æ¡£é€‰æ‹©ç¡®è®¤
const onDocSelect = (e) => {
  form.value.borrowId = e.id;
  form.value.documentationId = e.id;
  displayDocName.value = e.name;
  // è‡ªåŠ¨å¸¦å‡ºå€Ÿé˜…äººå’Œåº”å½’è¿˜æ—¥æœŸ
  form.value.borrower = e.borrower || "";
  form.value.dueReturnDate = e.dueReturnDate || "";
  showDocPicker.value = false;
};
// å½’还日期确认
const onReturnDateConfirm = (e) => {
  const date = new Date(e.value);
  form.value.returnDate = formatDate(date);
  showReturnDatePicker.value = false;
};
// æ ¼å¼åŒ–日期
const formatDate = (date) => {
  const year = date.getFullYear();
  const month = String(date.getMonth() + 1).padStart(2, "0");
  const day = String(date.getDate()).padStart(2, "0");
  return `${year}-${month}-${day}`;
};
// æäº¤è¡¨å•
const handleSubmit = () => {
  // å¦‚果已归还,禁止提交
  if (isReturned.value) {
    uni.showToast({ title: "已归还的记录不能编辑", icon: "none" });
    return;
  }
  formRef.value
    .validate()
    .then(async () => {
      try {
        loading.value = true;
        if (isEdit.value) {
          // ç¼–辑模式
          const res = await reventUpdate({
            id: form.value.id,
            documentationId: form.value.documentationId,
            borrower: form.value.borrower,
            returner: form.value.returner,
            borrowStatus: form.value.borrowStatus,
            returnDate: form.value.returnDate,
            dueReturnDate: form.value.dueReturnDate,
            remark: form.value.remark,
          });
          if (res.code === 200) {
            uni.showToast({ title: "编辑成功", icon: "success" });
            setTimeout(() => {
              goBack();
            }, 1500);
          } else {
            uni.showToast({ title: res.msg || "编辑失败", icon: "none" });
          }
        } else {
          // æ–°å¢žæ¨¡å¼
          const res = await returnDocument({
            borrowId: form.value.borrowId,
            borrower: form.value.borrower,
            returner: form.value.returner,
            borrowStatus: "归还",
            returnDate: form.value.returnDate,
            dueReturnDate: form.value.dueReturnDate,
            remark: form.value.remark,
          });
          if (res.code === 200) {
            uni.showToast({ title: "新增成功", icon: "success" });
            setTimeout(() => {
              goBack();
            }, 1500);
          } else {
            uni.showToast({ title: res.msg || "新增失败", icon: "none" });
          }
        }
      } catch (error) {
        uni.showToast({ title: "操作失败", icon: "none" });
      } finally {
        loading.value = false;
      }
    })
    .catch(() => {
      // éªŒè¯å¤±è´¥
    });
};
// é¡µé¢åŠ è½½
onLoad((options) => {
  if (options.id) {
    // ç¼–辑模式
    isEdit.value = true;
    returnId.value = options.id;
    // ä»Ž storage èŽ·å–ç¼–è¾‘æ•°æ®
    const editDataStr = uni.getStorageSync("returnEditData");
    if (editDataStr) {
      try {
        const data = JSON.parse(editDataStr);
        Object.assign(form.value, data);
        returnDateValue.value = new Date(data.returnDate).getTime();
        // ç›´æŽ¥ä½¿ç”¨ä¼ é€’çš„ docName æ˜¾ç¤º
        displayDocName.value = data.docName || "";
      } catch (e) {
        console.error("解析编辑数据失败", e);
      }
    }
  } else {
    // æ–°å¢žæ¨¡å¼ï¼ŒåŠ è½½æ–‡æ¡£åˆ—è¡¨å¹¶è®¾ç½®é»˜è®¤æ—¥æœŸ
    loadDocumentList();
    const today = new Date();
    form.value.returnDate = formatDate(today);
    returnDateValue.value = today.getTime();
  }
});
</script>
<style lang="scss">
@import "@/static/scss/form-common.scss";
.return-edit {
  min-height: 100vh;
  background: #f5f5f5;
}
</style>
src/pages/fileManagement/return/index.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,262 @@
<template>
  <view class="sales-account">
    <!-- ä½¿ç”¨é€šç”¨é¡µé¢å¤´éƒ¨ç»„ä»¶ -->
    <PageHeader title="归还管理" @back="goBack" />
    <!-- æœç´¢å’Œç­›é€‰åŒºåŸŸ -->
    <view class="search-section">
      <view class="search-bar">
        <view class="search-input">
          <up-input
            class="search-text"
            placeholder="请输入借阅人搜索"
            v-model="searchForm.borrower"
            @change="getList"
            clearable
          />
        </view>
        <view class="filter-button" @click="getList">
          <up-icon name="search" size="24" color="#999"></up-icon>
        </view>
      </view>
    </view>
    <!-- å½’还列表 -->
    <view class="ledger-list" v-if="returnList.length > 0">
      <view v-for="(item, index) in returnList" :key="index">
        <view class="ledger-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.docName || '-' }}</text>
            </view>
            <view class="item-tag" :class="getStatusClass(item.borrowStatus)">
              <text class="tag-text">{{ item.borrowStatus }}</text>
            </view>
          </view>
          <up-divider></up-divider>
          <view class="item-details">
            <view class="detail-row">
              <text class="detail-label">借阅人</text>
              <text class="detail-value">{{ item.borrower || '-' }}</text>
            </view>
            <view class="detail-row">
              <text class="detail-label">归还人</text>
              <text class="detail-value">{{ item.returner || '-' }}</text>
            </view>
            <view class="detail-row">
              <text class="detail-label">归还日期</text>
              <text class="detail-value">{{ item.returnDate || '-' }}</text>
            </view>
            <view class="detail-row">
              <text class="detail-label">应归还日期</text>
              <text class="detail-value">{{ item.dueReturnDate || '-' }}</text>
            </view>
            <view class="detail-row" v-if="item.remark">
              <text class="detail-label">备注</text>
              <text class="detail-value">{{ item.remark }}</text>
            </view>
          </view>
          <up-divider></up-divider>
          <view class="detail-buttons">
            <u-button
              v-if="item.borrowStatus !== '归还'"
              class="detail-button"
              size="small"
              type="primary"
              @click.stop="goEdit(item)"
            >
              ç¼–辑
            </u-button>
            <u-button
              v-if="item.borrowStatus !== '归还'"
              class="detail-button"
              size="small"
              type="error"
              plain
              @click.stop="handleDelete(item)"
            >
              åˆ é™¤
            </u-button>
            <u-button
              v-if="item.borrowStatus === '归还'"
              class="detail-button"
              size="small"
              type="primary"
              plain
              @click.stop="goView(item)"
            >
              æŸ¥çœ‹
            </u-button>
          </view>
        </view>
      </view>
    </view>
    <view v-else class="no-data">
      <text>暂无归还记录</text>
    </view>
    <!-- æµ®åŠ¨æ“ä½œæŒ‰é’® -->
    <view class="fab-button" @click="goAdd">
      <up-icon name="plus" size="24" color="#ffffff"></up-icon>
    </view>
  </view>
</template>
<script setup>
import { ref, reactive } from "vue";
import { onShow } from "@dcloudio/uni-app";
import PageHeader from "@/components/PageHeader.vue";
import { getReturnListPage, deleteReturn } from "@/api/fileManagement/return";
// æŸ¥è¯¢è¡¨å•
const searchForm = reactive({
  borrower: "",
});
// å½’还列表数据
const returnList = ref([]);
// åˆ†é¡µç›¸å…³
const pagination = reactive({
  currentPage: 1,
  pageSize: 10,
  total: 0,
});
// è¿”回上一页
const goBack = () => {
  uni.navigateBack();
};
// èŽ·å–çŠ¶æ€æ ·å¼ç±»
const getStatusClass = (status) => {
  if (status === "归还") return "tag-success";
  if (status === "借阅") return "tag-warning";
  return "tag-default";
};
// åŠ è½½å½’è¿˜åˆ—è¡¨
const getList = async () => {
  uni.showLoading({ title: "加载中...", mask: true });
  const query = {
    page: -1,
    size: -1,
    borrower: searchForm.borrower || undefined,
  };
  try {
    const res = await getReturnListPage(query);
    if (res.code === 200) {
      returnList.value = res.data.records || [];
      pagination.total = res.data.total || 0;
    } else {
      uni.showToast({ title: res.msg || "获取归还列表失败", icon: "none" });
      returnList.value = [];
    }
  } catch (error) {
    uni.showToast({ title: "获取归还列表失败", icon: "none" });
    returnList.value = [];
  } finally {
    uni.hideLoading();
  }
};
// è·³è½¬åˆ°æ–°å¢žé¡µé¢
const goAdd = () => {
  uni.navigateTo({
    url: "/pages/fileManagement/return/edit",
  });
};
// è·³è½¬åˆ°ç¼–辑页面
const goEdit = (item) => {
  uni.setStorageSync("returnEditData", JSON.stringify(item));
  uni.navigateTo({
    url: `/pages/fileManagement/return/edit?id=${item.id}`,
  });
};
// è·³è½¬åˆ°æŸ¥çœ‹é¡µé¢ï¼ˆå·²å½’还记录)
const goView = (item) => {
  uni.setStorageSync("returnEditData", JSON.stringify(item));
  uni.navigateTo({
    url: `/pages/fileManagement/return/edit?id=${item.id}`,
  });
};
// åˆ é™¤
const handleDelete = (row) => {
  uni.showModal({
    title: "删除确认",
    content: "选中的内容将被删除,是否确认删除?",
    confirmText: "确认",
    cancelText: "取消",
    success: async (res) => {
      if (res.confirm) {
        try {
          uni.showLoading({ title: "删除中...", mask: true });
          const result = await deleteReturn([row.id]);
          if (result.code === 200) {
            uni.showToast({ title: "删除成功", icon: "success" });
            getList();
          } else {
            uni.showToast({ title: result.msg || "删除失败", icon: "none" });
          }
        } catch (error) {
          uni.showToast({ title: "删除失败", icon: "none" });
        } finally {
          uni.hideLoading();
        }
      }
    },
  });
};
onShow(() => {
  getList();
});
</script>
<style scoped lang="scss">
@import "@/styles/sales-common.scss";
// æ ‡ç­¾æ ·å¼
.item-tag {
  border-radius: 4px;
  padding: 2px 8px;
  &.tag-success {
    background: #4caf50;
  }
  &.tag-warning {
    background: #ff9800;
  }
  &.tag-default {
    background: #9e9e9e;
  }
}
.tag-text {
  font-size: 11px;
  color: #ffffff;
  font-weight: 500;
}
// æŒ‰é’®æ ·å¼
.detail-buttons {
  padding: 12px 0;
  display: flex;
  gap: 12px;
}
.detail-button {
  flex: 1;
}
</style>
src/pages/works.vue
@@ -271,16 +271,13 @@
<script setup>
  import { ref, onMounted, nextTick, reactive, computed } from "vue";
  import { onShow } from "@dcloudio/uni-app";
  import { userLoginFacotryList } from "@/api/login";
  import { getProductWorkOrderById } from "@/api/productionManagement/productionReporting";
  import { createVersionUpgradeChecker } from "@/utils/versionUpgrade";
  import DownloadProgressMask from "@/components/DownloadProgressMask.vue";
  import modal from "@/plugins/modal";
  import useUserStore from "@/store/modules/user";
  const userStore = useUserStore();
  const { triggerVersionCheck } = createVersionUpgradeChecker({ logPrefix: "[version-works]" });
  const show = ref(false);
  const factoryList = ref([]);
  const factoryListTem = ref([]);
@@ -337,6 +334,10 @@
      icon: "/static/images/icon/caigouguanli.svg",
      label: "采购退货",
    },
    {
      icon: "/static/images/icon/gongyingshangdangan.svg",
      label: "供应商档案",
    },
  ]);
  // è´¢åŠ¡ç®¡ç†åŠŸèƒ½æ•°æ®
@@ -391,9 +392,13 @@
  const archiveManagementItems = reactive([
    {
      icon: "/static/images/icon/gongyingshangdangan.svg",
      label: "供应商档案",
      label: "借阅登记",
    },
  ]);
    {
      icon: "/static/images/icon/hetongguanli.svg",
      label: "归还登记",
    }
  ])
  // å”®åŽæœåŠ¡åŠŸèƒ½æ•°æ®
  const afterSalesServiceItems = reactive([
@@ -923,6 +928,16 @@
          url: "/pages/customerService/afterSalesHandling/index",
        });
        break;
      case "借阅登记":
        uni.navigateTo({
          url: "/pages/fileManagement/borrow/index",
        });
        break;
      case "归还登记":
        uni.navigateTo({
          url: "/pages/fileManagement/return/index",
        });
        break;
      default:
        uni.showToast({
          title: `点击了${item.label}`,
@@ -1111,7 +1126,7 @@
    // å®šä¹‰èœå•配置映射
    const menuMapping = {
      collaboration: { target: collaborationItems, specialMapping: { "规章制度": "规章制度管理" } },
      archiveManagement: { target: archiveManagementItems, specialMapping: { "供应商档案": "供应商管理" } },
      purchase: { specialMapping: { "供应商档案": "供应商管理" } },
    };
    console.log(allowedMenuTitles)
    // é€šç”¨è¿‡æ»¤å‡½æ•°
@@ -1128,9 +1143,8 @@
    // è¿‡æ»¤å„个模块
    filterArray(marketingItems);
    filterArray(purchaseItems);
    filterArray(purchaseItems, menuMapping.purchase.specialMapping);
    filterArray(financeManagementItems);
    filterArray(archiveManagementItems, menuMapping.archiveManagement.specialMapping);
    filterArray(collaborationItems, menuMapping.collaboration.specialMapping);
    filterArray(safetyItems);
    filterArray(humanResourcesItems);
@@ -1138,13 +1152,13 @@
    filterArray(qualityItems);
    filterArray(productionItems);
    filterArray(equipmentItems);
    filterArray(archiveManagementItems);
  };
  // æ£€æŸ¥æ¨¡å—是否有菜单项需要显示
  const hasMarketingItems = computed(() => marketingItems.length > 0);
  const hasPurchaseItems = computed(() => purchaseItems.length > 0);
  const hasFinanceManagementItems = computed(() => financeManagementItems.length > 0);
  const hasArchiveManagementItems = computed(() => archiveManagementItems.length > 0);
  const hasAfterSalesServiceItems = computed(() => afterSalesServiceItems.length > 0);
  const hasCollaborationItems = computed(() => collaborationItems.length > 0);
  const hasSafetyItems = computed(() => safetyItems.length > 0);
@@ -1153,9 +1167,9 @@
  const hasWarehouseLogisticsItems = computed(() => warehouseLogisticsItems.length > 0);
  const hasProductionItems = computed(() => productionItems.length > 0);
  const hasEquipmentItems = computed(() => equipmentItems.length > 0);
  const hasArchiveManagementItems = computed(() => archiveManagementItems.length > 0);
  onMounted(() => {
    triggerVersionCheck("onMounted");
    // æ¯æ¬¡è¿›å…¥é¦–页都强制刷新用户信息和路由权限,不做本地缓存判断
    userStore.getInfo().then(() => {
      userStore
@@ -1170,10 +1184,6 @@
    getUserLoginFacotryList();
    // å¯åŠ¨é€šçŸ¥çŠ¶æ€å®šæ—¶å™¨
    startStatusTimer();
  });
  onShow(() => {
    triggerVersionCheck("onShow");
  });
</script>
src/utils/versionUpgrade.js
@@ -1,6 +1,7 @@
import config from "@/config";
import { getAllVersion } from "@/api/viewIndex";
import bus from "@/plugins/bus";
let hasTriggeredVersionCheckInSession = false;
function compareVersion(v1, v2) {
  const s1 = String(v1 || "").replace(/[^\d.]/g, "").split(".").map((n) => Number(n) || 0);
@@ -264,12 +265,17 @@
  let lastVersionCheckAt = 0;
  const triggerVersionCheck = async (from = "unknown") => {
    if (hasTriggeredVersionCheckInSession) {
      console.log(`${logPrefix} è·³è¿‡ç‰ˆæœ¬æ£€æŸ¥ï¼Œæœ¬æ¬¡ä¼šè¯å·²æ£€æµ‹è¿‡ï¼Œæ¥æº=${from}`);
      return;
    }
    const now = Date.now();
    if (now - lastVersionCheckAt < throttleMs) {
      console.log(`${logPrefix} è·³è¿‡é‡å¤æ£€æŸ¥ï¼Œæ¥æº=${from}`);
      return;
    }
    lastVersionCheckAt = now;
    hasTriggeredVersionCheckInSession = true;
    console.log(`${logPrefix} è§¦å‘版本检查,来源=${from}`);
    const currentVersion = await getCurrentVersion(logPrefix);
    await checkAppVersionUpgrade(logPrefix, currentVersion);