gaoluyang
2 天以前 952240909a036a341300ec25a2259e6faed33362
设备保修真机测试,bug修改
已修改11个文件
1068 ■■■■ 文件已修改
src/pages/cooperativeOffice/clientVisit/detail.vue 5 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/pages/cooperativeOffice/clientVisit/index.vue 168 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/pages/cooperativeOffice/collaborativeApproval/index.vue 201 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/pages/equipmentManagement/ledger/index.vue 177 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/pages/equipmentManagement/repair/add.vue 39 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/pages/equipmentManagement/repair/index.vue 186 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/pages/equipmentManagement/repair/maintain.vue 37 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/pages/equipmentManagement/upkeep/index.vue 179 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/pages/login.vue 34 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/pages/sales/salesAccount/detail.vue 36 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/store/modules/user.ts 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/pages/cooperativeOffice/clientVisit/detail.vue
@@ -240,11 +240,8 @@
    Object.keys(source).forEach((k) => {
      submitData[k] = source[k]
    })
    console.log('提交数据:', submitData)
    const { code } = await clientVisitSignIn(submitData)
    console.log('code----', code);
    
    if (code === 200) {
      showToast('签到成功')
src/pages/cooperativeOffice/clientVisit/index.vue
@@ -1,30 +1,30 @@
<template>
  <view class="client-visit-list">
  <view class="sales-accoun">
    <!-- 使用通用页面头部组件 -->
    <PageHeader title="客户拜访" @back="goBack" />
    
    <!-- 搜索和筛选区域 -->
    <view class="search-filter-section">
    <view class="search-section">
      <view class="search-bar">
        <view class="search-input">
          <input
          <up-input
            class="search-text"
            placeholder="请输入客户名称"
            v-model="customerName"
            confirm-type="search"
            @confirm="getList"
            @blur="getList"
            clearable
          />
        </view>
        <view class="filter-button" @click="getList">
          <up-icon name="search" size="24" color="#999"></up-icon>
          <u-icon name="search" size="24" color="#999"></u-icon>
        </view>
      </view>
    </view>
    
    <!-- 拜访记录列表 -->
    <view class="visit-list" v-if="visitList.length > 0">
    <view class="ledger-list" v-if="visitList.length > 0">
      <view v-for="(item, index) in visitList" :key="index">
        <view class="visit-item">
        <view class="ledger-item">
          <view class="item-header">
            <view class="item-left">
              <view class="document-icon">
@@ -239,167 +239,35 @@
</script>
<style scoped lang="scss">
.u-divider {
  margin: 0 !important;
}
@import "../../../styles/sales-common.scss";
.client-visit-list {
// 页面特定的样式覆盖
.sales-accoun {
  min-height: 100vh;
  background: #f8f9fa;
  position: relative;
  padding-bottom: 80px;
}
.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: 10px 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;
}
.visit-list {
  padding: 20px;
}
.visit-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: #667eea;
  border-radius: 4px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: #667eea; // 保持页面特有的背景色
}
.item-id {
  font-size: 14px;
  color: #333;
  font-weight: 500;
}
// 特有样式
.visit-status {
  display: flex;
  align-items: center;
}
.item-details {
  padding: 16px 0;
}
.detail-row {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  margin-bottom: 8px;
  &:last-child {
    margin-bottom: 0;
  }
}
.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;
  word-break: break-all;
  word-break: break-all; // 保留页面特有的文本换行样式
}
.no-data {
  padding: 40px 0;
  text-align: center;
  color: #999;
}
.action-buttons {
  display: flex;
  gap: 12px;
  padding: 0 0 16px 0;
  justify-content: space-between;
}
.action-btn {
  flex: 1;
}
// 特定的浮动按钮样式
.fab-button {
  position: fixed;
  bottom: calc(30px + env(safe-area-inset-bottom));
  right: 30px;
  width: 56px;
  height: 56px;
  background: #667eea;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  box-shadow: 0 4px 16px rgba(102, 126, 234, 0.3);
  z-index: 1000;
  background: #667eea; // 保持页面特有的背景色
  box-shadow: 0 4px 16px rgba(102, 126, 234, 0.3); // 保持页面特有的阴影效果
}
</style>
src/pages/cooperativeOffice/collaborativeApproval/index.vue
@@ -5,13 +5,14 @@
        <PageHeader title="审批管理" @back="goBack" />
        <!-- 搜索和筛选区域 -->
        <view class="search-filter-section">
        <view class="search-section">
            <view class="search-bar">
                <view class="search-input">
                    <input
                    <up-input
                        class="search-text"
                        placeholder="请输入流程编号"
                        v-model="searchForm.approveId"
                        clearable
                    />
                </view>
                <view class="search-button" @click="getList">
@@ -77,7 +78,7 @@
                                        :disabled="item.approveStatus == 2 || item.approveStatus == 1 || item.approveStatus == 4"
                                        @click="handleItemClick(item)"
                                    >
                                        编辑
                                            编辑
                                    </u-button>
                                    <u-button
                                        type="success"
@@ -86,7 +87,7 @@
                                        :disabled="item.approveUserCurrentId == null || item.approveStatus == 2 || item.approveStatus == 3 || item.approveStatus == 4 || item.approveUserCurrentId !== userStore.id"
                                        @click="approve(item)"
                                    >
                                        审核
                                            审核
                                    </u-button>
                                </view>
                            </view>
@@ -98,7 +99,6 @@
        <view v-else class="no-data">
            <text>暂无审批数据</text>
        </view>
<!--        <van-floating-bubble icon="plus" @click="handleAdd"/>-->
        <!-- 浮动操作按钮 -->
        <view class="fab-button" @click="handleAdd">
            <up-icon name="plus" size="24" color="#ffffff"></up-icon>
@@ -229,178 +229,34 @@
</script>
<style scoped lang="scss">
    @import "../../../styles/sales-common.scss";
    .u-divider {
        margin: 0 !important;
    }
    .sales-account {
        min-height: 100vh;
        background: #f8f9fa;
        position: relative;
    }
    .search-input {
        flex: 1;
        background: #f5f5f5;
        border-radius: 24px;
        padding: 10px 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;
    }
    .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: 10px 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;
    // 浮动按钮样式 - 覆盖公共样式中的背景色
    .fab-button {
        background: #ed8d05;
    }
    .item-tag {
        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-row-user {
        display: flex;
        align-items: center;
        justify-content: space-between;
    }
    .detail-row-approveReason {
        display: flex;
        align-items: center;
        justify-content: space-between;
        margin-bottom: 8px;
    }
    .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 {
@@ -413,31 +269,11 @@
        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;
    }
    .approver-value {
        display: flex;
        justify-content: flex-end;
    }
    .approver-chip {
        display: inline-flex;
        align-items: center;
@@ -449,6 +285,7 @@
        padding: 4px 10px;
        max-width: 100%;
    }
    .approver-name {
        font-size: 12px;
        color: #2b7cff;
@@ -470,11 +307,5 @@
        line-height: 28px;
        padding: 0 12px;
    }
    .action-btn.edit {
        /* primary 样式来自组件,这里保留钩子以便后续需要扩展 */
    }
    .action-btn.approve {
        /* success 样式来自组件,这里保留钩子以便后续需要扩展 */
    }
    /* 已移除vant组件的样式引用 */
</style>
src/pages/equipmentManagement/ledger/index.vue
@@ -1,18 +1,18 @@
<template>
  <view class="device-ledger">
  <view class="sales-account">
    <!-- 使用通用页面头部组件 -->
    <PageHeader title="设备台账" @back="goBack" />
    
    <!-- 搜索和筛选区域 -->
    <view class="search-filter-section">
    <!-- 搜索区域 -->
    <view class="search-section">
      <view class="search-bar">
        <view class="search-input">
          <input
          <up-input
            class="search-text"
            placeholder="请输入设备名称"
            placeholder="请输入设备名称搜索"
            v-model="searchKeyword"
            confirm-type="search"
            @confirm="getList"
            @change="getList"
            clearable
          />
        </view>
        <view class="filter-button" @click="getList">
@@ -218,166 +218,7 @@
</script>
<style scoped lang="scss">
.u-divider {
  margin: 0 !important;
}
@import '@/styles/sales-common.scss';
.device-ledger {
  min-height: 100vh;
  background: #f8f9fa;
  position: relative;
  padding-bottom: 80px;
}
.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: 10px 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: #2979ff;
  border-radius: 4px;
  display: flex;
  align-items: center;
  justify-content: center;
}
.item-id {
  font-size: 14px;
  color: #333;
  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-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.highlight {
  color: #2979ff;
  font-weight: 500;
}
.no-data {
  padding: 40px 0;
  text-align: center;
  color: #999;
}
// 按钮样式
.action-buttons {
  display: flex;
  gap: 12px;
  padding: 0 0 16px 0;
  justify-content: space-between;
}
.action-btn {
  flex: 1;
}
.fab-button {
  position: fixed;
  bottom: calc(30px + env(safe-area-inset-bottom));
  right: 30px;
  width: 56px;
  height: 56px;
  background: #2979ff;
  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/equipmentManagement/repair/add.vue
@@ -169,7 +169,7 @@
            if (code == 200) {
                form.value.deviceLedgerId = data.deviceLedgerId;
                form.value.deviceModel = data.deviceModel;
                form.value.repairTime = data.repairTime;
                form.value.repairTime = dayjs(data.repairTime).format("YYYY-MM-DD");
                form.value.repairName = data.repairName;
                form.value.remark = data.remark;
                // 设置设备名称显示
@@ -185,23 +185,6 @@
        // 新增模式
        operationType.value = 'add';
    }
};
// 清除表单校验状态
const clearValidate = () => {
    formRef.value?.clearValidate();
};
// 重置表单数据和校验状态
const resetForm = () => {
    form.value = {
        deviceLedgerId: undefined,
        deviceModel: undefined,
        repairTime: dayjs().format("YYYY-MM-DD"),
        repairName: undefined,
        remark: undefined,
    };
    deviceNameText.value = '';
};
// 扫描二维码功能
@@ -283,6 +266,7 @@
// 确认日期选择
const onDateConfirm = (e) => {
    form.value.repairTime = formatDateToYMD(e.value);
    pickerDateValue.value = dayjs(e.value).format("YYYY-MM-DD");
    showDate.value = false;
};
@@ -355,19 +339,21 @@
// 返回上一页
const goBack = () => {
    uni.removeStorageSync('repairId');
    uni.navigateBack();
};
// 获取页面参数
const getPageParams = () => {
    const pages = getCurrentPages();
    const currentPage = pages[pages.length - 1];
    const options = currentPage.options;
    // 使用uni.getStorageSync获取id
    const id = uni.getStorageSync('repairId');
    
    // 根据是否有id参数来判断是新增还是编辑
    if (options.id) {
    if (id) {
        // 编辑模式,获取详情
        loadForm(options.id);
        loadForm(id);
        // 可选:获取后清除存储的id,避免影响后续操作
        // uni.removeStorageSync('repairId');
    } else {
        // 新增模式
        loadForm();
@@ -376,10 +362,9 @@
// 获取页面ID
const getPageId = () => {
    const pages = getCurrentPages();
    const currentPage = pages[pages.length - 1];
    const options = currentPage.options;
    return options.id;
    // 使用uni.getStorageSync获取id
    const id = uni.getStorageSync('repairId');
    return id;
};
</script>
src/pages/equipmentManagement/repair/index.vue
@@ -1,18 +1,18 @@
<template>
  <view class="device-repair">
  <view class="sales-account">
    <!-- 使用通用页面头部组件 -->
    <PageHeader title="设备报修" @back="goBack" />
    
    <!-- 搜索区域 -->
    <view class="search-filter-section">
    <view class="search-section">
      <view class="search-bar">
        <view class="search-input">
          <input
          <up-input
            class="search-text"
            placeholder="请输入设备名称"
            placeholder="请输入设备名称搜索"
            v-model="searchKeyword"
            confirm-type="search"
            @confirm="getList"
            @change="getList"
            clearable
          />
        </view>
        <view class="filter-button" @click="getList">
@@ -22,9 +22,9 @@
    </view>
    
    <!-- 设备报修列表 -->
    <view class="repair-list" v-if="repairList.length > 0">
    <view class="ledger-list" v-if="repairList.length > 0">
      <view v-for="(item, index) in repairList" :key="index">
        <view class="repair-item">
        <view class="ledger-item">
          <view class="item-header">
            <view class="item-left">
              <view class="document-icon">
@@ -76,6 +76,7 @@
              type="primary"
              size="small"
              class="action-btn"
              :disabled="item.status === 1"
              @click="edit(item.id)"
            >
              编辑
@@ -188,8 +189,10 @@
    showToast('参数错误')
    return
  }
  // 使用uni.setStorageSync存储id
  uni.setStorageSync('repairId', id)
  uni.navigateTo({
    url: `/pages/equipmentManagement/repair/maintain?id=${id}`
    url: '/pages/equipmentManagement/repair/maintain'
  })
}
@@ -203,8 +206,10 @@
// 编辑 - 跳转到add页面,通过id区分新增还是编辑
const edit = (id) => {
  if (!id) return
  // 使用uni.setStorageSync存储id
  uni.setStorageSync('repairId', id)
  uni.navigateTo({
    url: `/pages/equipmentManagement/repair/add?id=${id}`
    url: '/pages/equipmentManagement/repair/add'
  })
}
@@ -242,100 +247,11 @@
</script>
<style scoped lang="scss">
.u-divider {
  margin: 0 !important;
}
@import '@/styles/sales-common.scss';
.device-repair {
  min-height: 100vh;
  background: #f8f9fa;
  position: relative;
  padding-bottom: 80px;
}
.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: 10px 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;
}
.repair-list {
  padding: 20px;
}
.repair-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: #2979ff;
  border-radius: 4px;
  display: flex;
  align-items: center;
  justify-content: center;
}
.item-id {
  font-size: 14px;
  color: #333;
  font-weight: 500;
// 设备维修特有样式
.sales-account {
  padding-bottom: 80px; // 为浮动按钮留出空间
}
.status-tag {
@@ -343,69 +259,7 @@
  align-items: center;
}
.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-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.highlight {
  color: #2979ff;
  font-weight: 500;
}
.no-data {
  padding: 40px 0;
  text-align: center;
  color: #999;
}
.action-buttons {
  display: flex;
  gap: 8px;
  padding: 0 0 16px 0;
  justify-content: space-between;
}
.action-btn {
  flex: 1;
}
.fab-button {
    position: fixed;
    bottom: calc(30px + env(safe-area-inset-bottom));
    right: 30px;
    width: 56px;
    height: 56px;
    background: #2979ff;
    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;
    /* 确保浮动按钮不被底部安全区域遮挡 */
  gap: 8px; // 与公共样式中的 12px 不同
}
</style>
src/pages/equipmentManagement/repair/maintain.vue
@@ -50,9 +50,11 @@
        <up-datetime-picker
            :show="showDatePicker"
            v-model="pickerDateValue"
            mode="date"
            mode="datetime"
            title="选择日期"
            format="YYYY-MM-DD HH:mm:ss"
            @confirm="onDateConfirm"
            @cancel="showDatePicker = false"
        />
    </view>
</template>
@@ -64,7 +66,6 @@
import { addMaintain } from '@/api/equipmentManagement/repair';
import useUserStore from "@/store/modules/user";
import dayjs from "dayjs";
import { formatDateToYMD } from '@/utils/ruoyi'
defineOptions({
    name: "设备维修表单",
@@ -89,7 +90,7 @@
const form = ref({
    maintenanceName: userStore.nickName || '', // 默认使用当前用户昵称
    maintenanceResult: undefined, // 维修结果
    maintenanceTime: dayjs().format("YYYY-MM-DD"), // 维修日期(只显示日期)
    maintenanceTime: dayjs().format("YYYY-MM-DD HH:mm:ss"), // 维修日期(只显示日期)
});
// 自定义showToast函数
@@ -100,17 +101,12 @@
  })
};
// 清除表单校验状态
const clearValidate = () => {
    // uview-plus不需要手动清除验证状态,重置表单时会自动清除
};
// 重置表单数据和校验状态
const resetForm = () => {
    form.value = {
        maintenanceName: userStore.nickName || '',
        maintenanceResult: undefined,
        maintenanceTime: dayjs().format("YYYY-MM-DD"),
        maintenanceTime: dayjs().format("YYYY-MM-DD HH:mm:ss"),
    };
};
@@ -145,10 +141,6 @@
        
        // 准备提交数据,maintenanceTime 加上当前时分秒
        const submitData = { ...form.value };
        if (submitData.maintenanceTime && !submitData.maintenanceTime.includes(':')) {
            // 如果 maintenanceTime 只包含日期,添加当前时分秒
            submitData.maintenanceTime = submitData.maintenanceTime + ' ' + dayjs().format('HH:mm:ss');
        }
        
        const { code } = await addMaintain({ id: id, ...submitData });
        
@@ -156,12 +148,14 @@
            showToast('新增维修成功');
            resetFormAndValidate();
            setTimeout(() => {
                uni.navigateBack();
            }, 1500);
                goBack();
            }, 500);
        } else {
            loading.value = false;
        }
    } catch (e) {
        console.log(e);
        loading.value = false;
        showToast('操作失败');
    }
@@ -169,21 +163,20 @@
// 返回上一页
const goBack = () => {
    uni.removeStorageSync('repairId');
    uni.navigateBack();
};
// 获取页面ID
const getPageId = () => {
    const pages = getCurrentPages();
    const currentPage = pages[pages.length - 1];
    const options = currentPage.options;
    return options.id;
    const id = uni.getStorageSync('repairId');
    return id;
};
// 确认日期选择
const onDateConfirm = (e) => {
    form.value.maintenanceTime = formatDateToYMD(e.value)
    pickerDateValue.value = formatDateToYMD(e.value)
    form.value.maintenanceTime = dayjs(e.value).format('YYYY-MM-DD HH:mm:ss')
    pickerDateValue.value = e.value
    showDatePicker.value = false;
};
@@ -192,7 +185,7 @@
    // 设置维修人为当前用户昵称
    form.value.maintenanceName = userStore.nickName || '';
    // 设置当前日期(只包含年月日)
    form.value.maintenanceTime = dayjs().format('YYYY-MM-DD');
    form.value.maintenanceTime = dayjs().format('YYYY-MM-DD HH:mm:ss');
};
onShow(() => {
src/pages/equipmentManagement/upkeep/index.vue
@@ -1,18 +1,18 @@
<template>
  <view class="device-upkeep">
  <view class="sales-account">
    <!-- 使用通用页面头部组件 -->
    <PageHeader title="设备保养" @back="goBack" />
    
    <!-- 搜索区域 -->
    <view class="search-filter-section">
    <view class="search-section">
      <view class="search-bar">
        <view class="search-input">
          <input
          <up-input
            class="search-text"
            placeholder="请输入设备名称"
            placeholder="请输入设备名称搜索"
            v-model="searchKeyword"
            confirm-type="search"
            @confirm="getList"
            @change="getList"
            clearable
          />
        </view>
        <view class="filter-button" @click="getList">
@@ -22,9 +22,9 @@
    </view>
    
    <!-- 设备保养列表 -->
    <view class="upkeep-list" v-if="upkeepList.length > 0">
    <view class="ledger-list" v-if="upkeepList.length > 0">
      <view v-for="(item, index) in upkeepList" :key="index">
        <view class="upkeep-item" @click="toggleSelection(item)">
        <view class="ledger-item" @click="toggleSelection(item)">
          <view class="item-header">
            <view class="item-left">
              <view class="document-icon">
@@ -285,58 +285,11 @@
</script>
<style scoped lang="scss">
.u-divider {
  margin: 0 !important;
}
@import '@/styles/sales-common.scss';
.device-upkeep {
  min-height: 100vh;
  background: #f8f9fa;
  position: relative;
  padding-bottom: 80px;
}
.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: 10px 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;
// 设备保养特有样式
.sales-account {
  padding-bottom: 80px; // 为浮动按钮留出空间
}
.action-section {
@@ -345,36 +298,9 @@
  border-bottom: 1px solid #f0f0f0;
}
.action-buttons {
  display: flex;
  gap: 8px;
.action-section .action-buttons {
  gap: 8px; // 与公共样式中的 12px 不同
  justify-content: flex-start;
}
.upkeep-list {
  padding: 20px;
}
.upkeep-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;
}
.checkbox-wrapper {
@@ -382,93 +308,22 @@
  align-items: center;
}
.document-icon {
  width: 24px;
  height: 24px;
  background: #2979ff;
  border-radius: 4px;
  display: flex;
  align-items: center;
  justify-content: center;
}
.item-id {
  font-size: 14px;
  color: #333;
  font-weight: 500;
}
.status-tag {
  display: flex;
  align-items: center;
}
.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-label {
  font-size: 12px;
  color: #777777;
  min-width: 80px;
  min-width: 80px; // 与公共样式中的 60px 不同
}
.detail-value {
  font-size: 12px;
  color: #000000;
  text-align: right;
  flex: 1;
  margin-left: 16px;
  display: flex;
  justify-content: flex-end;
  align-items: center;
}
.detail-value.highlight {
  color: #2979ff;
  font-weight: 500;
}
.no-data {
  padding: 40px 0;
  text-align: center;
  color: #999;
}
.upkeep-item .action-buttons {
  display: flex;
  gap: 8px;
  padding: 0 0 16px 0;
  justify-content: space-between;
}
.action-btn {
  flex: 1;
}
.fab-button {
  position: fixed;
  bottom: calc(30px + env(safe-area-inset-bottom));
  right: 30px;
  width: 56px;
  height: 56px;
  background: #667eea;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  box-shadow: 0 4px 16px rgba(102, 126, 234, 0.3);
  z-index: 1000;
.ledger-item .action-buttons {
  gap: 8px; // 与公共样式中的 12px 不同
}
</style>
src/pages/login.vue
@@ -7,7 +7,7 @@
            <view class="input-item flex align-center">
                <up-input prefixIcon="account" placeholder="请输入账号" border="bottom"
                                    @blur="getUserLoginFacotryList"
                                    maxlength="30" v-model="loginForm.username" clearable></up-input>
                                    maxlength="30" v-model="loginForm.userName" clearable></up-input>
            </view>
            <view class="input-item flex align-center">
                <up-input prefixIcon="lock" placeholder="请输入密码" border="bottom" maxlength="20" v-model="loginForm.password" clearable type="password"></up-input>
@@ -42,7 +42,14 @@
</template>
<script setup>
import modal from '@/plugins/modal'
import {modal} from "@/plugins";
const showToast = (message) => {
    uni.showToast({
        title: message,
        icon: 'none'
    })
}
import { userLoginFacotryList} from '@/api/login'
import { ref, onMounted } from "vue";
import useUserStore from '@/store/modules/user'
@@ -54,7 +61,7 @@
const useWxLogin = ref(false); // 是否使用微信登录
const rememberPassword = ref(false); // 记住密码
const loginForm = ref({
    username: "",
    userName: "",
    password: "",
    factoryId: "",
    currentFatoryName: "",
@@ -64,7 +71,7 @@
// 保存密码到本地存储
function savePassword() {
    if (rememberPassword.value) {
        uni.setStorageSync('remembered_username', loginForm.value.username);
        uni.setStorageSync('remembered_username', loginForm.value.userName);
        uni.setStorageSync('remembered_password', loginForm.value.password);
        uni.setStorageSync('remember_password', true);
    } else {
@@ -82,7 +89,7 @@
        const savedUsername = uni.getStorageSync('remembered_username');
        const savedPassword = uni.getStorageSync('remembered_password');
        if (savedUsername) {
            loginForm.value.username = savedUsername;
            loginForm.value.userName = savedUsername;
        }
        if (savedPassword) {
            loginForm.value.password = savedPassword;
@@ -103,8 +110,9 @@
}
function getUserLoginFacotryList() {
    if(loginForm.value.username){
        userLoginFacotryList({userName:loginForm.value.username}).then(res => {
    if(loginForm.value.userName){
        userLoginFacotryList({userName:loginForm.value.userName}).then(res => {
            console.log('res',res)
            // 检查res.data是否为数组
            if (res.data && Array.isArray(res.data)) {
                // 重新组装数据格式:deptId变成id,deptName变成name
@@ -117,7 +125,7 @@
                factoryList.value = []
            }
        }).catch(error => {
            modal.msgError('获取公司列表失败:', error)
            showToast('获取公司列表失败:', error)
            factoryList.value = []
        })
    }else {
@@ -126,14 +134,14 @@
}
async function handleLogin() {
    if (loginForm.value.username === "") {
        modal.msgError("请输入您的账号")
    if (loginForm.value.userName === "") {
        showToast("请输入您的账号")
    } else if (loginForm.value.password === "") {
        modal.msgError("请输入您的密码")
        showToast("请输入您的密码")
    } else if (loginForm.value.factoryId === "") {
        modal.msgError("请选择公司")
        showToast("请选择公司")
    } else {
        modal.loading("登录中,请耐心等待...")
        showToast("登录中,请耐心等待...")
        pwdLogin()
    }
};
src/pages/sales/salesAccount/detail.vue
@@ -189,7 +189,7 @@
                            label="产品大类"
                            prop="productCategory"
                            required
                            :rules="productRules"
                            :rules="productRules.productCategory"
                        >
                            <up-input
                                v-model="product.productCategory"
@@ -210,7 +210,7 @@
                            label="规格型号"
                            prop="specificationModel"
                            required
                            :rules="productRules"
                            :rules="productRules.specificationModel"
                        >
                            <up-input
                                v-model="product.specificationModel"
@@ -231,7 +231,7 @@
                            label="单位"
                            prop="unit"
                            required
                            :rules="productRules"
                            :rules="productRules.unit"
                        >
                            <up-input
                                v-model="product.unit"
@@ -244,7 +244,7 @@
                            label="税率(%)"
                            prop="taxRate"
                            required
                            :rules="productRules"
                            :rules="productRules.taxRate"
                        >
                            <up-input
                                v-model="product.taxRate"
@@ -265,7 +265,7 @@
                            label="含税单价(元)"
                            prop="taxInclusiveUnitPrice"
                            required
                            :rules="productRules"
                            :rules="productRules.taxInclusiveUnitPrice"
                        >
                            <up-input
                                v-model="product.taxInclusiveUnitPrice"
@@ -280,7 +280,7 @@
                            label="数量"
                            prop="quantity"
                            required
                            :rules="productRules"
                            :rules="productRules.quantity"
                        >
                            <up-input
                                v-model="product.quantity"
@@ -295,7 +295,7 @@
                            label="含税总价(元)"
                            prop="taxInclusiveTotalPrice"
                            required
                            :rules="productRules"
                            :rules="productRules.taxInclusiveTotalPrice"
                        >
                            <up-input
                                v-model="product.taxInclusiveTotalPrice"
@@ -310,7 +310,7 @@
                            label="不含税总价(元)"
                            prop="taxExclusiveTotalPrice"
                            required
                            :rules="productRules"
                            :rules="productRules.taxExclusiveTotalPrice"
                        >
                            <up-input
                                v-model="product.taxExclusiveTotalPrice"
@@ -325,7 +325,7 @@
                            label="发票类型"
                            prop="invoiceType"
                            required
                            :rules="productRules"
                            :rules="productRules.invoiceType"
                        >
                            <up-input
                                v-model="product.invoiceType"
@@ -362,7 +362,6 @@
import { formatDateToYMD } from '@/utils/ruoyi'
import {
    addOrUpdateSalesLedger,
    addOrUpdateSalesLedgerProduct,
    customerList,
    getSalesLedgerWithProducts,
    modelList,
@@ -504,35 +503,35 @@
// 表单校验规则
const rules = {
    salesman: [
        { required: true, message: '请选择业务员', trigger: 'blur' }
        { required: true, message: '请选择业务员', trigger: 'change' }
    ],
    customerContractNo: [
        { required: true, message: '请输入客户合同号', trigger: 'blur' }
    ],
    customerName: [
        { required: true, message: '请选择客户名称', trigger: 'blur' }
        { required: true, message: '请选择客户名称', trigger: 'change' }
    ],
    projectName: [
        { required: true, message: '请输入项目名称', trigger: 'blur' }
    ],
    executionDate: [
        { required: true, message: '请选择签订日期', trigger: 'blur' }
        { required: true, message: '请选择签订日期', trigger: 'change' }
    ]
};
// 产品信息校验规则
const productRules = {
    productCategory: [
        { required: true, message: '请选择产品大类', trigger: 'blur' }
        { required: true, message: '请选择产品大类', trigger: 'change' }
    ],
    specificationModel: [
        { required: true, message: '请选择规格型号', trigger: 'blur' }
        { required: true, message: '请选择规格型号', trigger: 'change' }
    ],
    unit: [
        { required: true, message: '请输入单位', trigger: 'blur' }
    ],
    taxRate: [
        { required: true, message: '请选择税率', trigger: 'blur' }
        { required: true, message: '请选择税率', trigger: 'change' }
    ],
    taxInclusiveUnitPrice: [
        { required: true, message: '请输入含税单价', trigger: 'blur' },
@@ -551,7 +550,7 @@
        { type: 'number', min: 0, message: '不含税总价必须大于0', trigger: 'blur' }
    ],
    invoiceType: [
        { required: true, message: '请选择发票类型', trigger: 'blur' }
        { required: true, message: '请选择发票类型', trigger: 'change' }
    ]
};
@@ -580,7 +579,8 @@
// 日期确认事件
const onDateConfirm = (e) => {
    form.value.executionDate = formatDateToYMD(e.value)
    pickerDateValue.value = formatDateToYMD(e.value)
    // 保持pickerDateValue为时间戳格式,而不是格式化的字符串
    pickerDateValue.value = e.value
    showDatePicker.value = false;
}
src/store/modules/user.ts
@@ -5,7 +5,7 @@
import config from '@/config.js'
export interface LoginForm {
  username: string;
  userName: string;
  password: string;
  factoryId: string;
}
@@ -27,11 +27,11 @@
  actions: {
    // 部门登录
    loginCheckFactory(userInfo: any) {
      const username = userInfo.username.trim()
      const userName = userInfo.userName
      const password = userInfo.password
      const factoryId = userInfo.factoryId
      return new Promise((resolve, reject) => {
        loginCheckFactory(username, password, factoryId).then((res: any) => {
        loginCheckFactory(userName, password, factoryId).then((res: any) => {
          setToken(res.token)
          this.token = res.token
          resolve(null)