Commit 984b2e69cea685b431c7c3897944aed89dfd21b1

Authored by 刘淇
1 parent c09c0eda

养护

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) =&gt; { @@ -39,18 +53,43 @@ const formatDate = (value: any) =&gt; {
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(() =&gt; { @@ -61,29 +100,39 @@ onShow(() =&gt; {
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(()=&gt;{ @@ -91,63 +140,113 @@ onUnload(()=&gt;{
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;