Commit 25904bec21db0fc8d40aab3ec9216d652868b88b
1 parent
0c577b68
养护重新改
Showing
8 changed files
with
869 additions
and
340 deletions
pages-sub/daily/maintain-manage/index.vue
| ... | ... | @@ -4,7 +4,7 @@ |
| 4 | 4 | <up-sticky> |
| 5 | 5 | <view class="sticky-wrap"> |
| 6 | 6 | <!-- 第一行标签:养护类型 --> |
| 7 | - <up-tabs | |
| 7 | + <!-- <up-tabs | |
| 8 | 8 | v-model="activeType" |
| 9 | 9 | :list="typeTabs" |
| 10 | 10 | line-width="40rpx" |
| ... | ... | @@ -13,10 +13,10 @@ |
| 13 | 13 | :scrollable="true" |
| 14 | 14 | class="first-tabs" |
| 15 | 15 | @click="handleTypeChange" |
| 16 | - ></up-tabs> | |
| 16 | + ></up-tabs> --> | |
| 17 | 17 | |
| 18 | 18 | <!-- 第二行标签:状态筛选 --> |
| 19 | - <up-tabs | |
| 19 | + <!-- <up-tabs | |
| 20 | 20 | v-model="activeStatus" |
| 21 | 21 | :list="statusTabs" |
| 22 | 22 | line-width="40rpx" |
| ... | ... | @@ -25,7 +25,7 @@ |
| 25 | 25 | :scrollable="true" |
| 26 | 26 | class="second-tabs" |
| 27 | 27 | @click="handleStatusChange" |
| 28 | - ></up-tabs> | |
| 28 | + ></up-tabs> --> | |
| 29 | 29 | |
| 30 | 30 | <!-- 动态搜索框(道路名称/计划名称) --> |
| 31 | 31 | <up-search |
| ... | ... | @@ -40,7 +40,7 @@ |
| 40 | 40 | @custom="handleSearch" |
| 41 | 41 | :clearabled="false" |
| 42 | 42 | maxlength="50" |
| 43 | - style="margin: 20rpx 20rpx 0" | |
| 43 | + style="margin: 0rpx 20rpx 0" | |
| 44 | 44 | ></up-search> |
| 45 | 45 | </view> |
| 46 | 46 | </up-sticky> |
| ... | ... | @@ -58,7 +58,7 @@ |
| 58 | 58 | </template> |
| 59 | 59 | |
| 60 | 60 | <!-- 道路类型卡片 --> |
| 61 | - <view v-if="activeType === '道路'" class="common-card-list" style="padding-top: 144px;"> | |
| 61 | + <view v-if="activeType === '道路'" class="common-card-list" style="padding-top: 34px;"> | |
| 62 | 62 | |
| 63 | 63 | <up-card |
| 64 | 64 | :border="false" |
| ... | ... | @@ -81,8 +81,8 @@ |
| 81 | 81 | <!-- </up-button>--> |
| 82 | 82 | <!-- </view>--> |
| 83 | 83 | |
| 84 | - <view class="common-custom-btn " style="--btn-top: 68px;" @click="goToDetail(item)"> | |
| 85 | - 计划明细 | |
| 84 | + <view class="common-custom-btn" style="--btn-top: 28px;" @click="goToDetail(item)"> | |
| 85 | + 养护任务 | |
| 86 | 86 | </view> |
| 87 | 87 | <!-- <view class="u-body-item u-flex">--> |
| 88 | 88 | <!-- <view class="u-body-item-title">批次号:</view>--> |
| ... | ... | @@ -93,11 +93,11 @@ |
| 93 | 93 | <view class="u-line-1 u-body-value">{{ item.roadName || '-' }}</view> |
| 94 | 94 | </view> |
| 95 | 95 | |
| 96 | - <view class="u-body-item u-flex"> | |
| 96 | + <!-- <view class="u-body-item u-flex"> | |
| 97 | 97 | <view class="u-body-item-title">所属街道:</view> |
| 98 | 98 | <view class="u-line-1 u-body-value">{{ item.streetName }} |
| 99 | 99 | </view> |
| 100 | - </view> | |
| 100 | + </view> --> | |
| 101 | 101 | |
| 102 | 102 | <view class="u-body-item u-flex common-item-center common-justify-between"> |
| 103 | 103 | <view class="u-body-item-title">养护级别: {{uni.$dict.getDictLabel('conserve_level', item.levelId) || '-'}}</view> |
| ... | ... | @@ -308,8 +308,12 @@ const fetchData = async (pageNo, pageSize) => { |
| 308 | 308 | |
| 309 | 309 | // 跳转到计划明细页面 |
| 310 | 310 | const goToDetail = (item) => { |
| 311 | + // uni.navigateTo({ | |
| 312 | + // url: `/pages-sub/daily/maintain-manage/road-detail-list?roadId=${item.roadId}&finish_state=${item.finishState || ''} &businessType=${item.busiLine}` | |
| 313 | + // }) | |
| 314 | + | |
| 311 | 315 | uni.navigateTo({ |
| 312 | - url: `/pages-sub/daily/maintain-manage/road-detail-list?roadId=${item.roadId}&finish_state=${item.finishState || ''} &businessType=${item.busiLine}` | |
| 316 | + url: `/pages-sub/daily/maintain-manage/type-list?roadId=${item.roadId}&finish_state=${item.finishState || ''} &businessType=${item.busiLine}` | |
| 313 | 317 | }) |
| 314 | 318 | } |
| 315 | 319 | |
| ... | ... | @@ -343,7 +347,6 @@ onShow(()=>{ |
| 343 | 347 | <style scoped lang="scss"> |
| 344 | 348 | // 吸顶区域样式 |
| 345 | 349 | .sticky-wrap { |
| 346 | - margin-top: -10rpx; | |
| 347 | 350 | background-color: #fff; |
| 348 | 351 | padding-bottom: 10rpx; |
| 349 | 352 | border-bottom: 1px solid #eee; | ... | ... |
pages-sub/daily/maintain-manage/now-list-page.vue
0 → 100644
| 1 | +<template> | |
| 2 | + <view class="page-wrap"> | |
| 3 | + <!-- 顶部提示栏 --> | |
| 4 | + <view class="tip-bar"> | |
| 5 | + 一个任务可提交多次上报记录,每一次作业需如实上报。 | |
| 6 | + </view> | |
| 7 | + | |
| 8 | + <!-- 上报记录列表 --> | |
| 9 | + <view class="list-wrap" v-if="reportList.length > 0"> | |
| 10 | + <view class="report-item" v-for="(item, index) in reportList" :key="index"> | |
| 11 | + <view class="item-title">【第{{ item.no }}次上报】{{ item.taskName }}</view> | |
| 12 | + | |
| 13 | + <view class="item-row item-row-bottom"> | |
| 14 | + <view class="item-time">提交时间:{{ item.submitTime }}</view> | |
| 15 | + <view class="look-btn" @click="handleView(item)">查看</view> | |
| 16 | + </view> | |
| 17 | + </view> | |
| 18 | + </view> | |
| 19 | + | |
| 20 | + <!-- 暂无数据 --> | |
| 21 | + <view class="empty-wrap" v-else> | |
| 22 | + <empty-view text="暂无数据"></empty-view> | |
| 23 | + </view> | |
| 24 | + | |
| 25 | + <!-- 底部固定按钮 --> | |
| 26 | + <view class="fixed-bottom-btn-wrap"> | |
| 27 | + <up-button type="primary" size="large" block @click="handleAddReport">上报本次记录</up-button> | |
| 28 | + </view> | |
| 29 | + </view> | |
| 30 | +</template> | |
| 31 | + | |
| 32 | +<script setup lang="ts"> | |
| 33 | +import { ref } from 'vue' | |
| 34 | + | |
| 35 | +// 上报记录数据 | |
| 36 | +const reportList = ref([ | |
| 37 | + { | |
| 38 | + no:3, | |
| 39 | + taskName:'德胜门东大街月季补植', | |
| 40 | + varityName:'果汁阳台月季', | |
| 41 | + submitTime:'2026-06-22 14:34:33' | |
| 42 | + }, | |
| 43 | + { | |
| 44 | + no:2, | |
| 45 | + taskName:'德胜门东大街月季补植', | |
| 46 | + varityName:'蓝色风暴月季', | |
| 47 | + submitTime:'2026-06-21 10:34:33' | |
| 48 | + }, | |
| 49 | + { | |
| 50 | + no:1, | |
| 51 | + taskName:'德胜门东大街月季补植', | |
| 52 | + varityName:'金丝雀月季', | |
| 53 | + submitTime:'2026-06-20 10:34:33' | |
| 54 | + } | |
| 55 | +]) | |
| 56 | + | |
| 57 | +// 查看上报详情 | |
| 58 | +const handleView = (item) => { | |
| 59 | + console.log('查看详情', item) | |
| 60 | + uni.navigateTo({ | |
| 61 | + url: `/pages-sub/daily/maintain-manage/finish-plan-detail` | |
| 62 | + }) | |
| 63 | +} | |
| 64 | + | |
| 65 | +// 新增上报记录 | |
| 66 | +const handleAddReport = () => { | |
| 67 | + console.log('上报本次记录') | |
| 68 | + uni.navigateTo({ | |
| 69 | + url: `/pages-sub/daily/maintain-manage/add-record` | |
| 70 | + }) | |
| 71 | +} | |
| 72 | +</script> | |
| 73 | + | |
| 74 | +<style scoped lang="scss"> | |
| 75 | +.page-wrap { | |
| 76 | + min-height: 100vh; | |
| 77 | + padding-bottom: 120rpx; // 给底部按钮预留空间 | |
| 78 | + background: #ffffff; | |
| 79 | +} | |
| 80 | +// 顶部黄色提示条 | |
| 81 | +.tip-bar { | |
| 82 | + background-color: #f9e0a2; | |
| 83 | + color: #6b4b00; | |
| 84 | + font-size: 28rpx; | |
| 85 | + padding:24rpx 20rpx; | |
| 86 | + line-height:1.5; | |
| 87 | +} | |
| 88 | + | |
| 89 | +.list-wrap { | |
| 90 | + padding: 0; | |
| 91 | +} | |
| 92 | +.report-item { | |
| 93 | + padding:30rpx 24rpx; | |
| 94 | + border-bottom:1rpx solid #eee; | |
| 95 | + .item-title { | |
| 96 | + font-size:32rpx; | |
| 97 | + color:#222; | |
| 98 | + font-weight:500; | |
| 99 | + margin-bottom:20rpx; | |
| 100 | + } | |
| 101 | + .item-row { | |
| 102 | + font-size:28rpx; | |
| 103 | + color:#555; | |
| 104 | + margin-bottom:12rpx; | |
| 105 | + } | |
| 106 | + .item-row-bottom { | |
| 107 | + display:flex; | |
| 108 | + justify-content:space-between; | |
| 109 | + align-items:center; | |
| 110 | + margin-bottom:0; | |
| 111 | + } | |
| 112 | + .look-btn { | |
| 113 | + font-size:28rpx; | |
| 114 | + color:#1989fa; | |
| 115 | + } | |
| 116 | +} | |
| 117 | +.empty-wrap { | |
| 118 | + padding-top: 120rpx; | |
| 119 | +} | |
| 120 | + | |
| 121 | +</style> | ... | ... |
pages-sub/daily/maintain-manage/type-list-page.vue
0 → 100644
| 1 | +<template> | |
| 2 | + <view class="page-container"> | |
| 3 | + <up-sticky> | |
| 4 | + <view class="sticky-wrap"> | |
| 5 | + <up-tabs | |
| 6 | + v-model="activeStatus" | |
| 7 | + :list="statusTabs" | |
| 8 | + line-width="40rpx" | |
| 9 | + active-color="#1989fa" | |
| 10 | + inactive-color="#666" | |
| 11 | + :scrollable="false" | |
| 12 | + @change="handleStatusChange" | |
| 13 | + ></up-tabs> | |
| 14 | + </view> | |
| 15 | + </up-sticky> | |
| 16 | + <z-paging | |
| 17 | + ref="pagingRef" | |
| 18 | + v-model="currentList" | |
| 19 | + @query="fetchData" | |
| 20 | + :auto-show-system-loading="true" | |
| 21 | + > | |
| 22 | + <template #empty> | |
| 23 | + <empty-view/> | |
| 24 | + </template> | |
| 25 | + <view class="card-list"> | |
| 26 | + <view | |
| 27 | + class="task-card" | |
| 28 | + v-for="(item,index) in currentList" | |
| 29 | + :key="`${item.planNo}_${index}`" | |
| 30 | + > | |
| 31 | + <!-- 第一行:任务名称 + 置为失效 --> | |
| 32 | + <view class="row row-1"> | |
| 33 | + <view class="plan-name u-line-1">{{ item.planName || '无计划名称' }}</view> | |
| 34 | + <view | |
| 35 | + v-if="isMaintainLeader" | |
| 36 | + class="btn-set-invalid" | |
| 37 | + @click.stop="handleSetInvalid(item)" | |
| 38 | + > | |
| 39 | + 置为失效 | |
| 40 | + </view> | |
| 41 | + </view> | |
| 42 | + <!-- 第二行:任务次数 + 去作业按钮 --> | |
| 43 | + <view class="row row-2"> | |
| 44 | + <view class="info-text">任务次数:第{{ item.taskTimes || 1 }}次</view> | |
| 45 | + <view class="mini-btn" @click.stop="handleGoWork(item)">去作业</view> | |
| 46 | + </view> | |
| 47 | + <!-- 第三行:有效期 + 结束任务按钮 --> | |
| 48 | + <view class="row row-3"> | |
| 49 | + <view class="info-text u-line-1">有效期:{{ item.beginTime || '-' }}—{{ item.endTime || '-' }}</view> | |
| 50 | + <view class="mini-btn" @click.stop="handleEndTask(item)">结束任务</view> | |
| 51 | + </view> | |
| 52 | + </view> | |
| 53 | + </view> | |
| 54 | + </z-paging> | |
| 55 | + | |
| 56 | + <!-- ========== 置为失效弹窗(参考回退弹窗结构) ========== --> | |
| 57 | + <up-modal | |
| 58 | + :show="invalidModalShow" | |
| 59 | + title="失效原因" | |
| 60 | + :closeOnClickOverlay="false" | |
| 61 | + :showConfirmButton="true" | |
| 62 | + :showCancelButton="true" | |
| 63 | + @cancel="handleInvalidModalCancel" | |
| 64 | + @confirm="confirmSetInvalid" | |
| 65 | + > | |
| 66 | + <view class="invalid-modal-content"> | |
| 67 | + <up-textarea | |
| 68 | + v-model.trim="invalidReason" | |
| 69 | + placeholder="请输入失效原因(必填)" | |
| 70 | + rows="6" | |
| 71 | + :count="200" | |
| 72 | + maxlength="200" | |
| 73 | + class="invalid-textarea" | |
| 74 | + /> | |
| 75 | + <view class="upload-wrap mt-20"> | |
| 76 | + <view class="upload-title">上传图片(选填)</view> | |
| 77 | + <up-upload | |
| 78 | + :file-list="invalidImgs.rawImgList.value || []" | |
| 79 | + @after-read="invalidImgs.uploadImgs" | |
| 80 | + @delete="invalidImgs.deleteImg" | |
| 81 | + multiple | |
| 82 | + width="70" | |
| 83 | + height="70" | |
| 84 | + :max-count="invalidImgs.uploadConfig.maxCount" | |
| 85 | + :upload-text="invalidImgs.uploadConfig.uploadText" | |
| 86 | + :size-type="invalidImgs.uploadConfig.sizeType" | |
| 87 | + /> | |
| 88 | + </view> | |
| 89 | + </view> | |
| 90 | + </up-modal> | |
| 91 | + </view> | |
| 92 | +</template> | |
| 93 | + | |
| 94 | +<script setup lang="ts"> | |
| 95 | +import { ref, computed } from 'vue' | |
| 96 | +import { onShow } from '@dcloudio/uni-app' | |
| 97 | +import { useUserStore } from '@/pinia/user'; | |
| 98 | +// 引入图片上传hook(和你回退弹窗同一个工具) | |
| 99 | +import { useUploadImgs } from '@/common/utils/useUploadImgs' | |
| 100 | + | |
| 101 | +const userStore = useUserStore(); | |
| 102 | +const userRoles = computed<string[]>(() => userStore.userInfo?.roles || []); | |
| 103 | +const isMaintainLeader = computed(() => userRoles.value.includes('yl_worker')) | |
| 104 | + | |
| 105 | +const statusTabs = ref([ | |
| 106 | + { name: '待完成', id: '1' }, | |
| 107 | + { name: '已失效', id: '3' }, | |
| 108 | + { name: '已完成', id: '2' } | |
| 109 | +]) | |
| 110 | +const activeStatus = ref('1') | |
| 111 | +const pagingRef = ref(null) | |
| 112 | +const currentList = ref([]) | |
| 113 | + | |
| 114 | +// ===================== 失效弹窗状态 ===================== | |
| 115 | +const invalidModalShow = ref(false) | |
| 116 | +const invalidReason = ref('') | |
| 117 | +const currentInvalidItem = ref(null) | |
| 118 | +// 图片上传实例,和回退保持一致,最多3张 | |
| 119 | +const invalidImgs = useUploadImgs({ | |
| 120 | + maxCount: 3, | |
| 121 | + uploadText: '选择失效图片', | |
| 122 | + sizeType: ['compressed'], | |
| 123 | + formRef: null, | |
| 124 | + fieldName: 'invalidImgs' | |
| 125 | +}) | |
| 126 | + | |
| 127 | +const mockAllData = [ | |
| 128 | + { planNo: 'MH20260616001', planName: '德胜门东大街大街月季补植', taskTimes: 1, beginTime: '2026/06/16', endTime: '2026/12/31', finishState: '1' }, | |
| 129 | + { planNo: 'MH20260616002', planName: '西长安街行道树修剪养护作业任务', taskTimes: 2, beginTime: '2026/05/01', endTime: '2026/11/30', finishState: '1' }, | |
| 130 | + { planNo: 'MH20260616003', planName: '北三环绿地浇水、防寒养护专项任务超长名称测试文字溢出', taskTimes: 1, beginTime: '2026/04/10', endTime: '2026/12/20', finishState: '1' }, | |
| 131 | + { planNo: 'MH20260616004', planName: '奥森园区绿地保洁日常养护', taskTimes: 3, beginTime: '2026/03/01', endTime: '2026/10/15', finishState: '3' }, | |
| 132 | + { planNo: 'MH20260616005', planName: '护城河沿岸病虫害防治专项作业', taskTimes: 2, beginTime: '2026/02/15', endTime: '2026/09/30', finishState: '2' }, | |
| 133 | + { planNo: 'MH20260616006', planName: '朝阳公园施肥、除草春季养护任务', taskTimes: 1, beginTime: '2026/04/05', endTime: '2026/11/10', finishState: '1' }, | |
| 134 | + { planNo: 'MH20260616007', planName: '中关村大街灌木修剪与枯枝清理', taskTimes: 4, beginTime: '2026/01/20', endTime: '2026/12/25', finishState: '1' }, | |
| 135 | + { planNo: 'MH20260616008', planName: '永定河滨河绿地冬季防寒浇水作业', taskTimes: 1, beginTime: '2026/07/01', endTime: '2026/12/31', finishState: '3' }, | |
| 136 | + { planNo: 'MH20260616009', planName: '颐和园外围绿带病虫害防治', taskTimes: 2, beginTime: '2026/05/20', endTime: '2026/10/20', finishState: '2' }, | |
| 137 | + { planNo: 'MH20260616010', planName: '上地街道行道树补植更换任务', taskTimes: 1, beginTime: '2026/06/01', endTime: '2026/12/20', finishState: '1' } | |
| 138 | +] | |
| 139 | + | |
| 140 | +const fetchData = async (pageNo, pageSize) => { | |
| 141 | + await new Promise(resolve => setTimeout(resolve, 400)) | |
| 142 | + const filterList = mockAllData.filter(item => item.finishState === activeStatus.value) | |
| 143 | + const start = (pageNo - 1) * pageSize | |
| 144 | + const pageData = filterList.slice(start, start + pageSize) | |
| 145 | + pagingRef.value?.complete(pageData, filterList.length) | |
| 146 | +} | |
| 147 | + | |
| 148 | +const handleStatusChange = (item) => { | |
| 149 | + activeStatus.value = item.id | |
| 150 | + pagingRef.value?.reload() | |
| 151 | +} | |
| 152 | + | |
| 153 | +// 打开失效弹窗 | |
| 154 | +const handleSetInvalid = (item) => { | |
| 155 | + currentInvalidItem.value = item | |
| 156 | + invalidReason.value = '' | |
| 157 | + invalidImgs.clearImgs() | |
| 158 | + invalidModalShow.value = true | |
| 159 | +} | |
| 160 | + | |
| 161 | +// 关闭弹窗,重置数据 | |
| 162 | +const handleInvalidModalCancel = () => { | |
| 163 | + invalidModalShow.value = false | |
| 164 | + invalidReason.value = '' | |
| 165 | + invalidImgs.clearImgs() | |
| 166 | +} | |
| 167 | + | |
| 168 | +// 确认提交置为失效 | |
| 169 | +const confirmSetInvalid = async () => { | |
| 170 | + const reason = invalidReason.value.trim() | |
| 171 | + if (!reason) { | |
| 172 | + uni.showToast({ title: '请填写失效原因', icon: 'none' }) | |
| 173 | + return | |
| 174 | + } | |
| 175 | + const item = currentInvalidItem.value | |
| 176 | + if (!item) return | |
| 177 | + | |
| 178 | + uni.showLoading({ title: '提交中...', mask: true }) | |
| 179 | + try { | |
| 180 | + // 这里后续替换真实接口,获取上传图片url: invalidImgs.getSuccessImgUrls() | |
| 181 | + const imgList = invalidImgs.getSuccessImgUrls() | |
| 182 | + console.log('置为失效提交参数:', { | |
| 183 | + planNo: item.planNo, | |
| 184 | + reason, | |
| 185 | + imgList | |
| 186 | + }) | |
| 187 | + | |
| 188 | + // ============ 此处替换后端接口调用 ============ | |
| 189 | + // await api.setTaskInvalid({ ... }) | |
| 190 | + | |
| 191 | + uni.showToast({ title: '操作成功', icon: 'success' }) | |
| 192 | + handleInvalidModalCancel() | |
| 193 | + pagingRef.value?.reload() | |
| 194 | + } catch (err) { | |
| 195 | + console.error(err) | |
| 196 | + uni.showToast({ title: '提交失败,请重试', icon: 'none' }) | |
| 197 | + } finally { | |
| 198 | + uni.hideLoading() | |
| 199 | + } | |
| 200 | +} | |
| 201 | + | |
| 202 | +const handleGoWork = (item) => { | |
| 203 | + | |
| 204 | + uni.navigateTo({ | |
| 205 | + url: `/pages-sub/daily/maintain-manage/now-list-page?roadId=${item.roadId}&finish_state=${item.finishState || ''} &businessType=${item.busiLine}` | |
| 206 | + }) | |
| 207 | +} | |
| 208 | +const handleEndTask = (item) => console.log('结束任务', item) | |
| 209 | + | |
| 210 | +onShow(() => pagingRef.value?.reload()) | |
| 211 | +</script> | |
| 212 | + | |
| 213 | +<style scoped lang="scss"> | |
| 214 | +.page-container { | |
| 215 | + height: 100vh; | |
| 216 | + background-color: #f5f5f5; | |
| 217 | +} | |
| 218 | +.sticky-wrap { | |
| 219 | + background: #fff; | |
| 220 | + border-bottom: 1rpx solid #eee; | |
| 221 | +} | |
| 222 | +.card-list { | |
| 223 | + padding:100rpx 20rpx 20rpx; | |
| 224 | + display: flex; | |
| 225 | + flex-direction: column; | |
| 226 | + gap: 20rpx; | |
| 227 | +} | |
| 228 | +.task-card { | |
| 229 | + background: #fff; | |
| 230 | + border-radius: 12rpx; | |
| 231 | + padding: 24rpx; | |
| 232 | + display: flex; | |
| 233 | + flex-direction: column; | |
| 234 | + gap: 20rpx; | |
| 235 | +} | |
| 236 | +.row { | |
| 237 | + display: flex; | |
| 238 | + align-items: center; | |
| 239 | + justify-content: space-between; | |
| 240 | + gap: 16rpx; | |
| 241 | +} | |
| 242 | +.plan-name { | |
| 243 | + font-size: 30rpx; | |
| 244 | + color: #333; | |
| 245 | + font-weight: 500; | |
| 246 | + flex: 1; | |
| 247 | +} | |
| 248 | +.btn-set-invalid { | |
| 249 | + font-size: 26rpx; | |
| 250 | + color: #1677ff; | |
| 251 | + flex-shrink: 0; | |
| 252 | + padding-left: 16rpx; | |
| 253 | +} | |
| 254 | +.info-text { | |
| 255 | + font-size: 26rpx; | |
| 256 | + color: #666; | |
| 257 | + flex: 1; | |
| 258 | +} | |
| 259 | +.mini-btn { | |
| 260 | + font-size: 24rpx; | |
| 261 | + color: #333; | |
| 262 | + background: #f5f5f5; | |
| 263 | + border: 1rpx solid #ddd; | |
| 264 | + border-radius: 6rpx; | |
| 265 | + padding: 8rpx 20rpx; | |
| 266 | + flex-shrink: 0; | |
| 267 | +} | |
| 268 | + | |
| 269 | +// 弹窗样式,和回退弹窗保持一致 | |
| 270 | +.invalid-modal-content { | |
| 271 | + width: 100%; | |
| 272 | + box-sizing: border-box; | |
| 273 | + padding: 10rpx 0; | |
| 274 | +} | |
| 275 | +.upload-wrap { | |
| 276 | + .upload-title { | |
| 277 | + font-size: 28rpx; | |
| 278 | + color: #333; | |
| 279 | + margin-bottom: 10rpx; | |
| 280 | + } | |
| 281 | +} | |
| 282 | +.mt-20 { margin-top: 20rpx; } | |
| 283 | +</style> | ... | ... |
pages-sub/daily/maintain-manage/type-list.vue
0 → 100644
| 1 | +<template> | |
| 2 | + <view class="tag-wrap"> | |
| 3 | + <!-- 动态渲染标签列表 --> | |
| 4 | + <view class="tag-item" v-for="(item, idx) in tagList" :key="idx" hover-class="tag-item--hover" @click="toNextPage"> | |
| 5 | + <view class="tag-text"> | |
| 6 | + <!-- 文字区域:超长省略号,数字括号单独放后面,永远可见 --> | |
| 7 | + <text class="tag-name">{{ item.label }}</text> | |
| 8 | + <text class="tag-count">({{ item.count }})</text> | |
| 9 | + </view> | |
| 10 | + | |
| 11 | + </view> | |
| 12 | + </view> | |
| 13 | +</template> | |
| 14 | + | |
| 15 | +<script setup lang="ts"> | |
| 16 | +import { ref } from 'vue' | |
| 17 | + | |
| 18 | +// 数据源,完全动态,你可以接口返回覆盖 | |
| 19 | +const tagList = ref([ | |
| 20 | + { label: '补植', count: 5 }, | |
| 21 | + { label: '修剪', count: 2 }, | |
| 22 | + { label: '浇水、防寒', count: 3 }, | |
| 23 | + { label: '绿地保洁', count: 3 }, | |
| 24 | + { label: '病虫害防治', count: 3 }, | |
| 25 | + { label: '施肥、除草', count: 4 }, | |
| 26 | + // 测试超长文本 | |
| 27 | + { label: '非常长的养护任务名称测试文字溢出效果', count: 9 }, | |
| 28 | +]) | |
| 29 | + | |
| 30 | +const toNextPage = (item)=> { | |
| 31 | + uni.navigateTo({ | |
| 32 | + url: `/pages-sub/daily/maintain-manage/type-list-page?roadId=${item.roadId}&finish_state=${item.finishState || ''} &businessType=${item.busiLine}` | |
| 33 | + }) | |
| 34 | +} | |
| 35 | +</script> | |
| 36 | + | |
| 37 | +<style scoped lang="scss"> | |
| 38 | +.tag-wrap { | |
| 39 | + display: flex; | |
| 40 | + flex-wrap: wrap; | |
| 41 | + gap: 24rpx; | |
| 42 | + padding: 30rpx; | |
| 43 | +} | |
| 44 | + | |
| 45 | +.tag-item { | |
| 46 | + display: inline-flex; | |
| 47 | + align-items: center; | |
| 48 | + background: #e8f3ff; | |
| 49 | + border: 1rpx solid #94c5ff; | |
| 50 | + border-radius: 8rpx; | |
| 51 | + padding: 16rpx 24rpx; | |
| 52 | + max-width: 320rpx; // 限制标签最大宽度,超出自动省略 | |
| 53 | + transition: all 0.2s; | |
| 54 | + &--hover { | |
| 55 | + background: #d8eaff; | |
| 56 | + } | |
| 57 | +} | |
| 58 | + | |
| 59 | +.tag-text { | |
| 60 | + display: flex; | |
| 61 | + align-items: center; | |
| 62 | + flex: 1; | |
| 63 | + overflow: hidden; | |
| 64 | +} | |
| 65 | + | |
| 66 | +.tag-name { | |
| 67 | + // 核心:文字超长省略,只对名称生效 | |
| 68 | + white-space: nowrap; | |
| 69 | + overflow: hidden; | |
| 70 | + text-overflow: ellipsis; | |
| 71 | + color: #1677ff; | |
| 72 | + font-size: 28rpx; | |
| 73 | +} | |
| 74 | + | |
| 75 | +.tag-count { | |
| 76 | + color: #1677ff; | |
| 77 | + font-size: 28rpx; | |
| 78 | + flex-shrink: 0; // 重点!禁止压缩,保证(数字)永远显示 | |
| 79 | + margin-left: 4rpx; | |
| 80 | +} | |
| 81 | + | |
| 82 | +.tag-icon { | |
| 83 | + flex-shrink: 0; | |
| 84 | + margin-left: 12rpx; | |
| 85 | +} | |
| 86 | +</style> | |
| 87 | + | ... | ... |
pages-sub/daily/patrol-manage/add-patrol-record.vue
| 1 | 1 | <template> |
| 2 | 2 | <view class="u-page"> |
| 3 | -<!-- 原有模板内容不变,仅调整表单校验相关配置 --> | |
| 4 | -<view class="inspect-form-content commonPageLRpadding"> | |
| 5 | -<up-form label-position="left" :model="inspectForm" ref="inspectFormRef" labelWidth="200rpx"> | |
| 6 | -<!-- 1. 巡查描述 --> | |
| 7 | -<up-form-item label="巡查描述" prop="content" class="form-item" required> | |
| 8 | -<up-textarea v-model.trim="inspectForm.content" placeholder="请输入巡查描述" maxlength="200" count></up-textarea> | |
| 9 | -</up-form-item> | |
| 10 | -<!-- 2. 上传图片 --> | |
| 11 | -<up-form-item label="上传图片" prop="images" required border-bottom class="form-item"> | |
| 12 | -<up-upload :file-list="imagesList" @after-read="(event) => uploadImgs(event)" | |
| 3 | + <!-- 原有模板内容不变,仅调整表单校验相关配置 --> | |
| 4 | + <view class="inspect-form-content commonPageLRpadding"> | |
| 5 | + <up-form label-position="left" :model="inspectForm" ref="inspectFormRef" labelWidth="200rpx"> | |
| 6 | + <!-- 1. 巡查描述 --> | |
| 7 | + <up-form-item label="巡查描述" prop="content" class="form-item" required> | |
| 8 | + <up-textarea v-model.trim="inspectForm.content" placeholder="请输入巡查描述" maxlength="200" count></up-textarea> | |
| 9 | + </up-form-item> | |
| 10 | + <!-- 2. 上传图片 --> | |
| 11 | + <up-form-item label="上传图片" prop="images" required border-bottom class="form-item"> | |
| 12 | + <up-upload :file-list="imagesList" @after-read="(event) => uploadImgs(event)" | |
| 13 | 13 | @delete="(event) => deleteImg(event)" @on-exceed="handleExceed" multiple :max-count="3" upload-text="选择图片" |
| 14 | -del-color="#ff4d4f" class="upload-wrap" width="70" height="70"></up-upload> | |
| 15 | -</up-form-item> | |
| 16 | -<!-- 3. 转为工单 --> | |
| 17 | -<up-form-item label="转为工单" prop="isWorkOrder" required class="form-item"> | |
| 18 | -<up-radio-group v-model="inspectForm.isWorkOrder" active-color="#1989fa" direction="row" class="radio-group" | |
| 14 | + del-color="#ff4d4f" class="upload-wrap" width="70" height="70"></up-upload> | |
| 15 | + </up-form-item> | |
| 16 | + <!-- 3. 转为工单 --> | |
| 17 | + <up-form-item label="转为工单" prop="isWorkOrder" required class="form-item"> | |
| 18 | + <up-radio-group v-model="inspectForm.isWorkOrder" active-color="#1989fa" direction="row" class="radio-group" | |
| 19 | 19 | @change="handleWorkOrderChange"> |
| 20 | -<up-radio :custom-style="{ marginRight: '40rpx' }" v-for="(item, index) in radioList" :key="index" | |
| 20 | + <up-radio :custom-style="{ marginRight: '40rpx' }" v-for="(item, index) in radioList" :key="index" | |
| 21 | 21 | :label="item.label" :name="item.value"> |
| 22 | 22 | {{ item.label }} |
| 23 | -</up-radio> | |
| 24 | -</up-radio-group> | |
| 25 | -</up-form-item> | |
| 26 | -<!-- ========== 【新增】业务线(单选框,对齐参考页面) ========== --> | |
| 27 | -<up-form-item v-if="inspectForm.isWorkOrder === '2'" label="业务线" prop="busiLineCn" border-bottom required | |
| 28 | -class="form-item"> | |
| 29 | -<up-radio-group v-model="inspectForm.busiLineCn" placement="row" @change="handleBusiLineChange"> | |
| 30 | -<up-radio v-for="item in busiLineOptions" :key="item.name" :label="item.name" :name="item.name"></up-radio> | |
| 31 | -</up-radio-group> | |
| 32 | -</up-form-item> | |
| 33 | -<!-- ========== 【新增】问题类型(级联选择器,对齐参考页面) ========== --> | |
| 34 | -<up-form-item v-if="inspectForm.isWorkOrder === '2'" label="问题类型" prop="orderName" border-bottom required | |
| 35 | -class="form-item" @click="openCascader(); uni.hideKeyboard()"> | |
| 36 | -<up-input v-model="inspectForm.orderName" disabled disabled-color="#ffffff" placeholder="请选择问题类型" | |
| 37 | -border="none"></up-input> | |
| 38 | -<template #right> | |
| 39 | -<up-icon name="arrow-right" size="16"></up-icon> | |
| 40 | -</template> | |
| 41 | -</up-form-item> | |
| 42 | -<!-- 紧急程度(仍为必填) --> | |
| 43 | -<up-form-item v-if="inspectForm.isWorkOrder === '2'" label="紧急程度" prop="pressingTypeName" border-bottom required | |
| 44 | -class="form-item" @click="handleActionSheetOpen('pressingType')"> | |
| 45 | -<up-input v-model="inspectForm.pressingTypeName" disabled disabled-color="#ffffff" placeholder="请选择紧急程度" | |
| 46 | -border="none"></up-input> | |
| 47 | -<template #right> | |
| 48 | -<up-icon name="arrow-right" size="16"></up-icon> | |
| 49 | -</template> | |
| 50 | -</up-form-item> | |
| 51 | -<!-- 希望完成时间(移除 required 属性,改为非必填) --> | |
| 52 | -<up-form-item v-if="inspectForm.isWorkOrder === '2'" label="希望完成时间" prop="expectedFinishDate" class="form-item" | |
| 23 | + </up-radio> | |
| 24 | + </up-radio-group> | |
| 25 | + </up-form-item> | |
| 26 | + <!-- ========== 【新增】业务线(单选框,对齐参考页面) ========== --> | |
| 27 | + <up-form-item v-if="inspectForm.isWorkOrder === '2'" label="业务线" prop="busiLineCn" border-bottom required | |
| 28 | + class="form-item"> | |
| 29 | + <up-radio-group v-model="inspectForm.busiLineCn" placement="row" @change="handleBusiLineChange"> | |
| 30 | + <up-radio v-for="item in busiLineOptions" :key="item.name" :label="item.name" :name="item.name"></up-radio> | |
| 31 | + </up-radio-group> | |
| 32 | + </up-form-item> | |
| 33 | + <!-- ========== 【新增】问题类型(级联选择器,对齐参考页面) ========== --> | |
| 34 | + <up-form-item v-if="inspectForm.isWorkOrder === '2'" label="问题类型" prop="orderName" border-bottom required | |
| 35 | + class="form-item" @click="openCascader(); uni.hideKeyboard()"> | |
| 36 | + <up-input v-model="inspectForm.orderName" disabled disabled-color="#ffffff" placeholder="请选择问题类型" | |
| 37 | + border="none"></up-input> | |
| 38 | + <template #right> | |
| 39 | + <up-icon name="arrow-right" size="16"></up-icon> | |
| 40 | + </template> | |
| 41 | + </up-form-item> | |
| 42 | + <!-- 紧急程度(仍为必填) --> | |
| 43 | + <up-form-item v-if="inspectForm.isWorkOrder === '2'" label="紧急程度" prop="pressingTypeName" border-bottom required | |
| 44 | + class="form-item" @click="handleActionSheetOpen('pressingType')"> | |
| 45 | + <up-input v-model="inspectForm.pressingTypeName" disabled disabled-color="#ffffff" placeholder="请选择紧急程度" | |
| 46 | + border="none"></up-input> | |
| 47 | + <template #right> | |
| 48 | + <up-icon name="arrow-right" size="16"></up-icon> | |
| 49 | + </template> | |
| 50 | + </up-form-item> | |
| 51 | + <!-- 希望完成时间(移除 required 属性,改为非必填) --> | |
| 52 | + <up-form-item v-if="inspectForm.isWorkOrder === '2'" label="希望完成时间" prop="expectedFinishDate" class="form-item" | |
| 53 | 53 | @click="show = true; uni.hideKeyboard()"> |
| 54 | -<up-input v-model="inspectForm.expectedFinishDate" border="none" readonly placeholder="点击选择时间"> | |
| 55 | -</up-input> | |
| 56 | -<template #right> | |
| 57 | -<!-- 核心修复:用view包裹图标,添加双重@click.stop --> | |
| 58 | -<view v-if="inspectForm.expectedFinishDate" @click.stop> | |
| 59 | -<up-icon name="close" size="16" @click.stop="clearExpectedFinishDate"></up-icon> | |
| 60 | -</view> | |
| 61 | -<up-icon name="arrow-right" size="16" v-else></up-icon> | |
| 62 | -</template> | |
| 63 | -</up-form-item> | |
| 64 | -</up-form> | |
| 65 | -</view> | |
| 66 | -<!-- 底部提交按钮 --> | |
| 67 | -<view class="fixed-bottom-btn-wrap"> | |
| 68 | -<up-button type="primary" text="提交" @click="submitInspect" | |
| 54 | + <up-input v-model="inspectForm.expectedFinishDate" border="none" readonly placeholder="点击选择时间"> | |
| 55 | + </up-input> | |
| 56 | + <template #right> | |
| 57 | + <!-- 核心修复:用view包裹图标,添加双重@click.stop --> | |
| 58 | + <view v-if="inspectForm.expectedFinishDate" @click.stop> | |
| 59 | + <up-icon name="close" size="16" @click.stop="clearExpectedFinishDate"></up-icon> | |
| 60 | + </view> | |
| 61 | + <up-icon name="arrow-right" size="16" v-else></up-icon> | |
| 62 | + </template> | |
| 63 | + </up-form-item> | |
| 64 | + </up-form> | |
| 65 | + </view> | |
| 66 | + <!-- 底部提交按钮 --> | |
| 67 | + <view class="fixed-bottom-btn-wrap"> | |
| 68 | + <up-button type="primary" text="提交" @click="submitInspect" | |
| 69 | 69 | :style="{ width: '100%', height: '88rpx', fontSize: '32rpx', borderRadius: 0 }"></up-button> |
| 70 | -</view> | |
| 71 | -<!-- 紧急程度下拉弹窗 --> | |
| 72 | -<up-action-sheet :show="showActionSheet" :actions="pressingTypeList" title="请选择紧急程度" @close="handleActionSheetClose" | |
| 70 | + </view> | |
| 71 | + <!-- 紧急程度下拉弹窗 --> | |
| 72 | + <up-action-sheet :show="showActionSheet" :actions="pressingTypeList" title="请选择紧急程度" @close="handleActionSheetClose" | |
| 73 | 73 | @select="handlePressingTypeSelect"></up-action-sheet> |
| 74 | -<!-- ========== 新增级联选择器组件 ========== --> | |
| 75 | -<up-cascader v-model:show="showCascader" v-model="cascaderValue" :data="cascaderOptions" title="选择问题类型" | |
| 74 | + <!-- ========== 新增级联选择器组件 ========== --> | |
| 75 | + <up-cascader v-model:show="showCascader" v-model="cascaderValue" :data="cascaderOptions" title="选择问题类型" | |
| 76 | 76 | :auto-close="false" @confirm="cascaderConfirm"></up-cascader> |
| 77 | -<!-- 完成时间选择器 --> | |
| 78 | -<up-datetime-picker :show="show" v-model="datetimeValue" mode="datetime" :min-date="new Date()" | |
| 77 | + <!-- 完成时间选择器 --> | |
| 78 | + <up-datetime-picker :show="show" v-model="datetimeValue" mode="datetime" :min-date="new Date()" | |
| 79 | 79 | @cancel="show = false" @confirm="expectedFinishDateConfirm"></up-datetime-picker> |
| 80 | -</view> | |
| 80 | + </view> | |
| 81 | 81 | </template> |
| 82 | 82 | <script setup lang="ts"> |
| 83 | 83 | import { ref, getCurrentInstance } from 'vue' |
| ... | ... | @@ -98,68 +98,68 @@ const cascaderOptions = ref([]); |
| 98 | 98 | |
| 99 | 99 | // 打开级联弹窗 |
| 100 | 100 | const openCascader = () => { |
| 101 | -const busiLineEn = getBusiLineEnByCn(proxy.$data.inspectForm.busiLineCn) | |
| 102 | -if (!busiLineEn) { | |
| 103 | -uni.showToast({ title: '请先选择业务线', icon: 'none' }) | |
| 104 | -return | |
| 101 | + const busiLineEn = getBusiLineEnByCn(proxy.$data.inspectForm.busiLineCn) | |
| 102 | + if (!busiLineEn) { | |
| 103 | + uni.showToast({ title: '请先选择业务线', icon: 'none' }) | |
| 104 | + return | |
| 105 | 105 | } |
| 106 | -if (!cascaderOptions.value || cascaderOptions.value.length === 0) { | |
| 107 | -uni.showToast({ title: '正在加载问题类型,请稍等', icon: 'none' }); | |
| 108 | -loadProblemCascader(busiLineEn); | |
| 109 | -return; | |
| 106 | + if (!cascaderOptions.value || cascaderOptions.value.length === 0) { | |
| 107 | + uni.showToast({ title: '正在加载问题类型,请稍等', icon: 'none' }); | |
| 108 | + loadProblemCascader(busiLineEn); | |
| 109 | + return; | |
| 110 | 110 | } |
| 111 | -cascaderValue.value = []; | |
| 112 | -showCascader.value = true; | |
| 111 | + cascaderValue.value = []; | |
| 112 | + showCascader.value = true; | |
| 113 | 113 | }; |
| 114 | 114 | |
| 115 | 115 | // 级联确认回调 |
| 116 | 116 | const cascaderConfirm = (selectedArr) => { |
| 117 | -const getLabelByValueList = (list, valList) => { | |
| 118 | -const labelArr = []; | |
| 119 | -let currentList = list; | |
| 120 | -for (const val of valList) { | |
| 121 | -const target = currentList.find(item => item.value === val); | |
| 122 | -if (!target) break; | |
| 123 | -labelArr.push(target.label); | |
| 124 | -currentList = target.children || []; | |
| 117 | + const getLabelByValueList = (list, valList) => { | |
| 118 | + const labelArr = []; | |
| 119 | + let currentList = list; | |
| 120 | + for (const val of valList) { | |
| 121 | + const target = currentList.find(item => item.value === val); | |
| 122 | + if (!target) break; | |
| 123 | + labelArr.push(target.label); | |
| 124 | + currentList = target.children || []; | |
| 125 | 125 | } |
| 126 | -return labelArr.join('/'); | |
| 126 | + return labelArr.join('/'); | |
| 127 | 127 | }; |
| 128 | -const fullLabel = getLabelByValueList(cascaderOptions.value, selectedArr); | |
| 129 | -proxy.$data.inspectForm.orderName = fullLabel; | |
| 130 | -proxy.$data.inspectForm.orderCode = selectedArr.at(-1); | |
| 131 | -cascaderValue.value = selectedArr; | |
| 132 | -inspectFormRef.value?.validateField('orderName'); | |
| 128 | + const fullLabel = getLabelByValueList(cascaderOptions.value, selectedArr); | |
| 129 | + proxy.$data.inspectForm.orderName = fullLabel; | |
| 130 | + proxy.$data.inspectForm.orderCode = selectedArr.at(-1); | |
| 131 | + cascaderValue.value = selectedArr; | |
| 132 | + inspectFormRef.value?.validateField('orderName'); | |
| 133 | 133 | }; |
| 134 | 134 | |
| 135 | 135 | // 加载级联树形数据 |
| 136 | 136 | const loadProblemCascader = async (parentCode) => { |
| 137 | -if (!parentCode) { | |
| 138 | -cascaderOptions.value = [] | |
| 139 | -return | |
| 137 | + if (!parentCode) { | |
| 138 | + cascaderOptions.value = [] | |
| 139 | + return | |
| 140 | 140 | } |
| 141 | -try { | |
| 142 | -uni.showLoading({ title: '加载类型中...' }) | |
| 143 | -const res = await getProblemListByType({ parentCode }) | |
| 144 | -uni.hideLoading() | |
| 145 | -cascaderOptions.value = res || [] | |
| 141 | + try { | |
| 142 | + uni.showLoading({ title: '加载类型中...' }) | |
| 143 | + const res = await getProblemListByType({ parentCode }) | |
| 144 | + uni.hideLoading() | |
| 145 | + cascaderOptions.value = res || [] | |
| 146 | 146 | } catch (err) { |
| 147 | -uni.hideLoading() | |
| 148 | -console.error('获取问题类型失败', err) | |
| 149 | -uni.showToast({ title: '获取问题类型失败', icon: 'none' }) | |
| 150 | -cascaderOptions.value = [] | |
| 147 | + uni.hideLoading() | |
| 148 | + console.error('获取问题类型失败', err) | |
| 149 | + uni.showToast({ title: '获取问题类型失败', icon: 'none' }) | |
| 150 | + cascaderOptions.value = [] | |
| 151 | 151 | } |
| 152 | 152 | } |
| 153 | 153 | |
| 154 | 154 | const getBusiLineCnByEn = (busiLineEn) => { |
| 155 | -if (!busiLineEn) return ''; | |
| 156 | -return getDictLabel(BUSI_LINE_DICT_TYPE, busiLineEn) || busiLineEn; | |
| 155 | + if (!busiLineEn) return ''; | |
| 156 | + return getDictLabel(BUSI_LINE_DICT_TYPE, busiLineEn) || busiLineEn; | |
| 157 | 157 | }; |
| 158 | 158 | const getBusiLineEnByCn = (cnName) => { |
| 159 | -if (!cnName) return ''; | |
| 160 | -const code = getDictValue(BUSI_LINE_DICT_TYPE, cnName); | |
| 161 | -if (code) return code; | |
| 162 | -return CJK_RE.test(cnName) ? '' : cnName; | |
| 159 | + if (!cnName) return ''; | |
| 160 | + const code = getDictValue(BUSI_LINE_DICT_TYPE, cnName); | |
| 161 | + if (code) return code; | |
| 162 | + return CJK_RE.test(cnName) ? '' : cnName; | |
| 163 | 163 | }; |
| 164 | 164 | |
| 165 | 165 | // 暴露给选项式访问 |
| ... | ... | @@ -177,105 +177,105 @@ import { timeFormat } from '@/uni_modules/uview-plus' |
| 177 | 177 | import { useUserStore } from '@/pinia/user'; |
| 178 | 178 | import { getDictLabel } from '@/common/utils/dict'; |
| 179 | 179 | export default { |
| 180 | -data() { | |
| 181 | -return { | |
| 182 | -imagesList: [], | |
| 183 | -radioList: [ | |
| 180 | + data() { | |
| 181 | + return { | |
| 182 | + imagesList: [], | |
| 183 | + radioList: [ | |
| 184 | 184 | { label: '否', value: '1' }, |
| 185 | 185 | { label: '是', value: '2' } |
| 186 | 186 | ], |
| 187 | -pressingTypeList: [], | |
| 188 | -busiLineOptions: [], // 业务线移到data,不再放在setup | |
| 189 | -inspectForm: { | |
| 190 | -content: '', | |
| 191 | -isWorkOrder: '1', | |
| 192 | -pressingTypeName: '', | |
| 193 | -pressingType: '', | |
| 194 | -busiLineCn: '', | |
| 195 | -orderName: '', | |
| 196 | -orderCode: '', | |
| 197 | -expectedFinishDate: '' // 非必填,可空 | |
| 187 | + pressingTypeList: [], | |
| 188 | + busiLineOptions: [], // 业务线移到data,不再放在setup | |
| 189 | + inspectForm: { | |
| 190 | + content: '', | |
| 191 | + isWorkOrder: '1', | |
| 192 | + pressingTypeName: '', | |
| 193 | + pressingType: '', | |
| 194 | + busiLineCn: '', | |
| 195 | + orderName: '', | |
| 196 | + orderCode: '', | |
| 197 | + expectedFinishDate: '' // 非必填,可空 | |
| 198 | 198 | }, |
| 199 | -paramsOptins: {}, | |
| 200 | -showActionSheet: false, | |
| 201 | -show: false, | |
| 202 | -datetimeValue: Date.now(), | |
| 203 | -inspectFormRules: { | |
| 204 | -images: [ | |
| 199 | + paramsOptins: {}, | |
| 200 | + showActionSheet: false, | |
| 201 | + show: false, | |
| 202 | + datetimeValue: Date.now(), | |
| 203 | + inspectFormRules: { | |
| 204 | + images: [ | |
| 205 | 205 | { |
| 206 | -required: true, | |
| 207 | -message: '请上传图片', | |
| 208 | -trigger: 'change', | |
| 209 | -validator: (rule, value, callback) => { | |
| 210 | -const hasSuccessImg = this.imagesList.some(item => item.status === 'success') | |
| 211 | -const imgCount = this.imagesList.filter(item => item.status === 'success').length | |
| 212 | -if (!hasSuccessImg || imgCount < 1) { | |
| 213 | -callback(new Error('最少需要上传1张图片')) | |
| 206 | + required: true, | |
| 207 | + message: '请上传图片', | |
| 208 | + trigger: 'change', | |
| 209 | + validator: (rule, value, callback) => { | |
| 210 | + const hasSuccessImg = this.imagesList.some(item => item.status === 'success') | |
| 211 | + const imgCount = this.imagesList.filter(item => item.status === 'success').length | |
| 212 | + if (!hasSuccessImg || imgCount < 1) { | |
| 213 | + callback(new Error('最少需要上传1张图片')) | |
| 214 | 214 | } else if (imgCount > 3) { |
| 215 | -callback(new Error('最多只能上传3张图片')) | |
| 215 | + callback(new Error('最多只能上传3张图片')) | |
| 216 | 216 | } else { |
| 217 | -callback() | |
| 217 | + callback() | |
| 218 | 218 | } |
| 219 | 219 | } |
| 220 | 220 | } |
| 221 | 221 | ], |
| 222 | -content: [ | |
| 222 | + content: [ | |
| 223 | 223 | { type: 'string', required: true, message: '请输入巡查描述', trigger: ['change'] } |
| 224 | 224 | ], |
| 225 | -isWorkOrder: [ | |
| 225 | + isWorkOrder: [ | |
| 226 | 226 | { type: 'string', required: true, message: '请选择是否转为工单', trigger: ['change'] } |
| 227 | 227 | ], |
| 228 | -pressingTypeName: [ | |
| 228 | + pressingTypeName: [ | |
| 229 | 229 | { |
| 230 | -required: true, | |
| 231 | -message: '请选择紧急程度', | |
| 232 | -trigger: 'change', | |
| 233 | -validator: (rule, value, callback) => { | |
| 234 | -if (this.inspectForm.isWorkOrder === '2' && !value) { | |
| 235 | -callback(new Error('请选择紧急程度')) | |
| 230 | + required: true, | |
| 231 | + message: '请选择紧急程度', | |
| 232 | + trigger: 'change', | |
| 233 | + validator: (rule, value, callback) => { | |
| 234 | + if (this.inspectForm.isWorkOrder === '2' && !value) { | |
| 235 | + callback(new Error('请选择紧急程度')) | |
| 236 | 236 | } else { |
| 237 | -callback() | |
| 237 | + callback() | |
| 238 | 238 | } |
| 239 | 239 | } |
| 240 | 240 | } |
| 241 | 241 | ], |
| 242 | -busiLineCn: [ | |
| 242 | + busiLineCn: [ | |
| 243 | 243 | { |
| 244 | -required: true, | |
| 245 | -message: '请选择业务线', | |
| 246 | -trigger: 'change', | |
| 247 | -validator: (rule, value, callback) => { | |
| 248 | -if (this.inspectForm.isWorkOrder === '2' && !value) { | |
| 249 | -callback(new Error('请选择业务线')) | |
| 244 | + required: true, | |
| 245 | + message: '请选择业务线', | |
| 246 | + trigger: 'change', | |
| 247 | + validator: (rule, value, callback) => { | |
| 248 | + if (this.inspectForm.isWorkOrder === '2' && !value) { | |
| 249 | + callback(new Error('请选择业务线')) | |
| 250 | 250 | } else { |
| 251 | -callback() | |
| 251 | + callback() | |
| 252 | 252 | } |
| 253 | 253 | } |
| 254 | 254 | } |
| 255 | 255 | ], |
| 256 | -orderName: [ | |
| 256 | + orderName: [ | |
| 257 | 257 | { |
| 258 | -required: true, | |
| 259 | -message: '请选择问题类型', | |
| 260 | -trigger: 'change', | |
| 261 | -validator: (rule, value, callback) => { | |
| 262 | -if (this.inspectForm.isWorkOrder === '2' && !value) { | |
| 263 | -callback(new Error('请选择问题类型')) | |
| 258 | + required: true, | |
| 259 | + message: '请选择问题类型', | |
| 260 | + trigger: 'change', | |
| 261 | + validator: (rule, value, callback) => { | |
| 262 | + if (this.inspectForm.isWorkOrder === '2' && !value) { | |
| 263 | + callback(new Error('请选择问题类型')) | |
| 264 | 264 | } else { |
| 265 | -callback() | |
| 265 | + callback() | |
| 266 | 266 | } |
| 267 | 267 | } |
| 268 | 268 | } |
| 269 | 269 | ], |
| 270 | -expectedFinishDate: [ | |
| 270 | + expectedFinishDate: [ | |
| 271 | 271 | { |
| 272 | -message: '请选择有效的希望完成时间', | |
| 273 | -trigger: 'change', | |
| 274 | -validator: (rule, value, callback) => { | |
| 275 | -if (value && !/^\d{4}-\d{2}-\d{2}\s\d{2}:\d{2}:\d{2}$/.test(value)) { | |
| 276 | -callback(new Error('请选择有效的希望完成时间')) | |
| 272 | + message: '请选择有效的希望完成时间', | |
| 273 | + trigger: 'change', | |
| 274 | + validator: (rule, value, callback) => { | |
| 275 | + if (value && !/^\d{4}-\d{2}-\d{2}\s\d{2}:\d{2}:\d{2}$/.test(value)) { | |
| 276 | + callback(new Error('请选择有效的希望完成时间')) | |
| 277 | 277 | } else { |
| 278 | -callback() | |
| 278 | + callback() | |
| 279 | 279 | } |
| 280 | 280 | } |
| 281 | 281 | } |
| ... | ... | @@ -283,183 +283,183 @@ callback() |
| 283 | 283 | } |
| 284 | 284 | } |
| 285 | 285 | }, |
| 286 | -onLoad(option) { | |
| 287 | -this.paramsOptins = option | |
| 288 | -// 初始化业务线选项 | |
| 289 | -const userStore = useUserStore(); | |
| 290 | -if (userStore.userInfo?.user?.busiLine) { | |
| 291 | -const rawBusiLines = userStore.userInfo.user.busiLine.split(','); | |
| 292 | -this.busiLineOptions = rawBusiLines.map(item => ({ | |
| 293 | -name: getDictLabel('business_line', item.trim()) || item.trim() | |
| 294 | -})); | |
| 295 | -} | |
| 286 | + onLoad(option) { | |
| 287 | + this.paramsOptins = option | |
| 288 | + // 初始化业务线选项 | |
| 289 | + const userStore = useUserStore(); | |
| 290 | + if (userStore.userInfo?.user?.busiLine) { | |
| 291 | + const rawBusiLines = userStore.userInfo.user.busiLine.split(','); | |
| 292 | + this.busiLineOptions = rawBusiLines.map(item => ({ | |
| 293 | + name: getDictLabel('business_line', item.trim()) || item.trim() | |
| 294 | + })); | |
| 295 | + } | |
| 296 | 296 | }, |
| 297 | -onReady() { | |
| 298 | -this.$refs.inspectFormRef.setRules(this.inspectFormRules) | |
| 297 | + onReady() { | |
| 298 | + this.$refs.inspectFormRef.setRules(this.inspectFormRules) | |
| 299 | 299 | }, |
| 300 | -onShow() { | |
| 301 | -this.pressingTypeList = uni.$dict.transformLabelValueToNameValue(uni.$dict.getDictSimpleList('workorder_pressing_type')) | |
| 300 | + onShow() { | |
| 301 | + this.pressingTypeList = uni.$dict.transformLabelValueToNameValue(uni.$dict.getDictSimpleList('workorder_pressing_type')) | |
| 302 | 302 | }, |
| 303 | -methods: { | |
| 304 | -handleWorkOrderChange() { | |
| 305 | -if (this.inspectForm.isWorkOrder === '1') { | |
| 306 | -this.inspectForm.pressingTypeName = '' | |
| 307 | -this.inspectForm.pressingType = '' | |
| 308 | -this.inspectForm.busiLineCn = '' | |
| 309 | -this.inspectForm.orderName = '' | |
| 310 | -this.inspectForm.orderCode = '' | |
| 311 | -this.$setupCtx.cascaderOptions.value = [] | |
| 312 | -this.$setupCtx.cascaderValue.value = [] | |
| 313 | -this.inspectForm.expectedFinishDate = '' | |
| 314 | -this.$refs.inspectFormRef.validateField(['pressingTypeName', 'busiLineCn', 'orderName', 'expectedFinishDate']) | |
| 303 | + methods: { | |
| 304 | + handleWorkOrderChange() { | |
| 305 | + if (this.inspectForm.isWorkOrder === '1') { | |
| 306 | + this.inspectForm.pressingTypeName = '' | |
| 307 | + this.inspectForm.pressingType = '' | |
| 308 | + this.inspectForm.busiLineCn = '' | |
| 309 | + this.inspectForm.orderName = '' | |
| 310 | + this.inspectForm.orderCode = '' | |
| 311 | + this.$setupCtx.cascaderOptions.value = [] | |
| 312 | + this.$setupCtx.cascaderValue.value = [] | |
| 313 | + this.inspectForm.expectedFinishDate = '' | |
| 314 | + this.$refs.inspectFormRef.validateField(['pressingTypeName', 'busiLineCn', 'orderName', 'expectedFinishDate']) | |
| 315 | 315 | } else { |
| 316 | -// 修复点:直接读取data中的 busiLineOptions,不再访问setup | |
| 317 | -const busiOpts = this.busiLineOptions | |
| 318 | -if (busiOpts.length > 0) { | |
| 319 | -this.inspectForm.busiLineCn = busiOpts[0].name | |
| 320 | -this.handleBusiLineChange() | |
| 316 | + // 修复点:直接读取data中的 busiLineOptions,不再访问setup | |
| 317 | + const busiOpts = this.busiLineOptions | |
| 318 | + if (busiOpts.length > 0) { | |
| 319 | + this.inspectForm.busiLineCn = busiOpts[0].name | |
| 320 | + this.handleBusiLineChange() | |
| 321 | 321 | } |
| 322 | 322 | } |
| 323 | 323 | }, |
| 324 | -handleBusiLineChange() { | |
| 325 | -this.inspectForm.orderName = '' | |
| 326 | -this.inspectForm.orderCode = '' | |
| 327 | -this.$setupCtx.cascaderValue.value = [] | |
| 328 | -this.$setupCtx.cascaderOptions.value = [] | |
| 329 | -const busiLineEn = this.$setupCtx.getBusiLineEnByCn(this.inspectForm.busiLineCn) | |
| 330 | -this.$setupCtx.loadProblemCascader(busiLineEn) | |
| 331 | -this.$refs.inspectFormRef.validateField('busiLineCn') | |
| 324 | + handleBusiLineChange() { | |
| 325 | + this.inspectForm.orderName = '' | |
| 326 | + this.inspectForm.orderCode = '' | |
| 327 | + this.$setupCtx.cascaderValue.value = [] | |
| 328 | + this.$setupCtx.cascaderOptions.value = [] | |
| 329 | + const busiLineEn = this.$setupCtx.getBusiLineEnByCn(this.inspectForm.busiLineCn) | |
| 330 | + this.$setupCtx.loadProblemCascader(busiLineEn) | |
| 331 | + this.$refs.inspectFormRef.validateField('busiLineCn') | |
| 332 | 332 | }, |
| 333 | -handleActionSheetOpen(type) { | |
| 334 | -uni.hideKeyboard() | |
| 335 | -if (type === 'pressingType') { | |
| 336 | -this.showActionSheet = true | |
| 333 | + handleActionSheetOpen(type) { | |
| 334 | + uni.hideKeyboard() | |
| 335 | + if (type === 'pressingType') { | |
| 336 | + this.showActionSheet = true | |
| 337 | 337 | } |
| 338 | 338 | }, |
| 339 | -handleActionSheetClose() { | |
| 340 | -this.showActionSheet = false | |
| 339 | + handleActionSheetClose() { | |
| 340 | + this.showActionSheet = false | |
| 341 | 341 | }, |
| 342 | -handlePressingTypeSelect(e) { | |
| 343 | -this.inspectForm.pressingTypeName = e.name | |
| 344 | -this.inspectForm.pressingType = e.value | |
| 345 | -this.showActionSheet = false | |
| 346 | -this.$refs.inspectFormRef.validateField('pressingTypeName') | |
| 342 | + handlePressingTypeSelect(e) { | |
| 343 | + this.inspectForm.pressingTypeName = e.name | |
| 344 | + this.inspectForm.pressingType = e.value | |
| 345 | + this.showActionSheet = false | |
| 346 | + this.$refs.inspectFormRef.validateField('pressingTypeName') | |
| 347 | 347 | }, |
| 348 | -expectedFinishDateConfirm(e) { | |
| 349 | -this.inspectForm.expectedFinishDate = timeFormat(e.value, 'yyyy-mm-dd hh:MM:ss') | |
| 350 | -this.show = false | |
| 351 | -this.$refs.inspectFormRef.validateField('expectedFinishDate') | |
| 348 | + expectedFinishDateConfirm(e) { | |
| 349 | + this.inspectForm.expectedFinishDate = timeFormat(e.value, 'yyyy-mm-dd hh:MM:ss') | |
| 350 | + this.show = false | |
| 351 | + this.$refs.inspectFormRef.validateField('expectedFinishDate') | |
| 352 | 352 | }, |
| 353 | -clearExpectedFinishDate() { | |
| 354 | -this.inspectForm.expectedFinishDate = '' | |
| 355 | -this.$refs.inspectFormRef.validateField('expectedFinishDate') | |
| 353 | + clearExpectedFinishDate() { | |
| 354 | + this.inspectForm.expectedFinishDate = '' | |
| 355 | + this.$refs.inspectFormRef.validateField('expectedFinishDate') | |
| 356 | 356 | }, |
| 357 | -deleteImg(event) { | |
| 358 | -this.imagesList.splice(event.index, 1) | |
| 359 | -this.$refs.inspectFormRef.validateField('images') | |
| 360 | -uni.showToast({ title: '图片删除成功', icon: 'success' }) | |
| 357 | + deleteImg(event) { | |
| 358 | + this.imagesList.splice(event.index, 1) | |
| 359 | + this.$refs.inspectFormRef.validateField('images') | |
| 360 | + uni.showToast({ title: '图片删除成功', icon: 'success' }) | |
| 361 | 361 | }, |
| 362 | -async uploadImgs(event) { | |
| 363 | -const fileList = Array.isArray(event.file) ? event.file : [event.file] | |
| 364 | -const targetImgList = this.imagesList | |
| 365 | -const filePaths = fileList.map(item => item.url) | |
| 366 | -const tempItems = fileList.map(item => ({ | |
| 367 | -...item, | |
| 368 | -status: 'uploading', | |
| 369 | -message: '上传中' | |
| 362 | + async uploadImgs(event) { | |
| 363 | + const fileList = Array.isArray(event.file) ? event.file : [event.file] | |
| 364 | + const targetImgList = this.imagesList | |
| 365 | + const filePaths = fileList.map(item => item.url) | |
| 366 | + const tempItems = fileList.map(item => ({ | |
| 367 | + ...item, | |
| 368 | + status: 'uploading', | |
| 369 | + message: '上传中' | |
| 370 | 370 | })) |
| 371 | -const startIndex = targetImgList.length | |
| 372 | -targetImgList.push(...tempItems) | |
| 373 | -try { | |
| 374 | -const uploadResultUrls = await uploadImages({ | |
| 375 | -filePaths: filePaths, | |
| 376 | -ignoreError: true | |
| 371 | + const startIndex = targetImgList.length | |
| 372 | + targetImgList.push(...tempItems) | |
| 373 | + try { | |
| 374 | + const uploadResultUrls = await uploadImages({ | |
| 375 | + filePaths: filePaths, | |
| 376 | + ignoreError: true | |
| 377 | 377 | }) |
| 378 | -uploadResultUrls.forEach((url, index) => { | |
| 379 | -if (targetImgList[startIndex + index]) { | |
| 380 | -targetImgList.splice(startIndex + index, 1, { | |
| 381 | -...fileList[index], | |
| 382 | -status: 'success', | |
| 383 | -message: '', | |
| 384 | -url: url | |
| 378 | + uploadResultUrls.forEach((url, index) => { | |
| 379 | + if (targetImgList[startIndex + index]) { | |
| 380 | + targetImgList.splice(startIndex + index, 1, { | |
| 381 | + ...fileList[index], | |
| 382 | + status: 'success', | |
| 383 | + message: '', | |
| 384 | + url: url | |
| 385 | 385 | }) |
| 386 | 386 | } |
| 387 | 387 | }) |
| 388 | -if (uploadResultUrls.length < fileList.length) { | |
| 389 | -const failCount = fileList.length - uploadResultUrls.length | |
| 390 | -uni.showToast({ title: `成功上传${uploadResultUrls.length}张,失败${failCount}张`, icon: 'none' }) | |
| 388 | + if (uploadResultUrls.length < fileList.length) { | |
| 389 | + const failCount = fileList.length - uploadResultUrls.length | |
| 390 | + uni.showToast({ title: `成功上传${uploadResultUrls.length}张,失败${failCount}张`, icon: 'none' }) | |
| 391 | 391 | } else { |
| 392 | -uni.showToast({ title: `成功上传${fileList.length}张图片`, icon: 'success' }) | |
| 392 | + uni.showToast({ title: `成功上传${fileList.length}张图片`, icon: 'success' }) | |
| 393 | 393 | } |
| 394 | -this.$refs.inspectFormRef.validateField('images') | |
| 394 | + this.$refs.inspectFormRef.validateField('images') | |
| 395 | 395 | } catch (err) { |
| 396 | -console.error('图片上传失败:', err) | |
| 397 | -for (let i = 0; i < fileList.length; i++) { | |
| 398 | -if (targetImgList[startIndex + i]) { | |
| 399 | -targetImgList.splice(startIndex + i, 1, { | |
| 400 | -...fileList[i], | |
| 401 | -status: 'failed', | |
| 402 | -message: '上传失败' | |
| 396 | + console.error('图片上传失败:', err) | |
| 397 | + for (let i = 0; i < fileList.length; i++) { | |
| 398 | + if (targetImgList[startIndex + i]) { | |
| 399 | + targetImgList.splice(startIndex + i, 1, { | |
| 400 | + ...fileList[i], | |
| 401 | + status: 'failed', | |
| 402 | + message: '上传失败' | |
| 403 | 403 | }) |
| 404 | 404 | } |
| 405 | 405 | } |
| 406 | -uni.showToast({ title: '图片上传失败,请重试', icon: 'none' }) | |
| 407 | -this.$refs.inspectFormRef.validateField('images') | |
| 406 | + uni.showToast({ title: '图片上传失败,请重试', icon: 'none' }) | |
| 407 | + this.$refs.inspectFormRef.validateField('images') | |
| 408 | 408 | } |
| 409 | 409 | }, |
| 410 | -handleExceed() { | |
| 411 | -uni.showToast({ title: '最多只能上传3张图片', icon: 'none' }) | |
| 410 | + handleExceed() { | |
| 411 | + uni.showToast({ title: '最多只能上传3张图片', icon: 'none' }) | |
| 412 | 412 | }, |
| 413 | -getImgUrlList(imgList) { | |
| 414 | -return imgList.filter(item => item.status === 'success').map(item => item.url) | |
| 413 | + getImgUrlList(imgList) { | |
| 414 | + return imgList.filter(item => item.status === 'success').map(item => item.url) | |
| 415 | 415 | }, |
| 416 | -async submitInspect() { | |
| 417 | -console.log('当前选择是否转为工单:', this.inspectForm.isWorkOrder) | |
| 418 | -try { | |
| 419 | -await this.$refs.inspectFormRef.validate() | |
| 420 | -console.log(this.imagesList) | |
| 421 | -const baseSubmitData = { | |
| 422 | -"batchNo": this.paramsOptins.batchNo, | |
| 423 | -"planNo": this.paramsOptins.planNo, | |
| 424 | -"imgHost": "1", | |
| 425 | -"imgList": this.getImgUrlList(this.imagesList), | |
| 426 | -"inspectionState": this.inspectForm.isWorkOrder, | |
| 427 | -"transState": this.inspectForm.isWorkOrder === '1' ? '1' : '2', | |
| 428 | -"transWorkNo": "default'", | |
| 429 | -"remark": this.inspectForm.content.trim() | |
| 416 | + async submitInspect() { | |
| 417 | + console.log('当前选择是否转为工单:', this.inspectForm.isWorkOrder) | |
| 418 | + try { | |
| 419 | + await this.$refs.inspectFormRef.validate() | |
| 420 | + console.log(this.imagesList) | |
| 421 | + const baseSubmitData = { | |
| 422 | + "batchNo": this.paramsOptins.batchNo, | |
| 423 | + "planNo": this.paramsOptins.planNo, | |
| 424 | + "imgHost": "1", | |
| 425 | + "imgList": this.getImgUrlList(this.imagesList), | |
| 426 | + "inspectionState": this.inspectForm.isWorkOrder, | |
| 427 | + "transState": this.inspectForm.isWorkOrder === '1' ? '1' : '2', | |
| 428 | + "transWorkNo": "default'", | |
| 429 | + "remark": this.inspectForm.content.trim() | |
| 430 | 430 | } |
| 431 | -let submitData = { ...baseSubmitData } | |
| 432 | -if (this.inspectForm.isWorkOrder === '2') { | |
| 433 | -submitData.pressingType = this.inspectForm.pressingType | |
| 434 | -const busiLineEn = this.$setupCtx.getBusiLineEnByCn(this.inspectForm.busiLineCn) | |
| 435 | -submitData.busiLine = busiLineEn | |
| 436 | -submitData.orderName = this.inspectForm.orderName | |
| 437 | -submitData.orderCode = this.inspectForm.orderCode | |
| 438 | -if (this.inspectForm.expectedFinishDate) { | |
| 439 | -submitData.expectedFinishDate = new Date(this.inspectForm.expectedFinishDate).getTime() | |
| 431 | + let submitData = { ...baseSubmitData } | |
| 432 | + if (this.inspectForm.isWorkOrder === '2') { | |
| 433 | + submitData.pressingType = this.inspectForm.pressingType | |
| 434 | + const busiLineEn = this.$setupCtx.getBusiLineEnByCn(this.inspectForm.busiLineCn) | |
| 435 | + submitData.busiLine = busiLineEn | |
| 436 | + submitData.orderName = this.inspectForm.orderName | |
| 437 | + submitData.orderCode = this.inspectForm.orderCode | |
| 438 | + if (this.inspectForm.expectedFinishDate) { | |
| 439 | + submitData.expectedFinishDate = new Date(this.inspectForm.expectedFinishDate).getTime() | |
| 440 | 440 | } |
| 441 | 441 | } |
| 442 | -uni.showLoading({ title: '提交中...' }) | |
| 443 | -await inspectionCreate(submitData) | |
| 444 | -uni.hideLoading() | |
| 445 | -uni.showToast({ | |
| 446 | -title: '提交成功', | |
| 447 | -icon: 'success', | |
| 448 | -duration: 1000 | |
| 442 | + uni.showLoading({ title: '提交中...' }) | |
| 443 | + await inspectionCreate(submitData) | |
| 444 | + uni.hideLoading() | |
| 445 | + uni.showToast({ | |
| 446 | + title: '提交成功', | |
| 447 | + icon: 'success', | |
| 448 | + duration: 1000 | |
| 449 | 449 | }) |
| 450 | -setTimeout(() => { | |
| 451 | -uni.reLaunch({ | |
| 452 | -url: '/pages-sub/daily/patrol-manage/index' | |
| 450 | + setTimeout(() => { | |
| 451 | + uni.reLaunch({ | |
| 452 | + url: '/pages-sub/daily/patrol-manage/index' | |
| 453 | 453 | }) |
| 454 | 454 | }, 1000) |
| 455 | 455 | } catch (error) { |
| 456 | -uni.hideLoading() | |
| 457 | -if (!Array.isArray(error)) { | |
| 458 | -console.error('巡查表单提交失败:', error) | |
| 459 | -uni.showToast({ | |
| 460 | -title: '提交失败,请重试', | |
| 461 | -icon: 'none', | |
| 462 | -duration: 2000 | |
| 456 | + uni.hideLoading() | |
| 457 | + if (!Array.isArray(error)) { | |
| 458 | + console.error('巡查表单提交失败:', error) | |
| 459 | + uni.showToast({ | |
| 460 | + title: error.msg, | |
| 461 | + icon: 'none', | |
| 462 | + duration: 2000 | |
| 463 | 463 | }) |
| 464 | 464 | } |
| 465 | 465 | } |
| ... | ... | @@ -469,13 +469,15 @@ duration: 2000 |
| 469 | 469 | </script> |
| 470 | 470 | <style lang="scss" scoped> |
| 471 | 471 | .u-page { |
| 472 | -min-height: 100vh; | |
| 472 | + min-height: 100vh; | |
| 473 | 473 | } |
| 474 | + | |
| 474 | 475 | .inspect-form-content { |
| 475 | -background: #fff; | |
| 476 | -padding: 20rpx; | |
| 476 | + background: #fff; | |
| 477 | + padding: 20rpx; | |
| 477 | 478 | } |
| 479 | + | |
| 478 | 480 | .form-item { |
| 479 | -margin-bottom: 20rpx; | |
| 481 | + margin-bottom: 20rpx; | |
| 480 | 482 | } |
| 481 | 483 | </style> | ... | ... |
pages-sub/daily/patrol-manage/index.vue
| ... | ... | @@ -162,7 +162,7 @@ const queryList = async (pageNo, pageSize) => { |
| 162 | 162 | // 跳转明细 |
| 163 | 163 | const gotoDetail = (item) => { |
| 164 | 164 | uni.navigateTo({ |
| 165 | - url: `/pages-sub/daily/patrol-manage/pending-plan-detail?batchNo=${item.batchNo}&status=${activeTab.value}` | |
| 165 | + url: `/pages-sub/daily/patrol-manage/pending-plan-detail?batchNo=${item.batchNo}&status=${activeTab.value}&busiLine=${item.busiLine}` | |
| 166 | 166 | }); |
| 167 | 167 | }; |
| 168 | 168 | // 修复点5:优化页面生命周期逻辑 | ... | ... |
pages.json
| ... | ... | @@ -107,6 +107,23 @@ |
| 107 | 107 | }, |
| 108 | 108 | |
| 109 | 109 | { |
| 110 | + "path": "maintain-manage/type-list", | |
| 111 | + "style": { "navigationBarTitleText": "养护类型" } | |
| 112 | + }, | |
| 113 | + | |
| 114 | + { | |
| 115 | + "path": "maintain-manage/type-list-page", | |
| 116 | + "style": { "navigationBarTitleText": "养护" } | |
| 117 | + }, | |
| 118 | + | |
| 119 | + { | |
| 120 | + "path": "maintain-manage/now-list-page", | |
| 121 | + "style": { "navigationBarTitleText": "本次养护记录" } | |
| 122 | + }, | |
| 123 | + | |
| 124 | + | |
| 125 | + | |
| 126 | + { | |
| 110 | 127 | "path": "maintain-manage/add-record", |
| 111 | 128 | "style": { "navigationBarTitleText": "新增养护记录" } |
| 112 | 129 | }, | ... | ... |
pages/index/index.vue
| ... | ... | @@ -132,7 +132,7 @@ import { timeFormat } from '@/uni_modules/uview-plus'; |
| 132 | 132 | // import uniCharts from '@/components/uni-charts/uni-charts.vue'; |
| 133 | 133 | import { getUnreadCount } from "@/api/user"; |
| 134 | 134 | import { |
| 135 | - getTaskCompletionSummary, | |
| 135 | + // getTaskCompletionSummary, | |
| 136 | 136 | taskDetailsWithDistance, |
| 137 | 137 | taskDetailsWithSmartSort, |
| 138 | 138 | getCurrentOrg, |
| ... | ... | @@ -319,6 +319,20 @@ const baseList = ref<Array<{ num: string; title: string; name: string }>>([]); |
| 319 | 319 | const orgOptions = ref<any[]>([]); |
| 320 | 320 | const value1 = ref<number | string>(''); |
| 321 | 321 | const showActionSheet = ref(false); |
| 322 | +// 日期选择确认回调 | |
| 323 | +const handleDateConfirm = async (range: string[]) => { | |
| 324 | + console.log('选择的日期范围:', range); | |
| 325 | + dateRange.value = range; | |
| 326 | + const [startDate, endDate] = range; | |
| 327 | + // 1. 更新图表数据 | |
| 328 | + // await initChartData(startDate, endDate); | |
| 329 | + | |
| 330 | + // 2. 刷新组织指标卡片(数字指标4格卡片) | |
| 331 | + if(value1.value){ | |
| 332 | + await fetchOrgIndicator(Number(value1.value), startDate, endDate); | |
| 333 | + } | |
| 334 | +}; | |
| 335 | + | |
| 322 | 336 | watch(orgOptions, async (list) => { |
| 323 | 337 | if (list.length && !value1.value) { |
| 324 | 338 | value1.value = list[0].value; |
| ... | ... | @@ -382,6 +396,8 @@ const handleTabClick = (tabIndex: number) => { |
| 382 | 396 | currentTabValue.value = tabIndex; |
| 383 | 397 | showChartArea.value = true; |
| 384 | 398 | }; |
| 399 | + | |
| 400 | + | |
| 385 | 401 | // ========== 公共函数:请求 orgTaskIndicator 指标接口 ========== |
| 386 | 402 | const fetchOrgIndicator = async (orgId: number, beginDate: string, endDate: string) => { |
| 387 | 403 | try { |
| ... | ... | @@ -410,13 +426,13 @@ const initRecent7Days = () => { |
| 410 | 426 | const end = new Date(now); |
| 411 | 427 | end.setDate(end.getDate()); |
| 412 | 428 | const start = new Date(end); |
| 413 | - start.setDate(start.getDate() - 6); | |
| 429 | + start.setDate(start.getDate() ); | |
| 414 | 430 | dateRange.value = [ |
| 415 | 431 | timeFormat(start, 'yyyy-mm-dd'), |
| 416 | 432 | timeFormat(end, 'yyyy-mm-dd') |
| 417 | 433 | ]; |
| 418 | 434 | console.log(dateRange.value) |
| 419 | - initChartData(dateRange.value[0], dateRange.value[1]); | |
| 435 | + // initChartData(dateRange.value[0], dateRange.value[1]); | |
| 420 | 436 | }; |
| 421 | 437 | const getUnread = async () => { |
| 422 | 438 | try { |
| ... | ... | @@ -439,7 +455,7 @@ const getOrg = async () => { |
| 439 | 455 | const initChartData = async (beginTime: string, endTime: string) => { |
| 440 | 456 | try { |
| 441 | 457 | const postData = { beginTime, endTime }; |
| 442 | - const res = await getTaskCompletionSummary(postData); | |
| 458 | + // const res = await getTaskCompletionSummary(postData); | |
| 443 | 459 | klineCategories.value = res.map((item: any) => item.currentDate); |
| 444 | 460 | klineChartData.value[0].data = res.map((item: any) => item.completedNum); |
| 445 | 461 | klineChartData.value[1].data = res.map((item: any) => item.countPendingNum); |
| ... | ... | @@ -840,11 +856,11 @@ $border-color: #e5e5e5; |
| 840 | 856 | display: flex; |
| 841 | 857 | } |
| 842 | 858 | .task-item__name { |
| 843 | - width: 80rpx; | |
| 859 | + width: 88rpx; | |
| 844 | 860 | } |
| 845 | 861 | .task-name-text { |
| 846 | 862 | flex: 1; |
| 847 | - font-size: 24rpx; | |
| 863 | + font-size: 28rpx; | |
| 848 | 864 | color: $text-color; |
| 849 | 865 | display: -webkit-box; |
| 850 | 866 | -webkit-line-clamp: 2; |
| ... | ... | @@ -853,7 +869,7 @@ $border-color: #e5e5e5; |
| 853 | 869 | text-overflow: ellipsis; |
| 854 | 870 | } |
| 855 | 871 | &__name { |
| 856 | - font-size: 24rpx; | |
| 872 | + font-size: 28rpx; | |
| 857 | 873 | color: $text-color; |
| 858 | 874 | display: inline-block; |
| 859 | 875 | } |
| ... | ... | @@ -861,7 +877,7 @@ $border-color: #e5e5e5; |
| 861 | 877 | display: flex; |
| 862 | 878 | align-items: flex-start; |
| 863 | 879 | gap: 6rpx; |
| 864 | - font-size: 24rpx; | |
| 880 | + font-size: 26rpx; | |
| 865 | 881 | color: $text-color-light; |
| 866 | 882 | margin-top: $spacing-sm; |
| 867 | 883 | align-items: center; | ... | ... |