@didaoktv/didaoui-uniapp 1.0.0 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (114) hide show
  1. package/README.md +16 -7
  2. package/components/dd-action-sheet/dd-action-sheet.vue +3 -3
  3. package/components/dd-album/album.js +19 -0
  4. package/components/dd-album/dd-album.vue +345 -0
  5. package/components/dd-album/props.js +89 -0
  6. package/components/dd-avatar/avatar.js +19 -0
  7. package/components/dd-avatar/dd-avatar.vue +172 -160
  8. package/components/dd-avatar/props.js +84 -0
  9. package/components/dd-avatar-group/avatarGroup.js +14 -0
  10. package/components/dd-avatar-group/dd-avatar-group.vue +110 -0
  11. package/components/dd-avatar-group/props.js +57 -0
  12. package/components/dd-badge/dd-badge.vue +2 -2
  13. package/components/dd-barcode/dd-barcode.vue +1030 -0
  14. package/components/dd-bill-detail/dd-bill-detail.vue +265 -0
  15. package/components/dd-button/dd-button.vue +17 -17
  16. package/components/dd-calendar/dd-calendar.vue +357 -0
  17. package/components/dd-canvas/dd-canvas.vue +1088 -0
  18. package/components/dd-capsule-button/dd-capsule-button.vue +6 -6
  19. package/components/dd-car-keyboard/carKeyboard.js +6 -0
  20. package/components/dd-car-keyboard/dd-car-keyboard.vue +315 -0
  21. package/components/dd-car-keyboard/props.js +19 -0
  22. package/components/dd-cascader/dd-cascader.vue +405 -0
  23. package/components/dd-cell/dd-cell.vue +50 -23
  24. package/components/dd-cell-group/dd-cell-group.vue +32 -25
  25. package/components/dd-champion-card/dd-champion-card.vue +4 -4
  26. package/components/dd-checkbox/dd-checkbox.vue +30 -39
  27. package/components/dd-checkbox-group/dd-checkbox-group.vue +67 -0
  28. package/components/dd-copy/dd-copy.vue +74 -0
  29. package/components/dd-coupon/dd-coupon.vue +368 -0
  30. package/components/dd-cropper/dd-cropper.vue +1297 -0
  31. package/components/dd-dialog/dd-dialog.vue +1 -1
  32. package/components/dd-divider/dd-divider.vue +3 -3
  33. package/components/dd-dropdown-item/dd-dropdown-item.vue +5 -5
  34. package/components/dd-empty-state/dd-empty-state.vue +1 -1
  35. package/components/dd-field/dd-field.vue +531 -106
  36. package/components/dd-form/dd-form.vue +116 -0
  37. package/components/dd-form/rules.ts +84 -0
  38. package/components/dd-goods-sku/dd-goods-sku.vue +434 -0
  39. package/components/dd-icon/dd-icon.vue +2 -2
  40. package/components/dd-image/dd-image.vue +4 -4
  41. package/components/dd-input/dd-input.vue +5 -5
  42. package/components/dd-keyboard/dd-keyboard.vue +178 -0
  43. package/components/dd-keyboard/keyboard.js +22 -0
  44. package/components/dd-keyboard/props.js +89 -0
  45. package/components/dd-link/dd-link.vue +87 -0
  46. package/components/dd-link/link.js +18 -0
  47. package/components/dd-link/props.js +44 -0
  48. package/components/dd-list-cell/dd-list-cell.vue +4 -4
  49. package/components/dd-loading/dd-loading.vue +1 -1
  50. package/components/dd-loadmore/dd-loadmore.vue +2 -2
  51. package/components/dd-markdown/dd-markdown.vue +344 -0
  52. package/components/dd-markdown/marked.esm.mjs +7 -0
  53. package/components/dd-mini-program-navbar/dd-mini-program-navbar.vue +9 -9
  54. package/components/dd-navigation/dd-navigation.vue +5 -5
  55. package/components/dd-number-keyboard/dd-number-keyboard.vue +200 -0
  56. package/components/dd-number-keyboard/numberKeyboard.js +8 -0
  57. package/components/dd-number-keyboard/props.js +24 -0
  58. package/components/dd-parse/dd-parse.vue +534 -0
  59. package/components/dd-parse/node/handler.wxs +26 -0
  60. package/components/dd-parse/node/node.vue +603 -0
  61. package/components/dd-parse/parse.js +13 -0
  62. package/components/dd-parse/parser.js +1400 -0
  63. package/components/dd-parse/props.js +57 -0
  64. package/components/dd-popover/dd-popover.vue +10 -10
  65. package/components/dd-popover-item/dd-popover-item.vue +3 -3
  66. package/components/dd-popup/dd-popup.vue +5 -5
  67. package/components/dd-poster/dd-poster.vue +695 -0
  68. package/components/dd-progress/dd-progress.vue +3 -3
  69. package/components/dd-pull-refresh/dd-pull-refresh.vue +3 -3
  70. package/components/dd-qrcode/dd-qrcode.vue +509 -0
  71. package/components/dd-qrcode/qrcode.js +1283 -0
  72. package/components/dd-radio/dd-radio.vue +19 -20
  73. package/components/dd-radio-group/dd-radio-group.vue +53 -0
  74. package/components/dd-rate/dd-rate.vue +1 -1
  75. package/components/dd-room-card/dd-room-card.vue +3 -3
  76. package/components/dd-search-bar/dd-search-bar.vue +8 -8
  77. package/components/dd-segmented-tab/dd-segmented-tab.vue +6 -6
  78. package/components/dd-signature/dd-signature.vue +513 -0
  79. package/components/dd-skeleton/dd-skeleton.vue +1 -1
  80. package/components/dd-slider/dd-slider.vue +4 -4
  81. package/components/dd-stat-card/dd-stat-card.vue +5 -5
  82. package/components/dd-step/dd-step.vue +11 -11
  83. package/components/dd-stepper/dd-stepper.vue +6 -6
  84. package/components/dd-swipe-action/dd-swipe-action.vue +1 -1
  85. package/components/dd-swipeable-tab/dd-swipeable-tab.vue +1 -1
  86. package/components/dd-tabbar-item/dd-tabbar-item.vue +8 -8
  87. package/components/dd-tag/dd-tag.vue +17 -1
  88. package/components/dd-text/dd-text.vue +250 -0
  89. package/components/dd-text/props.js +120 -0
  90. package/components/dd-text/text.js +30 -0
  91. package/components/dd-text/value.js +87 -0
  92. package/components/dd-toast/dd-toast.vue +2 -2
  93. package/components/dd-upload/dd-upload.vue +4 -4
  94. package/components/dd-workorder-card/dd-workorder-card.vue +237 -0
  95. package/index.ts +50 -9
  96. package/libs/config/color.js +16 -0
  97. package/libs/config/config.js +25 -0
  98. package/libs/config/props.js +185 -0
  99. package/libs/config/zIndex.js +20 -0
  100. package/libs/function/digit.js +167 -0
  101. package/libs/function/index.js +932 -0
  102. package/libs/function/test.js +327 -0
  103. package/libs/i18n/index.d.ts +2 -0
  104. package/libs/i18n/index.js +89 -0
  105. package/libs/i18n/locales/zh-Hans.js +86 -0
  106. package/libs/mixin/button.js +18 -0
  107. package/libs/mixin/mixin.js +44 -0
  108. package/libs/mixin/mpMixin.js +13 -0
  109. package/libs/mixin/openType.js +27 -0
  110. package/libs/utils.ts +462 -0
  111. package/libs/vue.js +3 -0
  112. package/package.json +1 -1
  113. package/scss/_dd-shared.scss +40 -0
  114. package/scss/_variables.scss +4 -1
@@ -0,0 +1,405 @@
1
+ <template>
2
+ <dd-popup
3
+ v-model="popupShow"
4
+ position="bottom"
5
+ :closeable="closeable"
6
+ :safe-area-inset-bottom="true"
7
+ :close-on-click-overlay="maskCloseAble"
8
+ :z-index="uZIndex"
9
+ @close="close"
10
+ >
11
+ <!-- column 头部:垂直步骤(ponytail: dd-steps 无 dot 模式,用默认数字圆点步骤) -->
12
+ <view v-if="headerDirection === 'column'" class="dd-cascader__head dd-cascader__head--column">
13
+ <dd-steps v-if="popupShow" direction="vertical" :active="tabsIndex">
14
+ <view
15
+ v-for="(item, index) in genTabsList"
16
+ :key="index"
17
+ class="dd-cascader__step-item"
18
+ @click="toFatherIndex(index)"
19
+ >
20
+ <dd-step :title="item.name" />
21
+ </view>
22
+ </dd-steps>
23
+ </view>
24
+ <!-- ponytail: dd-segmented-tab 无横向滚动,层级名过长时溢出;升级路径:scroll-view 包裹 -->
25
+ <view v-else class="dd-cascader__head">
26
+ <dd-segmented-tab
27
+ v-if="popupShow"
28
+ :options="genTabsList.map((item) => item.name)"
29
+ v-model="tabsIndex"
30
+ variant="text"
31
+ />
32
+ </view>
33
+ <view class="dd-cascader__box">
34
+ <view
35
+ class="dd-cascader__cols"
36
+ :class="{ 'dd-cascader__cols--change': isChange }"
37
+ :style="{ transform: optionsCols == 2 && isChange ? 'translateX(-33.3333333%)' : '' }"
38
+ >
39
+ <template v-for="(levelData, levelIndex) in levelList" :key="levelIndex">
40
+ <view
41
+ v-if="optionsCols == 2 || levelIndex == tabsIndex"
42
+ class="dd-cascader__col"
43
+ :style="{ width: optionsCols == 2 ? '33.33333%' : '750rpx' }"
44
+ >
45
+ <view class="dd-cascader__pane">
46
+ <scroll-view :scroll-y="true" style="height: 100%">
47
+ <view v-if="levelIndex === 0 || selectedValueIndexs[levelIndex - 1] !== undefined">
48
+ <dd-cell
49
+ v-for="(item, index) in levelData"
50
+ :key="index"
51
+ :title="item[labelKey]"
52
+ @click="levelChange(levelIndex, index)"
53
+ >
54
+ <template #right-icon>
55
+ <dd-icon
56
+ v-if="selectedValueIndexs[levelIndex] === index"
57
+ size="17"
58
+ name="checked"
59
+ class="dd-cascader__check"
60
+ />
61
+ </template>
62
+ </dd-cell>
63
+ </view>
64
+ </scroll-view>
65
+ </view>
66
+ </view>
67
+ </template>
68
+ </view>
69
+ </view>
70
+ <!-- 底部按钮区域 -->
71
+ <view class="dd-cascader__action">
72
+ <view class="dd-cascader__action-item">
73
+ <dd-button type="secondary" block @click="handleCancel">{{ t('dd.common.cancel') }}</dd-button>
74
+ </view>
75
+ <view class="dd-cascader__action-item">
76
+ <dd-button type="primary" block @click="handleConfirm">{{ t('dd.common.confirm') }}</dd-button>
77
+ </view>
78
+ </view>
79
+ </dd-popup>
80
+ </template>
81
+
82
+ <script setup lang="ts">
83
+ import { computed, ref, watch } from 'vue'
84
+ import { t } from '../../libs/i18n'
85
+ import DdPopup from '../dd-popup/dd-popup.vue'
86
+ import DdSteps from '../dd-steps/dd-steps.vue'
87
+ import DdStep from '../dd-step/dd-step.vue'
88
+ import DdSegmentedTab from '../dd-segmented-tab/dd-segmented-tab.vue'
89
+ import DdCell from '../dd-cell/dd-cell.vue'
90
+ import DdIcon from '../dd-icon/dd-icon.vue'
91
+ import DdButton from '../dd-button/dd-button.vue'
92
+
93
+ interface CascaderOption {
94
+ label?: string
95
+ value?: string | number
96
+ children?: CascaderOption[]
97
+ [key: string]: any
98
+ }
99
+
100
+ interface Props {
101
+ /** 通过双向绑定控制组件的弹出与收起 */
102
+ show?: boolean
103
+ /** 级联数据 */
104
+ data?: CascaderOption[]
105
+ /** 默认选中的值 */
106
+ modelValue?: Array<string | number>
107
+ /** 指定选项的值为选项对象中的哪个属性值 */
108
+ valueKey?: string
109
+ /** 指定选项标签为选项对象中的哪个属性值 */
110
+ labelKey?: string
111
+ /** 指定选项的子选项为选项对象中的哪个属性值 */
112
+ childrenKey?: string
113
+ /** 是否允许通过点击遮罩关闭Picker */
114
+ maskCloseAble?: boolean
115
+ /** 弹出的z-index值 */
116
+ zIndex?: string | number
117
+ /** 是否在选择最后一级时自动关闭并触发confirm */
118
+ autoClose?: boolean
119
+ /** 选中项目的展示方向:column 垂直方向适合文字长度过长 */
120
+ headerDirection?: 'row' | 'column'
121
+ /** 选项区域列数,支持1列和2列 */
122
+ optionsCols?: number
123
+ /** 是否显示关闭图标 */
124
+ closeable?: boolean
125
+ }
126
+
127
+ const props = withDefaults(defineProps<Props>(), {
128
+ show: false,
129
+ data: () => [],
130
+ modelValue: () => [],
131
+ valueKey: 'value',
132
+ labelKey: 'label',
133
+ childrenKey: 'children',
134
+ maskCloseAble: true,
135
+ zIndex: 0,
136
+ autoClose: false,
137
+ headerDirection: 'row',
138
+ optionsCols: 2,
139
+ closeable: true,
140
+ })
141
+
142
+ const emit = defineEmits<{
143
+ (e: 'update:modelValue', val: Array<string | number>): void
144
+ (e: 'update:show', val: boolean): void
145
+ (e: 'change', val: Array<string | number>): void
146
+ (e: 'confirm', val: Array<string | number>): void
147
+ (e: 'cancel'): void
148
+ }>()
149
+
150
+ /** 存储每一级的数据 */
151
+ const levelList = ref<CascaderOption[][]>([])
152
+ /** 存储每一级选中的索引 */
153
+ const selectedValueIndexs = ref<number[]>([])
154
+ const tabsIndex = ref(0)
155
+ const popupShow = ref(false)
156
+ /** 存储确认的值 */
157
+ const confirmValues = ref<Array<string | number>>([])
158
+
159
+ watch(
160
+ () => props.data,
161
+ () => {
162
+ initLevelList()
163
+ setDefaultValue()
164
+ },
165
+ { immediate: true },
166
+ )
167
+
168
+ watch(
169
+ () => props.show,
170
+ (val) => {
171
+ popupShow.value = val
172
+ },
173
+ )
174
+
175
+ watch(
176
+ () => props.modelValue,
177
+ () => {
178
+ setDefaultValue()
179
+ },
180
+ { immediate: true },
181
+ )
182
+
183
+ const isChange = computed(() => tabsIndex.value > 1)
184
+
185
+ const genTabsList = computed(() => {
186
+ const tabsList: { name: string }[] = [{ name: t('dd.common.pleaseChoose') }]
187
+
188
+ // 根据选中的值动态生成tabs
189
+ for (let i = 0; i < selectedValueIndexs.value.length; i++) {
190
+ if (selectedValueIndexs.value[i] !== undefined && levelList.value[i]) {
191
+ const selectedItem = levelList.value[i][selectedValueIndexs.value[i]]
192
+ if (selectedItem) {
193
+ tabsList[i] = {
194
+ name: selectedItem[props.labelKey] ?? '',
195
+ }
196
+ // 如果还有下一级,则添加"请选择"
197
+ if (
198
+ i === selectedValueIndexs.value.length - 1 &&
199
+ selectedItem[props.childrenKey] &&
200
+ selectedItem[props.childrenKey].length > 0
201
+ ) {
202
+ tabsList.push({ name: t('dd.common.pleaseChoose') })
203
+ }
204
+ }
205
+ }
206
+ }
207
+
208
+ return tabsList
209
+ })
210
+
211
+ const uZIndex = computed(() => (props.zIndex ? Number(props.zIndex) : 2000))
212
+
213
+ function getSelectedValues(): Array<string | number> {
214
+ const result: Array<string | number> = []
215
+ for (let i = 0; i < selectedValueIndexs.value.length; i++) {
216
+ const selectedIndex = selectedValueIndexs.value[i]
217
+ if (selectedIndex === undefined) continue
218
+ if (!levelList.value[i] || !levelList.value[i][selectedIndex]) continue
219
+ result.push(levelList.value[i][selectedIndex][props.valueKey])
220
+ }
221
+ return result
222
+ }
223
+
224
+ function initLevelList() {
225
+ // 初始化第一级数据
226
+ if (props.data && props.data.length > 0) {
227
+ levelList.value = [props.data]
228
+ selectedValueIndexs.value = []
229
+ }
230
+ }
231
+
232
+ function setDefaultValue() {
233
+ // 检查data是否为空
234
+ if (!props.data || props.data.length == 0) return
235
+ // 检查modelValue是否为空
236
+ if (!props.modelValue || props.modelValue.length == 0) {
237
+ confirmValues.value = []
238
+ return
239
+ }
240
+ // 根据modelValue获取indexs给selectedValueIndexs
241
+ selectedValueIndexs.value = []
242
+ levelList.value = []
243
+ let currentLevelData = props.data
244
+
245
+ for (let i = 0; i < props.modelValue.length; i++) {
246
+ const value = props.modelValue[i]
247
+ const index = currentLevelData.findIndex((item) => item[props.valueKey] === value)
248
+ levelList.value[i] = currentLevelData
249
+
250
+ if (index !== -1) {
251
+ selectedValueIndexs.value.push(index)
252
+ // 更新下一级的数据
253
+ if (currentLevelData[index][props.childrenKey]) {
254
+ currentLevelData = currentLevelData[index][props.childrenKey]
255
+ } else {
256
+ // 如果没有子级数据,则停止处理
257
+ break
258
+ }
259
+ } else {
260
+ // 如果找不到匹配项,则停止处理
261
+ break
262
+ }
263
+ }
264
+ // 同步确认值,避免"仅回显未改动时确认返回空数组"
265
+ confirmValues.value = getSelectedValues()
266
+ }
267
+
268
+ function close() {
269
+ emit('cancel')
270
+ emit('update:show', false)
271
+ popupShow.value = false
272
+ }
273
+
274
+ function levelChange(levelIndex: number, index: number) {
275
+ // 设置当前级的选中值
276
+ selectedValueIndexs.value[levelIndex] = index
277
+
278
+ // 清除后续级别的选中值
279
+ selectedValueIndexs.value.splice(levelIndex + 1)
280
+ tabsIndex.value = Math.min(tabsIndex.value, levelIndex)
281
+
282
+ // 清除后续级别的列表
283
+ levelList.value.splice(levelIndex + 1)
284
+
285
+ // 获取当前选中项
286
+ const currentItem = levelList.value[levelIndex][index]
287
+
288
+ // 如果有子级数据,则初始化下一级
289
+ if (currentItem && currentItem[props.childrenKey] && currentItem[props.childrenKey].length > 0) {
290
+ // 确保levelList数组足够长
291
+ if (levelList.value.length <= levelIndex + 1) {
292
+ levelList.value.push(currentItem[props.childrenKey])
293
+ } else {
294
+ levelList.value[levelIndex + 1] = currentItem[props.childrenKey]
295
+ }
296
+ // 切换到下一级tab
297
+ tabsIndex.value = levelIndex + 1
298
+ } else {
299
+ // 没有子级数据,说明是最后一级
300
+ if (props.autoClose) {
301
+ // 如果启用自动关闭,则触发change事件并关闭
302
+ emitChange()
303
+ handleConfirm()
304
+ } else {
305
+ // 否则只触发change事件,不关闭
306
+ emitChange(false)
307
+ }
308
+ }
309
+ }
310
+
311
+ function emitChange(closePopup = true) {
312
+ // 构造选中结果
313
+ const result = getSelectedValues()
314
+
315
+ // 更新confirmValues
316
+ confirmValues.value = [...result]
317
+
318
+ // 触发change事件,返回value数组
319
+ emit('change', confirmValues.value)
320
+
321
+ // 根据参数决定是否关闭弹窗
322
+ if (closePopup) {
323
+ close()
324
+ }
325
+ }
326
+
327
+ function handleCancel() {
328
+ close()
329
+ }
330
+
331
+ function handleConfirm() {
332
+ const values = confirmValues.value.length ? confirmValues.value : getSelectedValues()
333
+ confirmValues.value = [...values]
334
+ // 确认时触发confirm事件
335
+ emit('update:modelValue', values)
336
+ emit('confirm', values)
337
+ close()
338
+ }
339
+
340
+ // 跳转父节点
341
+ function toFatherIndex(index: number) {
342
+ tabsIndex.value = index
343
+ }
344
+ </script>
345
+
346
+ <style lang="scss" scoped>
347
+ @import '../../scss/variables';
348
+ @import '../../scss/mixins';
349
+
350
+ .dd-cascader {
351
+ &__head {
352
+ padding-top: 20rpx;
353
+ margin-bottom: 10rpx;
354
+
355
+ &--column {
356
+ padding: 30rpx 20rpx 10rpx 20rpx;
357
+ }
358
+ }
359
+
360
+ &__step-item {
361
+ padding: 10rpx 0;
362
+ }
363
+
364
+ &__box {
365
+ width: 100%;
366
+ overflow: hidden;
367
+ height: 800rpx;
368
+ }
369
+
370
+ &__cols {
371
+ display: flex;
372
+ flex-direction: row;
373
+ width: 150%;
374
+ transition: transform 0.3s ease-in-out 0s;
375
+ transform: translateX(0);
376
+ }
377
+
378
+ &__col {
379
+ height: 800rpx;
380
+ }
381
+
382
+ &__pane {
383
+ height: 100%;
384
+ padding: 10rpx;
385
+ box-sizing: border-box;
386
+ background-color: $dd-bg-section;
387
+ }
388
+
389
+ &__check {
390
+ color: $dd-primary-400;
391
+ }
392
+
393
+ &__action {
394
+ display: flex;
395
+ flex-direction: row;
396
+ justify-content: space-between;
397
+ border-top: 1px solid $dd-border-default;
398
+ }
399
+
400
+ &__action-item {
401
+ flex: 1;
402
+ padding: 20rpx;
403
+ }
404
+ }
405
+ </style>
@@ -5,12 +5,12 @@
5
5
  `dd-cell--${size}`,
6
6
  {
7
7
  'dd-cell--center': center,
8
- 'dd-cell--required': required,
9
- 'dd-cell--borderless': borderless,
10
- 'dd-cell--link': isLink,
8
+ 'dd-cell--required': requiredState,
9
+ 'dd-cell--borderless': !border,
10
+ 'dd-cell--clickable': clickableState,
11
11
  },
12
12
  ]"
13
- :hover-class="isLink ? 'dd-cell--active' : ''"
13
+ :hover-class="clickableState ? 'dd-cell--active' : ''"
14
14
  :hover-stay-time="100"
15
15
  @click="handleClick"
16
16
  >
@@ -19,9 +19,11 @@
19
19
  <dd-icon v-if="icon" :name="icon" class="dd-cell__icon-text" />
20
20
  </slot>
21
21
  </view>
22
- <view v-if="required" class="dd-cell__required"><text>*</text></view>
22
+ <view v-if="requiredState" class="dd-cell__required"><text>*</text></view>
23
23
  <view class="dd-cell__content">
24
- <text v-if="title" class="dd-cell__title">{{ title }}</text>
24
+ <view v-if="title || $slots.title" class="dd-cell__title" :style="titleStyle">
25
+ <slot name="title">{{ title }}</slot>
26
+ </view>
25
27
  <text v-if="label || $slots.label" class="dd-cell__label">
26
28
  <slot name="label">{{ label }}</slot>
27
29
  </text>
@@ -41,7 +43,7 @@
41
43
  </template>
42
44
 
43
45
  <script setup lang="ts">
44
- import { useSlots } from 'vue'
46
+ import { computed } from 'vue'
45
47
  import DdIcon from '../dd-icon/dd-icon.vue'
46
48
 
47
49
  interface Props {
@@ -49,12 +51,18 @@ interface Props {
49
51
  label?: string
50
52
  value?: string
51
53
  icon?: string
52
- size?: 'sm' | 'md'
54
+ size?: 'normal' | 'large'
53
55
  isLink?: boolean
54
56
  arrowDirection?: 'left' | 'right' | 'up' | 'down'
55
- required?: boolean
57
+ required?: boolean | 'auto'
56
58
  center?: boolean
57
- borderless?: boolean
59
+ border?: boolean
60
+ /** 开启点击反馈样式(click 事件总是抛出,不受此 prop 限制) */
61
+ clickable?: boolean
62
+ /** 点击后经 uni.* 跳转的页面路径 */
63
+ url?: string
64
+ linkType?: 'navigateTo' | 'redirectTo' | 'reLaunch' | 'switchTab'
65
+ titleStyle?: string
58
66
  }
59
67
 
60
68
  const props = withDefaults(defineProps<Props>(), {
@@ -62,22 +70,43 @@ const props = withDefaults(defineProps<Props>(), {
62
70
  label: '',
63
71
  value: '',
64
72
  icon: '',
65
- size: 'md',
73
+ size: 'normal',
66
74
  isLink: false,
67
75
  arrowDirection: 'right',
68
76
  required: false,
69
77
  center: false,
70
- borderless: false,
78
+ border: true,
79
+ clickable: false,
80
+ url: '',
81
+ linkType: 'navigateTo',
82
+ titleStyle: '',
71
83
  })
72
84
 
73
85
  const emit = defineEmits<{ (e: 'click', val: Event): void }>()
74
86
 
75
- const slots = useSlots()
76
- void slots
87
+ // cell 自身 required='auto' 等价 false(dd-field 复用时 auto 由其 rules 决定)
88
+ const requiredState = computed(() => props.required === true)
89
+ const clickableState = computed(() => props.clickable || props.isLink || !!props.url)
90
+
91
+ function navigate() {
92
+ const opts = { url: props.url }
93
+ switch (props.linkType) {
94
+ case 'redirectTo':
95
+ uni.redirectTo(opts)
96
+ break
97
+ case 'reLaunch':
98
+ uni.reLaunch(opts)
99
+ break
100
+ case 'switchTab':
101
+ uni.switchTab(opts)
102
+ break
103
+ default:
104
+ uni.navigateTo(opts)
105
+ }
106
+ }
77
107
 
78
- // 仅当 isLink 时才向外抛 click
79
108
  function handleClick(e: Event) {
80
- if (!props.isLink) return
109
+ if (props.url) navigate()
81
110
  emit('click', e)
82
111
  }
83
112
  </script>
@@ -92,17 +121,17 @@ function handleClick(e: Event) {
92
121
  align-items: flex-start;
93
122
  box-sizing: border-box;
94
123
  width: 100%;
95
- padding: 0 24rpx 0 32rpx;
124
+ padding: 0 24rpx 0 $dd-space-4;
96
125
  background: $dd-bg-elevated;
97
126
  font-size: $dd-font-size-body;
98
127
  color: $dd-text-primary;
99
128
  @include dd-hairline-bottom($dd-border-subtle);
100
129
 
101
- &--sm {
130
+ &--normal {
102
131
  min-height: 96rpx;
103
132
  }
104
133
 
105
- &--md {
134
+ &--large {
106
135
  min-height: 112rpx;
107
136
  }
108
137
 
@@ -138,7 +167,7 @@ function handleClick(e: Event) {
138
167
  color: $dd-error-500;
139
168
  font-size: $dd-font-size-body;
140
169
  margin-right: 4rpx;
141
- line-height: 1.5;
170
+ line-height: $dd-line-height-caption;
142
171
  text {
143
172
  line-height: 1;
144
173
  }
@@ -180,9 +209,7 @@ function handleClick(e: Event) {
180
209
  }
181
210
 
182
211
  &__arrow {
183
- font-size: 32rpx;
184
- color: $dd-text-tertiary;
185
- line-height: 1;
212
+ font-size: $dd-font-size-h4;
186
213
 
187
214
  &--right {
188
215
  transform: rotate(0deg);
@@ -1,27 +1,28 @@
1
1
  <template>
2
- <view class="dd-cell-group">
3
- <view v-if="title || $slots.title" class="dd-cell-group__title">
2
+ <view>
3
+ <view v-if="title || $slots.title" class="dd-cell-group__title" :class="{ 'dd-cell-group__title--inset': inset }">
4
4
  <slot name="title">{{ title }}</slot>
5
5
  </view>
6
- <view class="dd-cell-group__body">
6
+ <view class="dd-cell-group" :class="{ 'dd-cell-group--inset': inset, 'dd-cell-group--border': border && !inset }">
7
7
  <slot></slot>
8
8
  </view>
9
9
  </view>
10
10
  </template>
11
11
 
12
12
  <script setup lang="ts">
13
- import { useSlots } from 'vue'
14
-
15
13
  interface Props {
16
14
  title?: string
15
+ /** 默认通栏;inset = 圆角卡片内嵌模式 */
16
+ inset?: boolean
17
+ /** 通栏模式下的首尾外框发丝线 */
18
+ border?: boolean
17
19
  }
18
20
 
19
21
  withDefaults(defineProps<Props>(), {
20
22
  title: '',
23
+ inset: false,
24
+ border: true,
21
25
  })
22
-
23
- const slots = useSlots()
24
- void slots
25
26
  </script>
26
27
 
27
28
  <style lang="scss" scoped>
@@ -29,28 +30,34 @@ void slots
29
30
  @import '../../scss/mixins';
30
31
 
31
32
  .dd-cell-group {
32
- display: flex;
33
- flex-direction: column;
34
- width: 100%;
35
-
36
- &__title {
37
- padding: 32rpx 32rpx 16rpx;
38
- font-size: $dd-font-size-caption;
39
- color: $dd-text-tertiary;
33
+ background: $dd-bg-elevated;
34
+
35
+ :deep(.dd-cell:last-child),
36
+ :deep(.dd-list-cell:last-child) {
37
+ &::after {
38
+ display: none;
39
+ }
40
40
  }
41
41
 
42
- &__body {
43
- background: $dd-bg-elevated;
42
+ &--inset {
44
43
  border-radius: $dd-radius-lg;
45
44
  overflow: hidden;
45
+ margin: 0 24rpx;
46
+ }
46
47
 
47
- // 去除最后一个子元素的底边框, 避免溢出到圆角外
48
- :deep(.dd-cell:last-child),
49
- :deep(.dd-list-cell:last-child) {
50
- &::after {
51
- display: none;
52
- }
53
- }
48
+ &--border {
49
+ @include dd-hairline-top($dd-border-subtle);
50
+ @include dd-hairline-bottom($dd-border-subtle);
51
+ }
52
+ }
53
+
54
+ .dd-cell-group__title {
55
+ padding: 32rpx 32rpx 16rpx;
56
+ font-size: $dd-font-size-caption;
57
+ color: $dd-text-tertiary;
58
+
59
+ &--inset {
60
+ padding: 32rpx 24rpx 16rpx;
54
61
  }
55
62
  }
56
63
  </style>
@@ -143,7 +143,7 @@ function onClick() {
143
143
  box-sizing: border-box;
144
144
 
145
145
  &--sm {
146
- border-width: 4rpx;
146
+ border-width: $dd-space-1;
147
147
  }
148
148
  }
149
149
 
@@ -211,8 +211,8 @@ function onClick() {
211
211
  &--sm {
212
212
  position: static;
213
213
  transform: none;
214
- width: 48rpx;
215
- height: 48rpx;
214
+ width: $dd-size-icon-lg;
215
+ height: $dd-size-icon-lg;
216
216
  flex-shrink: 0;
217
217
  }
218
218
  }
@@ -229,7 +229,7 @@ function onClick() {
229
229
  font-weight: 800;
230
230
  color: #FFD700;
231
231
  flex-shrink: 0;
232
- width: 48rpx;
232
+ width: $dd-size-icon-lg;
233
233
  text-align: center;
234
234
  }
235
235