Commit 53e7aa9670892fff70999c30a69d4d83c63923e7

Authored by 王彪总
1 parent ecfadea2

业务线 小程序不用写死,从后端接口获取

components/grouped-picker/grouped-picker.vue
@@ -4,8 +4,10 @@ @@ -4,8 +4,10 @@
4 path 只有 1 层 → 只有侧栏(原型「植物」屏:乔木/灌木/竹类… 纯侧栏,没有 tab); 4 path 只有 1 层 → 只有侧栏(原型「植物」屏:乔木/灌木/竹类… 纯侧栏,没有 tab);
5 path 有 2 层 → tab + 侧栏 + 平铺列表(原型「工具」屏:手工工具/电动工具/机械工具 → 剪切工具… → 太平剪); 5 path 有 2 层 → tab + 侧栏 + 平铺列表(原型「工具」屏:手工工具/电动工具/机械工具 → 剪切工具… → 太平剪);
6 配到 g3 → 再多一层吸顶分组标题(物料 类型→类别→明细→物料 折出来的形态)。 6 配到 g3 → 再多一层吸顶分组标题(物料 类型→类别→明细→物料 折出来的形态)。
7 - 选择控件按原型:多选+数量时右侧是步进器(未选一个「+」,已选「− n +」,减到 1 再减即取消),  
8 - 不放勾选框;按钮是小白底圆角方框 + 浅灰描边(加减同款,不是圆形、不是灰底)。 7 + 选择控件:**多选行左侧一律保留勾选框**(勾选框只管选中/取消),
  8 + 带数量的字段右侧再加步进器管件数(未选一个「+」,已选「− n +」,减到 1 再减即取消),
  9 + 按钮是小圆角方框 + 浅灰描边 + 白底,「+」「−」同款。
  10 + ⚠️ 原型弹层里没有勾选框(只有步进器),勾选框是按要求保留的、属于刻意覆盖原型。
9 行的勾选态由本组件的 draft 数据派生,不用 u-checkbox: 11 行的勾选态由本组件的 draft 数据派生,不用 u-checkbox:
10 u-checkbox 的勾选态是组件内部状态(u-checkbox.vue:199-221 只在 init 时从父组派生), 12 u-checkbox 的勾选态是组件内部状态(u-checkbox.vue:199-221 只在 init 时从父组派生),
11 而 u-checkbox-group 是把每个子实例的内部 isChecked 回读成数组(u-checkbox-group.vue:95-112), 13 而 u-checkbox-group 是把每个子实例的内部 isChecked 回读成数组(u-checkbox-group.vue:95-112),
@@ -42,14 +44,20 @@ @@ -42,14 +44,20 @@
42 <view v-if="group.label" class="gp-group-title">{{ group.label }}</view> 44 <view v-if="group.label" class="gp-group-title">{{ group.label }}</view>
43 <view v-for="row in group.rows" :key="row.value" class="gp-row" 45 <view v-for="row in group.rows" :key="row.value" class="gp-row"
44 :class="{ 'is-selected': isSelected(row), 'is-locked': isLocked(row) }" @click="onRowClick(row)"> 46 :class="{ 'is-selected': isSelected(row), 'is-locked': isLocked(row) }" @click="onRowClick(row)">
  47 + <!-- 多选:左侧勾选框(原型弹层里没有,按要求保留)。
  48 + 带数量的字段勾选框与步进器并存:勾选框只表达选中/取消,件数由右侧步进器调 -->
  49 + <view v-if="multiple" class="gp-check" :class="{ 'is-checked': isSelected(row) }"
  50 + @click.stop="onToggle(row)">
  51 + <text v-if="isSelected(row)" class="gp-check-mark">✓</text>
  52 + </view>
45 <view class="gp-row-main"> 53 <view class="gp-row-main">
46 <text class="gp-row-label">{{ row.label }}</text> 54 <text class="gp-row-label">{{ row.label }}</text>
47 <!-- 搜索态下补层级面包屑,否则不知道命中的项属于哪个分组 --> 55 <!-- 搜索态下补层级面包屑,否则不知道命中的项属于哪个分组 -->
48 <text v-if="breadcrumb(row)" class="gp-row-crumb">{{ breadcrumb(row) }}</text> 56 <text v-if="breadcrumb(row)" class="gp-row-crumb">{{ breadcrumb(row) }}</text>
49 </view> 57 </view>
50 - <!-- 多选 + 数量(原型形态):右侧步进器表达选中态 —— 未选只有一个「+」, 58 + <!-- 多选 + 数量(原型形态):右侧步进器 —— 未选只有一个「+」,
51 点了就选中并置 1;已选是「− n +」,减到 1 再减即取消选择 --> 59 点了就选中并置 1;已选是「− n +」,减到 1 再减即取消选择 -->
52 - <view v-if="needQuantity" class="gp-qty" @click.stop> 60 + <view v-if="multiple && needQuantity" class="gp-qty" @click.stop>
53 <view v-if="!isSelected(row)" class="gp-qty-btn is-plus" 61 <view v-if="!isSelected(row)" class="gp-qty-btn is-plus"
54 :class="{ 'is-disabled': isLocked(row) }" @click="onPlus(row)"> 62 :class="{ 'is-disabled': isLocked(row) }" @click="onPlus(row)">
55 <up-icon name="plus" size="12" color="#606266"></up-icon> 63 <up-icon name="plus" size="12" color="#606266"></up-icon>
@@ -64,12 +72,8 @@ @@ -64,12 +72,8 @@
64 </view> 72 </view>
65 </template> 73 </template>
66 </view> 74 </view>
67 - <!-- 多选无数值:原型没覆盖这种,保留自绘勾选框 -->  
68 - <view v-else-if="multiple" class="gp-check" :class="{ 'is-checked': isSelected(row) }">  
69 - <text v-if="isSelected(row)" class="gp-check-mark">✓</text>  
70 - </view>  
71 <!-- 单选:原型没覆盖,右侧给一个选中标记 --> 75 <!-- 单选:原型没覆盖,右侧给一个选中标记 -->
72 - <view v-else class="gp-radio"> 76 + <view v-else-if="!multiple" class="gp-radio">
73 <up-icon v-if="isSelected(row)" name="checkmark" size="16" color="#2979ff"></up-icon> 77 <up-icon v-if="isSelected(row)" name="checkmark" size="16" color="#2979ff"></up-icon>
74 </view> 78 </view>
75 </view> 79 </view>
@@ -271,6 +275,20 @@ const deselect = (v) =&gt; { @@ -271,6 +275,20 @@ const deselect = (v) =&gt; {
271 if (i > -1) draftSelected.value.splice(i, 1) 275 if (i > -1) draftSelected.value.splice(i, 1)
272 delete draftQty[v] 276 delete draftQty[v]
273 } 277 }
  278 +// 勾选框:只切选中态。取消会把该项的数量一起删掉,重新勾上从 1 起
  279 +const onToggle = (row) => {
  280 + const v = String(row.value)
  281 + if (isSelected(row)) {
  282 + deselect(v)
  283 + return
  284 + }
  285 + if (isLocked(row)) {
  286 + uni.showToast({ title: `最多选择 ${props.maxCount} 项`, icon: 'none' })
  287 + return
  288 + }
  289 + draftSelected.value.push(v)
  290 + if (props.needQuantity && !draftQty[v]) draftQty[v] = 1
  291 +}
274 // 「+」:未选先选中并置 1,已选则 +1 292 // 「+」:未选先选中并置 1,已选则 +1
275 const onPlus = (row) => { 293 const onPlus = (row) => {
276 if (isLocked(row)) { 294 if (isLocked(row)) {
@@ -316,18 +334,10 @@ const switchSide = (idx) =&gt; { @@ -316,18 +334,10 @@ const switchSide = (idx) =&gt; {
316 const onRowClick = (row) => { 334 const onRowClick = (row) => {
317 const v = String(row.value) 335 const v = String(row.value)
318 if (props.multiple) { 336 if (props.multiple) {
319 - // 整行点击也能选(不必非要点中那个「+」),选中就默认数量 1。  
320 - // 带数量的字段点整行「取消」要禁用:取消统一走「−」,否则误点一下就把加好的数量清了  
321 - if (isSelected(row)) {  
322 - if (!props.needQuantity) deselect(v)  
323 - return  
324 - }  
325 - if (isLocked(row)) {  
326 - uni.showToast({ title: `最多选择 ${props.maxCount} 项`, icon: 'none' })  
327 - return  
328 - }  
329 - draftSelected.value.push(v)  
330 - if (props.needQuantity && !draftQty[v]) draftQty[v] = 1 337 + // 整行点击也能选(不必非要点中勾选框),选中就默认数量 1。
  338 + // 带数量的字段点整行「取消」要禁用:取消统一走勾选框或「−」,否则误点一下就把加好的数量清了
  339 + if (isSelected(row) && props.needQuantity) return
  340 + onToggle(row)
331 return 341 return
332 } 342 }
333 // 单选:点行即确认并关闭,与底部 actionSheet 的即时选中语义一致 343 // 单选:点行即确认并关闭,与底部 actionSheet 的即时选中语义一致
@@ -490,6 +500,8 @@ watch( @@ -490,6 +500,8 @@ watch(
490 } 500 }
491 } 501 }
492 502
  503 +/* 多选勾选框(自绘,不用 u-checkbox —— 见文件头注释的幽灵勾选坑)。
  504 + 原型弹层里没有勾选框,是按要求保留的,不要照着原型删掉 */
493 .gp-check { 505 .gp-check {
494 flex-shrink: 0; 506 flex-shrink: 0;
495 width: 36rpx; 507 width: 36rpx;