@tplc/business 0.7.80 → 0.7.82

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.
@@ -0,0 +1,322 @@
1
+ # lcb-empty 组件实现总结
2
+
3
+ ## 🎯 实现目标
4
+
5
+ 将 empty 状态从 `lcb-product` 中抽离成独立的 `lcb-empty` 组件,实现在多个组件中复用。
6
+
7
+ ## ✅ 已完成的工作
8
+
9
+ ### 1. 创建独立组件
10
+
11
+ #### 新增文件
12
+ - `packages/business/components/lcb-empty/lcb-empty.vue` - 组件实现
13
+ - `packages/business/components/lcb-empty/types.ts` - 类型定义
14
+ - `packages/business/components/lcb-empty/README.md` - 使用文档
15
+
16
+ #### 组件特性
17
+ - ✅ 支持自定义图片和文字
18
+ - ✅ 支持自定义图片尺寸(imageWidth、imageHeight)
19
+ - ✅ 支持自定义文字样式(textColor、textSize、textWeight)
20
+ - ✅ 支持自定义图片与文字间距(gap)
21
+ - ✅ 支持自定义最小高度(minHeight)
22
+ - ✅ 支持自定义内边距(paddingTop/Right/Bottom/Left)
23
+ - ✅ 响应式设计,使用 rpx 单位
24
+ - ✅ 图片和文字可独立显示/隐藏
25
+
26
+ ### 2. 更新相关组件
27
+
28
+ #### lcb-product
29
+ **修改文件:**
30
+ - `types.ts` - 导入 `LcbEmptyProps`,替换原有 `EmptyProps`
31
+ - `lcb-product.vue` - 使用 `<lcb-empty>` 组件替换原有实现
32
+
33
+ **实现逻辑:**
34
+ ```typescript
35
+ // 计算是否显示空状态
36
+ const showEmpty = computed(() => {
37
+ return !loading.value && renderList.value.length === 0
38
+ })
39
+
40
+ // 合并配置(自动继承父组件的内边距)
41
+ const mergedEmptyProps = computed(() => {
42
+ return {
43
+ ...props.emptyProps,
44
+ paddingTop: props.emptyProps?.paddingTop ?? props.paddingVertical ?? 0,
45
+ paddingRight: props.emptyProps?.paddingRight ?? props.paddingHorizontal ?? 0,
46
+ paddingBottom: props.emptyProps?.paddingBottom ?? props.paddingVertical ?? 0,
47
+ paddingLeft: props.emptyProps?.paddingLeft ?? props.paddingHorizontal ?? 0,
48
+ }
49
+ })
50
+ ```
51
+
52
+ #### lcb-list
53
+ **修改文件:**
54
+ - `types.ts` - 导入 `LcbEmptyProps`,更新类型引用
55
+
56
+ **实现方式:**
57
+ - 通过 props 将 `emptyProps` 透传给内部的 `lcb-product` 组件
58
+
59
+ #### lcb-wrapper-list (新增支持)
60
+ **修改文件:**
61
+ - `types.ts` - 导入 `LcbEmptyProps`,添加 `emptyProps` 属性
62
+ - `lcb-wrapper-list.vue` - 添加空状态显示逻辑
63
+
64
+ **实现逻辑:**
65
+ ```typescript
66
+ // 计算是否显示空状态
67
+ const showEmpty = computed(() => {
68
+ return renderList.value.length === 0
69
+ })
70
+
71
+ // 合并配置
72
+ const mergedEmptyProps = computed(() => {
73
+ return {
74
+ ...props.emptyProps,
75
+ paddingTop: props.emptyProps?.paddingTop ?? props.paddingVertical ?? 0,
76
+ paddingRight: props.emptyProps?.paddingRight ?? props.paddingHorizontal ?? 0,
77
+ paddingBottom: props.emptyProps?.paddingBottom ?? props.paddingVertical ?? 0,
78
+ paddingLeft: props.emptyProps?.paddingLeft ?? props.paddingHorizontal ?? 0,
79
+ }
80
+ })
81
+ ```
82
+
83
+ ### 3. 更新文档
84
+
85
+ #### 组件文档
86
+ - `lcb-empty/README.md` - 详细的组件使用文档
87
+
88
+ #### 综合文档
89
+ - `EMPTY_STATE_README.md` - 更新为包含 lcb-empty 独立组件的说明
90
+ - `CHANGELOG_EMPTY.md` - 更新为包含组件抽离的变更记录
91
+ - `EMPTY_USAGE.md` - 保持不变(原有使用文档)
92
+ - `EMPTY_IMPLEMENTATION.md` - 保持不变(原有实现文档)
93
+ - `EMPTY_QUICK_REF.md` - 保持不变(原有快速参考)
94
+
95
+ ### 4. 示例页面
96
+
97
+ #### 新增示例
98
+ - `packages/engine/src/pages/lcb-wrapper-list/empty-demo.vue` - lcb-wrapper-list 使用示例
99
+
100
+ #### 已有示例
101
+ - `packages/engine/src/pages/lcb-product/empty-demo.vue` - lcb-product 使用示例(保持不变)
102
+
103
+ ## 📊 类型定义
104
+
105
+ ### LcbEmptyProps
106
+
107
+ ```typescript
108
+ export interface LcbEmptyProps {
109
+ /** 空状态图片地址 */
110
+ image?: string
111
+ /** 空状态文字 */
112
+ text?: string
113
+ /** 图片宽度(rpx) */
114
+ imageWidth?: number
115
+ /** 图片高度(rpx) */
116
+ imageHeight?: number
117
+ /** 文字颜色 */
118
+ textColor?: string
119
+ /** 文字大小(rpx) */
120
+ textSize?: number
121
+ /** 文字粗细 */
122
+ textWeight?: 'normal' | 'bold' | 100 | 200 | 300 | 400 | 500 | 600 | 700 | 800 | 900
123
+ /** 图片与文字的间距(rpx) */
124
+ gap?: number
125
+ /** 最小高度(rpx) */
126
+ minHeight?: number
127
+ /** 内边距 - 上(rpx) */
128
+ paddingTop?: number
129
+ /** 内边距 - 右(rpx) */
130
+ paddingRight?: number
131
+ /** 内边距 - 下(rpx) */
132
+ paddingBottom?: number
133
+ /** 内边距 - 左(rpx) */
134
+ paddingLeft?: number
135
+ }
136
+ ```
137
+
138
+ ### 默认值
139
+
140
+ ```typescript
141
+ {
142
+ text: '暂无数据',
143
+ imageWidth: 400,
144
+ imageHeight: 400,
145
+ textColor: '#999999',
146
+ textSize: 28,
147
+ textWeight: 'normal',
148
+ gap: 24,
149
+ minHeight: 400,
150
+ paddingTop: 0,
151
+ paddingRight: 0,
152
+ paddingBottom: 0,
153
+ paddingLeft: 0,
154
+ }
155
+ ```
156
+
157
+ ## 🎨 使用方式
158
+
159
+ ### 1. 直接使用 lcb-empty
160
+
161
+ ```vue
162
+ <template>
163
+ <lcb-empty
164
+ image="/static/empty.png"
165
+ text="暂无数据"
166
+ :imageWidth="500"
167
+ :imageHeight="500"
168
+ />
169
+ </template>
170
+ ```
171
+
172
+ ### 2. 在 lcb-product 中使用
173
+
174
+ ```vue
175
+ <template>
176
+ <lcb-product
177
+ :items="[]"
178
+ :emptyProps="{
179
+ image: '/static/empty.png',
180
+ text: '还没有点亮记录',
181
+ }"
182
+ />
183
+ </template>
184
+ ```
185
+
186
+ ### 3. 在 lcb-list 中使用
187
+
188
+ ```vue
189
+ <template>
190
+ <lcb-list
191
+ pageFilterType="product-filter"
192
+ :emptyProps="{
193
+ image: '/static/empty.png',
194
+ text: '还没有点亮记录',
195
+ }"
196
+ />
197
+ </template>
198
+ ```
199
+
200
+ ### 4. 在 lcb-wrapper-list 中使用
201
+
202
+ ```vue
203
+ <template>
204
+ <lcb-wrapper-list
205
+ :dataSource="dataSource"
206
+ :emptyProps="{
207
+ image: '/static/empty.png',
208
+ text: '暂无数据',
209
+ }"
210
+ >
211
+ <template #default="{ data }">
212
+ <view>{{ data }}</view>
213
+ </template>
214
+ </lcb-wrapper-list>
215
+ </template>
216
+ ```
217
+
218
+ ## 🔧 技术实现
219
+
220
+ ### 组件结构
221
+
222
+ ```
223
+ lcb-empty
224
+ ├── template
225
+ │ └── view.lcb-empty
226
+ │ ├── wd-img (图片)
227
+ │ └── view.lcb-empty__text (文字)
228
+ ├── script
229
+ │ ├── props 定义
230
+ │ ├── transformValueUnit 工具函数
231
+ │ └── defineExpose
232
+ └── style
233
+ └── scoped styles
234
+ ```
235
+
236
+ ### 自动注册
237
+
238
+ 组件通过 `packages/business/index.ts` 中的 glob 导入自动注册:
239
+
240
+ ```typescript
241
+ const importFn = import.meta.glob('./components/lcb-*/lcb-*.vue', { eager: true })
242
+ ```
243
+
244
+ ### 内边距继承
245
+
246
+ 在父组件中,空状态的内边距会自动继承父组件的 `paddingVertical` 和 `paddingHorizontal` 设置:
247
+
248
+ ```typescript
249
+ const mergedEmptyProps = computed(() => {
250
+ return {
251
+ ...props.emptyProps,
252
+ paddingTop: props.emptyProps?.paddingTop ?? props.paddingVertical ?? 0,
253
+ paddingRight: props.emptyProps?.paddingRight ?? props.paddingHorizontal ?? 0,
254
+ paddingBottom: props.emptyProps?.paddingBottom ?? props.paddingVertical ?? 0,
255
+ paddingLeft: props.emptyProps?.paddingLeft ?? props.paddingHorizontal ?? 0,
256
+ }
257
+ })
258
+ ```
259
+
260
+ ## ✅ 验证结果
261
+
262
+ - ✅ TypeScript 类型检查通过
263
+ - ✅ 无 Linter 错误
264
+ - ✅ 组件可以独立使用
265
+ - ✅ 在 lcb-product 中正常工作
266
+ - ✅ 在 lcb-list 中正常工作
267
+ - ✅ 在 lcb-wrapper-list 中正常工作
268
+ - ✅ 向下兼容,不影响现有功能
269
+ - ✅ 文档完整
270
+
271
+ ## 🎉 优势
272
+
273
+ 1. **代码复用** - 一个组件,多处使用
274
+ 2. **易于维护** - 修改只需在一个地方进行
275
+ 3. **独立使用** - 可以在任何地方单独使用 lcb-empty
276
+ 4. **类型安全** - 完整的 TypeScript 支持
277
+ 5. **灵活配置** - 支持继承父组件配置,也可以完全自定义
278
+ 6. **文档完善** - 多份文档覆盖不同使用场景
279
+
280
+ ## 📁 文件清单
281
+
282
+ ### 新增文件
283
+ ```
284
+ packages/business/components/
285
+ ├── lcb-empty/
286
+ │ ├── lcb-empty.vue (新增)
287
+ │ ├── types.ts (新增)
288
+ │ ├── README.md (新增)
289
+ │ └── IMPLEMENTATION_SUMMARY.md (新增)
290
+ └── packages/engine/src/pages/
291
+ └── lcb-wrapper-list/
292
+ └── empty-demo.vue (新增)
293
+ ```
294
+
295
+ ### 修改文件
296
+ ```
297
+ packages/business/components/
298
+ ├── lcb-product/
299
+ │ ├── lcb-product.vue (修改)
300
+ │ └── types.ts (修改)
301
+ ├── lcb-list/
302
+ │ └── types.ts (修改)
303
+ ├── lcb-wrapper-list/
304
+ │ ├── lcb-wrapper-list.vue (修改)
305
+ │ └── types.ts (修改)
306
+ ├── EMPTY_STATE_README.md (更新)
307
+ └── CHANGELOG_EMPTY.md (更新)
308
+ ```
309
+
310
+ ## 🎯 适用组件
311
+
312
+ - ✅ lcb-empty (独立组件)
313
+ - ✅ lcb-product
314
+ - ✅ lcb-list
315
+ - ✅ lcb-wrapper-list
316
+ - 🔄 可扩展到其他需要空状态的组件
317
+
318
+ ---
319
+
320
+ **实现时间**: 2026-01-19
321
+ **版本**: v2.0.0 (组件抽离版本)
322
+ **状态**: ✅ 已完成并测试通过
@@ -0,0 +1,183 @@
1
+ # lcb-empty 组件
2
+
3
+ 通用的空状态展示组件,用于在列表、数据为空时显示友好的提示信息。
4
+
5
+ ## 功能特性
6
+
7
+ - ✅ 支持自定义图片和文字
8
+ - ✅ 支持自定义图片尺寸
9
+ - ✅ 支持自定义文字样式(颜色、大小、粗细)
10
+ - ✅ 支持自定义图片与文字的间距
11
+ - ✅ 支持自定义内边距
12
+ - ✅ 响应式设计,使用 rpx 单位
13
+
14
+ ## Props
15
+
16
+ ### LcbEmptyProps
17
+
18
+ | 属性 | 类型 | 默认值 | 说明 |
19
+ |------|------|--------|------|
20
+ | `image` | `string` | `undefined` | 空状态图片地址 |
21
+ | `text` | `string` | `'暂无数据'` | 空状态文字 |
22
+ | `imageWidth` | `number` | `400` | 图片宽度(rpx) |
23
+ | `imageHeight` | `number` | `400` | 图片高度(rpx) |
24
+ | `textColor` | `string` | `'#999999'` | 文字颜色 |
25
+ | `textSize` | `number` | `28` | 文字大小(rpx) |
26
+ | `textWeight` | `string \| number` | `'normal'` | 文字粗细 |
27
+ | `gap` | `number` | `24` | 图片与文字间距(rpx) |
28
+ | `minHeight` | `number` | `400` | 最小高度(rpx) |
29
+ | `paddingTop` | `number` | `0` | 内边距 - 上(rpx) |
30
+ | `paddingRight` | `number` | `0` | 内边距 - 右(rpx) |
31
+ | `paddingBottom` | `number` | `0` | 内边距 - 下(rpx) |
32
+ | `paddingLeft` | `number` | `0` | 内边距 - 左(rpx) |
33
+
34
+ ## 使用示例
35
+
36
+ ### 基础使用
37
+
38
+ ```vue
39
+ <template>
40
+ <lcb-empty
41
+ image="/static/empty.png"
42
+ text="暂无数据"
43
+ />
44
+ </template>
45
+ ```
46
+
47
+ ### 完整配置
48
+
49
+ ```vue
50
+ <template>
51
+ <lcb-empty
52
+ image="/static/empty.png"
53
+ text="还没有点亮记录"
54
+ :imageWidth="500"
55
+ :imageHeight="500"
56
+ textColor="#666666"
57
+ :textSize="32"
58
+ textWeight="bold"
59
+ :gap="32"
60
+ :minHeight="600"
61
+ :paddingTop="40"
62
+ :paddingBottom="40"
63
+ />
64
+ </template>
65
+ ```
66
+
67
+ ### 只显示图片
68
+
69
+ ```vue
70
+ <template>
71
+ <lcb-empty
72
+ image="/static/empty.png"
73
+ text=""
74
+ />
75
+ </template>
76
+ ```
77
+
78
+ ### 只显示文字
79
+
80
+ ```vue
81
+ <template>
82
+ <lcb-empty text="暂无数据" />
83
+ </template>
84
+ ```
85
+
86
+ ## 在其他组件中使用
87
+
88
+ ### lcb-product
89
+
90
+ ```vue
91
+ <template>
92
+ <lcb-product
93
+ :items="[]"
94
+ :emptyProps="{
95
+ image: '/static/empty.png',
96
+ text: '还没有点亮记录',
97
+ imageWidth: 500,
98
+ imageHeight: 500,
99
+ }"
100
+ />
101
+ </template>
102
+ ```
103
+
104
+ ### lcb-list
105
+
106
+ ```vue
107
+ <template>
108
+ <lcb-list
109
+ pageFilterType="product-filter"
110
+ :emptyProps="{
111
+ image: '/static/empty.png',
112
+ text: '还没有点亮记录',
113
+ }"
114
+ />
115
+ </template>
116
+ ```
117
+
118
+ ### lcb-wrapper-list
119
+
120
+ ```vue
121
+ <template>
122
+ <lcb-wrapper-list
123
+ :dataSource="dataSource"
124
+ :emptyProps="{
125
+ image: '/static/empty.png',
126
+ text: '暂无数据',
127
+ imageWidth: 400,
128
+ imageHeight: 400,
129
+ }"
130
+ >
131
+ <template #default="{ data }">
132
+ <view>{{ data }}</view>
133
+ </template>
134
+ </lcb-wrapper-list>
135
+ </template>
136
+ ```
137
+
138
+ ## 样式定制
139
+
140
+ ### 文字粗细选项
141
+
142
+ `textWeight` 支持以下值:
143
+ - `'normal'` - 正常
144
+ - `'bold'` - 粗体
145
+ - `100` - 细体
146
+ - `200` - 特细
147
+ - `300` - 细
148
+ - `400` - 正常(等同于 'normal')
149
+ - `500` - 中等
150
+ - `600` - 半粗
151
+ - `700` - 粗(等同于 'bold')
152
+ - `800` - 特粗
153
+ - `900` - 黑体
154
+
155
+ ## 布局说明
156
+
157
+ 组件采用 Flexbox 垂直居中布局:
158
+ - 图片和文字垂直排列
159
+ - 内容水平居中
160
+ - 图片使用 `aspectFit` 模式保持比例
161
+ - 文字自动换行,最大宽度 100%
162
+
163
+ ## 注意事项
164
+
165
+ 1. **单位说明**:所有尺寸属性(如 `imageWidth`、`textSize`、`gap` 等)的单位都是 `rpx`
166
+ 2. **可选元素**:图片和文字都是可选的,可以只显示其中一个
167
+ 3. **响应式**:使用 `rpx` 单位确保在不同设备上显示一致
168
+ 4. **内边距继承**:在 `lcb-product`、`lcb-list`、`lcb-wrapper-list` 等父组件中使用时,会自动继承父组件的内边距设置
169
+
170
+ ## 相关组件
171
+
172
+ - `lcb-product` - 商品列表组件(支持 empty 状态)
173
+ - `lcb-list` - 通用列表组件(支持 empty 状态)
174
+ - `lcb-wrapper-list` - 包装列表组件(支持 empty 状态)
175
+
176
+ ## 更新日志
177
+
178
+ ### v1.0.0 (2026-01-19)
179
+
180
+ - 🎉 初始版本
181
+ - ✅ 从 `lcb-product` 中抽离成独立组件
182
+ - ✅ 支持在多个组件中复用
183
+ - ✅ 完整的类型支持
@@ -0,0 +1,69 @@
1
+ <template>
2
+ <view
3
+ class="lcb-empty flex flex-col items-center justify-center"
4
+ :style="{
5
+ padding: `${paddingTop}rpx ${paddingRight}rpx ${paddingBottom}rpx ${paddingLeft}rpx`,
6
+ minHeight: `${minHeight}rpx`,
7
+ gap: transformValueUnit(gap),
8
+ }"
9
+ >
10
+ <wd-img v-if="image" :src="image" :height="imageHeight" :width="imageWidth" mode="aspectFit" />
11
+ <view
12
+ v-if="text"
13
+ class="lcb-empty__text"
14
+ :style="{
15
+ color: textColor,
16
+ fontSize: `${textSize}rpx`,
17
+ fontWeight: textWeight,
18
+ }"
19
+ >
20
+ {{ text }}
21
+ </view>
22
+ </view>
23
+ </template>
24
+
25
+ <script setup lang="ts">
26
+ import { transformValueUnit } from '../../utils/transform'
27
+ import { LcbEmptyProps } from './types'
28
+
29
+ defineOptions({
30
+ name: 'LcbEmpty',
31
+ options: {
32
+ addGlobalClass: true,
33
+ virtualHost: true,
34
+ styleIsolation: 'shared',
35
+ },
36
+ })
37
+
38
+ const props = withDefaults(defineProps<LcbEmptyProps>(), {
39
+ text: '暂无数据',
40
+ imageWidth: 400,
41
+ imageHeight: 400,
42
+ textColor: '#999999',
43
+ textSize: 28,
44
+ textWeight: 'normal',
45
+ gap: 24,
46
+ minHeight: 400,
47
+ paddingTop: 0,
48
+ paddingRight: 0,
49
+ paddingBottom: 0,
50
+ paddingLeft: 0,
51
+ })
52
+
53
+ // 导出 props 供父组件使用
54
+ defineExpose({
55
+ props,
56
+ })
57
+ </script>
58
+
59
+ <style lang="scss" scoped>
60
+ .lcb-empty {
61
+ box-sizing: border-box;
62
+
63
+ &__text {
64
+ text-align: center;
65
+ word-wrap: break-word;
66
+ max-width: 100%;
67
+ }
68
+ }
69
+ </style>
@@ -0,0 +1,28 @@
1
+ export interface LcbEmptyProps {
2
+ /** 空状态图片地址 */
3
+ image?: string
4
+ /** 空状态文字 */
5
+ text?: string
6
+ /** 图片宽度(rpx) */
7
+ imageWidth?: number
8
+ /** 图片高度(rpx) */
9
+ imageHeight?: number
10
+ /** 文字颜色 */
11
+ textColor?: string
12
+ /** 文字大小(rpx) */
13
+ textSize?: number
14
+ /** 文字粗细 */
15
+ textWeight?: 'normal' | 'bold' | 100 | 200 | 300 | 400 | 500 | 600 | 700 | 800 | 900
16
+ /** 图片与文字的间距(rpx) */
17
+ gap?: number
18
+ /** 最小高度(rpx) */
19
+ minHeight?: number
20
+ /** 内边距 - 上(rpx) */
21
+ paddingTop?: number
22
+ /** 内边距 - 右(rpx) */
23
+ paddingRight?: number
24
+ /** 内边距 - 下(rpx) */
25
+ paddingBottom?: number
26
+ /** 内边距 - 左(rpx) */
27
+ paddingLeft?: number
28
+ }
@@ -45,6 +45,7 @@
45
45
  :items="items"
46
46
  filterList
47
47
  ref="productRef"
48
+ :emptyProps="emptyProps"
48
49
  v-if="$slots.item"
49
50
  >
50
51
  <template #item="{ item }">
@@ -56,6 +57,7 @@
56
57
  filterList
57
58
  :items="items"
58
59
  ref="productRef"
60
+ :emptyProps="emptyProps"
59
61
  v-else
60
62
  />
61
63
  </template>
@@ -1,6 +1,7 @@
1
1
  import { PageListProps } from './components/FilterList/type'
2
2
  import { LcbProductProps } from '../lcb-product/types'
3
3
  import { LcbBlockProps } from '../lcb-block/types'
4
+ import { LcbEmptyProps } from '../lcb-empty/types'
4
5
 
5
6
  export interface LcbListProps extends LcbBlockProps {
6
7
  pageFilterType?: string
@@ -45,6 +46,7 @@ export interface LcbListProps extends LcbBlockProps {
45
46
  mapTagMode?: 'single' | 'multiple'
46
47
  mapConfigParams?: string
47
48
  tagPosition?: 'left' | 'right'
49
+ emptyProps?: LcbEmptyProps // 空状态配置
48
50
  }
49
51
  export interface Option {
50
52
  label: string