Commit 6847fb738acf1f94440161cc900f584eeea8c8a3

Authored by 刘淇
1 parent a4ce4276

置为失效

api/maintain-manage/maintain-manage.js
... ... @@ -76,7 +76,7 @@ export const getDetailList = (params) => {
76 76 * @returns {Promise}
77 77 */
78 78 export const maintainPlan= (params) => {
79   - return get('/admin-api/garden/maintain-plan/page',params);
  79 + return get('/app-api/app/garden/maintain-plan-today/page',params);
80 80 };
81 81 /**
82 82 * 养护类型次数
... ... @@ -111,7 +111,8 @@ export const finishPlan= (params = {}) => {
111 111 * @returns {Promise}
112 112 */
113 113 export const invalidatePlan= (params) => {
114   - return put('/admin-api/garden/maintain-plan-detail/invalidate',params);
  114 + const commitId = params && params.commitId != null ? params.commitId : '';
  115 + return post(`/admin-api/garden/maintain-plan-detail/invalidate?commitId=${encodeURIComponent(commitId)}`,params);
115 116 };
116 117  
117 118  
... ...
pages-sub/daily/maintain-manage/add-record.vue
... ... @@ -157,6 +157,7 @@ import { getByType, getOptionsByCode, getMaterialByCode, workRecordSubmit } from
157 157 export default {
158 158 data() {
159 159 return {
  160 + commitId:'',
160 161 submitting: false,
161 162 imagesList: [],
162 163 initProgress: 0,
... ... @@ -229,8 +230,11 @@ export default {
229 230 onLoad(option) {
230 231 console.log('页面参数:', option)
231 232 this.paramsOptins = option
232   - const { businessType, planTypeId } = option
  233 + const { businessType, planTypeId,commitId } = option
233 234 this.loadDynamicFields(businessType, planTypeId)
  235 + if(commitId){
  236 + this.commitId = commitId
  237 + }
234 238 },
235 239 onReady() {
236 240 this.$refs.inspectFormRef.setRules(this.inspectFormRules)
... ...
pages-sub/daily/maintain-manage/index.vue
... ... @@ -92,10 +92,10 @@
92 92 <view class="u-body-item-title">道路名称:</view>
93 93 <view class="u-line-1 u-body-value">{{ item.roadName || '-' }}</view>
94 94 </view>
95   - <view class="u-body-item u-flex">
  95 + <!-- <view class="u-body-item u-flex">
96 96 <view class="u-body-item-title">计划名称:</view>
97 97 <view class="u-line-1 u-body-value">{{ item.planName || '-' }}</view>
98   - </view>
  98 + </view> -->
99 99  
100 100  
101 101 <!-- <view class="u-body-item u-flex">
... ... @@ -307,7 +307,7 @@ const goToDetail = (item) =&gt; {
307 307 // })
308 308  
309 309 uni.navigateTo({
310   - url: `/pages-sub/daily/maintain-manage/type-list?roadName=${encodeURIComponent(item.roadName)}&levelId=${item.levelId}`
  310 + url: `/pages-sub/daily/maintain-manage/type-list?roadName=${encodeURIComponent(item.roadName)}&planTypeId=${item.planTypeId}`
311 311 })
312 312  
313 313 }
... ...
pages-sub/daily/maintain-manage/now-list-page.vue
... ... @@ -5,11 +5,11 @@
5 5 一个任务可提交多次上报记录,每一次作业需如实上报。
6 6 </view>
7 7 <!-- 上报记录列表 -->
8   - <view class="list-wrap" v-if="reportList.length > 0">
9   - <view class="report-item" v-for="(item, index) in reportList" :key="index">
10   - <view class="item-title">【第{{ item.sortNum || (index + 1) }}次上报】{{ item.planName }}</view>
  8 + <view class="list-wrap" v-if="dataList.length > 0">
  9 + <view class="report-item" v-for="(item, index) in dataList" :key="index">
  10 + <view class="item-title">【第{{ item.sortNum || (index + 1) }}次上报】{{ planName }}</view>
11 11 <view class="item-row item-row-bottom">
12   - <view class="item-time">提交时间:{{ timeFormat(item.createTime,'yyyy-mm-dd')}}</view>
  12 + <view class="item-time">提交时间:{{ timeFormat(item.createTime,'yyyy-mm-dd hh:MM:ss')}}</view>
13 13 <view class="look-btn" @click="handleView(item)">查看</view>
14 14 </view>
15 15 </view>
... ... @@ -30,11 +30,17 @@ import { onShow, onLoad } from &#39;@dcloudio/uni-app&#39;
30 30 import { maintainPlanList } from "@/api/maintain-manage/maintain-manage";
31 31 import {timeFormat} from '@/uni_modules/uview-plus';
32 32 // 上报记录数据
  33 +const dataList = ref<any[]>([])
33 34 const reportList = ref<any[]>([])
  35 +
34 36 let planNo = ref('')
35 37 let planTypeId = ref('')
36 38 let businessType = ref('')
  39 +let planName = ref('')
37 40 let isView = ref(true)
  41 +// 存储commitState=1对应的commitId,没有则为空字符串
  42 +const currentCommitId = ref('')
  43 +
38 44 // onLoad接收url传过来的planNo
39 45 onLoad((options) => {
40 46 if (options.planNo) {
... ... @@ -42,13 +48,11 @@ onLoad((options) =&gt; {
42 48 planTypeId.value = options.planTypeId
43 49 businessType.value = options.businessType
44 50 isView.value = options.isView
45   - // planTypeId=${item.planTypeId}&businessType=${item.busiLine}
46 51 getReportList()
47 52 } else {
48 53 uni.showToast({ title: 'planNo参数缺失', icon: 'none' })
49 54 }
50 55 })
51   -
52 56 // 请求上报记录接口
53 57 const getReportList = async () => {
54 58 console.log('3123')
... ... @@ -62,7 +66,24 @@ const getReportList = async () =&gt; {
62 66 }
63 67 const res = await maintainPlanList(data)
64 68 // 接口返回list,无数据则reportList为空,页面自动显示empty
65   - reportList.value = res?.list || []
  69 + dataList.value = res?.list[0].workRecords
  70 + planName.value = res?.list[0].planName
  71 + reportList.value = res?.list || []
  72 +
  73 +
  74 +
  75 + // ============ 新增逻辑:寻找commitState ===1 的commitId ============
  76 + currentCommitId.value = ''
  77 + if(reportList.value.length > 0){
  78 + // 找到第一条 commitState ===1 的数据
  79 + const activeItem = reportList.value.find(item => item.commitState === 1)
  80 + if(activeItem){
  81 + currentCommitId.value = activeItem.commitId || ''
  82 + }
  83 + // 没有找到 activeItem,currentCommitId保持 ''
  84 + }
  85 + // reportList为空直接 currentCommitId=''
  86 +
66 87 } catch (err) {
67 88 console.error('获取上报记录失败', err)
68 89 uni.showToast({ title: '加载失败', icon: 'none' })
... ... @@ -70,7 +91,6 @@ const getReportList = async () =&gt; {
70 91 uni.hideLoading()
71 92 }
72 93 }
73   -
74 94 // 查看上报详情
75 95 const handleView = (item) => {
76 96 console.log('查看详情', item)
... ... @@ -79,11 +99,11 @@ const handleView = (item) =&gt; {
79 99 url: `/pages-sub/daily/maintain-manage/finish-plan-detail?planNo=${item.planNo}&commitId=${item.commitId}`
80 100 })
81 101 }
82   -// 新增上报记录,把planNo带到新增页面
  102 +// 新增上报记录,把planNo + currentCommitId带到新增页面
83 103 const handleAddReport = () => {
84   - console.log('上报本次记录')
  104 + console.log('上报本次记录', currentCommitId.value)
85 105 uni.navigateTo({
86   - url: `/pages-sub/daily/maintain-manage/add-record?planNo=${planNo.value}&planTypeId=${planTypeId.value}&businessType=${businessType.value}`
  106 + url: `/pages-sub/daily/maintain-manage/add-record?planNo=${planNo.value}&planTypeId=${planTypeId.value}&businessType=${businessType.value}&commitId=${currentCommitId.value}`
87 107 })
88 108 }
89 109 </script>
... ... @@ -93,7 +113,6 @@ const handleAddReport = () =&gt; {
93 113 padding-bottom: 120rpx; // 给底部按钮预留空间
94 114 background: #ffffff;
95 115 }
96   -
97 116 // 顶部黄色提示条
98 117 .tip-bar {
99 118 background-color: #f9e0a2;
... ... @@ -102,45 +121,37 @@ const handleAddReport = () =&gt; {
102 121 padding: 24rpx 20rpx;
103 122 line-height: 1.5;
104 123 }
105   -
106 124 .list-wrap {
107 125 padding: 0;
108 126 }
109   -
110 127 .report-item {
111 128 padding: 30rpx 24rpx;
112 129 border-bottom: 1rpx solid #eee;
113   -
114 130 .item-title {
115 131 font-size: 32rpx;
116 132 color: #222;
117 133 font-weight: 500;
118 134 margin-bottom: 20rpx;
119 135 }
120   -
121 136 .item-row {
122 137 font-size: 28rpx;
123 138 color: #555;
124 139 margin-bottom: 12rpx;
125 140 }
126   -
127 141 .item-row-bottom {
128 142 display: flex;
129 143 justify-content: space-between;
130 144 align-items: center;
131 145 margin-bottom: 0;
132 146 }
133   -
134 147 .look-btn {
135 148 font-size: 28rpx;
136 149 color: #1989fa;
137 150 }
138 151 }
139   -
140 152 .empty-wrap {
141 153 padding-top: 120rpx;
142 154 }
143   -
144 155 .fixed-bottom-btn-wrap {
145 156 // position: fixed;
146 157 // bottom: 0;
... ...
pages-sub/daily/maintain-manage/type-list-page.vue
... ... @@ -23,7 +23,7 @@
23 23 </view>
24 24 <!-- 第二行:任务次数 + 去作业按钮 -->
25 25 <view class="row row-2">
26   - <view class="info-text">任务次数:第{{ item.planNum || 1 }}次</view>
  26 + <view class="info-text">任务次数:第{{ item.planFinishNum +1 }}次</view>
27 27 <!-- 待完成:去作业;已完成:去查看 -->
28 28 <view v-if="activeStatus === '1'" class="mini-btn" @click.stop="handleGoWork(item)">去作业</view>
29 29 <view v-else-if="activeStatus === '2'" class="mini-btn" @click.stop="handleGoWork(item)">去查看</view>
... ... @@ -42,23 +42,14 @@
42 42 </view>
43 43 </view>
44 44 </z-paging>
45   - <!-- ========== 置为失效弹窗(参考回退弹窗结构) ========== -->
46   - <up-modal :show="invalidModalShow" title="失效原因" :closeOnClickOverlay="false" :showConfirmButton="true"
  45 + <!-- ========== 置为失效 简单二次确认弹窗【修改后】 ========== -->
  46 + <up-modal :show="invalidModalShow" title="提示" :closeOnClickOverlay="false" :showConfirmButton="true"
47 47 :showCancelButton="true" @cancel="handleInvalidModalCancel" @confirm="confirmSetInvalid">
48 48 <view class="invalid-modal-content">
49   - <up-textarea v-model.trim="invalidReason" placeholder="请输入失效原因(必填)" rows="6" :count="200"
50   - maxlength="200" class="invalid-textarea" />
51   - <view class="upload-wrap mt-20">
52   - <view class="upload-title">上传图片(选填)</view>
53   - <up-upload :file-list="invalidImgs.rawImgList.value || []" @after-read="invalidImgs.uploadImgs"
54   - @delete="invalidImgs.deleteImg" multiple width="70" height="70"
55   - :max-count="invalidImgs.uploadConfig.maxCount"
56   - :upload-text="invalidImgs.uploadConfig.uploadText"
57   - :size-type="invalidImgs.uploadConfig.sizeType" />
58   - </view>
  49 + <text>确定要置为失效该任务吗?</text>
59 50 </view>
60 51 </up-modal>
61   - <!-- ========== 结束任务二次确认弹窗【新增】 ========== -->
  52 + <!-- ========== 结束任务二次确认弹窗 ========== -->
62 53 <up-modal :show="endTaskModalShow" title="提示" :closeOnClickOverlay="false" :showConfirmButton="true"
63 54 :showCancelButton="true" @cancel="handleEndTaskModalCancel" @confirm="confirmEndTask">
64 55 <view class="end-task-modal-content">
... ... @@ -71,9 +62,8 @@
71 62 import { ref, computed } from 'vue'
72 63 import { onShow, onUnload, onLoad } from '@dcloudio/uni-app'
73 64 import { useUserStore } from '@/pinia/user';
74   -import { maintainPlanNum, finishPlan, invalidatePlan } from "@/api/maintain-manage/maintain-manage";
  65 +import { maintainPlanNum, finishPlan, invalidatePlan, maintainCreate } from "@/api/maintain-manage/maintain-manage";
75 66 import { timeFormat } from '@/uni_modules/uview-plus';
76   -import { useUploadImgs } from '@/common/utils/useUploadImgs'
77 67  
78 68 /** 获取当天日期 yyyy-MM-dd */
79 69 const getTodayStr = () => {
... ... @@ -83,7 +73,6 @@ const getTodayStr = () =&gt; {
83 73 const day = String(d.getDate()).padStart(2, '0')
84 74 return `${year}-${month}-${day}`
85 75 }
86   -
87 76 const userStore = useUserStore();
88 77 const userRoles = computed<string[]>(() => userStore.userInfo?.roles || []);
89 78 // 判断是否拥有置为失效权限:任意一个组长角色就可以
... ... @@ -100,28 +89,19 @@ const statusTabs = ref([
100 89 const activeStatus = ref('1')
101 90 const pagingRef = ref(null)
102 91 const currentList = ref([])
103   -// 保存上一页传过来的原始数组
104   -let originRawList: any[] = []
  92 +// originRawList:存储batchNo字符串数组,例 ["BN17925709862917163193","xxx"]
  93 +let originRawList: string[] = []
105 94 // 合并之后全部接口返回的总数据
106 95 const allTotalData = ref<any[]>([])
107 96 // ===================== 失效弹窗状态 =====================
108 97 const invalidModalShow = ref(false)
109   -const invalidReason = ref('')
110 98 const currentInvalidItem = ref(null)
111   -// ===================== 结束任务确认弹窗【新增】 =====================
  99 +// ===================== 结束任务确认弹窗 =====================
112 100 const endTaskModalShow = ref(false)
113 101 const currentEndTaskItem = ref<any>(null)
114   -// 图片上传实例,和回退保持一致,最多3张
115   -const invalidImgs = useUploadImgs({
116   - maxCount: 3,
117   - uploadText: '选择失效图片',
118   - sizeType: ['compressed'],
119   - formRef: null,
120   - fieldName: 'invalidImgs'
121   -})
  102 +
122 103 // 加载数据,根据当前activeStatus动态调用接口
123 104 const loadData = async () => {
124   - // originRawList = uni.getStorageSync('temp_maintain_rawList')
125 105 console.log('123123')
126 106 if (!originRawList || originRawList.length === 0) {
127 107 return
... ... @@ -141,16 +121,17 @@ const loadData = async () =&gt; {
141 121 // 已完成,只查2
142 122 stateArr = ['2']
143 123 }
144   - // 遍历state数组,每个状态,循环rawList里面所有batchNo请求
  124 + // 遍历state数组
145 125 for (const finishState of stateArr) {
146   - for (const item of originRawList) {
  126 + // originRawList 为batchNo字符串数组,循环每一个batchNo去请求
  127 + for (const batchNoItem of originRawList) {
147 128 const apiParams: any = {
148 129 pageNo: 1,
149 130 pageSize: 10,
150   - planNo: item.planNo || '',
  131 + planNo: '',
151 132 planAttr: '',
152 133 finishState: finishState,
153   - batchNo: item.batchNo
  134 + batchNo: batchNoItem
154 135 }
155 136 // 待完成状态追加当天日期 beginTime endTime
156 137 if (activeStatus.value === '1') {
... ... @@ -177,11 +158,9 @@ const planTypeId = ref(&#39;&#39;)
177 158 onLoad((options) => {
178 159 planTypeId.value = options.planTypeId
179 160 });
180   -// onShow 只保留一处,读取storage,只第一次读取storage
  161 +// onShow 只保留一处,读取storage,originRawList接收batchNo字符串数组
181 162 onShow(async () => {
182 163 originRawList = uni.getStorageSync('temp_maintain_rawList') || []
183   - // ✅ 读取完立刻删除,防止脏数据
184   - // uni.removeStorageSync('temp_maintain_rawList')
185 164 await loadData()
186 165 })
187 166 // z-paging分页查询,直接使用allTotalData
... ... @@ -200,41 +179,49 @@ const handleStatusChange = async (tabItem) =&gt; {
200 179 // 打开失效弹窗
201 180 const handleSetInvalid = (item) => {
202 181 currentInvalidItem.value = item
203   - invalidReason.value = ''
204   - invalidImgs.clearImgs()
205 182 invalidModalShow.value = true
206 183 }
207 184 // 关闭弹窗,重置数据
208 185 const handleInvalidModalCancel = () => {
209 186 invalidModalShow.value = false
210   - invalidReason.value = ''
211   - invalidImgs.clearImgs()
  187 + currentInvalidItem.value = null
212 188 }
213 189 // 确认提交置为失效
214 190 const confirmSetInvalid = async () => {
215   - const reason = invalidReason.value.trim()
216   - if (!reason) {
217   - uni.showToast({ title: '请填写失效原因', icon: 'none' })
218   - return
219   - }
220 191 const item = currentInvalidItem.value
221   - if (!item || !item.commitId) {
222   - uni.showToast({ title: '缺少commitId,无法操作', icon: 'none' })
  192 + console.log(currentInvalidItem.value)
  193 + if (!item) {
  194 + uni.showToast({ title: '数据异常', icon: 'none' })
223 195 return
224 196 }
225 197 uni.showLoading({ title: '提交中...', mask: true })
226 198 try {
227   - // 获取上传成功图片url数组,拼接逗号
228   - const imgUrlArr = invalidImgs.getSuccessImgUrls()
229   - const invalidFiles = imgUrlArr.join(',')
  199 + let targetCommitId = item.commitId
  200 + // ✅ 如果没有 commitId,先执行 maintainCreate 创建草稿
  201 + if (!targetCommitId) {
  202 + const submitData = {
  203 + planNo: item.planNo,
  204 + imgHost: '1',
  205 + beginImg: [],
  206 + commonUserList: [],
  207 + remark: ''
  208 + }
  209 + const createRes: any = await maintainCreate(submitData)
  210 + // 兼容后端两种返回:裸id / {id:xxx}
  211 + targetCommitId = createRes && typeof createRes === 'object' ? createRes.id : createRes
  212 + if (!targetCommitId) {
  213 + uni.hideLoading()
  214 + uni.showToast({ title: '创建养护草稿失败,无法置为失效', icon: 'none' })
  215 + return
  216 + }
  217 + }
  218 +
230 219 const params = {
231   - commitId: item.commitId,
232   - invalidReason: reason,
233   - invalidFiles: invalidFiles
  220 + commitId: targetCommitId,
234 221 }
235 222 console.log('置为失效提交参数:', params)
236   - // 调用接口 invalidatePlan
237   - await invalidatePlan(params)
  223 + console.log(params.commitId)
  224 + await invalidatePlan({ commitId: params.commitId })
238 225 uni.showToast({ title: '操作成功', icon: 'success' })
239 226 handleInvalidModalCancel()
240 227 // 重新加载数据刷新列表
... ... @@ -262,26 +249,21 @@ const handleEndTaskModalCancel = () =&gt; {
262 249 endTaskModalShow.value = false
263 250 currentEndTaskItem.value = null
264 251 }
265   -// 确认结束任务,真正调用接口【新增】
  252 +// 确认结束任务,真正调用接口
266 253 const confirmEndTask = async () => {
267 254 const item = currentEndTaskItem.value
268   - // commitId 由明细列表接口回填(commit_state=1),按钮只在有值时渲染
269 255 if (!item || !item.commitId) return
270 256 endTaskModalShow.value = false
271 257 uni.showLoading({ title: '提交中...', mask: true })
272 258 try {
273   - // 后端 /finish 只认 commitId,且要求本次养护至少有一条有效子上报
274 259 await finishPlan({ commitId: item.commitId })
275   - // 先关 loading 再弹提示:微信端 showLoading/showToast 共用同一个 toast,顺序反了会把成功提示顶掉
276 260 uni.hideLoading()
277 261 uni.showToast({ title: '结束任务成功', icon: 'success' })
278   - // 操作成功,重新加载数据,刷新列表(commitId 随之清空,按钮消失)
279 262 await loadData()
280 263 pagingRef.value?.reload()
281 264 } catch (err) {
282 265 console.error('结束任务失败', err)
283 266 uni.hideLoading()
284   - // 业务错误 request.js 已弹过后端 msg,这里不重复弹
285 267 if (err && err.msg) return
286 268 uni.showToast({ title: '结束任务失败,请重试', icon: 'none' })
287 269 } finally {
... ... @@ -349,20 +331,9 @@ onUnload(() =&gt; {
349 331 padding: 8rpx 20rpx;
350 332 flex-shrink: 0;
351 333 }
352   -// 弹窗样式,和回退弹窗保持一致
353 334 .invalid-modal-content {
354 335 width: 100%;
355 336 box-sizing: border-box;
356 337 padding: 10rpx 0;
357 338 }
358   -.upload-wrap {
359   - .upload-title {
360   - font-size: 28rpx;
361   - color: #333;
362   - margin-bottom: 10rpx;
363   - }
364   -}
365   -.mt-20 {
366   - margin-top: 20rpx;
367   -}
368 339 </style>
... ...
pages-sub/daily/maintain-manage/type-list.vue
... ... @@ -6,8 +6,8 @@
6 6 @click="toNextPage(item)">
7 7 <view class="tag-text">
8 8 <!-- 文字区域:超长省略号,数字括号单独放后面,永远可见 -->
9   - <text class="tag-name">{{ item.label }}</text>
10   - <text class="tag-count">({{ item.count }})</text>
  9 + <text class="tag-name">{{ item.planTypeName }}</text>
  10 + <text class="tag-count">({{ item.todayPendingCount }})</text>
11 11 </view>
12 12 </view>
13 13 </template>
... ... @@ -38,7 +38,7 @@ const roadName = ref&lt;string | null&gt;(null)
38 38 const levelId = ref<string | null>(null)
39 39 onLoad((options) => {
40 40 roadName.value = decodeURIComponent(options.roadName)
41   - levelId.value = decodeURIComponent(options.levelId);
  41 + // levelId.value = decodeURIComponent(options.levelId);
42 42 });
43 43 onShow(() => {
44 44 if (!roadName.value) {
... ... @@ -55,10 +55,14 @@ const fetchData = async () =&gt; {
55 55 try {
56 56 const res = await maintainPlan({
57 57 roadName: roadName.value,
58   - levelId: levelId.value
  58 + // roadName: '月坛南街',
  59 + pageNo:1,
  60 + pageSize:100,
  61 + finishState:1
  62 + // levelId: levelId.value
59 63 })
60 64 console.log('maintainPlan返回', res)
61   - if (!Array.isArray(res.list) || res.list.length === 0) {
  65 + if (res.list.length == 0) {
62 66 tagList.value = []
63 67 uni.showToast({
64 68 title: '暂无养护类型',
... ... @@ -66,7 +70,8 @@ const fetchData = async () =&gt; {
66 70 });
67 71 return
68 72 }
69   - await requestBatchList(res.list)
  73 + tagList.value = res.list[0].planTypes
  74 + // await requestBatchList(res.list)
70 75 } catch (error) {
71 76 console.error('请求失败:', error)
72 77 uni.showToast({ title: '网络异常,请重试', icon: 'none' })
... ... @@ -145,7 +150,7 @@ const requestBatchList = async (list: any[]) =&gt; {
145 150 // 标签点击跳转,rawList存入storage,并且把planTypeId拼到url传给下一页
146 151 const toNextPage = (item: any) => {
147 152 // maintainStore.setRawList(item.rawList)
148   - uni.setStorageSync('temp_maintain_rawList', item.rawList)
  153 + uni.setStorageSync('temp_maintain_rawList', item.batchNos)
149 154 uni.navigateTo({
150 155 url: `/pages-sub/daily/maintain-manage/type-list-page?planTypeId=${item.planTypeId}`
151 156 })
... ...