已修改13个文件
371 ■■■■ 文件已修改
src/App.vue 24 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/login.js 28 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/pages/humanResources/attendance/checkin.vue 120 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/pages/managementMeetings/knowledgeBase/detail.vue 45 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/pages/managementMeetings/knowledgeBase/index.vue 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/pages/managementMeetings/rulesRegulationsManagement/index.vue 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/pages/managementMeetings/sealManagement/index.vue 18 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/pages/message.vue 35 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/pages/procurementManagement/paymentEntry/add.vue 11 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/pages/procurementManagement/procurementLedger/index.vue 29 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/pages/sales/salesAccount/detail.vue 10 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/pages/sales/salesAccount/index.vue 39 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/utils/request.ts 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/App.vue
@@ -7,6 +7,7 @@
<script setup>
  import { ref, onMounted } from "vue";
  import Splash from "./components/Splash.vue";
  import { confirmMessage } from "@/api/login.js";
  const showSplash = ref(true);
  onMounted(() => {
@@ -54,16 +55,21 @@
  // 处理推送消息点击事件
  const handlePushClick = msg => {
    console.log("点击推送消息:", msg);
    console.log("解析后:", msg.payload.noticeId);
    try {
      if (msg.payload.indexOf("/") === 0) {
        uni.navigateTo({
          url: msg.payload,
        });
      } else {
        uni.navigateTo({
          url: "/" + msg.payload,
        });
      }
      confirmMessage(msg.payload.noticeId, 1).then(res => {
        if (msg.payload.url) {
          if (msg.payload.url.indexOf("/") === 0) {
            uni.navigateTo({
              url: msg.payload.url,
            });
          } else {
            uni.navigateTo({
              url: "/" + msg.payload.url,
            });
          }
        }
      });
    } catch (error) {
      uni.showToast({
        title: "路径:" + msg.payload,
src/api/login.js
@@ -76,4 +76,30 @@
    method: 'get',
    params: { consigneeId }
  })
}
}
// 标记消息为已读
export function markAsRead(noticeId, status) {
  return request({
    url: "/system/notice",
    method: "put",
    data: { noticeId, status },
  });
}
// 一键标记所有消息为已读
export function markAllAsRead() {
  return request({
    url: "/system/notice/readAll",
    method: "post",
  });
}
// 确认消息
export function confirmMessage(noticeId, status) {
  return request({
    url: "/system/notice",
    method: "put",
    data: { noticeId, status },
  });
}
src/pages/humanResources/attendance/checkin.vue
@@ -14,14 +14,14 @@
          <u-icon name="calendar"
                  color="#348fe2"
                  size="16"></u-icon>
          <text class="shift-text">白班: {{ workTimeDict.startAt }}-{{ workTimeDict.endAt }}</text>
          <text class="shift-text">白班: {{ todayRecord.startAt }}-{{ todayRecord.endAt }}</text>
        </view>
      </view>
      <!-- 打卡按钮 -->
      <view class="checkin-button-container">
        <view class="checkin-button-wrapper">
          <view class="checkin-button"
                :class="{ 'disabled': todayRecord.workEndAt }"
                :class="{ 'disabled': todayRecord.workEndAt || noNeedCheckIn }"
                @click="handleCheckInOut">
            <text class="checkin-button-text">{{ checkInOutText }}</text>
            <text class="checkin-time">{{ nowTime.split(' ')[1] }}</text>
@@ -114,6 +114,12 @@
  // 当前时间展示
  const nowTime = ref("");
  let timer = null;
  // 上次打卡时间
  const lastCheckInTime = ref(null);
  // 打卡冷却时间(毫秒)
  const CHECKIN_COOLDOWN = 5000;
  // 返回上一页
  const goBack = () => {
    uni.navigateBack();
@@ -121,12 +127,22 @@
  // 查询今日打卡信息
  const fetchTodayData = () => {
    findTodayPersonalAttendanceRecord({}).then(res => {
      todayRecord.value = res.data;
      if (res.data) {
        todayRecord.value = res.data;
        noNeedCheckIn.value = false;
      } else {
        // 页面显示“无需打卡”
        todayRecord.value = {};
        noNeedCheckIn.value = true;
      }
    });
  };
  // 打卡范围状态
  const inCheckRange = ref(true);
  // 是否无需打卡
  const noNeedCheckIn = ref(false);
  // 当前位置
  const currentLocation = ref(null);
@@ -147,6 +163,9 @@
  // 打卡按钮文本
  const checkInOutText = computed(() => {
    if (noNeedCheckIn.value) {
      return "无需打卡";
    }
    if (!todayRecord.value || !todayRecord.value.workStartAt) {
      return "上班打卡";
    }
@@ -217,26 +236,52 @@
      // #endif
    });
  };
  const form = ref({
    longitude: "",
    latitude: "",
  });
  // 获取当前位置
  const getCurrentLocation = () => {
    return new Promise((resolve, reject) => {
      uni.getLocation({
        type: "wgs84",
        success: res => {
          currentLocation.value = res;
          // 模拟检查是否在打卡范围内(实际项目中应根据公司位置和允许的半径进行计算)
          // 这里简单模拟为始终在范围内
          inCheckRange.value = true;
          resolve(res);
        },
        fail: err => {
          console.error("获取位置失败:", err);
          // 失败时默认允许打卡(实际项目中应根据业务需求处理)
          inCheckRange.value = true;
          reject(err);
        },
      });
    uni.showLoading({ title: "获取位置中..." });
    uni.getLocation({
      type: "gcj02",
      success: res => {
        uni.hideLoading();
        form.value.latitude = res.latitude;
        form.value.longitude = res.longitude;
      },
      fail: err => {
        uni.hideLoading();
        console.error("获取位置失败:", err);
        // 显示错误提示并引导用户检查权限
        showToast("获取位置失败,请检查定位权限");
        // 引导用户检查权限设置
        uni.showModal({
          title: "位置权限提示",
          content:
            "获取位置失败,可能是因为位置权限未开启,请在设备设置中检查并开启位置权限。",
          confirmText: "知道了",
          cancelText: "取消",
          success: res => {
            if (res.confirm) {
              // 可以尝试打开设置页面(如果支持)
              if (uni.openSetting) {
                uni.openSetting({
                  success: settingRes => {
                    console.log("设置结果:", settingRes);
                  },
                });
              }
            }
          },
        });
        // 失败时显示错误信息
        form.value.visitAddress = "位置获取失败";
      },
    });
  };
@@ -259,6 +304,14 @@
  // 打卡逻辑
  const handleCheckInOut = async () => {
    if (noNeedCheckIn.value) {
      uni.showToast({
        title: "今日无需打卡",
        icon: "none",
      });
      return;
    }
    if (todayRecord.value.workEndAt) {
      uni.showToast({
        title: "您已经打过卡了,无需重复打卡!!!",
@@ -266,6 +319,21 @@
      });
      return;
    }
    // 检查是否在打卡冷却时间内
    if (lastCheckInTime.value) {
      const currentTime = Date.now();
      const timeDiff = currentTime - lastCheckInTime.value;
      if (timeDiff < CHECKIN_COOLDOWN) {
        const remainingTime = Math.ceil((CHECKIN_COOLDOWN - timeDiff) / 1000);
        uni.showToast({
          title: `请${remainingTime}秒后再试`,
          icon: "none",
        });
        return;
      }
    }
    // 检查是否在打卡范围内
    if (!inCheckRange.value) {
      uni.showToast({
@@ -276,8 +344,13 @@
    }
    // 调用打卡API
    createPersonalAttendanceRecord({})
    createPersonalAttendanceRecord({
      ...form.value,
    })
      .then(res => {
        // 记录打卡时间
        lastCheckInTime.value = Date.now();
        uni.showToast({
          title: "打卡成功!",
          icon: "success",
@@ -286,7 +359,6 @@
        fetchTodayData();
      })
      .catch(error => {
        console.error("打卡失败:", error);
        uni.showToast({
          title: error.msg || "打卡失败,请重试",
          icon: "none",
@@ -302,7 +374,7 @@
    // 获取位置权限并检查位置
    try {
      await getLocationPermission();
      // await getLocationPermission();
      await getCurrentLocation();
    } catch (error) {
      console.error("位置权限获取失败:", error);
src/pages/managementMeetings/knowledgeBase/detail.vue
@@ -32,7 +32,7 @@
                   prop="scenario"
                   border-bottom>
        <u-input v-model="form.scenario"
                 readonly="readonly"
                 :readonly="readonly"
                 placeholder="请输入适用场景" />
      </u-form-item>
      <u-form-item label="解决效率"
@@ -81,8 +81,17 @@
                   prop="creator"
                   border-bottom>
        <u-input v-model="form.creator"
                 readonly
                 placeholder="请选择创建人"
                 @click="openCreatorSheet" />
        <template v-if="!readonly"
                  #right>
          <up-icon name="arrow-right"
                   @click="openCreatorSheet"></up-icon>
        </template>
        <!-- <u-input v-model="form.creator"
                 :readonly="readonly"
                 placeholder="请输入创建人" />
                 placeholder="请输入创建人" /> -->
      </u-form-item>
      <u-form-item label="使用次数"
                   prop="usageCount"
@@ -109,6 +118,10 @@
                     :actions="equipmentOptions"
                     @select="handleEquipmentChange"
                     @close="showEquipmentSheet = false" />
    <up-action-sheet :show="showCreatorSheet"
                     :actions="creatorOptions"
                     @select="handleCreatorChange"
                     @close="showCreatorSheet = false" />
    <!-- <u-popup :show="showEquipmentSheet"
             mode="bottom"
             @close="showEquipmentSheet = false"
@@ -157,6 +170,7 @@
    addKnowledgeBase,
    updateKnowledgeBase,
  } from "@/api/managementMeetings/knowledgeBase";
  import { userListNoPageByTenantId } from "@/api/system/user";
  const userStore = useUserStore();
@@ -198,6 +212,32 @@
    form.value.efficiency = action.value;
    statusname.value = action.name;
    showStatusSheet.value = false;
  };
  const showCreatorSheet = ref(false);
  const creatorOptions = ref([]);
  const openCreatorSheet = () => {
    showCreatorSheet.value = true;
  };
  const getCreatorOptions = async () => {
    try {
      const res = await userListNoPageByTenantId();
      if (res.code === 200) {
        creatorOptions.value = res.data || [];
        creatorOptions.value.forEach(item => {
          item.name = item.nickName;
          item.value = item.userId;
        });
      } else {
        showToast("获取创建人列表失败");
      }
    } catch (e) {
      console.error("获取创建人列表失败:", e);
      showToast("获取创建人列表失败");
    }
  };
  // 创建人选择
  const handleCreatorChange = val => {
    form.value.creator = val.name;
  };
  const equipmentname = ref("");
  // 设备配置选择
@@ -305,6 +345,7 @@
  });
  onMounted(() => {
    getCreatorOptions();
    // 从本地存储中获取知识数据
    const knowledgeBase = uni.getStorageSync("knowledgeBase");
    if (knowledgeBase) {
src/pages/managementMeetings/knowledgeBase/index.vue
@@ -91,7 +91,7 @@
    </view>
    <view v-else
          class="no-data">
      <text>暂无会议室记录</text>
      <text>暂无知识记录</text>
    </view>
    <!-- 浮动新增按钮 -->
    <view class="fab-button"
src/pages/managementMeetings/rulesRegulationsManagement/index.vue
@@ -127,7 +127,7 @@
    </view>
    <view v-else
          class="no-data">
      <text>暂无会议室记录</text>
      <text>暂无规章制度</text>
    </view>
    <!-- 浮动新增按钮 -->
    <view class="fab-button"
src/pages/managementMeetings/sealManagement/index.vue
@@ -97,7 +97,7 @@
    </view>
    <view v-else
          class="no-data">
      <text>暂无会议室记录</text>
      <text>暂无用印记录</text>
    </view>
    <!-- 浮动新增按钮 -->
    <view class="fab-button"
@@ -199,14 +199,14 @@
    };
    listSealApplication(params)
      .then(res => {
        const currentFactoryName = userStore.currentFactoryName;
        if (currentFactoryName) {
          visitList.value = res.data.records.filter(
            item => item.department === currentFactoryName
          );
        } else {
          visitList.value = res.data.records;
        }
        // const currentFactoryName = userStore.currentFactoryName;
        // if (currentFactoryName) {
        //   visitList.value = res.data.records.filter(
        //     item => item.department === currentFactoryName
        //   );
        // } else {
        visitList.value = res.data.records;
        // }
        closeToast();
      })
      .catch(() => {
src/pages/message.vue
@@ -37,10 +37,11 @@
            <text class="message-time">{{ formatTime(item.createTime) }}</text>
          </view>
          <text class="message-desc">{{ item.noticeContent }}</text>
          <view class="message-footer">
          <view v-if="activeTab === 0"
                class="message-footer">
            <text class="message-view"
                  @click="goToDetail(item)">
              去查看 >
              确认消息
            </text>
          </view>
        </view>
@@ -61,7 +62,7 @@
<script setup>
  import { ref, reactive, onMounted } from "vue";
  import { listNotice } from "@/api/login.js";
  import { listNotice, confirmMessage } from "@/api/login.js";
  import useUserStore from "@/store/modules/user";
  // 标签页数据
@@ -100,15 +101,25 @@
  // 跳转到详情页
  const goToDetail = item => {
    if (item.appJumpPath.indexOf("/") === 0) {
      uni.navigateTo({
        url: item.appJumpPath,
      });
    } else {
      uni.navigateTo({
        url: "/" + item.appJumpPath,
      });
    }
    confirmMessage(item.noticeId, 1).then(res => {
      if (res.code === 200) {
        // uni.showToast({ title: "确认成功", icon: "success" });
        loadMessages(false);
        if (item.appJumpPath) {
          if (item.appJumpPath.indexOf("/") === 0) {
            uni.navigateTo({
              url: item.appJumpPath,
            });
          } else {
            uni.navigateTo({
              url: "/" + item.appJumpPath,
            });
          }
        }
      } else {
        uni.showToast({ title: "确认失败", icon: "none" });
      }
    });
  };
  const userStore = useUserStore();
  const userId = ref("");
src/pages/procurementManagement/paymentEntry/add.vue
@@ -163,7 +163,9 @@
    registrant: "",
    paymentDate: "",
    registrationtDate: "",
    ticketRegistrationId: "",
    // ticketRegistrationId: "",
    purchaseLedgerId: "",
    salesLedgerProductId: "",
  });
  const currentNoReceiptAmount = ref(0);
@@ -231,7 +233,7 @@
      return;
    }
    loading.value = true;
    paymentRegistrationAdd(form.value)
    paymentRegistrationAdd([form.value])
      .then(() => {
        showToast("提交成功");
        onClickLeft();
@@ -246,7 +248,7 @@
    const rowStr = uni.getStorageSync("invoiceLedgerEditRow");
    const row = JSON.parse(rowStr);
    form.value = { ...row };
    form.value.ticketRegistrationId = row.id;
    // form.value.ticketRegistrationId = row.id;
    form.value.id = null;
    form.value.id = "";
    currentNoReceiptAmount.value = row.pendingTicketsTotal
@@ -255,6 +257,9 @@
    form.value.registrant = userStore.nickName;
    form.value.registrationtDate = getCurrentDate();
    form.value.paymentDate = getCurrentDate();
    form.value.salesLedgerProductId = row.id || "";
    form.value.purchaseLedgerId = row.salesLedgerId || "";
  };
  // 获取当前日期并格式化为 YYYY-MM-DD
  function getCurrentDate() {
src/pages/procurementManagement/procurementLedger/index.vue
@@ -77,17 +77,13 @@
              </view>
            </view>
            <!-- 仅非“审批通过”的台账展示删除按钮 -->
            <view
              class="detail-row"
              v-if="item.approvalStatus !== 3"
              style="justify-content: flex-end; margin-top: 8px;"
            >
              <up-button
                type="error"
                size="small"
                plain
                @click.stop="handleDelete(item)"
              >
            <view class="detail-row"
                  v-if="item.approvalStatus !== 3"
                  style="justify-content: flex-end; margin-top: 8px;">
              <up-button type="error"
                         size="small"
                         plain
                         @click.stop="handleDelete(item)">
                删除
              </up-button>
            </view>
@@ -114,7 +110,10 @@
  import { onShow } from "@dcloudio/uni-app";
  import useUserStore from "@/store/modules/user";
  import PageHeader from "@/components/PageHeader.vue";
  import { purchaseListPage, delPurchase } from "@/api/procurementManagement/procurementLedger";
  import {
    purchaseListPage,
    delPurchase,
  } from "@/api/procurementManagement/procurementLedger";
  const userStore = useUserStore();
  const approvalStatusText = {
    1: "待审核",
@@ -180,6 +179,7 @@
    try {
      // 设置操作类型
      uni.setStorageSync("operationType", type);
      uni.removeStorageSync("editData");
      // 如果是查看或编辑操作
      if (type !== "add") {
@@ -265,7 +265,10 @@
              // 只有在真正异常时,才在这里兜底提示
              const msg =
                (error && error.msg) ||
                (error && error.response && error.response.data && error.response.data.msg) ||
                (error &&
                  error.response &&
                  error.response.data &&
                  error.response.data.msg) ||
                (error && error.message) ||
                "删除失败";
              uni.showToast({
src/pages/sales/salesAccount/detail.vue
@@ -25,7 +25,7 @@
                  placeholder="点击选择业务员" />
        <template #right>
          <up-icon name="arrow-right"
                   @click="showPicker = true"></up-icon>
                   @click=" showPicker = true"></up-icon>
        </template>
      </up-form-item>
      <up-form-item label="客户名称"
@@ -184,7 +184,7 @@
                        @click="openCategoryPicker(idx)" />
              <template #right>
                <up-icon name="arrow-right"
                         @click="showCategoryPicker = true"></up-icon>
                         @click="openCategoryPicker(idx)"></up-icon>
              </template>
            </up-form-item>
            <!-- 规格型号 -->
@@ -197,7 +197,7 @@
                        @click="openSpecificationPicker(idx)" />
              <template #right>
                <up-icon name="arrow-right"
                         @click="showSpecificationPicker = true"></up-icon>
                         @click="openSpecificationPicker(idx)"></up-icon>
              </template>
            </up-form-item>
            <!-- 绑定机器 -->
@@ -229,7 +229,7 @@
                        @click="openTaxRatePicker(idx)" />
              <template #right>
                <up-icon name="arrow-right"
                         @click="showTaxRatePicker = true"></up-icon>
                         @click="openTaxRatePicker(idx)"></up-icon>
              </template>
            </up-form-item>
            <!-- 含税单价 -->
@@ -278,7 +278,7 @@
                        @click="openInvoiceTypePicker(idx)" />
              <template #right>
                <up-icon name="arrow-right"
                         @click="showInvoiceTypePicker = true"></up-icon>
                         @click="openInvoiceTypePicker(idx)"></up-icon>
              </template>
            </up-form-item>
          </view>
src/pages/sales/salesAccount/index.vue
@@ -26,8 +26,7 @@
          v-if="ledgerList.length > 0">
      <view v-for="(item, index) in ledgerList"
            :key="index">
        <view class="ledger-item"
              @click="handleInfo('edit', item)">
        <view class="ledger-item">
          <view class="item-header">
            <view class="item-left">
              <view class="document-icon">
@@ -81,18 +80,25 @@
            <up-divider></up-divider>
            <view class="detail-buttons">
              <u-button class="detail-button"
                      size="small"
                      type="primary"
                      @click="openOut(item)">
              发货状态
            </u-button>
            <u-button class="detail-button"
                      size="small"
                      type="error"
                      plain
                      @click.stop="handleDelete(item)">
              删除
            </u-button>
                        size="small"
                        type="primary"
                        @click.stop="handleInfo('edit', item)">
                编辑
              </u-button>
              <u-button class="detail-button"
                        size="small"
                        type="primary"
                        plain
                        @click.stop="openOut(item)">
                发货状态
              </u-button>
              <u-button class="detail-button"
                        size="small"
                        type="error"
                        plain
                        @click.stop="handleDelete(item)">
                删除
              </u-button>
            </view>
          </view>
        </view>
@@ -146,9 +152,7 @@
      const statusStr = (p.shippingStatus ?? "").toString();
      // 包含“发货”或有发货日期/车牌号视为已发货
      return (
        statusStr.includes("发货") ||
        !!p.shippingDate ||
        !!p.shippingCarNumber
        statusStr.includes("发货") || !!p.shippingDate || !!p.shippingCarNumber
      );
    });
  };
@@ -234,6 +238,7 @@
    try {
      // 设置操作类型
      uni.setStorageSync("operationType", type);
      uni.removeStorageSync("editData");
      // 如果是查看或编辑操作
      if (type !== "add") {
src/utils/request.ts
@@ -54,6 +54,11 @@
      //   code: code,
      //   data: data
      // })
      console.log('接收到的参数:', {
        url: (config.baseUrl || baseUrl) + config.url,
        code: code,
        data: data
      })
      if (code === 401) {
        showConfirm('登录状态已过期,您可以继续留在该页面,或者重新登录?').then(res => {
          if (res.confirm) {
@@ -65,7 +70,8 @@
        reject('无效的会话,或者会话已过期,请重新登录。')
      } else if (code === 500) {
        toast(msg)
        reject('500')
        console.error('500错误:', data)
        reject(data)
      } else if (code !== 200) {
        toast(msg)
        reject(code)