Commit 13203a04c9c4ee0ac0b95a6b92b11eeb4d95ebdc
1 parent
2d57b60f
首页 统计
Showing
4 changed files
with
290 additions
and
212 deletions
pages-sub/daily/maintain-manage/add-record.vue
| @@ -4,14 +4,21 @@ | @@ -4,14 +4,21 @@ | ||
| 4 | <up-form label-position="left" :model="inspectForm" ref="inspectFormRef" label-width="140rpx"> | 4 | <up-form label-position="left" :model="inspectForm" ref="inspectFormRef" label-width="140rpx"> |
| 5 | <!-- ========== 动态表单区域 ========== --> | 5 | <!-- ========== 动态表单区域 ========== --> |
| 6 | <template v-for="item in dynamicFields" :key="item.fieldCode"> | 6 | <template v-for="item in dynamicFields" :key="item.fieldCode"> |
| 7 | - <up-form-item :label="item.fieldName" :prop="item.fieldCode" :required="item.required === 1" class="form-item" | ||
| 8 | - @click="openPickerIfNeeded(item)"> | 7 | + <up-form-item :label="item.fieldName" :prop="item.fieldCode" class="form-item" @click="openPickerIfNeeded(item)"> |
| 8 | + | ||
| 9 | <!-- type 1 数值:u-number-box,最多2位小数,min=0,max取item.length --> | 9 | <!-- type 1 数值:u-number-box,最多2位小数,min=0,max取item.length --> |
| 10 | <view v-if="item.fieldType === 1" class="number-box-wrap"> | 10 | <view v-if="item.fieldType === 1" class="number-box-wrap"> |
| 11 | - <u-number-box v-model="inspectForm[item.fieldCode]" min="1" :step="1" | ||
| 12 | - :max="item.length ? 10 ** Number(item.length) - 1 : null" | ||
| 13 | - :placeholder="`请输入${item.fieldName}${item.unit} `" @change="valChange(item)" class="large-number-box"> | ||
| 14 | - </u-number-box> | 11 | + <u-number-box |
| 12 | + v-model="inspectForm[item.fieldCode]" | ||
| 13 | + min="1" | ||
| 14 | + :step="1" | ||
| 15 | + :max="item.length ? 10 ** Number(item.length) - 1 : null" | ||
| 16 | + :placeholder="`请输入${item.fieldName}${item.unit} `" | ||
| 17 | + @change="valChange(item)" | ||
| 18 | + @blur="valChange(item)" | ||
| 19 | + class="large-number-box"> | ||
| 20 | +</u-number-box> | ||
| 21 | + | ||
| 15 | <text class="unit-text" v-if="item.unit">{{ item.unit }}</text> | 22 | <text class="unit-text" v-if="item.unit">{{ item.unit }}</text> |
| 16 | </view> | 23 | </view> |
| 17 | <!-- type 2 文本 --> | 24 | <!-- type 2 文本 --> |
| @@ -132,10 +139,14 @@ | @@ -132,10 +139,14 @@ | ||
| 132 | </up-form> | 139 | </up-form> |
| 133 | </view> | 140 | </view> |
| 134 | <!-- 底部提交按钮 --> | 141 | <!-- 底部提交按钮 --> |
| 135 | - <view class="fixed-bottom-btn-wrap"> | ||
| 136 | - <up-button type="primary" text="提交" @click="submitInspect" | ||
| 137 | - style="width: 100%; height: 88rpx; font-size:32rpx; border-radius: 0;"></up-button> | ||
| 138 | - </view> | 142 | + <view v-if="dynamicFields.length === 0" class="empty-field-tip"> |
| 143 | + <text>请去平台配置业务类型字段</text> | ||
| 144 | +</view> | ||
| 145 | +<!-- ========== 底部提交按钮:只有存在动态字段才显示 ========== --> | ||
| 146 | +<view class="fixed-bottom-btn-wrap" v-if="dynamicFields.length > 0"> | ||
| 147 | +<up-button type="primary" text="提交" @click="submitInspect" | ||
| 148 | +style="width: 100%; height: 88rpx; font-size:32rpx; border-radius: 0;"></up-button> | ||
| 149 | +</view> | ||
| 139 | <!-- uview-plus 日期时间选择器(全局复用) --> | 150 | <!-- uview-plus 日期时间选择器(全局复用) --> |
| 140 | <up-datetime-picker :show="datePickerShow" v-model="datePickerValue" mode="datetime" close-on-click-overlay | 151 | <up-datetime-picker :show="datePickerShow" v-model="datePickerValue" mode="datetime" close-on-click-overlay |
| 141 | @confirm="onDateConfirm" @cancel="onDateClose" @close="onDateClose"></up-datetime-picker> | 152 | @confirm="onDateConfirm" @cancel="onDateClose" @close="onDateClose"></up-datetime-picker> |
| @@ -646,31 +657,51 @@ export default { | @@ -646,31 +657,51 @@ export default { | ||
| 646 | * 7/8/9/11 的值是数组或对象,async-validator 的 required 按默认 string 类型判定, | 657 | * 7/8/9/11 的值是数组或对象,async-validator 的 required 按默认 string 类型判定, |
| 647 | * 会放过「空数组」「null」⇒ 必须用 validator 显式判空,否则未选也能提交 | 658 | * 会放过「空数组」「null」⇒ 必须用 validator 显式判空,否则未选也能提交 |
| 648 | */ | 659 | */ |
| 649 | - buildRequiredRule(field: any) { | ||
| 650 | - const type = field.fieldType | ||
| 651 | - if (type === 6 || type === 7 || type === 8) { | ||
| 652 | - const action = type === 6 ? '请选择' : '请上传' | ||
| 653 | - return { | ||
| 654 | - required: true, | ||
| 655 | - trigger: 'change', | ||
| 656 | - validator: (rule, value, callback) => { | ||
| 657 | - Array.isArray(value) && value.length > 0 ? callback() : callback(new Error(`${action}${field.fieldName}`)) | ||
| 658 | - } | ||
| 659 | - } | 660 | +buildRequiredRule(field: any) { |
| 661 | + const type = field.fieldType | ||
| 662 | + if (type === 6 || type === 7 || type === 8) { | ||
| 663 | + const action = type === 6 ? '请选择' : '请上传' | ||
| 664 | + return { | ||
| 665 | + required: true, | ||
| 666 | + trigger: ['change','blur'], | ||
| 667 | + validator: (rule, value, callback) => { | ||
| 668 | + Array.isArray(value) && value.length > 0 ? callback() : callback(new Error(`${action}${field.fieldName}`)) | ||
| 660 | } | 669 | } |
| 661 | - if (type === 9 || type === 11) { | ||
| 662 | - return { | ||
| 663 | - required: true, | ||
| 664 | - trigger: 'change', | ||
| 665 | - validator: (rule, value, callback) => { | ||
| 666 | - value ? callback() : callback(new Error(type === 9 ? `请选择${field.fieldName}` : `请选择${field.fieldName}的位置`)) | ||
| 667 | - } | 670 | + } |
| 671 | + } | ||
| 672 | + if (type === 9 || type === 11) { | ||
| 673 | + return { | ||
| 674 | + required: true, | ||
| 675 | + trigger: ['change','blur'], | ||
| 676 | + validator: (rule, value, callback) => { | ||
| 677 | + value ? callback() : callback(new Error(type === 9 ? `请选择${field.fieldName}` : `请选择${field.fieldName}的位置`)) | ||
| 678 | + } | ||
| 679 | + } | ||
| 680 | + } | ||
| 681 | + // ========= 新增:数值类型单独校验 ========= | ||
| 682 | + if (type === 1) { | ||
| 683 | + return { | ||
| 684 | + required: true, | ||
| 685 | + trigger: ['change','blur'], | ||
| 686 | + validator: (rule, value, callback) => { | ||
| 687 | + // 空字符串、null、undefined 才是空;数字 1,7,100 全部合法 | ||
| 688 | + if (value === '' || value === null || value === undefined) { | ||
| 689 | + callback(new Error(`请填写${field.fieldName}`)) | ||
| 690 | + } else { | ||
| 691 | + callback() | ||
| 668 | } | 692 | } |
| 669 | } | 693 | } |
| 670 | - // 1数值/2文本/4日期/5布尔/10链接 为字符串;3枚举/6单选为选择项 | ||
| 671 | - const action = type === 3 || type === 5 ? '请选择' : '请填写' | ||
| 672 | - return { required: true, message: `${action}${field.fieldName}`, trigger: 'change' } | ||
| 673 | - }, | 694 | + } |
| 695 | + } | ||
| 696 | + // 2文本 /4日期 /5布尔 /10链接 | ||
| 697 | + const action = type === 3 || type === 5 ? '请选择' : '请填写' | ||
| 698 | + return { | ||
| 699 | + required: true, | ||
| 700 | + message: `${action}${field.fieldName}`, | ||
| 701 | + trigger: ['change','blur'] | ||
| 702 | + } | ||
| 703 | +}, | ||
| 704 | + | ||
| 674 | /** 幂等流水号(后端按 userId+clientSeq 去重,命中则返回已存在的 recordId) */ | 705 | /** 幂等流水号(后端按 userId+clientSeq 去重,命中则返回已存在的 recordId) */ |
| 675 | genClientSeq() { | 706 | genClientSeq() { |
| 676 | return `${Date.now()}-${Math.random().toString(16).slice(2, 10)}` | 707 | return `${Date.now()}-${Math.random().toString(16).slice(2, 10)}` |
| @@ -910,6 +941,12 @@ this.$refs.inspectFormRef.validateField(code) | @@ -910,6 +941,12 @@ this.$refs.inspectFormRef.validateField(code) | ||
| 910 | * 重试安全:commitId 一旦取到就缓存住,重试只补写 ②(② 自身按 clientSeq 幂等),避免重复创建养护记录 | 941 | * 重试安全:commitId 一旦取到就缓存住,重试只补写 ②(② 自身按 clientSeq 幂等),避免重复创建养护记录 |
| 911 | */ | 942 | */ |
| 912 | async submitInspect() { | 943 | async submitInspect() { |
| 944 | + // 调试打印,打开小程序控制台查看 | ||
| 945 | + console.log('=====调试=====') | ||
| 946 | + console.log('dynamicFields', this.dynamicFields) | ||
| 947 | + this.dynamicFields.forEach(item=>{ | ||
| 948 | + console.log(item.fieldCode, this.inspectForm[item.fieldCode], typeof this.inspectForm[item.fieldCode]) | ||
| 949 | + }) | ||
| 913 | try { | 950 | try { |
| 914 | await this.$refs.inspectFormRef.validate() | 951 | await this.$refs.inspectFormRef.validate() |
| 915 | const dynamicValues = this.buildDynamicFields() | 952 | const dynamicValues = this.buildDynamicFields() |
| @@ -1068,4 +1105,13 @@ this.$refs.inspectFormRef.validateField(code) | @@ -1068,4 +1105,13 @@ this.$refs.inspectFormRef.validateField(code) | ||
| 1068 | } | 1105 | } |
| 1069 | } | 1106 | } |
| 1070 | } | 1107 | } |
| 1108 | + | ||
| 1109 | +.empty-field-tip { | ||
| 1110 | + padding: 80rpx 30rpx; | ||
| 1111 | + text-align: center; | ||
| 1112 | + font-size: 30rpx; | ||
| 1113 | + color: #999; | ||
| 1114 | +} | ||
| 1115 | + | ||
| 1116 | + | ||
| 1071 | </style> | 1117 | </style> |
pages-sub/daily/maintain-manage/finish-plan-detail.vue
| @@ -95,7 +95,7 @@ | @@ -95,7 +95,7 @@ | ||
| 95 | title="提交人" | 95 | title="提交人" |
| 96 | :value="i.userName || '--'" | 96 | :value="i.userName || '--'" |
| 97 | align="middle" | 97 | align="middle" |
| 98 | - :border="false" | 98 | + |
| 99 | ></up-cell> | 99 | ></up-cell> |
| 100 | </up-cell-group> | 100 | </up-cell-group> |
| 101 | 101 | ||
| @@ -105,9 +105,12 @@ | @@ -105,9 +105,12 @@ | ||
| 105 | :border="false" | 105 | :border="false" |
| 106 | inset | 106 | inset |
| 107 | title="" | 107 | title="" |
| 108 | - style="margin-top: 16rpx;" | 108 | + |
| 109 | > | 109 | > |
| 110 | - <up-cell v-for="(f, fi) in i.fieldRows" :key="fi" :title="f.name" align="middle"> | 110 | + <up-cell v-for="(f, fi) in i.fieldRows" :key="fi" align="middle"> |
| 111 | + <template #title> | ||
| 112 | + <view class="field-cell-title-multi">{{f.name}}</view> | ||
| 113 | + </template> | ||
| 111 | <template #value> | 114 | <template #value> |
| 112 | <!-- 7 图片:复用本页照片的相册组件(预览/尺寸一致) --> | 115 | <!-- 7 图片:复用本页照片的相册组件(预览/尺寸一致) --> |
| 113 | <up-album | 116 | <up-album |
| @@ -616,4 +619,8 @@ onLoad((options) => { | @@ -616,4 +619,8 @@ onLoad((options) => { | ||
| 616 | font-size: 26rpx; | 619 | font-size: 26rpx; |
| 617 | word-break: break-all; | 620 | word-break: break-all; |
| 618 | } | 621 | } |
| 622 | +:deep(.field-cell-title-multi) { | ||
| 623 | + min-width: 160rpx; // 固定左侧标题最大宽度,文字会在这个宽度内自动换行 | ||
| 624 | +} | ||
| 625 | + | ||
| 619 | </style> | 626 | </style> |
| 620 | \ No newline at end of file | 627 | \ No newline at end of file |
pages-sub/problem/regional-order-manage/list-detail.vue
| @@ -96,8 +96,8 @@ | @@ -96,8 +96,8 @@ | ||
| 96 | <up-album | 96 | <up-album |
| 97 | v-if="!!orderDetail.problemsImgs?.length" | 97 | v-if="!!orderDetail.problemsImgs?.length" |
| 98 | :urls="orderDetail.problemsImgs.slice(0, 3)" | 98 | :urls="orderDetail.problemsImgs.slice(0, 3)" |
| 99 | - :singleSize="70" | ||
| 100 | - :multipleSize="70" | 99 | + singleSize="70" |
| 100 | + multipleSize="70" | ||
| 101 | :preview-full-image="true" | 101 | :preview-full-image="true" |
| 102 | ></up-album> | 102 | ></up-album> |
| 103 | <text v-else class="empty-text">暂无问题照片</text> | 103 | <text v-else class="empty-text">暂无问题照片</text> |
pages/index/index.vue
| @@ -8,27 +8,25 @@ | @@ -8,27 +8,25 @@ | ||
| 8 | <view class="login-desc">蓟城山水全域智能运营管理平台</view> | 8 | <view class="login-desc">蓟城山水全域智能运营管理平台</view> |
| 9 | </view> | 9 | </view> |
| 10 | </view> | 10 | </view> |
| 11 | - <view class="msg-icon" @click="handleMsgClick" hover-class="msg-icon--hover"> | 11 | + <!-- <view class="msg-icon" @click="handleMsgClick" hover-class="msg-icon--hover"> |
| 12 | <up-icon name="chat" color="#fff" size="24" /> | 12 | <up-icon name="chat" color="#fff" size="24" /> |
| 13 | <view class="msg-badge"> | 13 | <view class="msg-badge"> |
| 14 | - <up-badge type="error" showZero="true" max="999" :value="msgCount"></up-badge> | 14 | + <up-badge type="error" show-zero max="999" :value="msgCount"></up-badge> |
| 15 | </view> | 15 | </view> |
| 16 | - </view> | 16 | + </view> --> |
| 17 | </view> | 17 | </view> |
| 18 | - | ||
| 19 | <view class="content-wrap"> | 18 | <view class="content-wrap"> |
| 20 | <!-- 图表区域 增加平滑动画容器 --> | 19 | <!-- 图表区域 增加平滑动画容器 --> |
| 21 | <view class="chart-wrap" v-show="showChartArea"> | 20 | <view class="chart-wrap" v-show="showChartArea"> |
| 22 | <!-- 任务完成情况标题 --> | 21 | <!-- 任务完成情况标题 --> |
| 23 | <view class="module-title">任务完成情况</view> | 22 | <view class="module-title">任务完成情况</view> |
| 24 | - | ||
| 25 | <!-- 任务完成情况卡片 --> | 23 | <!-- 任务完成情况卡片 --> |
| 26 | <view class="task-chart-card"> | 24 | <view class="task-chart-card"> |
| 27 | <view class="card-header"> | 25 | <view class="card-header"> |
| 28 | <view class="unit-tip">数字指标</view> | 26 | <view class="unit-tip">数字指标</view> |
| 29 | <!-- ActionSheet 点击唤起 --> | 27 | <!-- ActionSheet 点击唤起 --> |
| 30 | <view class="sort-trigger" @click="openActionSheet"> | 28 | <view class="sort-trigger" @click="openActionSheet"> |
| 31 | - {{ sortLabel }} | 29 | + <view class="sort-text">{{ sortLabel }}</view> |
| 32 | <up-icon name="arrow-down" size="14" style="margin-left:4rpx;"></up-icon> | 30 | <up-icon name="arrow-down" size="14" style="margin-left:4rpx;"></up-icon> |
| 33 | </view> | 31 | </view> |
| 34 | <!-- ActionSheet组件 --> | 32 | <!-- ActionSheet组件 --> |
| @@ -40,14 +38,11 @@ | @@ -40,14 +38,11 @@ | ||
| 40 | @popup-hide="handlePopupHide" /> | 38 | @popup-hide="handlePopupHide" /> |
| 41 | </view> | 39 | </view> |
| 42 | </view> | 40 | </view> |
| 43 | - | ||
| 44 | - | ||
| 45 | <!-- 双折线K线图 --> | 41 | <!-- 双折线K线图 --> |
| 46 | <!-- <view class="chart-container"> | 42 | <!-- <view class="chart-container"> |
| 47 | <uni-charts v-if="!isDatePickerOpen" type="line" :data="klineChartData" :categories="klineCategories" | 43 | <uni-charts v-if="!isDatePickerOpen" type="line" :data="klineChartData" :categories="klineCategories" |
| 48 | :option="klineOption" :width="chartWidth" :height="chartHeight" /> | 44 | :option="klineOption" :width="chartWidth" :height="chartHeight" /> |
| 49 | </view> --> | 45 | </view> --> |
| 50 | - | ||
| 51 | <up-grid :border="false" col="4"> | 46 | <up-grid :border="false" col="4"> |
| 52 | <up-grid-item v-for="(baseListItem, baseListIndex) in baseList" :key="baseListIndex"> | 47 | <up-grid-item v-for="(baseListItem, baseListIndex) in baseList" :key="baseListIndex"> |
| 53 | <view class="grid-item-icon-box"> | 48 | <view class="grid-item-icon-box"> |
| @@ -57,14 +52,30 @@ | @@ -57,14 +52,30 @@ | ||
| 57 | </view> | 52 | </view> |
| 58 | </up-grid-item> | 53 | </up-grid-item> |
| 59 | </up-grid> | 54 | </up-grid> |
| 60 | - | ||
| 61 | </view> | 55 | </view> |
| 62 | </view> | 56 | </view> |
| 63 | - | ||
| 64 | <view class="con-wrap"> | 57 | <view class="con-wrap"> |
| 65 | - <view class="con-title">养护任务 </view> | ||
| 66 | - | ||
| 67 | - <!-- 手写Tab切换:胶囊分段样式 --> | 58 | + <!-- ========= 一级大Tab【养护任务 / 巡检任务 / 工单】权限控制 ========= --> |
| 59 | + <view class="main-tab-wrap"> | ||
| 60 | + <view | ||
| 61 | + v-if="showMainTabYh" | ||
| 62 | + class="main-tab-item" | ||
| 63 | + :class="{active: mainTab === 'maintain'}" | ||
| 64 | + @click="handleMainTabClick('maintain')" | ||
| 65 | + >养护任务</view> | ||
| 66 | + <view | ||
| 67 | + v-if="showMainTabXj" | ||
| 68 | + class="main-tab-item" | ||
| 69 | + :class="{active: mainTab === 'inspect'}" | ||
| 70 | + @click="handleMainTabClick('inspect')" | ||
| 71 | + >巡检任务</view> | ||
| 72 | + <view | ||
| 73 | + class="main-tab-item" | ||
| 74 | + :class="{active: mainTab === 'workorder'}" | ||
| 75 | + @click="handleMainTabClick('workorder')" | ||
| 76 | + >工单</view> | ||
| 77 | + </view> | ||
| 78 | + <!-- 手写Tab切换:胶囊分段样式(待办/已办)【原有样式完全保留不动】 --> | ||
| 68 | <view class="custom-tab-wrap"> | 79 | <view class="custom-tab-wrap"> |
| 69 | <view class="tab-capsule" :class="{ active: currentTabValue === 0 }" @click="handleTabClick(0)"> | 80 | <view class="tab-capsule" :class="{ active: currentTabValue === 0 }" @click="handleTabClick(0)"> |
| 70 | 待办事项({{ todoTotal }}) | 81 | 待办事项({{ todoTotal }}) |
| @@ -73,38 +84,27 @@ | @@ -73,38 +84,27 @@ | ||
| 73 | 已办事项({{ doneTotal }}) | 84 | 已办事项({{ doneTotal }}) |
| 74 | </view> | 85 | </view> |
| 75 | </view> | 86 | </view> |
| 76 | - | ||
| 77 | - | ||
| 78 | - <!-- 动态组信息文案 --> | ||
| 79 | - <!-- <view class="tip-top" style="padding: 8px 0 0 70px;"> | ||
| 80 | - <text>{{ tipText }}</text> | ||
| 81 | - </view> --> | ||
| 82 | - | ||
| 83 | <!-- 顶部进度提示栏 --> | 87 | <!-- 顶部进度提示栏 --> |
| 84 | <view v-if="showTipHeader" class="tip-header"> | 88 | <view v-if="showTipHeader" class="tip-header"> |
| 85 | <up-icon name="checkmark-circle" color="#00b42a" size="20"></up-icon> | 89 | <up-icon name="checkmark-circle" color="#00b42a" size="20"></up-icon> |
| 86 | <text style="color: #1677ff;">今日组内:您已经完成{{ finishNum }}项,小组均值{{ avgNum }}项</text> | 90 | <text style="color: #1677ff;">今日组内:您已经完成{{ finishNum }}项,小组均值{{ avgNum }}项</text> |
| 87 | </view> | 91 | </view> |
| 88 | - | ||
| 89 | - | ||
| 90 | - <scroll-view class="task-list-container" scroll-y @scroll="onListScroll" @scrolltoupper="handleTouchTop" | ||
| 91 | - enhanced> | 92 | + <scroll-view class="task-list-container" scroll-y @scroll="onListScroll" @scrolltoupper="handleTouchTop" enhanced> |
| 92 | <view v-if="taskList.length === 0" class="empty-box"> | 93 | <view v-if="taskList.length === 0" class="empty-box"> |
| 93 | - <up-empty /> | 94 | + <up-empty></up-empty> |
| 94 | </view> | 95 | </view> |
| 95 | <view class="task-item" v-for="(item, index) in taskList" :key="`${item.taskName}_${index}`" | 96 | <view class="task-item" v-for="(item, index) in taskList" :key="`${item.taskName}_${index}`" |
| 96 | hover-class="task-item--hover" @click="handleTaskClick(item)"> | 97 | hover-class="task-item--hover" @click="handleTaskClick(item)"> |
| 97 | <view class="task-item__content"> | 98 | <view class="task-item__content"> |
| 98 | <view class="name-fixed-wrap"> | 99 | <view class="name-fixed-wrap"> |
| 99 | - <view class="task-item__name "> | 100 | + <view class="task-item__name"> |
| 100 | 事项{{ index + 1 }} | 101 | 事项{{ index + 1 }} |
| 101 | </view> | 102 | </view> |
| 102 | <view class="task-name-text"> | 103 | <view class="task-name-text"> |
| 103 | {{ item.taskName || '无' }} | 104 | {{ item.taskName || '无' }} |
| 104 | </view> | 105 | </view> |
| 105 | </view> | 106 | </view> |
| 106 | - | ||
| 107 | - <view v-if="currentTabValue === 0" class="task-item__footer" style="padding-left: 60px;"> | 107 | + <view v-if="currentTabValue === 0" class="task-item__footer" style="padding-left: 60rpx;"> |
| 108 | <image class="loc-icon" src="https://img.jichengshanshui.com.cn:28207/appimg/定位icon@3x.png" | 108 | <image class="loc-icon" src="https://img.jichengshanshui.com.cn:28207/appimg/定位icon@3x.png" |
| 109 | mode="aspectFit"></image> | 109 | mode="aspectFit"></image> |
| 110 | <template v-if="isWalkTextMode"> | 110 | <template v-if="isWalkTextMode"> |
| @@ -129,7 +129,7 @@ import { ref, computed, nextTick, watch } from 'vue'; | @@ -129,7 +129,7 @@ import { ref, computed, nextTick, watch } from 'vue'; | ||
| 129 | import { onShow, onUnload } from '@dcloudio/uni-app'; | 129 | import { onShow, onUnload } from '@dcloudio/uni-app'; |
| 130 | import { useUserStore } from '@/pinia/user'; | 130 | import { useUserStore } from '@/pinia/user'; |
| 131 | import { timeFormat } from '@/uni_modules/uview-plus'; | 131 | import { timeFormat } from '@/uni_modules/uview-plus'; |
| 132 | -import uniCharts from '@/components/uni-charts/uni-charts.vue'; | 132 | +// import uniCharts from '@/components/uni-charts/uni-charts.vue'; |
| 133 | import { getUnreadCount } from "@/api/user"; | 133 | import { getUnreadCount } from "@/api/user"; |
| 134 | import { | 134 | import { |
| 135 | getTaskCompletionSummary, | 135 | getTaskCompletionSummary, |
| @@ -189,6 +189,59 @@ const isWalkTextMode = computed(() => currentGroup.value.useWalkText); | @@ -189,6 +189,59 @@ const isWalkTextMode = computed(() => currentGroup.value.useWalkText); | ||
| 189 | const useDistanceApi = computed(() => currentGroup.value.useWalkText); | 189 | const useDistanceApi = computed(() => currentGroup.value.useWalkText); |
| 190 | // ========================================================================= | 190 | // ========================================================================= |
| 191 | 191 | ||
| 192 | +// ========== 一级Tab:养护/巡检/工单 ========= | ||
| 193 | +// 默认期望打开 maintain,watch权限自动修正 | ||
| 194 | +const mainTab = ref<'maintain' | 'inspect' | 'workorder'>('maintain'); | ||
| 195 | + | ||
| 196 | +// ✅ 修复:用户角色数组 | ||
| 197 | +const userRoles = computed<string[]>(() => userStore.userInfo?.roles || []); | ||
| 198 | +console.log('当前用户角色数组:', userRoles.value) | ||
| 199 | + | ||
| 200 | +// 权限控制角色列表:包含这些角色,则隐藏对应tab | ||
| 201 | +const hideYhRoleList = ['patrol_leader', 'patrol_global', 'yl_inspector', 'hjws_inspector', 'zxgl_inspector']; | ||
| 202 | +const hideXjRoleList = ['zxgl_worker', 'team_leader_hjws', 'hjws_worker', 'team_leader_wy', 'wy_worker', 'yl_worker', 'team_leader_yl']; | ||
| 203 | + | ||
| 204 | +// ✅ 修复:用户角色数组 和 黑名单数组 存在交集 → 隐藏养护tab | ||
| 205 | +const showMainTabYh = computed(() => { | ||
| 206 | + // 判断:用户角色里是否存在任意一个在hideYhRoleList中的角色 | ||
| 207 | + const hasHideRole = userRoles.value.some(role => hideYhRoleList.includes(role)); | ||
| 208 | + return !hasHideRole; | ||
| 209 | +}); | ||
| 210 | +// ✅ 修复:巡检tab权限 | ||
| 211 | +const showMainTabXj = computed(() => { | ||
| 212 | + const hasHideRole = userRoles.value.some(role => hideXjRoleList.includes(role)); | ||
| 213 | + return !hasHideRole; | ||
| 214 | +}); | ||
| 215 | + | ||
| 216 | +// 获取可见tab数组,用于自动选中 | ||
| 217 | +const availableTabList = computed(() => { | ||
| 218 | + const list: Array<'maintain' | 'inspect' | 'workorder'> = []; | ||
| 219 | + if (showMainTabYh.value) list.push('maintain'); | ||
| 220 | + if (showMainTabXj.value) list.push('inspect'); | ||
| 221 | + list.push('workorder'); | ||
| 222 | + return list; | ||
| 223 | +}); | ||
| 224 | + | ||
| 225 | +// 监听权限变化:如果当前选中tab不可见,自动切到第一个可用tab | ||
| 226 | +watch([showMainTabYh, showMainTabXj], () => { | ||
| 227 | + const available = availableTabList.value; | ||
| 228 | + console.log('可用tab列表', available); | ||
| 229 | + if (!available.includes(mainTab.value)) { | ||
| 230 | + mainTab.value = available[0]; | ||
| 231 | + console.log(`当前角色无【养护任务】权限,自动切换至:${mainTab.value}`) | ||
| 232 | + } | ||
| 233 | +}, { immediate: true }); | ||
| 234 | + | ||
| 235 | +// 一级Tab切换事件 | ||
| 236 | +const handleMainTabClick = async (tabKey: 'maintain' | 'inspect' | 'workorder') => { | ||
| 237 | + if (mainTab.value === tabKey) return; | ||
| 238 | + mainTab.value = tabKey; | ||
| 239 | + currentTabValue.value = 0; // 切大tab默认回到待办 | ||
| 240 | + showChartArea.value = true; | ||
| 241 | + // 重新拉取对应类型任务 | ||
| 242 | + await loadAllTaskByDept(); | ||
| 243 | +}; | ||
| 244 | + | ||
| 192 | const finishNum = ref(0); | 245 | const finishNum = ref(0); |
| 193 | const avgNum = ref(0); | 246 | const avgNum = ref(0); |
| 194 | const msgCount = ref(0); | 247 | const msgCount = ref(0); |
| @@ -205,7 +258,6 @@ const handlePopupShow = () => { | @@ -205,7 +258,6 @@ const handlePopupShow = () => { | ||
| 205 | const handlePopupHide = () => { | 258 | const handlePopupHide = () => { |
| 206 | isDatePickerOpen.value = false; | 259 | isDatePickerOpen.value = false; |
| 207 | }; | 260 | }; |
| 208 | - | ||
| 209 | const todoTotal = ref(0); | 261 | const todoTotal = ref(0); |
| 210 | const doneTotal = ref(0); | 262 | const doneTotal = ref(0); |
| 211 | const todoFullList = ref<any[]>([]); | 263 | const todoFullList = ref<any[]>([]); |
| @@ -217,7 +269,6 @@ const chooseOptions = computed(() => [ | @@ -217,7 +269,6 @@ const chooseOptions = computed(() => [ | ||
| 217 | { title: `待办事项(${todoTotal.value})`, id: 'todo' }, | 269 | { title: `待办事项(${todoTotal.value})`, id: 'todo' }, |
| 218 | { title: `已办事项(${doneTotal.value})`, id: 'done' }, | 270 | { title: `已办事项(${doneTotal.value})`, id: 'done' }, |
| 219 | ]); | 271 | ]); |
| 220 | - | ||
| 221 | const currentLon = ref<string>(''); | 272 | const currentLon = ref<string>(''); |
| 222 | const currentLat = ref<string>(''); | 273 | const currentLat = ref<string>(''); |
| 223 | const chartWidth = ref(0); | 274 | const chartWidth = ref(0); |
| @@ -264,12 +315,10 @@ ${params[1].seriesName}: ${params[1].value}`; | @@ -264,12 +315,10 @@ ${params[1].seriesName}: ${params[1].value}`; | ||
| 264 | textStyle: { fontSize: 12 } | 315 | textStyle: { fontSize: 12 } |
| 265 | } | 316 | } |
| 266 | }); | 317 | }); |
| 267 | - | ||
| 268 | -const baseList = ref<Array<{ num: string; title: string }>>([]); | 318 | +const baseList = ref<Array<{ num: string; title: string; name: string }>>([]); |
| 269 | const orgOptions = ref<any[]>([]); | 319 | const orgOptions = ref<any[]>([]); |
| 270 | const value1 = ref<number | string>(''); | 320 | const value1 = ref<number | string>(''); |
| 271 | const showActionSheet = ref(false); | 321 | const showActionSheet = ref(false); |
| 272 | - | ||
| 273 | watch(orgOptions, async (list) => { | 322 | watch(orgOptions, async (list) => { |
| 274 | if (list.length && !value1.value) { | 323 | if (list.length && !value1.value) { |
| 275 | value1.value = list[0].value; | 324 | value1.value = list[0].value; |
| @@ -279,7 +328,6 @@ watch(orgOptions, async (list) => { | @@ -279,7 +328,6 @@ watch(orgOptions, async (list) => { | ||
| 279 | } | 328 | } |
| 280 | } | 329 | } |
| 281 | }, { immediate: true }); | 330 | }, { immediate: true }); |
| 282 | - | ||
| 283 | const actionSheetOptions = computed(() => { | 331 | const actionSheetOptions = computed(() => { |
| 284 | return orgOptions.value.map(opt => ({ | 332 | return orgOptions.value.map(opt => ({ |
| 285 | name: opt.label, | 333 | name: opt.label, |
| @@ -302,13 +350,11 @@ const handleSheetSelect = async (item: { name: string; value: number }) => { | @@ -302,13 +350,11 @@ const handleSheetSelect = async (item: { name: string; value: number }) => { | ||
| 302 | await fetchOrgIndicator(item.value, dateRange.value[0], dateRange.value[1]); | 350 | await fetchOrgIndicator(item.value, dateRange.value[0], dateRange.value[1]); |
| 303 | } | 351 | } |
| 304 | }; | 352 | }; |
| 305 | - | ||
| 306 | -const userName = computed(() => userStore.userInfo?.nickname || '用户'); | 353 | +const userName = computed(() => userStore.userInfo.user.nickname || '用户'); |
| 307 | const rpx2px = (rpx: number) => { | 354 | const rpx2px = (rpx: number) => { |
| 308 | const systemInfo = uni.getSystemInfoSync(); | 355 | const systemInfo = uni.getSystemInfoSync(); |
| 309 | return Math.floor(systemInfo.screenWidth / 750 * rpx); | 356 | return Math.floor(systemInfo.screenWidth / 750 * rpx); |
| 310 | }; | 357 | }; |
| 311 | - | ||
| 312 | // ========== 滚动逻辑 ========== | 358 | // ========== 滚动逻辑 ========== |
| 313 | const showChartArea = ref(true); | 359 | const showChartArea = ref(true); |
| 314 | const scrollHideThreshold = rpx2px(80); | 360 | const scrollHideThreshold = rpx2px(80); |
| @@ -336,7 +382,6 @@ const handleTabClick = (tabIndex: number) => { | @@ -336,7 +382,6 @@ const handleTabClick = (tabIndex: number) => { | ||
| 336 | currentTabValue.value = tabIndex; | 382 | currentTabValue.value = tabIndex; |
| 337 | showChartArea.value = true; | 383 | showChartArea.value = true; |
| 338 | }; | 384 | }; |
| 339 | - | ||
| 340 | // ========== 公共函数:请求 orgTaskIndicator 指标接口 ========== | 385 | // ========== 公共函数:请求 orgTaskIndicator 指标接口 ========== |
| 341 | const fetchOrgIndicator = async (orgId: number, beginDate: string, endDate: string) => { | 386 | const fetchOrgIndicator = async (orgId: number, beginDate: string, endDate: string) => { |
| 342 | try { | 387 | try { |
| @@ -355,19 +400,16 @@ const fetchOrgIndicator = async (orgId: number, beginDate: string, endDate: stri | @@ -355,19 +400,16 @@ const fetchOrgIndicator = async (orgId: number, beginDate: string, endDate: stri | ||
| 355 | { num: String(res.pendingCnt ?? 0), title: '待办任务数', name: 'clock' }, | 400 | { num: String(res.pendingCnt ?? 0), title: '待办任务数', name: 'clock' }, |
| 356 | { num: String(res.overdueCnt ?? 0), title: '超时未完成', name: 'close-circle' } | 401 | { num: String(res.overdueCnt ?? 0), title: '超时未完成', name: 'close-circle' } |
| 357 | ]; | 402 | ]; |
| 358 | - | ||
| 359 | } catch (err) { | 403 | } catch (err) { |
| 360 | console.error('orgTaskIndicator 请求失败:', err); | 404 | console.error('orgTaskIndicator 请求失败:', err); |
| 361 | } | 405 | } |
| 362 | }; | 406 | }; |
| 363 | - | ||
| 364 | // ========== 初始化日期范围(近7天) ========== | 407 | // ========== 初始化日期范围(近7天) ========== |
| 365 | const initRecent7Days = () => { | 408 | const initRecent7Days = () => { |
| 366 | const now = new Date(); | 409 | const now = new Date(); |
| 367 | const end = new Date(now); | 410 | const end = new Date(now); |
| 368 | - end.setDate(end.getDate() - 1); | 411 | + end.setDate(end.getDate()); |
| 369 | const start = new Date(end); | 412 | const start = new Date(end); |
| 370 | - console.log(start) | ||
| 371 | start.setDate(start.getDate() - 6); | 413 | start.setDate(start.getDate() - 6); |
| 372 | dateRange.value = [ | 414 | dateRange.value = [ |
| 373 | timeFormat(start, 'yyyy-mm-dd'), | 415 | timeFormat(start, 'yyyy-mm-dd'), |
| @@ -376,7 +418,6 @@ const initRecent7Days = () => { | @@ -376,7 +418,6 @@ const initRecent7Days = () => { | ||
| 376 | console.log(dateRange.value) | 418 | console.log(dateRange.value) |
| 377 | initChartData(dateRange.value[0], dateRange.value[1]); | 419 | initChartData(dateRange.value[0], dateRange.value[1]); |
| 378 | }; | 420 | }; |
| 379 | - | ||
| 380 | const getUnread = async () => { | 421 | const getUnread = async () => { |
| 381 | try { | 422 | try { |
| 382 | const res = await getUnreadCount(); | 423 | const res = await getUnreadCount(); |
| @@ -385,7 +426,6 @@ const getUnread = async () => { | @@ -385,7 +426,6 @@ const getUnread = async () => { | ||
| 385 | console.error('获取未读消息失败:', error); | 426 | console.error('获取未读消息失败:', error); |
| 386 | } | 427 | } |
| 387 | }; | 428 | }; |
| 388 | - | ||
| 389 | // getOrg:只拉组织下拉选项,不处理指标 | 429 | // getOrg:只拉组织下拉选项,不处理指标 |
| 390 | const getOrg = async () => { | 430 | const getOrg = async () => { |
| 391 | try { | 431 | try { |
| @@ -396,7 +436,6 @@ const getOrg = async () => { | @@ -396,7 +436,6 @@ const getOrg = async () => { | ||
| 396 | console.error('获取组织下拉失败:', error); | 436 | console.error('获取组织下拉失败:', error); |
| 397 | } | 437 | } |
| 398 | }; | 438 | }; |
| 399 | - | ||
| 400 | const initChartData = async (beginTime: string, endTime: string) => { | 439 | const initChartData = async (beginTime: string, endTime: string) => { |
| 401 | try { | 440 | try { |
| 402 | const postData = { beginTime, endTime }; | 441 | const postData = { beginTime, endTime }; |
| @@ -408,11 +447,10 @@ const initChartData = async (beginTime: string, endTime: string) => { | @@ -408,11 +447,10 @@ const initChartData = async (beginTime: string, endTime: string) => { | ||
| 408 | console.error('图表数据请求失败:', error); | 447 | console.error('图表数据请求失败:', error); |
| 409 | } | 448 | } |
| 410 | }; | 449 | }; |
| 411 | - | ||
| 412 | -const loadDistanceApiTask = async (lon: string, lat: string) => { | 450 | +const loadDistanceApiTask = async (lon: string, lat: string, taskType: string) => { |
| 413 | try { | 451 | try { |
| 414 | - const paramsTodo = { queryType: 1, currentLon: lon, currentLat: lat }; | ||
| 415 | - const paramsDone = { queryType: 2, currentLon: lon, currentLat: lat }; | 452 | + const paramsTodo = { queryType: 1, currentLon: lon, currentLat: lat, taskType }; |
| 453 | + const paramsDone = { queryType: 2, currentLon: lon, currentLat: lat, taskType }; | ||
| 416 | const [todoRes, doneRes] = await Promise.all([ | 454 | const [todoRes, doneRes] = await Promise.all([ |
| 417 | taskDetailsWithDistance(paramsTodo), | 455 | taskDetailsWithDistance(paramsTodo), |
| 418 | taskDetailsWithDistance(paramsDone) | 456 | taskDetailsWithDistance(paramsDone) |
| @@ -433,11 +471,11 @@ const loadDistanceApiTask = async (lon: string, lat: string) => { | @@ -433,11 +471,11 @@ const loadDistanceApiTask = async (lon: string, lat: string) => { | ||
| 433 | doneTotal.value = 0; | 471 | doneTotal.value = 0; |
| 434 | } | 472 | } |
| 435 | }; | 473 | }; |
| 436 | -const loadSmartSortTask = async (lon: string, lat: string) => { | 474 | +const loadSmartSortTask = async (lon: string, lat: string, taskType: string) => { |
| 437 | try { | 475 | try { |
| 438 | const [todoRes, doneRes] = await Promise.all([ | 476 | const [todoRes, doneRes] = await Promise.all([ |
| 439 | - taskDetailsWithSmartSort({ queryType: 1, currentLon: lon, currentLat: lat }), | ||
| 440 | - taskDetailsWithSmartSort({ queryType: 2, currentLon: lon, currentLat: lat }) | 477 | + taskDetailsWithSmartSort({ queryType: 1, currentLon: lon, currentLat: lat, taskType }), |
| 478 | + taskDetailsWithSmartSort({ queryType: 2, currentLon: lon, currentLat: lat, taskType }) | ||
| 441 | ]); | 479 | ]); |
| 442 | todoFullList.value = todoRes?.sortedTasks || []; | 480 | todoFullList.value = todoRes?.sortedTasks || []; |
| 443 | doneFullList.value = doneRes?.sortedTasks || []; | 481 | doneFullList.value = doneRes?.sortedTasks || []; |
| @@ -459,22 +497,27 @@ const loadAllTaskByDept = async () => { | @@ -459,22 +497,27 @@ const loadAllTaskByDept = async () => { | ||
| 459 | const loc = await getCurrentLocation(); | 497 | const loc = await getCurrentLocation(); |
| 460 | currentLon.value = loc.lon; | 498 | currentLon.value = loc.lon; |
| 461 | currentLat.value = loc.lat; | 499 | currentLat.value = loc.lat; |
| 462 | - if (useDistanceApi.value) { | ||
| 463 | - await loadDistanceApiTask(loc.lon, loc.lat); | ||
| 464 | - } else { | ||
| 465 | - await loadSmartSortTask(loc.lon, loc.lat); | ||
| 466 | - } | ||
| 467 | -}; | ||
| 468 | - | ||
| 469 | -// 日期确认回调:更新图表 + 重新请求指标orgTaskIndicator | ||
| 470 | -const handleDateConfirm = async (e: string[]) => { | ||
| 471 | - dateRange.value = e; | ||
| 472 | - await initChartData(e[0], e[1]); | ||
| 473 | - if (value1.value) { | ||
| 474 | - await fetchOrgIndicator(Number(value1.value), e[0], e[1]); | 500 | + // 根据一级Tab选择不同接口 |
| 501 | + if (mainTab.value === 'maintain') { | ||
| 502 | + if (useDistanceApi.value) { | ||
| 503 | + await loadDistanceApiTask(loc.lon, loc.lat, 'maintain'); | ||
| 504 | + } else { | ||
| 505 | + await loadSmartSortTask(loc.lon, loc.lat, 'maintain'); | ||
| 506 | + } | ||
| 507 | + } else if (mainTab.value === 'inspect') { | ||
| 508 | + if (useDistanceApi.value) { | ||
| 509 | + await loadDistanceApiTask(loc.lon, loc.lat, 'inspect'); | ||
| 510 | + } else { | ||
| 511 | + await loadSmartSortTask(loc.lon, loc.lat, 'inspect'); | ||
| 512 | + } | ||
| 513 | + } else if (mainTab.value === 'workorder') { | ||
| 514 | + // ========= 工单tab,后续对接工单接口,先置空列表占位 ========= | ||
| 515 | + todoFullList.value = []; | ||
| 516 | + doneFullList.value = []; | ||
| 517 | + todoTotal.value = 0; | ||
| 518 | + doneTotal.value = 0; | ||
| 475 | } | 519 | } |
| 476 | }; | 520 | }; |
| 477 | - | ||
| 478 | const getCurrentLocation = (): Promise<{ lon: string; lat: string }> => { | 521 | const getCurrentLocation = (): Promise<{ lon: string; lat: string }> => { |
| 479 | return new Promise((resolve, reject) => { | 522 | return new Promise((resolve, reject) => { |
| 480 | uni.getSetting({ | 523 | uni.getSetting({ |
| @@ -533,7 +576,6 @@ const getCurrentLocation = (): Promise<{ lon: string; lat: string }> => { | @@ -533,7 +576,6 @@ const getCurrentLocation = (): Promise<{ lon: string; lat: string }> => { | ||
| 533 | }); | 576 | }); |
| 534 | }); | 577 | }); |
| 535 | }; | 578 | }; |
| 536 | - | ||
| 537 | const handleMsgClick = () => { | 579 | const handleMsgClick = () => { |
| 538 | uni.navigateTo({ url: '/pages-sub/msg/msg' }); | 580 | uni.navigateTo({ url: '/pages-sub/msg/msg' }); |
| 539 | }; | 581 | }; |
| @@ -561,39 +603,34 @@ const handleTaskClick = (item: any) => { | @@ -561,39 +603,34 @@ const handleTaskClick = (item: any) => { | ||
| 561 | } | 603 | } |
| 562 | } | 604 | } |
| 563 | }; | 605 | }; |
| 564 | - | ||
| 565 | onShow(async () => { | 606 | onShow(async () => { |
| 566 | showChartArea.value = true; | 607 | showChartArea.value = true; |
| 567 | chartWidth.value = rpx2px(750 - 60); | 608 | chartWidth.value = rpx2px(750 - 60); |
| 568 | chartHeight.value = rpx2px(300); | 609 | chartHeight.value = rpx2px(300); |
| 569 | initRecent7Days(); | 610 | initRecent7Days(); |
| 570 | - getUnread(); | 611 | + // getUnread(); |
| 571 | await getOrg(); // 拉取组织下拉列表 | 612 | await getOrg(); // 拉取组织下拉列表 |
| 572 | await loadAllTaskByDept(); | 613 | await loadAllTaskByDept(); |
| 573 | }); | 614 | }); |
| 574 | - | ||
| 575 | onUnload(() => { | 615 | onUnload(() => { |
| 576 | if (scrollTimer) clearTimeout(scrollTimer); | 616 | if (scrollTimer) clearTimeout(scrollTimer); |
| 577 | }); | 617 | }); |
| 578 | </script> | 618 | </script> |
| 579 | 619 | ||
| 580 | - | ||
| 581 | - | ||
| 582 | <style scoped lang="scss"> | 620 | <style scoped lang="scss"> |
| 583 | $primary-color: #1677ff; | 621 | $primary-color: #1677ff; |
| 584 | $danger-color: #E53935; | 622 | $danger-color: #E53935; |
| 585 | $text-color: #333; | 623 | $text-color: #333; |
| 586 | $text-color-light: #666; | 624 | $text-color-light: #666; |
| 587 | -$text-color-placeholder: #999; | 625 | +$text-placeholder: #999; |
| 588 | $bg-color: #f5f5f7; | 626 | $bg-color: #f5f5f7; |
| 589 | $card-bg: #fff; | 627 | $card-bg: #fff; |
| 590 | -$border-radius: 16px; | ||
| 591 | -$card-radius: 5px; | ||
| 592 | -$spacing-sm: 5px; | ||
| 593 | -$spacing-md: 10px; | ||
| 594 | -$spacing-lg: 15px; | 628 | +$border-radius: 16rpx; |
| 629 | +$card-radius: 5rpx; | ||
| 630 | +$spacing-sm: 5rpx; | ||
| 631 | +$spacing-md: 10rpx; | ||
| 632 | +$spacing-lg: 15rpx; | ||
| 595 | $border-color: #e5e5e5; | 633 | $border-color: #e5e5e5; |
| 596 | - | ||
| 597 | .page-container { | 634 | .page-container { |
| 598 | height: 100vh; | 635 | height: 100vh; |
| 599 | background-color: $bg-color; | 636 | background-color: $bg-color; |
| @@ -601,128 +638,134 @@ $border-color: #e5e5e5; | @@ -601,128 +638,134 @@ $border-color: #e5e5e5; | ||
| 601 | display: flex; | 638 | display: flex; |
| 602 | flex-direction: column; | 639 | flex-direction: column; |
| 603 | } | 640 | } |
| 604 | - | ||
| 605 | .user-info-bar { | 641 | .user-info-bar { |
| 606 | flex-shrink: 0; | 642 | flex-shrink: 0; |
| 607 | background: url("https://img.jichengshanshui.com.cn:28207/appimg/bg.jpg") no-repeat; | 643 | background: url("https://img.jichengshanshui.com.cn:28207/appimg/bg.jpg") no-repeat; |
| 608 | background-size: 100% 100%; | 644 | background-size: 100% 100%; |
| 609 | - padding: 80px $spacing-lg 135px; | 645 | + padding: 140rpx $spacing-lg 165rpx; |
| 610 | display: flex; | 646 | display: flex; |
| 611 | justify-content: space-between; | 647 | justify-content: space-between; |
| 612 | align-items: center; | 648 | align-items: center; |
| 613 | color: #fff; | 649 | color: #fff; |
| 614 | - | ||
| 615 | .username { | 650 | .username { |
| 616 | - font-size: 16px; | ||
| 617 | - margin-bottom: 4px; | 651 | + font-size: 32rpx; |
| 652 | + margin-bottom: 4rpx; | ||
| 618 | } | 653 | } |
| 619 | - | ||
| 620 | .login-desc { | 654 | .login-desc { |
| 621 | - font-size: 16px; | 655 | + font-size: 28rpx; |
| 622 | } | 656 | } |
| 623 | - | ||
| 624 | .msg-icon { | 657 | .msg-icon { |
| 625 | position: relative; | 658 | position: relative; |
| 626 | - padding: 5px; | ||
| 627 | - top: 10px; | 659 | + padding: 5rpx; |
| 660 | + top: 10rpx; | ||
| 628 | border-radius: 50%; | 661 | border-radius: 50%; |
| 629 | - | ||
| 630 | &--hover { | 662 | &--hover { |
| 631 | background-color: rgba(255, 255, 255, 0.2); | 663 | background-color: rgba(255, 255, 255, 0.2); |
| 632 | } | 664 | } |
| 633 | - | ||
| 634 | .msg-badge { | 665 | .msg-badge { |
| 635 | position: absolute; | 666 | position: absolute; |
| 636 | - top: -2px; | ||
| 637 | - right: -3px; | 667 | + top: -2rpx; |
| 668 | + right: -3rpx; | ||
| 638 | } | 669 | } |
| 639 | } | 670 | } |
| 640 | } | 671 | } |
| 641 | - | ||
| 642 | .content-wrap { | 672 | .content-wrap { |
| 643 | flex: 1; | 673 | flex: 1; |
| 644 | - margin-top: -122px; | 674 | + margin-top: -122rpx; |
| 645 | border-radius: $border-radius $border-radius 0 0; | 675 | border-radius: $border-radius $border-radius 0 0; |
| 646 | background-color: $bg-color; | 676 | background-color: $bg-color; |
| 647 | overflow: hidden; | 677 | overflow: hidden; |
| 648 | display: flex; | 678 | display: flex; |
| 649 | flex-direction: column; | 679 | flex-direction: column; |
| 650 | } | 680 | } |
| 651 | - | ||
| 652 | .chart-wrap { | 681 | .chart-wrap { |
| 653 | flex-shrink: 0; | 682 | flex-shrink: 0; |
| 654 | transition: all 0.35s ease-out; | 683 | transition: all 0.35s ease-out; |
| 655 | opacity: 1; | 684 | opacity: 1; |
| 656 | overflow: hidden; | 685 | overflow: hidden; |
| 686 | + &[hidden] { | ||
| 687 | + opacity: 0; | ||
| 688 | + height: 0; | ||
| 689 | + margin: 0; | ||
| 690 | + } | ||
| 657 | } | 691 | } |
| 658 | - | ||
| 659 | -.chart-wrap[hidden] { | ||
| 660 | - opacity: 0; | ||
| 661 | - height: 0; | ||
| 662 | - margin: 0; | ||
| 663 | -} | ||
| 664 | - | ||
| 665 | .module-title { | 692 | .module-title { |
| 666 | padding: $spacing-lg; | 693 | padding: $spacing-lg; |
| 667 | - font-size: 14px; | 694 | + font-size: 28rpx; |
| 668 | font-weight: 600; | 695 | font-weight: 600; |
| 669 | color: $text-color-light; | 696 | color: $text-color-light; |
| 670 | flex-shrink: 0; | 697 | flex-shrink: 0; |
| 671 | } | 698 | } |
| 672 | - | ||
| 673 | .task-chart-card { | 699 | .task-chart-card { |
| 674 | background-color: $card-bg; | 700 | background-color: $card-bg; |
| 675 | border-radius: $card-radius; | 701 | border-radius: $card-radius; |
| 676 | margin: 0 $spacing-lg $spacing-md; | 702 | margin: 0 $spacing-lg $spacing-md; |
| 677 | padding: $spacing-md; | 703 | padding: $spacing-md; |
| 678 | flex-shrink: 0; | 704 | flex-shrink: 0; |
| 679 | - | ||
| 680 | .card-header { | 705 | .card-header { |
| 681 | display: flex; | 706 | display: flex; |
| 682 | justify-content: space-between; | 707 | justify-content: space-between; |
| 683 | align-items: center; | 708 | align-items: center; |
| 684 | - font-size: 12px; | ||
| 685 | - color: $text-color-placeholder; | 709 | + font-size: 24rpx; |
| 710 | + color: $text-placeholder; | ||
| 686 | margin-bottom: $spacing-md; | 711 | margin-bottom: $spacing-md; |
| 687 | - | ||
| 688 | .date-picker-wrap { | 712 | .date-picker-wrap { |
| 689 | - border-radius: 3px; | 713 | + border-radius: 3rpx; |
| 690 | transition: background-color 0.2s; | 714 | transition: background-color 0.2s; |
| 691 | position: relative; | 715 | position: relative; |
| 692 | z-index: 999; | 716 | z-index: 999; |
| 693 | - | ||
| 694 | &:active { | 717 | &:active { |
| 695 | background-color: $bg-color; | 718 | background-color: $bg-color; |
| 696 | } | 719 | } |
| 697 | } | 720 | } |
| 698 | } | 721 | } |
| 699 | - | ||
| 700 | .chart-container { | 722 | .chart-container { |
| 701 | width: 100%; | 723 | width: 100%; |
| 702 | - height: 150px; | 724 | + height: 150rpx; |
| 703 | display: flex; | 725 | display: flex; |
| 704 | align-items: center; | 726 | align-items: center; |
| 705 | justify-content: center; | 727 | justify-content: center; |
| 706 | } | 728 | } |
| 707 | } | 729 | } |
| 708 | - | ||
| 709 | .con-wrap { | 730 | .con-wrap { |
| 710 | - border-radius: 8px; | 731 | + border-radius: 8rpx; |
| 711 | background-color: #fff; | 732 | background-color: #fff; |
| 712 | - margin: 0 15px; | 733 | + margin: 0 15rpx; |
| 713 | flex: 1; | 734 | flex: 1; |
| 714 | min-height: 0; | 735 | min-height: 0; |
| 715 | display: flex; | 736 | display: flex; |
| 716 | flex-direction: column; | 737 | flex-direction: column; |
| 717 | overflow: hidden; | 738 | overflow: hidden; |
| 718 | } | 739 | } |
| 719 | - | ||
| 720 | -.con-title { | ||
| 721 | - padding: 10px 15px; | ||
| 722 | - border-bottom: 1px solid #f0e9e9; | ||
| 723 | - flex-shrink: 0; | 740 | +// ========= 【仅一级Tab:养护/巡检/工单】下划线样式,其余全部保留原有css ========= |
| 741 | +.main-tab-wrap { | ||
| 742 | + display: flex; | ||
| 743 | + align-items: center; | ||
| 744 | + background: #fff; | ||
| 745 | + padding: 0 30rpx; | ||
| 724 | } | 746 | } |
| 725 | - | 747 | +.main-tab-item { |
| 748 | + padding: 24rpx 16rpx; | ||
| 749 | + font-size: 30rpx; | ||
| 750 | + color: #666; | ||
| 751 | + position: relative; | ||
| 752 | + transition: color 0.24s; | ||
| 753 | + &.active { | ||
| 754 | + color: #1677ff; | ||
| 755 | + font-weight: 500; | ||
| 756 | + &::after { | ||
| 757 | + content: ''; | ||
| 758 | + position: absolute; | ||
| 759 | + left: 0; | ||
| 760 | + bottom: 0; | ||
| 761 | + width: 100%; | ||
| 762 | + height: 4rpx; | ||
| 763 | + background-color: #1677ff; | ||
| 764 | + border-radius: 2rpx; | ||
| 765 | + } | ||
| 766 | + } | ||
| 767 | +} | ||
| 768 | +// 待办/已办胶囊tab【原样保留你原来的样式,完全没改动!!】 | ||
| 726 | .custom-tab-wrap { | 769 | .custom-tab-wrap { |
| 727 | display: flex; | 770 | display: flex; |
| 728 | align-items: center; | 771 | align-items: center; |
| @@ -731,88 +774,76 @@ $border-color: #e5e5e5; | @@ -731,88 +774,76 @@ $border-color: #e5e5e5; | ||
| 731 | background: #fff; | 774 | background: #fff; |
| 732 | flex-shrink: 0; | 775 | flex-shrink: 0; |
| 733 | } | 776 | } |
| 734 | - | ||
| 735 | .tab-capsule { | 777 | .tab-capsule { |
| 736 | padding: 10rpx 20rpx; | 778 | padding: 10rpx 20rpx; |
| 737 | - display: flex; | ||
| 738 | - align-items: center; | ||
| 739 | - justify-content: center; | ||
| 740 | font-size: 28rpx; | 779 | font-size: 28rpx; |
| 741 | color: #999; | 780 | color: #999; |
| 742 | background: #f5f5f5; | 781 | background: #f5f5f5; |
| 743 | border-radius: 0; | 782 | border-radius: 0; |
| 744 | transition: all 0.2s ease; | 783 | transition: all 0.2s ease; |
| 745 | font-weight: 500; | 784 | font-weight: 500; |
| 785 | + &.active { | ||
| 786 | + color: #d4af37; | ||
| 787 | + background: #fff8dc; | ||
| 788 | + } | ||
| 746 | } | 789 | } |
| 747 | - | ||
| 748 | -.tab-capsule.active { | ||
| 749 | - color: #d4af37; | ||
| 750 | - background: #fff8dc; | ||
| 751 | -} | ||
| 752 | - | ||
| 753 | .tip-header { | 790 | .tip-header { |
| 754 | display: flex; | 791 | display: flex; |
| 755 | align-items: center; | 792 | align-items: center; |
| 756 | gap: 8rpx; | 793 | gap: 8rpx; |
| 757 | padding: 12rpx 15rpx; | 794 | padding: 12rpx 15rpx; |
| 758 | background: #e6f7ff; | 795 | background: #e6f7ff; |
| 759 | - font-size: 14px; | 796 | + font-size: 28rpx; |
| 760 | color: #000; | 797 | color: #000; |
| 761 | flex-shrink: 0; | 798 | flex-shrink: 0; |
| 762 | } | 799 | } |
| 763 | - | ||
| 764 | .tip-top { | 800 | .tip-top { |
| 765 | - padding: 8px 0 0 70px; | 801 | + padding: 8rpx 0 0 70rpx; |
| 766 | flex-shrink: 0; | 802 | flex-shrink: 0; |
| 767 | } | 803 | } |
| 768 | - | ||
| 769 | .task-list-container { | 804 | .task-list-container { |
| 770 | width: 100%; | 805 | width: 100%; |
| 771 | height: 100%; | 806 | height: 100%; |
| 772 | padding-bottom: 300rpx; | 807 | padding-bottom: 300rpx; |
| 773 | box-sizing: border-box; | 808 | box-sizing: border-box; |
| 774 | } | 809 | } |
| 775 | - | ||
| 776 | .empty-box { | 810 | .empty-box { |
| 777 | padding: 60rpx 0; | 811 | padding: 60rpx 0; |
| 778 | } | 812 | } |
| 779 | - | ||
| 780 | .sort-trigger { | 813 | .sort-trigger { |
| 781 | display: flex; | 814 | display: flex; |
| 782 | align-items: center; | 815 | align-items: center; |
| 783 | - font-size: 12px; | ||
| 784 | - color: $text-color-placeholder; | 816 | + font-size: 24rpx; |
| 817 | + color: $text-placeholder; | ||
| 818 | + .sort-text { | ||
| 819 | + white-space: nowrap; | ||
| 820 | + overflow: hidden; | ||
| 821 | + text-overflow: ellipsis; | ||
| 822 | + max-width: 220rpx; | ||
| 823 | + } | ||
| 785 | } | 824 | } |
| 786 | - | ||
| 787 | - | ||
| 788 | .task-item { | 825 | .task-item { |
| 789 | padding: $spacing-md; | 826 | padding: $spacing-md; |
| 790 | transition: background-color 0.2s; | 827 | transition: background-color 0.2s; |
| 791 | - border-bottom: 1px solid $border-color; | ||
| 792 | - | 828 | + border-bottom: 1rpx solid $border-color; |
| 793 | &:last-child { | 829 | &:last-child { |
| 794 | border-bottom: none; | 830 | border-bottom: none; |
| 795 | } | 831 | } |
| 796 | - | ||
| 797 | &--hover { | 832 | &--hover { |
| 798 | background-color: $bg-color; | 833 | background-color: $bg-color; |
| 799 | } | 834 | } |
| 800 | - | ||
| 801 | &__content { | 835 | &__content { |
| 802 | width: 100%; | 836 | width: 100%; |
| 803 | } | 837 | } |
| 804 | - | ||
| 805 | .name-fixed-wrap { | 838 | .name-fixed-wrap { |
| 806 | display: flex; | 839 | display: flex; |
| 807 | } | 840 | } |
| 808 | - | ||
| 809 | .task-item__name { | 841 | .task-item__name { |
| 810 | - width: 60px; | 842 | + width: 80rpx; |
| 811 | } | 843 | } |
| 812 | - | ||
| 813 | .task-name-text { | 844 | .task-name-text { |
| 814 | flex: 1; | 845 | flex: 1; |
| 815 | - font-size: 14px; | 846 | + font-size: 24rpx; |
| 816 | color: $text-color; | 847 | color: $text-color; |
| 817 | display: -webkit-box; | 848 | display: -webkit-box; |
| 818 | -webkit-line-clamp: 2; | 849 | -webkit-line-clamp: 2; |
| @@ -820,49 +851,43 @@ $border-color: #e5e5e5; | @@ -820,49 +851,43 @@ $border-color: #e5e5e5; | ||
| 820 | overflow: hidden; | 851 | overflow: hidden; |
| 821 | text-overflow: ellipsis; | 852 | text-overflow: ellipsis; |
| 822 | } | 853 | } |
| 823 | - | ||
| 824 | &__name { | 854 | &__name { |
| 825 | - font-size: 15px; | 855 | + font-size: 24rpx; |
| 826 | color: $text-color; | 856 | color: $text-color; |
| 827 | display: inline-block; | 857 | display: inline-block; |
| 828 | } | 858 | } |
| 829 | - | ||
| 830 | &__footer { | 859 | &__footer { |
| 831 | display: flex; | 860 | display: flex; |
| 832 | align-items: flex-start; | 861 | align-items: flex-start; |
| 833 | gap: 6rpx; | 862 | gap: 6rpx; |
| 834 | - font-size: 13px; | 863 | + font-size: 24rpx; |
| 835 | color: $text-color-light; | 864 | color: $text-color-light; |
| 836 | margin-top: $spacing-sm; | 865 | margin-top: $spacing-sm; |
| 837 | align-items: center; | 866 | align-items: center; |
| 838 | } | 867 | } |
| 839 | } | 868 | } |
| 840 | - | ||
| 841 | .loc-icon { | 869 | .loc-icon { |
| 842 | - width: 20px; | ||
| 843 | - height: 20px; | 870 | + width: 28rpx; |
| 871 | + height: 28rpx; | ||
| 844 | } | 872 | } |
| 845 | - | ||
| 846 | .urgency-tag { | 873 | .urgency-tag { |
| 847 | color: #7D7D7D; | 874 | color: #7D7D7D; |
| 848 | } | 875 | } |
| 849 | - | ||
| 850 | .grid-item-icon-box { | 876 | .grid-item-icon-box { |
| 851 | - display:flex; | ||
| 852 | - flex-direction:column; | ||
| 853 | - align-items:center; | ||
| 854 | - padding:16rpx; | 877 | + display: flex; |
| 878 | + flex-direction: column; | ||
| 879 | + align-items: center; | ||
| 880 | + padding: 16rpx; | ||
| 855 | } | 881 | } |
| 856 | .grid-num-icon { | 882 | .grid-num-icon { |
| 857 | - font-size:40rpx; | ||
| 858 | - font-weight:600; | ||
| 859 | - color:#333; | ||
| 860 | - margin-top:8rpx; | 883 | + font-size: 40rpx; |
| 884 | + font-weight: 600; | ||
| 885 | + color: #333; | ||
| 886 | + margin-top: 8rpx; | ||
| 861 | } | 887 | } |
| 862 | .grid-label-icon { | 888 | .grid-label-icon { |
| 863 | - font-size:22rpx; | ||
| 864 | - color:#666; | ||
| 865 | - margin-top:4rpx; | 889 | + font-size: 22rpx; |
| 890 | + color: #666; | ||
| 891 | + margin-top: 4rpx; | ||
| 866 | } | 892 | } |
| 867 | - | ||
| 868 | -</style> | ||
| 869 | \ No newline at end of file | 893 | \ No newline at end of file |
| 894 | +</style> |