stellar-ui-plus 1.19.2 → 1.20.1

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 (57) hide show
  1. package/components/ste-barcode/encode.ts +16 -16
  2. package/components/ste-checkbox/ste-checkbox.vue +157 -63
  3. package/components/ste-date-user/ATTRIBUTES.md +9 -0
  4. package/components/ste-date-user/README.md +65 -0
  5. package/components/ste-date-user/config.json +5 -0
  6. package/components/ste-date-user/props.ts +6 -0
  7. package/components/ste-date-user/ste-date-user.easycom.json +42 -0
  8. package/components/ste-date-user/ste-date-user.vue +135 -0
  9. package/components/ste-dropdown-menu/props.ts +24 -23
  10. package/components/ste-dropdown-menu/ste-dropdown-menu.scss +1 -1
  11. package/components/ste-dropdown-menu/ste-dropdown-menu.vue +1 -1
  12. package/components/ste-filter-tool/ATTRIBUTES.md +17 -0
  13. package/components/ste-filter-tool/README.md +101 -0
  14. package/components/ste-filter-tool/config.json +5 -0
  15. package/components/ste-filter-tool/props.ts +31 -0
  16. package/components/ste-filter-tool/ste-filter-tool.easycom.json +72 -0
  17. package/components/ste-filter-tool/ste-filter-tool.vue +290 -0
  18. package/components/ste-goods-info/ATTRIBUTES.md +22 -0
  19. package/components/ste-goods-info/README.md +162 -0
  20. package/components/ste-goods-info/config.json +5 -0
  21. package/components/ste-goods-info/props.ts +73 -0
  22. package/components/ste-goods-info/ste-goods-info.easycom.json +108 -0
  23. package/components/ste-goods-info/ste-goods-info.vue +186 -0
  24. package/components/ste-goods-list/ATTRIBUTES.md +10 -0
  25. package/components/ste-goods-list/README.md +155 -0
  26. package/components/ste-goods-list/config.json +5 -0
  27. package/components/ste-goods-list/props.ts +9 -0
  28. package/components/ste-goods-list/ste-goods-list.easycom.json +36 -0
  29. package/components/ste-goods-list/ste-goods-list.vue +116 -0
  30. package/components/ste-icon/iconfont.css +6 -6
  31. package/components/ste-navbar/ATTRIBUTES.md +25 -0
  32. package/components/ste-navbar/README.md +96 -0
  33. package/components/ste-navbar/config.json +5 -0
  34. package/components/ste-navbar/props.ts +17 -0
  35. package/components/ste-navbar/ste-navbar.easycom.json +129 -0
  36. package/components/ste-navbar/ste-navbar.vue +151 -0
  37. package/components/ste-popup/ste-popup.vue +2 -2
  38. package/components/ste-price/ste-price.vue +2 -2
  39. package/components/ste-qrcode/uqrcode.js +33 -33
  40. package/components/ste-search/ATTRIBUTES.md +1 -0
  41. package/components/ste-search/props.ts +127 -122
  42. package/components/ste-search/ste-search.easycom.json +7 -0
  43. package/components/ste-search/ste-search.vue +1 -0
  44. package/components/ste-search-box/ATTRIBUTES.md +18 -0
  45. package/components/ste-search-box/README.md +66 -0
  46. package/components/ste-search-box/config.json +5 -0
  47. package/components/ste-search-box/props.ts +39 -0
  48. package/components/ste-search-box/ste-search-box.easycom.json +87 -0
  49. package/components/ste-search-box/ste-search-box.vue +173 -0
  50. package/index.ts +12 -2
  51. package/package.json +4 -1
  52. package/types/components.d.ts +12 -2
  53. package/types/dayjs.d.ts +429 -0
  54. package/types/index.d.ts +2 -3
  55. package/types/refComponents.d.ts +12 -2
  56. package/utils/utils.ts +13 -1
  57. package/components/ste-donut-chart/ATTRIBUTES.md +0 -33
@@ -172,7 +172,7 @@ export function stringToCode128(text: string) {
172
172
 
173
173
  codes = codes.concat(codesForChar(b1, b2, barc.currcs))
174
174
  // code C takes 2 chars each time
175
- if (barc.currcs === CODESET.C)
175
+ if (barc.currcs === CODESET.C)
176
176
  i++
177
177
  }
178
178
 
@@ -203,7 +203,7 @@ export function stringToCode128(text: string) {
203
203
  function perhapsCodeC(bytes: number[], codeset: number) {
204
204
  for (let i = 0; i < bytes.length; i++) {
205
205
  const b = bytes[i]
206
- if ((b < 48 || b > 57) && b !== CHAR_TILDE)
206
+ if ((b < 48 || b > 57) && b !== CHAR_TILDE)
207
207
  return codeset
208
208
  }
209
209
  return CODESET.C
@@ -221,13 +221,13 @@ export function stringToCode128(text: string) {
221
221
  if (chr2 === -1) {
222
222
  shifter === SET_CODEB
223
223
  currcs = CODESET.B
224
- }
224
+ }
225
225
  else if (chr2 !== -1 && !charCompatible(chr2, currcs)) {
226
226
  // need to check ahead as well
227
227
  if (charCompatible(chr2, CODESET.A)) {
228
228
  shifter = SET_CODEA
229
229
  currcs = CODESET.A
230
- }
230
+ }
231
231
  else {
232
232
  shifter = SET_CODEB
233
233
  currcs = CODESET.B
@@ -235,7 +235,7 @@ export function stringToCode128(text: string) {
235
235
  }
236
236
  }
237
237
  /* eslint-enable no-unused-expressions */
238
- }
238
+ }
239
239
  else {
240
240
  // if there is a next char AND that next char is also not compatible
241
241
 
@@ -251,11 +251,11 @@ export function stringToCode128(text: string) {
251
251
  currcs = CODESET.A
252
252
  break
253
253
  }
254
- }
254
+ }
255
255
  else {
256
256
  // no need to shift code sets, a temporary SHIFT will suffice
257
257
  shifter = SET_SHIFT
258
- }
258
+ }
259
259
  }
260
260
 
261
261
  // ok some type of shift is nessecary
@@ -263,12 +263,12 @@ export function stringToCode128(text: string) {
263
263
  result.push(shifter)
264
264
  // result.push(codeValue(chr2));-----------------------------------
265
265
  result.push(codeValue(chr1))
266
- }
266
+ }
267
267
  else {
268
268
  if (currcs === CODESET.C) {
269
269
  // include next as well
270
270
  result.push(codeValue(chr1, chr2))
271
- }
271
+ }
272
272
  else {
273
273
  result.push(codeValue(chr1))
274
274
  }
@@ -284,19 +284,19 @@ function codeValue(chr1: number, chr2: any = undefined) {
284
284
  if (typeof chr2 === 'undefined')
285
285
  return chr1 >= 32 ? chr1 - 32 : chr1 + 64
286
286
  else
287
- return Number.parseInt(String.fromCharCode(chr1) + String.fromCharCode(chr2))
287
+ return Number.parseInt(String.fromCharCode(chr1) + String.fromCharCode(chr2))
288
288
  }
289
289
 
290
290
  function charCompatible(chr: number, codeset: number) {
291
291
  const csa = codeSetAllowedFor(chr)
292
- if (csa === CODESET.ANY)
292
+ if (csa === CODESET.ANY)
293
293
  return true
294
294
  // if we need to change from current
295
- if (csa === CODESET.AB)
295
+ if (csa === CODESET.AB)
296
296
  return true
297
- if (csa === CODESET.A && codeset === CODESET.A)
297
+ if (csa === CODESET.A && codeset === CODESET.A)
298
298
  return true
299
- if (csa === CODESET.B && codeset === CODESET.B)
299
+ if (csa === CODESET.B && codeset === CODESET.B)
300
300
  return true
301
301
  return false
302
302
  }
@@ -305,11 +305,11 @@ function codeSetAllowedFor(chr: number) {
305
305
  if (chr >= 48 && chr <= 57) {
306
306
  // 0-9
307
307
  return CODESET.ANY
308
- }
308
+ }
309
309
  else if (chr >= 32 && chr <= 95) {
310
310
  // 0-9 A-Z
311
311
  return CODESET.AB
312
- }
312
+ }
313
313
  else {
314
314
  // if non printable
315
315
  return chr < 32 ? CODESET.A : CODESET.B
@@ -1,11 +1,12 @@
1
1
  <script lang="ts" setup>
2
- import { useSlots, computed, ref, type CSSProperties } from 'vue';
2
+ import { useSlots, computed, ref, nextTick, markRaw, type CSSProperties } from 'vue';
3
3
  import { useColorStore } from '../../store/color';
4
4
  let { getColor } = useColorStore();
5
5
  import utils from '../../utils/utils';
6
6
  import propsData, { CHECKBOX_KEY, type CheckboxEmits } from './props';
7
7
  import type { CheckboxGroupProps } from '../ste-checkbox-group/props';
8
8
  import { useInject } from '../../utils/mixin';
9
+
9
10
  const componentName = `ste-checkbox`;
10
11
  defineOptions({
11
12
  name: componentName,
@@ -13,13 +14,21 @@ defineOptions({
13
14
  virtualHost: true,
14
15
  },
15
16
  });
17
+
16
18
  const props = defineProps(propsData);
17
19
  const emits = defineEmits<CheckboxEmits>();
18
20
  const slots = useSlots();
19
21
 
22
+ // 静态配置使用 markRaw 避免不必要的响应式
23
+ const staticConfig = markRaw({
24
+ defaultIconSizeMultiplier: 0.8,
25
+ borderWidth: 2,
26
+ });
27
+
20
28
  const Parent = useInject<{ props: Required<CheckboxGroupProps>; updateValue: (value: any[]) => void }>(CHECKBOX_KEY);
21
29
  const parentProps = computed(() => Parent?.parent?.props);
22
30
 
31
+ // 基础计算属性
23
32
  const cmpReadonly = computed(() => getDefaultData('readonly', false));
24
33
  const cmpShape = computed(() => getDefaultData('shape', 'circle'));
25
34
  const cmpIconSize = computed(() => getDefaultData('iconSize', 36));
@@ -33,15 +42,29 @@ const cmpMarginLeft = computed(() => getDefaultData('marginLeft', '0'));
33
42
  const cmpMarginRight = computed(() => getDefaultData('marginRight', '0'));
34
43
  const cmpColumnGap = computed(() => getDefaultData('columnGap', '16'));
35
44
 
36
- const cmpSlotProps = computed(() => ({ checked: cmpChecked.value, disabled: cmpDisabled.value, readonly: cmpReadonly.value }));
45
+ const cmpSlotProps = computed(() => ({
46
+ checked: cmpChecked.value,
47
+ disabled: cmpDisabled.value,
48
+ readonly: cmpReadonly.value,
49
+ }));
50
+
51
+ // 拆分计算属性依赖 - 静态样式
52
+ const baseRootStyle = computed(() => ({
53
+ fontSize: `var(--font-size-${cmpTextSize.value},${utils.formatPx(cmpTextSize.value)})`,
54
+ marginLeft: utils.formatPx(cmpMarginLeft.value),
55
+ marginRight: utils.formatPx(cmpMarginRight.value),
56
+ }));
57
+
58
+ // 拆分计算属性依赖 - 动态样式
59
+ const dynamicRootStyle = computed(() => ({
60
+ color: cmpChecked.value ? cmpTextActiveColor.value : cmpTextInactiveColor.value,
61
+ flexDirection: cmpTextPosition.value == 'right' ? 'row' : 'row-reverse',
62
+ }));
63
+
64
+ // 拆分计算属性依赖 - 交互样式
65
+ const interactiveRootStyle = computed(() => {
66
+ const style: CSSProperties = {};
37
67
 
38
- const cmpRootStyle = computed(() => {
39
- let style: CSSProperties = {};
40
- style['fontSize'] = `var(--font-size-${cmpTextSize.value},${utils.formatPx(cmpTextSize.value)})`;
41
- style['color'] = cmpChecked.value ? cmpTextActiveColor.value : cmpTextInactiveColor.value;
42
- style['flexDirection'] = cmpTextPosition.value == 'right' ? 'row' : 'row-reverse';
43
- style['marginLeft'] = utils.formatPx(cmpMarginLeft.value);
44
- style['marginRight'] = utils.formatPx(cmpMarginRight.value);
45
68
  // #ifdef H5
46
69
  if (cmpDisabled.value || cmpReadonly.value) {
47
70
  style['cursor'] = 'not-allowed';
@@ -51,27 +74,55 @@ const cmpRootStyle = computed(() => {
51
74
  style['cursor'] = 'pointer';
52
75
  }
53
76
  // #endif
77
+
54
78
  if (cmpTextDisabled.value) {
55
79
  style['pointerEvents'] = 'none';
56
80
  }
81
+
57
82
  return style;
58
83
  });
59
84
 
60
- const cmpIconStyle = computed(() => {
61
- let style: CSSProperties = {};
62
- style['marginRight'] = utils.formatPx(cmpColumnGap.value);
63
- return style;
85
+ // 合并所有根样式
86
+ const cmpRootStyle = computed(() => ({
87
+ ...baseRootStyle.value,
88
+ ...dynamicRootStyle.value,
89
+ ...interactiveRootStyle.value,
90
+ }));
91
+
92
+ // 图标样式(相对简单,保持原样)
93
+ const cmpIconStyle = computed(() => ({
94
+ marginRight: utils.formatPx(cmpColumnGap.value),
95
+ }));
96
+
97
+ // 拆分输入框样式 - 基础样式
98
+ const baseInputStyle = computed(() => ({
99
+ borderRadius: cmpShape.value == 'circle' ? '50%' : '0',
100
+ width: `var(--font-size-${cmpIconSize.value},${utils.formatPx(cmpIconSize.value)})`,
101
+ height: `var(--font-size-${cmpIconSize.value},${utils.formatPx(cmpIconSize.value)})`,
102
+ lineHeight: `var(--font-size-${cmpIconSize.value},${utils.formatPx(cmpIconSize.value)})`,
103
+ columnGap: slots.default ? undefined : 0,
104
+ }));
105
+
106
+ // 拆分输入框样式 - 动态样式
107
+ const dynamicInputStyle = computed(() => ({
108
+ border: `${utils.formatPx(staticConfig.borderWidth)} solid ${cmpChecked.value ? cmpCheckedColor.value : '#BBBBBB'}`,
109
+ background: cmpChecked.value ? cmpCheckedColor.value : '#FFFFFF',
110
+ }));
111
+
112
+ // 拆分输入框样式 - 禁用状态样式
113
+ const disabledInputStyle = computed(() => {
114
+ if (!cmpDisabled.value) return {};
115
+
116
+ return {
117
+ background: '#eeeeee',
118
+ borderColor: '#bbbbbb',
119
+ };
64
120
  });
65
121
 
66
- const cmpInputStyle = computed(() => {
67
- let style: CSSProperties = {};
68
- // 没有icon 则默认样式
69
- style['borderRadius'] = cmpShape.value == 'circle' ? '50%' : '0';
70
- style['border'] = `${utils.formatPx(2)} solid ${cmpChecked.value ? cmpCheckedColor.value : '#BBBBBB'}`;
71
- style['background'] = cmpChecked.value ? cmpCheckedColor.value : '#FFFFFF';
72
- style['width'] = `var(--font-size-${cmpIconSize.value},${utils.formatPx(cmpIconSize.value)})`;
73
- style['height'] = `var(--font-size-${cmpIconSize.value},${utils.formatPx(cmpIconSize.value)})`;
74
- style['lineHeight'] = `var(--font-size-${cmpIconSize.value},${utils.formatPx(cmpIconSize.value)})`;
122
+ // 拆分输入框样式 - 交互样式
123
+ const interactiveInputStyle = computed(() => {
124
+ const style: CSSProperties = {};
125
+
75
126
  // #ifdef H5
76
127
  if (cmpDisabled.value || cmpReadonly.value) {
77
128
  style['cursor'] = 'not-allowed';
@@ -79,18 +130,18 @@ const cmpInputStyle = computed(() => {
79
130
  style['cursor'] = 'pointer';
80
131
  }
81
132
  // #endif
82
- if (cmpDisabled.value) {
83
- style['background'] = '#eeeeee';
84
- style['borderColor'] = '#bbbbbb';
85
- }
86
133
 
87
- // 在没有使用插槽内容时去掉边距
88
- if (!slots.default) {
89
- style['columnGap'] = 0;
90
- }
91
134
  return style;
92
135
  });
93
136
 
137
+ // 合并所有输入框样式
138
+ const cmpInputStyle = computed(() => ({
139
+ ...baseInputStyle.value,
140
+ ...dynamicInputStyle.value,
141
+ ...disabledInputStyle.value,
142
+ ...interactiveInputStyle.value,
143
+ }));
144
+
94
145
  const cmpChecked = computed(() => {
95
146
  let v = num.value && parentProps.value ? parentProps.value.modelValue.includes(props.name) : props.modelValue;
96
147
  return v;
@@ -106,45 +157,88 @@ const cmpDisabled = computed(() => {
106
157
  }
107
158
  return disabled;
108
159
  });
160
+
109
161
  // 强制更新选中状态
110
162
  let num = ref(1);
111
- async function click() {
112
- if (!cmpDisabled.value && !cmpReadonly.value) {
113
- let next = true;
114
- const stop = new Promise((resolve, reject) => {
115
- emits(
116
- 'click',
117
- props.modelValue,
118
- () => (next = false),
119
- () => resolve(props.modelValue),
120
- () => reject()
121
- );
122
- });
123
- if (!next) {
124
- try {
125
- await stop;
126
- } catch (e) {
127
- return;
128
- }
163
+
164
+ // 批处理更新相关
165
+ const isBatchUpdating = ref(false);
166
+ const pendingUpdate = ref(false);
167
+
168
+ // 批处理更新函数
169
+ const batchedUpdate = async (updateFn: () => Promise<void>) => {
170
+ if (isBatchUpdating.value) {
171
+ pendingUpdate.value = true;
172
+ return;
173
+ }
174
+
175
+ isBatchUpdating.value = true;
176
+
177
+ try {
178
+ await updateFn();
179
+ } finally {
180
+ await nextTick();
181
+ isBatchUpdating.value = false;
182
+
183
+ // 处理待处理的更新
184
+ if (pendingUpdate.value) {
185
+ pendingUpdate.value = false;
186
+ // 如果有待处理的更新,延迟一帧再处理
187
+ requestAnimationFrame(() => {
188
+ if (!isBatchUpdating.value) {
189
+ handleClick();
190
+ }
191
+ });
129
192
  }
193
+ }
194
+ };
130
195
 
131
- let value: boolean | any[];
132
- if (parentProps.value) {
133
- value = parentProps.value.modelValue;
134
- if (cmpChecked.value) {
135
- value = value.filter(value => value != props.name);
136
- } else {
137
- value.push(props.name);
138
- }
139
- Parent.parent?.updateValue(value);
140
- num.value++;
196
+ // 实际的点击处理逻辑
197
+ const handleClick = async () => {
198
+ if (cmpDisabled.value || cmpReadonly.value) {
199
+ return;
200
+ }
201
+
202
+ let next = true;
203
+ const stop = new Promise((resolve, reject) => {
204
+ emits(
205
+ 'click',
206
+ props.modelValue,
207
+ () => (next = false),
208
+ () => resolve(props.modelValue),
209
+ () => reject()
210
+ );
211
+ });
212
+
213
+ if (!next) {
214
+ try {
215
+ await stop;
216
+ } catch (e) {
217
+ return;
218
+ }
219
+ }
220
+
221
+ let value: boolean | any[];
222
+ if (parentProps.value) {
223
+ // 使用浅拷贝避免直接修改原数组
224
+ value = [...parentProps.value.modelValue];
225
+ if (cmpChecked.value) {
226
+ value = value.filter(v => v !== props.name);
141
227
  } else {
142
- value = !cmpChecked.value;
143
- emits('update:modelValue', !cmpChecked.value);
228
+ value.push(props.name);
144
229
  }
145
- emits('change', value);
230
+ Parent.parent?.updateValue(value);
231
+ num.value++;
232
+ } else {
233
+ value = !cmpChecked.value;
234
+ emits('update:modelValue', value);
146
235
  }
147
- }
236
+ emits('change', value);
237
+ };
238
+
239
+ const click = () => {
240
+ batchedUpdate(handleClick);
241
+ };
148
242
 
149
243
  type PropsKeyTypee = keyof typeof props;
150
244
  function getDefaultData(key: PropsKeyTypee, value: any) {
@@ -167,7 +261,7 @@ function getDefaultData(key: PropsKeyTypee, value: any) {
167
261
  <view class="icon" :style="[cmpIconStyle]">
168
262
  <slot name="icon" :slotProps="cmpSlotProps">
169
263
  <view class="input-icon" :style="[cmpInputStyle]">
170
- <ste-icon v-if="cmpChecked && cmpIconSize" :size="cmpIconSize * 0.8" code="&#xe67a;" :color="cmpDisabled ? '#bbbbbb' : '#fff'" bold></ste-icon>
264
+ <ste-icon v-if="cmpChecked && cmpIconSize" :size="cmpIconSize * staticConfig.defaultIconSizeMultiplier" code="&#xe67a;" :color="cmpDisabled ? '#bbbbbb' : '#fff'" bold />
171
265
  </view>
172
266
  </slot>
173
267
  </view>
@@ -0,0 +1,9 @@
1
+ #### Props
2
+ | 属性名 | 说明 | 类型 | 默认值 | 可选值 | 支持版本 |
3
+ | ----- | ----- | --- | ------- | ------ | -------- |
4
+ | `type` | 组件类型 | `String` | `date` | `date`:日期<br/>`user`:人员 | - |
5
+ | `date` | 日期 | `String` | `new Date()` | - | - |
6
+ | `avatar` | 头像 | `String` | `` | - | - |
7
+ | `nickname` | 昵称 | `String` | `` | - | - |
8
+
9
+
@@ -0,0 +1,65 @@
1
+ # DateUser 人员信息以及日期
2
+
3
+ 提供日期和用户信息展示。
4
+
5
+ ---$
6
+
7
+ ## 代码演示
8
+
9
+ ### 日期类型
10
+
11
+ - 通过 `type`设置组件类型,默认为`date`
12
+ - 通过 `date`设置日期时间,默认为`当天`
13
+
14
+ ```html
15
+ <template>
16
+ <ste-date-user date="2025-10-01"></ste-date-user>
17
+ </template>
18
+ ```
19
+
20
+ ### 返回按钮配置
21
+
22
+ - 通过 `type`设置组件类型,值为`user`
23
+ - 通过 `avatar` 属性来设置头像,默认``
24
+ - 通过 `desc` 插槽来设置用户描述,默认``
25
+
26
+ ```html
27
+ <template>
28
+ <ste-date-user type="user" avatar="https://image.whzb.com/chain/StellarUI/图片.jpg" nickname="张三">
29
+ <template v-slot:desc>
30
+ <view class="desc">
31
+ <view class="title">店长</view>
32
+ <ste-icon code="&#xe6c7;" color="#0275FF" size="15"></ste-icon>
33
+ </view>
34
+ </template>
35
+ </ste-date-user>
36
+ </template>
37
+
38
+ <style>
39
+ .desc {
40
+ display: flex;
41
+ align-items: center;
42
+ .title {
43
+ font-size: 24rpx;
44
+ color: #0275ff;
45
+ margin: 4rpx;
46
+ margin-right: 14rpx;
47
+ }
48
+ }
49
+ </style>
50
+ ```
51
+
52
+ ---$
53
+
54
+ ### API
55
+
56
+ <!-- props -->
57
+
58
+ #### Slots
59
+
60
+ | 插槽名 | 说明 | 插槽参数 | 支持版本 |
61
+ | ------ | -------- | -------- | -------- |
62
+ | `desc` | 用户描述 | - | - |
63
+
64
+ ---$
65
+ {{qinpengfei}}
@@ -0,0 +1,5 @@
1
+ {
2
+ "group": "业务组件",
3
+ "title": "DateUser 人员信息以及日期",
4
+ "icon": "https://image.whzb.com/chain/StellarUI/组件图标/loading.png"
5
+ }
@@ -0,0 +1,6 @@
1
+ export default {
2
+ type: { type: String, default: 'date' },
3
+ date: { type: String, default: new Date() },
4
+ avatar: { type: String, default: '' },
5
+ nickname: { type: String, default: '' },
6
+ };
@@ -0,0 +1,42 @@
1
+ {
2
+ "name": "ste-date-user",
3
+ "description": "提供日期和用户信息展示。",
4
+ "example": "<ste-date-user></ste-date-user>",
5
+ "tutorial": "https://stellar-ui.intecloud.com.cn/plus/#/?active=date-user",
6
+ "attributes": [
7
+ {
8
+ "name": "type",
9
+ "description": "组件类型",
10
+ "type": "String",
11
+ "default": "date",
12
+ "values": [
13
+ {
14
+ "name": "date",
15
+ "description": "日期"
16
+ },
17
+ {
18
+ "name": "user",
19
+ "description": "人员"
20
+ }
21
+ ]
22
+ },
23
+ {
24
+ "name": "date",
25
+ "description": "日期",
26
+ "type": "String",
27
+ "default": "new Date()"
28
+ },
29
+ {
30
+ "name": "avatar",
31
+ "description": "头像",
32
+ "type": "String",
33
+ "default": ""
34
+ },
35
+ {
36
+ "name": "nickname",
37
+ "description": "昵称",
38
+ "type": "String",
39
+ "default": ""
40
+ }
41
+ ]
42
+ }
@@ -0,0 +1,135 @@
1
+ <script setup lang="ts">
2
+ import { ref, defineComponent, onMounted } from 'vue';
3
+ import { getDateInfo } from '@swjs/chinese-holidays';
4
+ import propsData from './props';
5
+ defineComponent({
6
+ name: 'ste-date-user',
7
+ });
8
+
9
+ const props = defineProps(propsData);
10
+ let time: any = ref(props.date);
11
+ let day = ref('');
12
+ let year = ref('');
13
+ onMounted(async () => {
14
+ time.value = await getDateInfo(time.value);
15
+ let date = time.value.date.split('-');
16
+ day.value = date[date.length - 1];
17
+ year.value = `${date[0]}年${date[1]}月`;
18
+ });
19
+ </script>
20
+
21
+ <template>
22
+ <view class="ste-date-user-root">
23
+ <view class="box">
24
+ <template v-if="type == 'date'">
25
+ <view class="left">
26
+ <view class="day">{{ day }}</view>
27
+ </view>
28
+ <view class="right">
29
+ <view class="top">
30
+ <view class="year">{{ year }}</view>
31
+ </view>
32
+ <view class="bottom">
33
+ <view class="time">{{ time.day }}</view>
34
+ <view class="line" v-if="time.type == 3"></view>
35
+ <view class="time" v-if="time.type == 3">{{ time.name }}</view>
36
+ </view>
37
+ </view>
38
+ </template>
39
+ <template v-if="type == 'user'">
40
+ <view class="left">
41
+ <view class="image">
42
+ <ste-image :width="80" :height="80" :src="avatar"></ste-image>
43
+ </view>
44
+ </view>
45
+ <view class="right">
46
+ <view class="top">
47
+ <view class="year">{{ nickname }}</view>
48
+ </view>
49
+ <view class="bottom">
50
+ <view class="desc">
51
+ <slot name="desc"></slot>
52
+ </view>
53
+ </view>
54
+ </view>
55
+ </template>
56
+ </view>
57
+ </view>
58
+ </template>
59
+
60
+ <style lang="scss" scoped>
61
+ .ste-date-user-root {
62
+ background-color: 'red';
63
+
64
+ .box {
65
+ min-width: 336rpx;
66
+ height: 128rpx;
67
+ border-radius: 12rpx;
68
+ display: flex;
69
+ align-items: center;
70
+ background-color: #fff;
71
+ padding-right: 20rpx;
72
+
73
+ .left {
74
+ width: 80rpx;
75
+ height: 80rpx;
76
+ background: #e6e8ea;
77
+ border-radius: 8rpx;
78
+ margin: 0 28rpx;
79
+ display: flex;
80
+ justify-content: center;
81
+ align-items: center;
82
+
83
+ .day {
84
+ font-size: var(--font-size-40, 40rpx);
85
+ color: #1c1f23;
86
+ line-height: 56rpx;
87
+ height: 56rpx;
88
+ }
89
+
90
+ .image {
91
+ width: 80rpx;
92
+ height: 80rpx;
93
+ background: #ecf6ff;
94
+ border-radius: 8rpx;
95
+ overflow: hidden;
96
+ }
97
+ }
98
+
99
+ .right {
100
+ .year {
101
+ line-height: 40rpx;
102
+ height: 40rpx;
103
+ font-size: var(--font-size-28, 28rpx);
104
+ color: #1c1f23;
105
+ }
106
+
107
+ .bottom {
108
+ margin-top: 6rpx;
109
+ display: flex;
110
+ align-items: center;
111
+
112
+ .line {
113
+ border-left: 4rpx solid #1c1f23;
114
+ border-radius: 2rpx;
115
+ width: 0;
116
+ height: 22rpx;
117
+ margin: 0 13rpx;
118
+ }
119
+
120
+ .time {
121
+ font-size: var(--font-size-28, 28rpx);
122
+ color: #1c1f23;
123
+ }
124
+
125
+ .desc {
126
+ width: 96rpx;
127
+ height: 38rpx;
128
+ background: #ebf4ff;
129
+ border-radius: 4rpx;
130
+ }
131
+ }
132
+ }
133
+ }
134
+ }
135
+ </style>