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,7 +4,7 @@ | ||
| 4 | <up-sticky> | 4 | <up-sticky> |
| 5 | <view class="sticky-wrap"> | 5 | <view class="sticky-wrap"> |
| 6 | <!-- 第一行标签:养护类型 --> | 6 | <!-- 第一行标签:养护类型 --> |
| 7 | - <up-tabs | 7 | + <!-- <up-tabs |
| 8 | v-model="activeType" | 8 | v-model="activeType" |
| 9 | :list="typeTabs" | 9 | :list="typeTabs" |
| 10 | line-width="40rpx" | 10 | line-width="40rpx" |
| @@ -13,10 +13,10 @@ | @@ -13,10 +13,10 @@ | ||
| 13 | :scrollable="true" | 13 | :scrollable="true" |
| 14 | class="first-tabs" | 14 | class="first-tabs" |
| 15 | @click="handleTypeChange" | 15 | @click="handleTypeChange" |
| 16 | - ></up-tabs> | 16 | + ></up-tabs> --> |
| 17 | 17 | ||
| 18 | <!-- 第二行标签:状态筛选 --> | 18 | <!-- 第二行标签:状态筛选 --> |
| 19 | - <up-tabs | 19 | + <!-- <up-tabs |
| 20 | v-model="activeStatus" | 20 | v-model="activeStatus" |
| 21 | :list="statusTabs" | 21 | :list="statusTabs" |
| 22 | line-width="40rpx" | 22 | line-width="40rpx" |
| @@ -25,7 +25,7 @@ | @@ -25,7 +25,7 @@ | ||
| 25 | :scrollable="true" | 25 | :scrollable="true" |
| 26 | class="second-tabs" | 26 | class="second-tabs" |
| 27 | @click="handleStatusChange" | 27 | @click="handleStatusChange" |
| 28 | - ></up-tabs> | 28 | + ></up-tabs> --> |
| 29 | 29 | ||
| 30 | <!-- 动态搜索框(道路名称/计划名称) --> | 30 | <!-- 动态搜索框(道路名称/计划名称) --> |
| 31 | <up-search | 31 | <up-search |
| @@ -40,7 +40,7 @@ | @@ -40,7 +40,7 @@ | ||
| 40 | @custom="handleSearch" | 40 | @custom="handleSearch" |
| 41 | :clearabled="false" | 41 | :clearabled="false" |
| 42 | maxlength="50" | 42 | maxlength="50" |
| 43 | - style="margin: 20rpx 20rpx 0" | 43 | + style="margin: 0rpx 20rpx 0" |
| 44 | ></up-search> | 44 | ></up-search> |
| 45 | </view> | 45 | </view> |
| 46 | </up-sticky> | 46 | </up-sticky> |
| @@ -58,7 +58,7 @@ | @@ -58,7 +58,7 @@ | ||
| 58 | </template> | 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 | <up-card | 63 | <up-card |
| 64 | :border="false" | 64 | :border="false" |
| @@ -81,8 +81,8 @@ | @@ -81,8 +81,8 @@ | ||
| 81 | <!-- </up-button>--> | 81 | <!-- </up-button>--> |
| 82 | <!-- </view>--> | 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 | </view> | 86 | </view> |
| 87 | <!-- <view class="u-body-item u-flex">--> | 87 | <!-- <view class="u-body-item u-flex">--> |
| 88 | <!-- <view class="u-body-item-title">批次号:</view>--> | 88 | <!-- <view class="u-body-item-title">批次号:</view>--> |
| @@ -93,11 +93,11 @@ | @@ -93,11 +93,11 @@ | ||
| 93 | <view class="u-line-1 u-body-value">{{ item.roadName || '-' }}</view> | 93 | <view class="u-line-1 u-body-value">{{ item.roadName || '-' }}</view> |
| 94 | </view> | 94 | </view> |
| 95 | 95 | ||
| 96 | - <view class="u-body-item u-flex"> | 96 | + <!-- <view class="u-body-item u-flex"> |
| 97 | <view class="u-body-item-title">所属街道:</view> | 97 | <view class="u-body-item-title">所属街道:</view> |
| 98 | <view class="u-line-1 u-body-value">{{ item.streetName }} | 98 | <view class="u-line-1 u-body-value">{{ item.streetName }} |
| 99 | </view> | 99 | </view> |
| 100 | - </view> | 100 | + </view> --> |
| 101 | 101 | ||
| 102 | <view class="u-body-item u-flex common-item-center common-justify-between"> | 102 | <view class="u-body-item u-flex common-item-center common-justify-between"> |
| 103 | <view class="u-body-item-title">养护级别: {{uni.$dict.getDictLabel('conserve_level', item.levelId) || '-'}}</view> | 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,8 +308,12 @@ const fetchData = async (pageNo, pageSize) => { | ||
| 308 | 308 | ||
| 309 | // 跳转到计划明细页面 | 309 | // 跳转到计划明细页面 |
| 310 | const goToDetail = (item) => { | 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 | uni.navigateTo({ | 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,7 +347,6 @@ onShow(()=>{ | ||
| 343 | <style scoped lang="scss"> | 347 | <style scoped lang="scss"> |
| 344 | // 吸顶区域样式 | 348 | // 吸顶区域样式 |
| 345 | .sticky-wrap { | 349 | .sticky-wrap { |
| 346 | - margin-top: -10rpx; | ||
| 347 | background-color: #fff; | 350 | background-color: #fff; |
| 348 | padding-bottom: 10rpx; | 351 | padding-bottom: 10rpx; |
| 349 | border-bottom: 1px solid #eee; | 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 | <template> | 1 | <template> |
| 2 | <view class="u-page"> | 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 | @delete="(event) => deleteImg(event)" @on-exceed="handleExceed" multiple :max-count="3" upload-text="选择图片" | 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 | @change="handleWorkOrderChange"> | 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 | :label="item.label" :name="item.value"> | 21 | :label="item.label" :name="item.value"> |
| 22 | {{ item.label }} | 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 | @click="show = true; uni.hideKeyboard()"> | 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 | :style="{ width: '100%', height: '88rpx', fontSize: '32rpx', borderRadius: 0 }"></up-button> | 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 | @select="handlePressingTypeSelect"></up-action-sheet> | 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 | :auto-close="false" @confirm="cascaderConfirm"></up-cascader> | 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 | @cancel="show = false" @confirm="expectedFinishDateConfirm"></up-datetime-picker> | 79 | @cancel="show = false" @confirm="expectedFinishDateConfirm"></up-datetime-picker> |
| 80 | -</view> | 80 | + </view> |
| 81 | </template> | 81 | </template> |
| 82 | <script setup lang="ts"> | 82 | <script setup lang="ts"> |
| 83 | import { ref, getCurrentInstance } from 'vue' | 83 | import { ref, getCurrentInstance } from 'vue' |
| @@ -98,68 +98,68 @@ const cascaderOptions = ref([]); | @@ -98,68 +98,68 @@ const cascaderOptions = ref([]); | ||
| 98 | 98 | ||
| 99 | // 打开级联弹窗 | 99 | // 打开级联弹窗 |
| 100 | const openCascader = () => { | 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 | const cascaderConfirm = (selectedArr) => { | 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 | const loadProblemCascader = async (parentCode) => { | 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 | } catch (err) { | 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 | const getBusiLineCnByEn = (busiLineEn) => { | 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 | const getBusiLineEnByCn = (cnName) => { | 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,105 +177,105 @@ import { timeFormat } from '@/uni_modules/uview-plus' | ||
| 177 | import { useUserStore } from '@/pinia/user'; | 177 | import { useUserStore } from '@/pinia/user'; |
| 178 | import { getDictLabel } from '@/common/utils/dict'; | 178 | import { getDictLabel } from '@/common/utils/dict'; |
| 179 | export default { | 179 | export default { |
| 180 | -data() { | ||
| 181 | -return { | ||
| 182 | -imagesList: [], | ||
| 183 | -radioList: [ | 180 | + data() { |
| 181 | + return { | ||
| 182 | + imagesList: [], | ||
| 183 | + radioList: [ | ||
| 184 | { label: '否', value: '1' }, | 184 | { label: '否', value: '1' }, |
| 185 | { label: '是', value: '2' } | 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 | } else if (imgCount > 3) { | 214 | } else if (imgCount > 3) { |
| 215 | -callback(new Error('最多只能上传3张图片')) | 215 | + callback(new Error('最多只能上传3张图片')) |
| 216 | } else { | 216 | } else { |
| 217 | -callback() | 217 | + callback() |
| 218 | } | 218 | } |
| 219 | } | 219 | } |
| 220 | } | 220 | } |
| 221 | ], | 221 | ], |
| 222 | -content: [ | 222 | + content: [ |
| 223 | { type: 'string', required: true, message: '请输入巡查描述', trigger: ['change'] } | 223 | { type: 'string', required: true, message: '请输入巡查描述', trigger: ['change'] } |
| 224 | ], | 224 | ], |
| 225 | -isWorkOrder: [ | 225 | + isWorkOrder: [ |
| 226 | { type: 'string', required: true, message: '请选择是否转为工单', trigger: ['change'] } | 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 | } else { | 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 | } else { | 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 | } else { | 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 | } else { | 277 | } else { |
| 278 | -callback() | 278 | + callback() |
| 279 | } | 279 | } |
| 280 | } | 280 | } |
| 281 | } | 281 | } |
| @@ -283,183 +283,183 @@ callback() | @@ -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 | } else { | 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 | } else { | 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 | } catch (err) { | 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 | }, 1000) | 454 | }, 1000) |
| 455 | } catch (error) { | 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,13 +469,15 @@ duration: 2000 | ||
| 469 | </script> | 469 | </script> |
| 470 | <style lang="scss" scoped> | 470 | <style lang="scss" scoped> |
| 471 | .u-page { | 471 | .u-page { |
| 472 | -min-height: 100vh; | 472 | + min-height: 100vh; |
| 473 | } | 473 | } |
| 474 | + | ||
| 474 | .inspect-form-content { | 475 | .inspect-form-content { |
| 475 | -background: #fff; | ||
| 476 | -padding: 20rpx; | 476 | + background: #fff; |
| 477 | + padding: 20rpx; | ||
| 477 | } | 478 | } |
| 479 | + | ||
| 478 | .form-item { | 480 | .form-item { |
| 479 | -margin-bottom: 20rpx; | 481 | + margin-bottom: 20rpx; |
| 480 | } | 482 | } |
| 481 | </style> | 483 | </style> |
pages-sub/daily/patrol-manage/index.vue
| @@ -162,7 +162,7 @@ const queryList = async (pageNo, pageSize) => { | @@ -162,7 +162,7 @@ const queryList = async (pageNo, pageSize) => { | ||
| 162 | // 跳转明细 | 162 | // 跳转明细 |
| 163 | const gotoDetail = (item) => { | 163 | const gotoDetail = (item) => { |
| 164 | uni.navigateTo({ | 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 | // 修复点5:优化页面生命周期逻辑 | 168 | // 修复点5:优化页面生命周期逻辑 |
pages.json
| @@ -107,6 +107,23 @@ | @@ -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 | "path": "maintain-manage/add-record", | 127 | "path": "maintain-manage/add-record", |
| 111 | "style": { "navigationBarTitleText": "新增养护记录" } | 128 | "style": { "navigationBarTitleText": "新增养护记录" } |
| 112 | }, | 129 | }, |
pages/index/index.vue
| @@ -132,7 +132,7 @@ import { timeFormat } from '@/uni_modules/uview-plus'; | @@ -132,7 +132,7 @@ 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, |
| 136 | taskDetailsWithDistance, | 136 | taskDetailsWithDistance, |
| 137 | taskDetailsWithSmartSort, | 137 | taskDetailsWithSmartSort, |
| 138 | getCurrentOrg, | 138 | getCurrentOrg, |
| @@ -319,6 +319,20 @@ const baseList = ref<Array<{ num: string; title: string; name: string }>>([]); | @@ -319,6 +319,20 @@ const baseList = ref<Array<{ num: string; title: string; name: string }>>([]); | ||
| 319 | const orgOptions = ref<any[]>([]); | 319 | const orgOptions = ref<any[]>([]); |
| 320 | const value1 = ref<number | string>(''); | 320 | const value1 = ref<number | string>(''); |
| 321 | const showActionSheet = ref(false); | 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 | watch(orgOptions, async (list) => { | 336 | watch(orgOptions, async (list) => { |
| 323 | if (list.length && !value1.value) { | 337 | if (list.length && !value1.value) { |
| 324 | value1.value = list[0].value; | 338 | value1.value = list[0].value; |
| @@ -382,6 +396,8 @@ const handleTabClick = (tabIndex: number) => { | @@ -382,6 +396,8 @@ const handleTabClick = (tabIndex: number) => { | ||
| 382 | currentTabValue.value = tabIndex; | 396 | currentTabValue.value = tabIndex; |
| 383 | showChartArea.value = true; | 397 | showChartArea.value = true; |
| 384 | }; | 398 | }; |
| 399 | + | ||
| 400 | + | ||
| 385 | // ========== 公共函数:请求 orgTaskIndicator 指标接口 ========== | 401 | // ========== 公共函数:请求 orgTaskIndicator 指标接口 ========== |
| 386 | const fetchOrgIndicator = async (orgId: number, beginDate: string, endDate: string) => { | 402 | const fetchOrgIndicator = async (orgId: number, beginDate: string, endDate: string) => { |
| 387 | try { | 403 | try { |
| @@ -410,13 +426,13 @@ const initRecent7Days = () => { | @@ -410,13 +426,13 @@ const initRecent7Days = () => { | ||
| 410 | const end = new Date(now); | 426 | const end = new Date(now); |
| 411 | end.setDate(end.getDate()); | 427 | end.setDate(end.getDate()); |
| 412 | const start = new Date(end); | 428 | const start = new Date(end); |
| 413 | - start.setDate(start.getDate() - 6); | 429 | + start.setDate(start.getDate() ); |
| 414 | dateRange.value = [ | 430 | dateRange.value = [ |
| 415 | timeFormat(start, 'yyyy-mm-dd'), | 431 | timeFormat(start, 'yyyy-mm-dd'), |
| 416 | timeFormat(end, 'yyyy-mm-dd') | 432 | timeFormat(end, 'yyyy-mm-dd') |
| 417 | ]; | 433 | ]; |
| 418 | console.log(dateRange.value) | 434 | console.log(dateRange.value) |
| 419 | - initChartData(dateRange.value[0], dateRange.value[1]); | 435 | + // initChartData(dateRange.value[0], dateRange.value[1]); |
| 420 | }; | 436 | }; |
| 421 | const getUnread = async () => { | 437 | const getUnread = async () => { |
| 422 | try { | 438 | try { |
| @@ -439,7 +455,7 @@ const getOrg = async () => { | @@ -439,7 +455,7 @@ const getOrg = async () => { | ||
| 439 | const initChartData = async (beginTime: string, endTime: string) => { | 455 | const initChartData = async (beginTime: string, endTime: string) => { |
| 440 | try { | 456 | try { |
| 441 | const postData = { beginTime, endTime }; | 457 | const postData = { beginTime, endTime }; |
| 442 | - const res = await getTaskCompletionSummary(postData); | 458 | + // const res = await getTaskCompletionSummary(postData); |
| 443 | klineCategories.value = res.map((item: any) => item.currentDate); | 459 | klineCategories.value = res.map((item: any) => item.currentDate); |
| 444 | klineChartData.value[0].data = res.map((item: any) => item.completedNum); | 460 | klineChartData.value[0].data = res.map((item: any) => item.completedNum); |
| 445 | klineChartData.value[1].data = res.map((item: any) => item.countPendingNum); | 461 | klineChartData.value[1].data = res.map((item: any) => item.countPendingNum); |
| @@ -840,11 +856,11 @@ $border-color: #e5e5e5; | @@ -840,11 +856,11 @@ $border-color: #e5e5e5; | ||
| 840 | display: flex; | 856 | display: flex; |
| 841 | } | 857 | } |
| 842 | .task-item__name { | 858 | .task-item__name { |
| 843 | - width: 80rpx; | 859 | + width: 88rpx; |
| 844 | } | 860 | } |
| 845 | .task-name-text { | 861 | .task-name-text { |
| 846 | flex: 1; | 862 | flex: 1; |
| 847 | - font-size: 24rpx; | 863 | + font-size: 28rpx; |
| 848 | color: $text-color; | 864 | color: $text-color; |
| 849 | display: -webkit-box; | 865 | display: -webkit-box; |
| 850 | -webkit-line-clamp: 2; | 866 | -webkit-line-clamp: 2; |
| @@ -853,7 +869,7 @@ $border-color: #e5e5e5; | @@ -853,7 +869,7 @@ $border-color: #e5e5e5; | ||
| 853 | text-overflow: ellipsis; | 869 | text-overflow: ellipsis; |
| 854 | } | 870 | } |
| 855 | &__name { | 871 | &__name { |
| 856 | - font-size: 24rpx; | 872 | + font-size: 28rpx; |
| 857 | color: $text-color; | 873 | color: $text-color; |
| 858 | display: inline-block; | 874 | display: inline-block; |
| 859 | } | 875 | } |
| @@ -861,7 +877,7 @@ $border-color: #e5e5e5; | @@ -861,7 +877,7 @@ $border-color: #e5e5e5; | ||
| 861 | display: flex; | 877 | display: flex; |
| 862 | align-items: flex-start; | 878 | align-items: flex-start; |
| 863 | gap: 6rpx; | 879 | gap: 6rpx; |
| 864 | - font-size: 24rpx; | 880 | + font-size: 26rpx; |
| 865 | color: $text-color-light; | 881 | color: $text-color-light; |
| 866 | margin-top: $spacing-sm; | 882 | margin-top: $spacing-sm; |
| 867 | align-items: center; | 883 | align-items: center; |