Commit 984b2e69cea685b431c7c3897944aed89dfd21b1
1 parent
c09c0eda
养护
Showing
1 changed file
with
152 additions
and
53 deletions
pages-sub/daily/maintain-manage/type-list.vue
| @@ -3,12 +3,20 @@ | @@ -3,12 +3,20 @@ | ||
| 3 | <template v-if="cardList.length > 0"> | 3 | <template v-if="cardList.length > 0"> |
| 4 | <view class="type-card" v-for="item in cardList" :key="item.key" hover-class="type-card--hover" | 4 | <view class="type-card" v-for="item in cardList" :key="item.key" hover-class="type-card--hover" |
| 5 | @click="toNextPage(item)"> | 5 | @click="toNextPage(item)"> |
| 6 | - <view class="info-row" v-for="row in item.rows" :key="row.label"> | ||
| 7 | - <!-- ✅计划类型:不渲染左侧label文字;其他行正常显示label --> | ||
| 8 | - <text class="info-label" v-if="row.label !== '计划类型'">{{ row.label }}:</text> | ||
| 9 | - <view class="info-value"> | ||
| 10 | - <view class="info-line" v-for="(value, idx) in row.values" :key="idx" | ||
| 11 | - :class="{ 'info-line--count': row.label === '待完成数' }">{{ value }}</view> | 6 | + |
| 7 | + <!-- 左上图标:按计划类型显示不同颜色图标 --> | ||
| 8 | + <view class="card-icon" :class="item.iconClass || 'icon-default'"> | ||
| 9 | + <text class="icon-text">{{ item.iconChar || '📋' }}</text> | ||
| 10 | + </view> | ||
| 11 | + | ||
| 12 | + <!-- 名称:第一行大字 --> | ||
| 13 | + <view class="card-name">{{ item.nameText }}</view> | ||
| 14 | + | ||
| 15 | + <!-- 底部:灰色文字 + 右侧数字 --> | ||
| 16 | + <view class="card-bottom"> | ||
| 17 | + <text class="card-label">待完成任务</text> | ||
| 18 | + <view class="card-badge"> | ||
| 19 | + <text class="card-count">{{ item.countText }}</text> | ||
| 12 | </view> | 20 | </view> |
| 13 | </view> | 21 | </view> |
| 14 | </view> | 22 | </view> |
| @@ -18,16 +26,22 @@ | @@ -18,16 +26,22 @@ | ||
| 18 | </template> | 26 | </template> |
| 19 | </view> | 27 | </view> |
| 20 | </template> | 28 | </template> |
| 29 | + | ||
| 21 | <script setup lang="ts"> | 30 | <script setup lang="ts"> |
| 22 | import { ref } from 'vue' | 31 | import { ref } from 'vue' |
| 23 | -import { onShow, onUnload } from '@dcloudio/uni-app'; | 32 | +import { onShow, onUnload } from '@dcloudio/uni-app' |
| 33 | + | ||
| 24 | const cardList = ref<Array<{ | 34 | const cardList = ref<Array<{ |
| 25 | key: string | 35 | key: string |
| 26 | planTypeId: string | number | 36 | planTypeId: string | number |
| 27 | batchNos: string[] | 37 | batchNos: string[] |
| 38 | + nameText: string | ||
| 39 | + countText: string | ||
| 40 | + iconClass?: string | ||
| 41 | + iconChar?: string | ||
| 28 | rows: Array<{ label: string; values: string[] }> | 42 | rows: Array<{ label: string; values: string[] }> |
| 29 | }>>([]) | 43 | }>>([]) |
| 30 | -/** 日期字段可能是 'yyyy‑MM‑dd' 字符串(LocalDate)或时间戳,统一转成 yyyy‑MM‑dd */ | 44 | + |
| 31 | const formatDate = (value: any) => { | 45 | const formatDate = (value: any) => { |
| 32 | if (value === null || value === undefined || value === '') return '--' | 46 | if (value === null || value === undefined || value === '') return '--' |
| 33 | if (Array.isArray(value)) { | 47 | if (Array.isArray(value)) { |
| @@ -39,18 +53,43 @@ const formatDate = (value: any) => { | @@ -39,18 +53,43 @@ const formatDate = (value: any) => { | ||
| 39 | } | 53 | } |
| 40 | return String(value).slice(0, 10) | 54 | return String(value).slice(0, 10) |
| 41 | } | 55 | } |
| 42 | -/** 去重并保持原顺序,合并卡片时避免同一个值重复占一行 */ | 56 | + |
| 43 | const uniq = (list: any[]) => Array.from(new Set(list.filter(v => v !== null && v !== undefined && v !== ''))) | 57 | const uniq = (list: any[]) => Array.from(new Set(list.filter(v => v !== null && v !== undefined && v !== ''))) |
| 58 | + | ||
| 59 | +/** 根据计划类型返回不同图标样式 */ | ||
| 60 | +const getIconByType = (name: string) => { | ||
| 61 | + const n = (name || '').toLowerCase() | ||
| 62 | + if (n.includes('补植') || n.includes('种植')) { | ||
| 63 | + return { iconClass: 'icon-blue', iconChar: '🌱' } | ||
| 64 | + } | ||
| 65 | + if (n.includes('修剪')) { | ||
| 66 | + return { iconClass: 'icon-orange', iconChar: '✂️' } | ||
| 67 | + } | ||
| 68 | + if (n.includes('浇水') || n.includes('防寒') || n.includes('灌溉')) { | ||
| 69 | + return { iconClass: 'icon-cyan', iconChar: '💧' } | ||
| 70 | + } | ||
| 71 | + if (n.includes('保洁') || n.includes('清洁')) { | ||
| 72 | + return { iconClass: 'icon-green', iconChar: '🗑️' } | ||
| 73 | + } | ||
| 74 | + if (n.includes('病虫害') || n.includes('防治')) { | ||
| 75 | + return { iconClass: 'icon-red', iconChar: '🛡️' } | ||
| 76 | + } | ||
| 77 | + if (n.includes('施肥') || n.includes('除草')) { | ||
| 78 | + return { iconClass: 'icon-sky', iconChar: '🎯' } | ||
| 79 | + } | ||
| 80 | + return { iconClass: 'icon-default', iconChar: '📋' } | ||
| 81 | +} | ||
| 82 | + | ||
| 44 | onShow(() => { | 83 | onShow(() => { |
| 45 | const item = uni.getStorageSync('temp_maintain_item') | 84 | const item = uni.getStorageSync('temp_maintain_item') |
| 46 | if (!item) { | 85 | if (!item) { |
| 47 | uni.showToast({ | 86 | uni.showToast({ |
| 48 | title: '数据异常,请返回重试', | 87 | title: '数据异常,请返回重试', |
| 49 | icon: 'none' | 88 | icon: 'none' |
| 50 | - }); | 89 | + }) |
| 51 | return | 90 | return |
| 52 | } | 91 | } |
| 53 | - const roadName = item.roadName || '--' | 92 | + |
| 54 | cardList.value = (item.planTypes || []).map((type: any) => { | 93 | cardList.value = (item.planTypes || []).map((type: any) => { |
| 55 | const batches = Array.isArray(type.batches) && type.batches.length | 94 | const batches = Array.isArray(type.batches) && type.batches.length |
| 56 | ? type.batches | 95 | ? type.batches |
| @@ -61,29 +100,39 @@ onShow(() => { | @@ -61,29 +100,39 @@ onShow(() => { | ||
| 61 | endTime: null, | 100 | endTime: null, |
| 62 | todayPendingCount: type.todayPendingCount | 101 | todayPendingCount: type.todayPendingCount |
| 63 | })) | 102 | })) |
| 103 | + | ||
| 64 | const batchNos = batches.map((batch: any) => batch.batchNo).filter(Boolean) | 104 | const batchNos = batches.map((batch: any) => batch.batchNo).filter(Boolean) |
| 65 | const pendingCount = batches.reduce((sum: number, batch: any) => sum + Number(batch.todayPendingCount || 0), 0) | 105 | const pendingCount = batches.reduce((sum: number, batch: any) => sum + Number(batch.todayPendingCount || 0), 0) |
| 106 | + const icon = getIconByType(type.planTypeName || '') | ||
| 107 | + | ||
| 66 | return { | 108 | return { |
| 67 | key: String(type.planTypeId), | 109 | key: String(type.planTypeId), |
| 68 | planTypeId: type.planTypeId, | 110 | planTypeId: type.planTypeId, |
| 69 | batchNos, | 111 | batchNos, |
| 112 | + nameText: type.planTypeName || '--', | ||
| 113 | + countText: `${pendingCount}`, | ||
| 114 | + iconClass: icon.iconClass, | ||
| 115 | + iconChar: icon.iconChar, | ||
| 70 | rows: [ | 116 | rows: [ |
| 71 | { label: '计划类型', values: [type.planTypeName || '--'] }, | 117 | { label: '计划类型', values: [type.planTypeName || '--'] }, |
| 72 | { label: '待完成数', values: [`${pendingCount}次`] } | 118 | { label: '待完成数', values: [`${pendingCount}次`] } |
| 73 | ] | 119 | ] |
| 74 | } | 120 | } |
| 75 | }) | 121 | }) |
| 76 | -}); | 122 | +}) |
| 123 | + | ||
| 77 | const toNextPage = (item: any) => { | 124 | const toNextPage = (item: any) => { |
| 78 | uni.setStorageSync('temp_maintain_rawList', item.batchNos || []) | 125 | uni.setStorageSync('temp_maintain_rawList', item.batchNos || []) |
| 79 | uni.navigateTo({ | 126 | uni.navigateTo({ |
| 80 | url: `/pages-sub/daily/maintain-manage/type-list-page?planTypeId=${item.planTypeId}` | 127 | url: `/pages-sub/daily/maintain-manage/type-list-page?planTypeId=${item.planTypeId}` |
| 81 | }) | 128 | }) |
| 82 | } | 129 | } |
| 83 | -onUnload(()=>{ | 130 | + |
| 131 | +onUnload(() => { | ||
| 84 | uni.removeStorageSync('temp_maintain_item') | 132 | uni.removeStorageSync('temp_maintain_item') |
| 85 | }) | 133 | }) |
| 86 | </script> | 134 | </script> |
| 135 | + | ||
| 87 | <style scoped lang="scss"> | 136 | <style scoped lang="scss"> |
| 88 | .type-grid { | 137 | .type-grid { |
| 89 | display: flex; | 138 | display: flex; |
| @@ -91,63 +140,113 @@ onUnload(()=>{ | @@ -91,63 +140,113 @@ onUnload(()=>{ | ||
| 91 | gap: 24rpx; | 140 | gap: 24rpx; |
| 92 | padding: 24rpx; | 141 | padding: 24rpx; |
| 93 | } | 142 | } |
| 94 | -/* 一行两张卡片,总宽度扣除中间间隙 */ | 143 | + |
| 95 | .type-card { | 144 | .type-card { |
| 96 | width: calc((100% - 24rpx) / 2); | 145 | width: calc((100% - 24rpx) / 2); |
| 146 | + // min-height: 240rpx; | ||
| 97 | box-sizing: border-box; | 147 | box-sizing: border-box; |
| 98 | display: flex; | 148 | display: flex; |
| 99 | flex-direction: column; | 149 | flex-direction: column; |
| 100 | - gap: 8rpx; | 150 | + justify-content: space-between; |
| 101 | background: #ffffff; | 151 | background: #ffffff; |
| 102 | - border-radius: 16rpx; | ||
| 103 | - padding: 24rpx; | ||
| 104 | - box-shadow: 0 4rpx 16rpx rgba(17, 24, 39, 0.06); | ||
| 105 | - transition: background-color 0.15s ease; | 152 | + border-radius: 24rpx; |
| 153 | + padding: 20rpx 20rpx; | ||
| 154 | + box-shadow: 0 4rpx 20rpx rgba(17, 24, 39, 0.08); | ||
| 155 | + transition: transform 0.15s ease, background-color 0.15s ease; | ||
| 156 | + | ||
| 106 | &--hover { | 157 | &--hover { |
| 107 | - background: #F4F5F7; | 158 | + background: #F7F8FA; |
| 108 | } | 159 | } |
| 109 | } | 160 | } |
| 110 | -.info-row { | 161 | + |
| 162 | +/* 左上图标 */ | ||
| 163 | +.card-icon { | ||
| 164 | + width: 62rpx; | ||
| 165 | + height: 62rpx; | ||
| 166 | + border-radius: 16rpx; | ||
| 111 | display: flex; | 167 | display: flex; |
| 112 | - align-items: flex-start; | 168 | + align-items: center; |
| 169 | + justify-content: center; | ||
| 170 | + background: #F3F4F6; | ||
| 113 | } | 171 | } |
| 114 | -.info-label { | ||
| 115 | - width: 130rpx !important; | ||
| 116 | - flex-shrink: 0; /* 标签禁止压缩 */ | ||
| 117 | - font-size: 26rpx; | ||
| 118 | - color: #6B7280; | ||
| 119 | - line-height: 1.5; | 172 | + |
| 173 | +.icon-text { | ||
| 174 | + font-size: 32rpx; | ||
| 120 | } | 175 | } |
| 121 | -.info-value { | ||
| 122 | - flex: 1; | ||
| 123 | - min-width: 0; | ||
| 124 | - /* ✅计划类型没有label时,去掉左边padding,顶格显示 */ | ||
| 125 | - padding-left: 16rpx; | 176 | + |
| 177 | +.icon-blue { | ||
| 178 | + background: #EAF4FF; | ||
| 126 | } | 179 | } |
| 127 | -/* 当该行没有label的时候,value不要左边边距 */ | ||
| 128 | -.info-row:not(:has(.info-label)) .info-value { | ||
| 129 | - padding-left: 0; | 180 | + |
| 181 | +.icon-orange { | ||
| 182 | + background: #FFF3E0; | ||
| 130 | } | 183 | } |
| 131 | -.info-line { | ||
| 132 | - font-size: 26rpx; | 184 | + |
| 185 | +.icon-cyan { | ||
| 186 | + background: #E0F7FA; | ||
| 187 | +} | ||
| 188 | + | ||
| 189 | +.icon-green { | ||
| 190 | + background: #E8F5E9; | ||
| 191 | +} | ||
| 192 | + | ||
| 193 | +.icon-red { | ||
| 194 | + background: #FCE4EC; | ||
| 195 | +} | ||
| 196 | + | ||
| 197 | +.icon-sky { | ||
| 198 | + background: #E3F2FD; | ||
| 199 | +} | ||
| 200 | + | ||
| 201 | +.icon-default { | ||
| 202 | + background: #ECEFF1; | ||
| 203 | +} | ||
| 204 | + | ||
| 205 | +/* 名称 */ | ||
| 206 | +.card-name { | ||
| 207 | + margin-top: 10rpx; | ||
| 208 | + font-size: 32rpx; | ||
| 209 | + font-weight: 600; | ||
| 133 | color: #1F2937; | 210 | color: #1F2937; |
| 134 | - line-height: 1.5; | ||
| 135 | - /* 普通计划类型文字:超长省略 */ | ||
| 136 | - &:not(.info-line--count) { | ||
| 137 | - overflow: hidden; | ||
| 138 | - text-overflow: ellipsis; | ||
| 139 | - white-space: nowrap; | ||
| 140 | - } | ||
| 141 | - /* ✅待完成数:禁止省略、禁止截断,数字必须完整显示 */ | ||
| 142 | - &--count { | ||
| 143 | - color: #2563EB; | ||
| 144 | - font-weight: 500; | ||
| 145 | - white-space: normal !important; | ||
| 146 | - overflow: visible !important; | ||
| 147 | - text-overflow: clip !important; | ||
| 148 | - } | 211 | + line-height: 1.4; |
| 212 | + overflow: hidden; | ||
| 213 | + text-overflow: ellipsis; | ||
| 214 | + white-space: nowrap; | ||
| 215 | +} | ||
| 216 | + | ||
| 217 | +/* 底部:灰色文字 + 数字 */ | ||
| 218 | +.card-bottom { | ||
| 219 | + // margin-top:10px; | ||
| 220 | + // padding-top: 20rpx; | ||
| 221 | + display: flex; | ||
| 222 | + align-items: center; | ||
| 223 | + justify-content: space-between; | ||
| 224 | +} | ||
| 225 | + | ||
| 226 | +.card-label { | ||
| 227 | + font-size: 24rpx; | ||
| 228 | + color: #9CA3AF; | ||
| 229 | +} | ||
| 230 | + | ||
| 231 | +.card-badge { | ||
| 232 | + min-width: 48rpx; | ||
| 233 | + height: 48rpx; | ||
| 234 | + padding: 0 14rpx; | ||
| 235 | + border-radius: 24rpx; | ||
| 236 | + background: #F3F4F6; | ||
| 237 | + display: flex; | ||
| 238 | + align-items: center; | ||
| 239 | + justify-content: center; | ||
| 240 | +} | ||
| 241 | + | ||
| 242 | +.card-count { | ||
| 243 | + font-size: 26rpx; | ||
| 244 | + font-weight: 600; | ||
| 245 | + color: #2563EB; | ||
| 149 | } | 246 | } |
| 247 | + | ||
| 150 | .type-empty { | 248 | .type-empty { |
| 249 | + width: 100%; | ||
| 151 | padding: 120rpx 0; | 250 | padding: 120rpx 0; |
| 152 | text-align: center; | 251 | text-align: center; |
| 153 | font-size: 26rpx; | 252 | font-size: 26rpx; |