@tplc/business 0.0.37 → 0.0.39
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.
- package/CHANGELOG.md +24 -0
- package/components/lcb-area-picker/api/index.ts +16 -0
- package/components/lcb-area-picker/lcb-area-picker.vue +12 -6
- package/components/lcb-area-picker/types.ts +1 -1
- package/components/lcb-list/api.ts +1 -1
- package/components/lcb-list/components/FilterList/index.vue +30 -2
- package/components/lcb-list/components/FilterList/type.ts +2 -0
- package/components/lcb-list/lcb-list.vue +7 -15
- package/components/lcb-list/types.ts +16 -0
- package/components/lcb-nav/lcb-nav.vue +7 -1
- package/components/lcb-product/lcb-product.vue +30 -25
- package/components/lcb-product/types.ts +7 -11
- package/components/lcb-product-item/lcb-product-item.vue +146 -83
- package/components/lcb-product-item/readme.md +22 -0
- package/components/lcb-product-item/types.ts +55 -11
- package/package.json +2 -2
- package/types/components/lcb-area-picker/api/index.d.ts +10 -0
- package/types/components/lcb-area-picker/lcb-area-picker.vue.d.ts +15 -3
- package/types/components/lcb-area-picker/types.d.ts +3 -1
- package/types/components/lcb-list/components/FilterList/type.d.ts +2 -0
- package/types/components/lcb-list/lcb-list.vue.d.ts +5 -30
- package/types/components/lcb-list/types.d.ts +4 -0
- package/types/components/lcb-product/lcb-product.vue.d.ts +8 -3
- package/types/components/lcb-product/types.d.ts +3 -11
- package/types/components/lcb-product-item/lcb-product-item.vue.d.ts +37 -19
- package/types/components/lcb-product-item/types.d.ts +36 -11
- package/types/utils/createReuse.d.ts +59 -0
- package/utils/createReuse.tsx +121 -0
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,30 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
|
|
4
4
|
|
|
5
|
+
### [0.0.39](http://gitlab888.30jia.com.cn/bhBank/zero-code-pro/compare/v0.0.38...v0.0.39) (2024-10-23)
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
### ✨ Features | 新功能
|
|
9
|
+
|
|
10
|
+
* 优化 lcb-list 相关逻辑 ([c81aeb8](http://gitlab888.30jia.com.cn/bhBank/zero-code-pro/commit/c81aeb8e0f9b3b5931f6c227133e2b7a314fa089))
|
|
11
|
+
* 优化 product-item 实现 ([40ad6c6](http://gitlab888.30jia.com.cn/bhBank/zero-code-pro/commit/40ad6c6ee4beb15a66210771b2e32972484a0341))
|
|
12
|
+
* 修改返回按钮尺寸 ([7c946aa](http://gitlab888.30jia.com.cn/bhBank/zero-code-pro/commit/7c946aa3cd4c9d02b663044618eededa8542ba8b))
|
|
13
|
+
|
|
14
|
+
### [0.0.38](http://gitlab888.30jia.com.cn/bhBank/zero-code-pro/compare/v0.1.17...v0.0.38) (2024-10-22)
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
### 🚀 Chore | 构建/工程依赖/工具
|
|
18
|
+
|
|
19
|
+
* husky changed ([96139b0](http://gitlab888.30jia.com.cn/bhBank/zero-code-pro/commit/96139b0e4f3fb469a62fd433f9446cfdf6a65016))
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
### ✨ Features | 新功能
|
|
23
|
+
|
|
24
|
+
* city 支持mode ([9686a0e](http://gitlab888.30jia.com.cn/bhBank/zero-code-pro/commit/9686a0e1f19c4b05d936e1b674933b4744c1b3ba))
|
|
25
|
+
* gap支持safe-top ([d21834c](http://gitlab888.30jia.com.cn/bhBank/zero-code-pro/commit/d21834cb8b67da98667fc6216624dfa1962790e5))
|
|
26
|
+
* 优化 lcb-list 过滤器吸顶逻辑;增加 unocss 插件触发文件 ([ff8d6ef](http://gitlab888.30jia.com.cn/bhBank/zero-code-pro/commit/ff8d6ef0c7703823f1a7833482d3b17bb272ae82))
|
|
27
|
+
* 调整 lcb-product-item 样式与逻辑 ([22810b7](http://gitlab888.30jia.com.cn/bhBank/zero-code-pro/commit/22810b709783b44920a778d9c038e028dcce06ad))
|
|
28
|
+
|
|
5
29
|
### [0.0.37](http://gitlab888.30jia.com.cn/bhBank/zero-code-pro/compare/v0.0.36...v0.0.37) (2024-10-21)
|
|
6
30
|
|
|
7
31
|
### [0.0.36](http://gitlab888.30jia.com.cn/bhBank/zero-code-pro/compare/v0.0.35...v0.0.36) (2024-10-21)
|
|
@@ -43,3 +43,19 @@ export const getProvinceCityArea = async () => {
|
|
|
43
43
|
}
|
|
44
44
|
})
|
|
45
45
|
}
|
|
46
|
+
|
|
47
|
+
export const getProvinceCity = async () => {
|
|
48
|
+
const { data } = await uni.$lcb.http.post<ProvinceCityArea[]>('/provinces/provinceCityArea')
|
|
49
|
+
return data.map(({ provinceId, provinceName, cityList }) => {
|
|
50
|
+
return {
|
|
51
|
+
label: provinceName,
|
|
52
|
+
value: provinceId,
|
|
53
|
+
children: cityList.map(({ cityId, cityName }) => {
|
|
54
|
+
return {
|
|
55
|
+
label: cityName,
|
|
56
|
+
value: cityId,
|
|
57
|
+
}
|
|
58
|
+
}),
|
|
59
|
+
}
|
|
60
|
+
})
|
|
61
|
+
}
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
<script setup lang="ts">
|
|
14
14
|
import { onMounted, ref, watch } from 'vue'
|
|
15
15
|
import { LcbAreaPickerProps } from './types'
|
|
16
|
-
import { AreaOptions, getProvinceCityArea } from './api'
|
|
16
|
+
import { AreaOptions, getProvinceCity, getProvinceCityArea } from './api'
|
|
17
17
|
import { ColPickerColumnChangeOption } from '@tplc/wot/types/components/wd-col-picker/types'
|
|
18
18
|
defineOptions({
|
|
19
19
|
name: 'LcbAreaPicker',
|
|
@@ -23,7 +23,7 @@ defineOptions({
|
|
|
23
23
|
styleIsolation: 'shared',
|
|
24
24
|
},
|
|
25
25
|
})
|
|
26
|
-
withDefaults(defineProps<LcbAreaPickerProps>(), {})
|
|
26
|
+
const props = withDefaults(defineProps<LcbAreaPickerProps>(), { mode: 'area' })
|
|
27
27
|
const emits = defineEmits<{
|
|
28
28
|
(event: 'confirm', payload: AreaOptions[]): void
|
|
29
29
|
}>()
|
|
@@ -40,7 +40,7 @@ const columnChange = ({ selectedItem, resolve, finish }: ColPickerColumnChangeOp
|
|
|
40
40
|
}
|
|
41
41
|
}
|
|
42
42
|
onMounted(async () => {
|
|
43
|
-
const data = await getProvinceCityArea()
|
|
43
|
+
const data = props.mode === 'area' ? await getProvinceCityArea() : await getProvinceCity()
|
|
44
44
|
area.value = [data]
|
|
45
45
|
})
|
|
46
46
|
const stopWatch = watch(
|
|
@@ -57,9 +57,15 @@ const stopWatch = watch(
|
|
|
57
57
|
return acc
|
|
58
58
|
}, [] as string[])
|
|
59
59
|
const cityItem = areas[0].find((item) => item.value === value[0])
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
60
|
+
if (cityItem?.children) {
|
|
61
|
+
if (props.mode === 'area') {
|
|
62
|
+
const areaItem = cityItem?.children?.find((item) => item.value === value[1])
|
|
63
|
+
if (areaItem?.children) area.value = [areas[0], cityItem.children, areaItem.children]
|
|
64
|
+
} else {
|
|
65
|
+
area.value = [areas[0], cityItem.children]
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
63
69
|
stopWatch()
|
|
64
70
|
}
|
|
65
71
|
},
|
|
@@ -7,14 +7,15 @@
|
|
|
7
7
|
@query="queryList"
|
|
8
8
|
use-page-scroll
|
|
9
9
|
>
|
|
10
|
-
<lcb-product v-bind="{ ...productProps }" :items="
|
|
10
|
+
<lcb-product v-bind="{ ...productProps }" :listType="listType" :items="normalizeDataList" />
|
|
11
11
|
</z-paging>
|
|
12
12
|
</template>
|
|
13
13
|
|
|
14
14
|
<script setup lang="ts">
|
|
15
|
-
import { ref, watch } from 'vue'
|
|
15
|
+
import { computed, ref, watch } from 'vue'
|
|
16
16
|
import useZPaging from 'z-paging/components/z-paging/js/hooks/useZPaging'
|
|
17
17
|
import { LcbFilterListProps } from './type'
|
|
18
|
+
import { formatJson } from '../../../../utils/utils'
|
|
18
19
|
|
|
19
20
|
defineOptions({
|
|
20
21
|
name: 'FilterList',
|
|
@@ -28,6 +29,26 @@ const props = defineProps<LcbFilterListProps>()
|
|
|
28
29
|
const dataList = ref<unknown[]>([])
|
|
29
30
|
const paging = ref()
|
|
30
31
|
useZPaging(paging)
|
|
32
|
+
|
|
33
|
+
const normalizeDataList = computed(() => {
|
|
34
|
+
const list = dataList.value?.map?.((item: any) => {
|
|
35
|
+
const imgArr = formatJson(item.coverImg, [])
|
|
36
|
+
const tags = formatJson(item.tags, [])
|
|
37
|
+
return {
|
|
38
|
+
...item,
|
|
39
|
+
image: imgArr?.[1] ?? imgArr?.[0],
|
|
40
|
+
title: item?.productName,
|
|
41
|
+
tags,
|
|
42
|
+
price: item?.price,
|
|
43
|
+
location: item?.cityAreaName,
|
|
44
|
+
priceSuffix: item?.behindUnit,
|
|
45
|
+
}
|
|
46
|
+
})
|
|
47
|
+
// console.log('list', list)
|
|
48
|
+
|
|
49
|
+
return list
|
|
50
|
+
})
|
|
51
|
+
|
|
31
52
|
watch(
|
|
32
53
|
() => props.url,
|
|
33
54
|
async (val) => {
|
|
@@ -67,6 +88,13 @@ const queryList = async (page: number, limit: number) => {
|
|
|
67
88
|
paging.value.complete(false)
|
|
68
89
|
}
|
|
69
90
|
}
|
|
91
|
+
|
|
92
|
+
// watch(
|
|
93
|
+
// () => dataList.value,
|
|
94
|
+
// () => {
|
|
95
|
+
// console.log('dataList', dataList.value)
|
|
96
|
+
// },
|
|
97
|
+
// )
|
|
70
98
|
</script>
|
|
71
99
|
<style lang="scss" scoped>
|
|
72
100
|
.action-view {
|
|
@@ -2,8 +2,10 @@ import { LcbListInfo } from '../../api'
|
|
|
2
2
|
import { LcbProductProps } from '../../../lcb-product/types'
|
|
3
3
|
export interface PageListProps {
|
|
4
4
|
emptyImage?: string
|
|
5
|
+
listType?: LcbProductProps['listType']
|
|
5
6
|
productProps?: LcbProductProps
|
|
6
7
|
}
|
|
7
8
|
export interface LcbFilterListProps extends PageListProps, LcbListInfo {
|
|
8
9
|
filter?: Record<string, any>
|
|
10
|
+
test?: any
|
|
9
11
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<view v-if="info">
|
|
3
|
-
<wd-sticky @sticky="sticky = $event">
|
|
2
|
+
<view v-if="info" class="bg-gray-100">
|
|
3
|
+
<wd-sticky @sticky="sticky = $event" :offset-top="0.0001">
|
|
4
4
|
<view
|
|
5
5
|
:class="{
|
|
6
6
|
'lcb-filter__border-top': showPlain ? false : border,
|
|
@@ -67,13 +67,13 @@
|
|
|
67
67
|
</view>
|
|
68
68
|
</wd-sticky>
|
|
69
69
|
|
|
70
|
-
<FilterList v-bind="{ ...info.listInfo,
|
|
70
|
+
<FilterList v-bind="{ ...info.listInfo, listType, filter }" test2="11" />
|
|
71
71
|
</view>
|
|
72
72
|
</template>
|
|
73
73
|
|
|
74
74
|
<script setup lang="ts">
|
|
75
75
|
import { computed, inject, Ref, ref, watch } from 'vue'
|
|
76
|
-
import { LcbListProps } from './types'
|
|
76
|
+
import { LcbListProps, defaultLcbListProps } from './types'
|
|
77
77
|
import { FilterComponent, getFilterDetail, LcbFilterResult } from './api'
|
|
78
78
|
import FilterSelect from './components/FilterSelect/index.vue'
|
|
79
79
|
import TreeSelect from './components/TreeSelect/index.vue'
|
|
@@ -83,6 +83,7 @@ import FilterList from './components/FilterList/index.vue'
|
|
|
83
83
|
import FilterTabs from './components/FilterTabs/index.vue'
|
|
84
84
|
import './index.scss'
|
|
85
85
|
import { FORM_KEY } from '../../constants'
|
|
86
|
+
|
|
86
87
|
defineOptions({
|
|
87
88
|
name: 'LcbList',
|
|
88
89
|
options: {
|
|
@@ -93,23 +94,14 @@ defineOptions({
|
|
|
93
94
|
})
|
|
94
95
|
const form = inject<Ref<Record<string, any>>>(FORM_KEY)
|
|
95
96
|
const dropMenu = ref()
|
|
96
|
-
const props = withDefaults(defineProps<LcbListProps>(),
|
|
97
|
-
pageFilterType: 'hotelTravelFilter',
|
|
98
|
-
border: true,
|
|
99
|
-
styleMode: 'default',
|
|
100
|
-
pageListProps: () => ({
|
|
101
|
-
productProps: {
|
|
102
|
-
styleGroup: 1,
|
|
103
|
-
},
|
|
104
|
-
}),
|
|
105
|
-
})
|
|
97
|
+
const props = withDefaults(defineProps<LcbListProps>(), defaultLcbListProps as any)
|
|
106
98
|
const info = ref<LcbFilterResult>()
|
|
107
99
|
const filter = ref<Record<string, any>>({})
|
|
108
100
|
const titleObj = ref<Record<string, any>>({})
|
|
109
101
|
/** 是否悬停 */
|
|
110
102
|
const sticky = ref(false)
|
|
111
103
|
const showPlain = computed(() => {
|
|
112
|
-
console.log(props.styleMode, sticky.value, 'showPlain')
|
|
104
|
+
// console.log(props.styleMode, sticky.value, 'showPlain')
|
|
113
105
|
return props.styleMode === 'plain' && !sticky.value
|
|
114
106
|
})
|
|
115
107
|
watch(
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
import { PageListProps } from './components/FilterList/type'
|
|
2
|
+
import { LcbProductProps } from '../lcb-product/types'
|
|
2
3
|
|
|
3
4
|
export interface LcbListProps {
|
|
4
5
|
pageFilterType?: string
|
|
5
6
|
pageListProps?: PageListProps
|
|
6
7
|
border?: boolean
|
|
7
8
|
styleMode?: 'default' | 'plain'
|
|
9
|
+
listType?: LcbProductProps['listType']
|
|
8
10
|
}
|
|
9
11
|
export interface Option {
|
|
10
12
|
label: string
|
|
@@ -20,4 +22,18 @@ export interface FilterItemProps {
|
|
|
20
22
|
mode?: 'multiple' | 'single'
|
|
21
23
|
apiPath?: string
|
|
22
24
|
options?: Option[]
|
|
25
|
+
test?: 1
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export const defaultLcbListProps: LcbListProps = {
|
|
29
|
+
pageFilterType: 'hotelTravelFilter',
|
|
30
|
+
border: true,
|
|
31
|
+
styleMode: 'default',
|
|
32
|
+
listType: 'grid',
|
|
33
|
+
// @ts-ignore
|
|
34
|
+
pageListProps: () => ({
|
|
35
|
+
productProps: {
|
|
36
|
+
// listType: 'list',
|
|
37
|
+
},
|
|
38
|
+
}),
|
|
23
39
|
}
|
|
@@ -47,7 +47,13 @@
|
|
|
47
47
|
</view>
|
|
48
48
|
</view>
|
|
49
49
|
<template v-else-if="back">
|
|
50
|
-
<wd-icon
|
|
50
|
+
<wd-icon
|
|
51
|
+
class-prefix="lcb"
|
|
52
|
+
name="zuo_left"
|
|
53
|
+
@click="toBack"
|
|
54
|
+
:color="contentColor"
|
|
55
|
+
size="44rpx"
|
|
56
|
+
/>
|
|
51
57
|
</template>
|
|
52
58
|
<view class="ml-2" v-if="titleLocation === 'left'">
|
|
53
59
|
<Search
|
|
@@ -1,15 +1,34 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<lcb-block v-bind="$props">
|
|
3
|
-
<
|
|
4
|
-
<view v-for="(item, index) in items" :key="index">
|
|
5
|
-
|
|
6
|
-
<lcb-product-item :styleProps="styleProps" :idx="index" v-bind="item" />
|
|
3
|
+
<view class="flex flex-col gap-2 p-2" v-if="listType === 'list'">
|
|
4
|
+
<view v-for="(item, index) in items" :key="`${item?.productId}:${index}`">
|
|
5
|
+
<lcb-product-item v-bind="item" />
|
|
7
6
|
</view>
|
|
8
|
-
</
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
7
|
+
</view>
|
|
8
|
+
|
|
9
|
+
<view class="flex p-1 flex-wrap" v-if="listType === 'grid'">
|
|
10
|
+
<view v-for="(item, index) in items" :key="`${item?.productId}:${index}`" class="w-1/2">
|
|
11
|
+
<view class="p-1 overflow-hidden">
|
|
12
|
+
<view class="rounded overflow-hidden h-560rpx">
|
|
13
|
+
<lcb-product-item
|
|
14
|
+
v-bind="item"
|
|
15
|
+
layoutType="vertical"
|
|
16
|
+
class="!h-560rpx"
|
|
17
|
+
imageClass="!h-300rpx"
|
|
18
|
+
/>
|
|
19
|
+
</view>
|
|
20
|
+
</view>
|
|
21
|
+
</view>
|
|
22
|
+
</view>
|
|
23
|
+
|
|
24
|
+
<scroll-view v-if="listType == 'horizontal'" scroll-x>
|
|
25
|
+
<view class="p-2 flex gap-2 whitespace-nowrap overflow-auto flex-nowrap">
|
|
26
|
+
<view
|
|
27
|
+
v-for="(item, index) in items"
|
|
28
|
+
:key="`${item?.productId}:${index}`"
|
|
29
|
+
class="!w-66vw flex-shrink-0"
|
|
30
|
+
>
|
|
31
|
+
<lcb-product-item v-bind="item" imageClass="!w-1/2" />
|
|
13
32
|
</view>
|
|
14
33
|
</view>
|
|
15
34
|
</scroll-view>
|
|
@@ -18,7 +37,7 @@
|
|
|
18
37
|
|
|
19
38
|
<script setup lang="ts">
|
|
20
39
|
import { computed } from 'vue'
|
|
21
|
-
import { LcbProductProps } from './types'
|
|
40
|
+
import { LcbProductProps, defaultLcbProductProps } from './types'
|
|
22
41
|
defineOptions({
|
|
23
42
|
name: 'LcbProduct',
|
|
24
43
|
options: {
|
|
@@ -27,21 +46,7 @@ defineOptions({
|
|
|
27
46
|
styleIsolation: 'shared',
|
|
28
47
|
},
|
|
29
48
|
})
|
|
30
|
-
const props = withDefaults(defineProps<LcbProductProps>(),
|
|
31
|
-
const styleProps = computed(() => {
|
|
32
|
-
// console.log('props.items', JSON.stringify(props.items))
|
|
33
|
-
return {
|
|
34
|
-
styleGroup: props.styleGroup,
|
|
35
|
-
productStyle: props.productStyle,
|
|
36
|
-
productTitle: props.productTitle,
|
|
37
|
-
showTags: props.showTags,
|
|
38
|
-
showPrice: props.showPrice,
|
|
39
|
-
showScribePrice: props.showScribePrice,
|
|
40
|
-
showCart: props.showCart,
|
|
41
|
-
showLocation: props.showLocation,
|
|
42
|
-
showCollection: props.showCollection,
|
|
43
|
-
}
|
|
44
|
-
})
|
|
49
|
+
const props = withDefaults(defineProps<LcbProductProps>(), defaultLcbProductProps as any)
|
|
45
50
|
</script>
|
|
46
51
|
|
|
47
52
|
<style lang="scss" scoped></style>
|
|
@@ -1,14 +1,10 @@
|
|
|
1
1
|
export interface LcbProductProps {
|
|
2
2
|
// Define the component's prop types here
|
|
3
|
-
|
|
4
|
-
items?: Record<string, any>
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
showScribePrice?: boolean
|
|
11
|
-
showCart?: boolean
|
|
12
|
-
showLocation?: boolean
|
|
13
|
-
showCollection?: boolean
|
|
3
|
+
listType?: 'list' | 'horizontal' | 'grid' | 'waterfall' // 1列表 2 左右滑动 3一行两个 4瀑布流
|
|
4
|
+
items?: Record<string, any>[]
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
export const defaultLcbProductProps: LcbProductProps = {
|
|
8
|
+
listType: 'list',
|
|
9
|
+
items: [],
|
|
14
10
|
}
|
|
@@ -1,50 +1,16 @@
|
|
|
1
|
-
<template>
|
|
2
|
-
<view
|
|
3
|
-
:style="{
|
|
4
|
-
paddingTop: `${transformValueUnit(15)}`,
|
|
5
|
-
paddingBottom: `${transformValueUnit(15)}`,
|
|
6
|
-
paddingLeft: styleProps?.styleGroup != 1 && idx > 0 ? transformValueUnit(15) : 0,
|
|
7
|
-
width: styleProps?.styleGroup != 1 ? transformValueUnit(picWidth) : 'auto',
|
|
8
|
-
// paddingHorizontal: styleProps?.styleGroup == 1 ? null : 15,
|
|
9
|
-
}"
|
|
10
|
-
>
|
|
11
|
-
<view :class="`${styleProps?.styleGroup == 1 ? 'flex' : ''}`">
|
|
12
|
-
<wd-img
|
|
13
|
-
:src="realImg"
|
|
14
|
-
:width="transformValueUnit(picWidth)"
|
|
15
|
-
:height="transformValueUnit(picHeight)"
|
|
16
|
-
/>
|
|
17
|
-
<view
|
|
18
|
-
v-if="styleProps?.productStyle != 'image'"
|
|
19
|
-
:class="`${styleProps?.styleGroup == 1 ? 'flex-1 pl-20rpx' : 'pt-20rpx'} pb-20rpx${styleProps?.productTitle == 1 ? ' ellipsis ' : ''}`"
|
|
20
|
-
>
|
|
21
|
-
<view
|
|
22
|
-
:class="`${styleProps?.productTitle == 1 ? 'ellipsis' : styleProps?.productTitle == 2 ? 'mulEllipsis' : 'wordBreak'} text-32rpx color-#333`"
|
|
23
|
-
>
|
|
24
|
-
{{ productName }}
|
|
25
|
-
</view>
|
|
26
|
-
<lcb-tags v-if="!!styleProps?.showTags" :mode="2" :tagRadius="3" :items="tags" />
|
|
27
|
-
<view>{{ subTitle }}</view>
|
|
28
|
-
<view class="flex items-center mt-15rpx">
|
|
29
|
-
<view v-if="!!styleProps?.showPrice" class="text-30rpx color-red">¥</view>
|
|
30
|
-
<view v-if="!!styleProps?.showPrice" class="text-32rpx color-red">{{ price }}</view>
|
|
31
|
-
<view
|
|
32
|
-
v-if="!!styleProps?.showScribePrice"
|
|
33
|
-
class="line-through text-22rpx color-#999 ml-10rpx pt-5rpx"
|
|
34
|
-
>
|
|
35
|
-
¥{{ scribePrice }}
|
|
36
|
-
</view>
|
|
37
|
-
</view>
|
|
38
|
-
</view>
|
|
39
|
-
</view>
|
|
40
|
-
</view>
|
|
41
|
-
</template>
|
|
42
|
-
|
|
43
1
|
<script setup lang="ts">
|
|
44
|
-
import { computed } from 'vue'
|
|
2
|
+
import { computed, useAttrs } from 'vue'
|
|
45
3
|
import { transformValueUnit } from '../../utils/transform'
|
|
46
|
-
import { LcbProductItemProps } from './types'
|
|
4
|
+
import { LcbProductItemProps, defaultLcbProductItemProps } from './types'
|
|
47
5
|
import { formatJson } from '../../utils/utils'
|
|
6
|
+
import { createReusableTemplate } from '../../utils/createReuse'
|
|
7
|
+
import { isArray } from '@tplc/wot/components/common/util'
|
|
8
|
+
|
|
9
|
+
const [DefineMainContent, MainContent] = createReusableTemplate()
|
|
10
|
+
const [DefineSectionWrapper, SectionWrapper] = createReusableTemplate()
|
|
11
|
+
const [DefineSection, Section] = createReusableTemplate()
|
|
12
|
+
const [DefineSectionGroup, SectionGroup] = createReusableTemplate()
|
|
13
|
+
|
|
48
14
|
defineOptions({
|
|
49
15
|
name: 'LcbProductItem',
|
|
50
16
|
options: {
|
|
@@ -54,44 +20,141 @@ defineOptions({
|
|
|
54
20
|
},
|
|
55
21
|
})
|
|
56
22
|
|
|
57
|
-
const props = withDefaults(defineProps<LcbProductItemProps>(),
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
})
|
|
62
|
-
const realImg = computed(() => {
|
|
63
|
-
console.log('props', props.styleProps)
|
|
64
|
-
const imgArr = formatJson(props.coverImg, [])
|
|
65
|
-
return imgArr[1] || imgArr[0]
|
|
66
|
-
})
|
|
23
|
+
const props = withDefaults(defineProps<LcbProductItemProps>(), defaultLcbProductItemProps)
|
|
24
|
+
const attrs = useAttrs()
|
|
25
|
+
|
|
26
|
+
// console.log('attrs', attrs)
|
|
67
27
|
</script>
|
|
68
28
|
|
|
69
|
-
<
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
29
|
+
<template>
|
|
30
|
+
<!-- 内容容器定义 -->
|
|
31
|
+
<DefineSectionWrapper v-slot="{ prop, $slots, class: className }">
|
|
32
|
+
<view
|
|
33
|
+
v-if="
|
|
34
|
+
(props?.[`${prop}Visible`] ?? true) &&
|
|
35
|
+
!!props?.[`${prop}`] &&
|
|
36
|
+
(isArray(props?.[`${prop}`]) ? props?.[`${prop}`]?.length > 0 : true)
|
|
37
|
+
"
|
|
38
|
+
:class="[className, props?.[`${prop}Class`]]"
|
|
39
|
+
>
|
|
40
|
+
<component v-if="!!$slots.default" :is="$slots.default" />
|
|
41
|
+
<view v-else>{{ props?.[`${prop}`] }}</view>
|
|
42
|
+
</view>
|
|
43
|
+
</DefineSectionWrapper>
|
|
44
|
+
|
|
45
|
+
<!-- 定义各个内容展示节点 -->
|
|
46
|
+
<DefineSection v-slot="{ prop, class: className }">
|
|
47
|
+
<!-- 图片 -->
|
|
48
|
+
<SectionWrapper v-if="prop === 'image'" prop="image" :class="className">
|
|
49
|
+
<image :src="image" class="w-full h-full" mode="aspectFill" />
|
|
50
|
+
</SectionWrapper>
|
|
51
|
+
|
|
52
|
+
<!-- 标题 -->
|
|
53
|
+
<SectionWrapper
|
|
54
|
+
:class="className"
|
|
55
|
+
v-if="prop === 'title'"
|
|
56
|
+
prop="title"
|
|
57
|
+
class="text-ellipsis line-clamp-2"
|
|
58
|
+
/>
|
|
59
|
+
|
|
60
|
+
<!-- 位置 -->
|
|
61
|
+
<SectionWrapper
|
|
62
|
+
:class="className"
|
|
63
|
+
v-if="prop === 'location'"
|
|
64
|
+
prop="location"
|
|
65
|
+
class="text-gray-500 text-22rpx flex gap-3rpx items-center"
|
|
66
|
+
>
|
|
67
|
+
<wd-icon name="location" size="32rpx"></wd-icon>
|
|
68
|
+
<view>{{ location }}</view>
|
|
69
|
+
</SectionWrapper>
|
|
70
|
+
|
|
71
|
+
<!-- 标签 -->
|
|
72
|
+
<SectionWrapper
|
|
73
|
+
:class="className"
|
|
74
|
+
v-if="prop === 'tags'"
|
|
75
|
+
prop="tags"
|
|
76
|
+
class="flex gap-1 whitespace-nowrap overflow-auto"
|
|
77
|
+
>
|
|
78
|
+
<wd-tag
|
|
79
|
+
v-for="tag in tags"
|
|
80
|
+
:key="tag"
|
|
81
|
+
class="!text-20rpx"
|
|
82
|
+
:class="tagsClass"
|
|
83
|
+
plain
|
|
84
|
+
type="primary"
|
|
85
|
+
>
|
|
86
|
+
{{ tag }}
|
|
87
|
+
</wd-tag>
|
|
88
|
+
</SectionWrapper>
|
|
89
|
+
|
|
90
|
+
<!-- 价格单位 -->
|
|
91
|
+
<SectionWrapper
|
|
92
|
+
:class="className"
|
|
93
|
+
v-if="prop === 'priceUnit'"
|
|
94
|
+
prop="priceUnit"
|
|
95
|
+
class="text-red-500 font-bold text-22rpx"
|
|
96
|
+
/>
|
|
97
|
+
|
|
98
|
+
<!-- 价格 -->
|
|
99
|
+
<SectionWrapper
|
|
100
|
+
:class="className"
|
|
101
|
+
v-if="prop === 'price'"
|
|
102
|
+
prop="price"
|
|
103
|
+
class="text-red-500 font-bold text-27rpx"
|
|
104
|
+
/>
|
|
105
|
+
|
|
106
|
+
<!-- 价格后缀 -->
|
|
107
|
+
<SectionWrapper
|
|
108
|
+
:class="className"
|
|
109
|
+
v-if="prop === 'priceSuffix'"
|
|
110
|
+
prop="priceSuffix"
|
|
111
|
+
class="text-22rpx"
|
|
112
|
+
/>
|
|
113
|
+
|
|
114
|
+
<!-- 价格区域 -->
|
|
115
|
+
</DefineSection>
|
|
116
|
+
|
|
117
|
+
<!-- 内容组定义 -->
|
|
118
|
+
<DefineSectionGroup v-slot="{ group, class: className }">
|
|
119
|
+
<view :class="className">
|
|
120
|
+
<Section v-for="prop in group" :prop="prop" :key="prop" />
|
|
121
|
+
</view>
|
|
122
|
+
</DefineSectionGroup>
|
|
123
|
+
|
|
124
|
+
<!-- 主内容的展示节点 -->
|
|
125
|
+
<DefineMainContent v-slot="{ class: className }">
|
|
126
|
+
<view
|
|
127
|
+
:class="className"
|
|
128
|
+
class="flex flex-col flex-1 gap-2 justify-between text-26rpx overflow-hidden"
|
|
129
|
+
>
|
|
130
|
+
<SectionGroup
|
|
131
|
+
class="flex flex-col gap-2 overflow-hidden"
|
|
132
|
+
:group="['title', 'location', 'tags']"
|
|
133
|
+
/>
|
|
134
|
+
<view class="flex gap-2">
|
|
135
|
+
<SectionGroup
|
|
136
|
+
class="flex gap-[4rpx] items-end"
|
|
137
|
+
:group="['priceUnit', 'price', 'priceSuffix']"
|
|
138
|
+
/>
|
|
139
|
+
</view>
|
|
140
|
+
</view>
|
|
141
|
+
</DefineMainContent>
|
|
142
|
+
|
|
143
|
+
<!-- 横向布局 -->
|
|
144
|
+
<view
|
|
145
|
+
v-if="layoutType === 'horizontal'"
|
|
146
|
+
:class="attrs?.class"
|
|
147
|
+
class="flex gap-3 px-2 py-3 bg-white"
|
|
148
|
+
>
|
|
149
|
+
<Section prop="image" class="w-1/3 h-220rpx bg-gray-100 rounded-sm overflow-hidden" />
|
|
150
|
+
<MainContent />
|
|
151
|
+
</view>
|
|
152
|
+
|
|
153
|
+
<!-- 竖向布局 -->
|
|
154
|
+
<view v-if="layoutType === 'vertical'" :class="attrs?.class" class="flex flex-col gap-2 bg-white">
|
|
155
|
+
<Section prop="image" class="overflow-hidden" />
|
|
156
|
+
<MainContent class="p-2" />
|
|
157
|
+
</view>
|
|
158
|
+
</template>
|
|
159
|
+
|
|
160
|
+
<style lang="scss" scoped></style>
|
|
@@ -1,14 +1,58 @@
|
|
|
1
1
|
export interface LcbProductItemProps {
|
|
2
2
|
// Define the component's prop types here
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
3
|
+
|
|
4
|
+
layoutType?: 'vertical' | 'horizontal'
|
|
5
|
+
image?: any
|
|
6
|
+
title?: any
|
|
7
|
+
subTitle?: any
|
|
8
|
+
price?: any
|
|
9
|
+
priceUnit?: any
|
|
10
|
+
priceSuffix?: any
|
|
11
|
+
originPrice?: any
|
|
12
|
+
originPriceUnit?: any
|
|
13
|
+
tags?: any
|
|
14
|
+
location?: any
|
|
15
|
+
distance?: any
|
|
16
|
+
|
|
17
|
+
imageVisible?: boolean
|
|
18
|
+
titleVisible?: boolean
|
|
19
|
+
subTitleVisible?: boolean
|
|
20
|
+
priceVisible?: boolean
|
|
21
|
+
priceUnitVisible?: boolean
|
|
22
|
+
priceSuffixVisible?: boolean
|
|
23
|
+
originPriceVisible?: boolean
|
|
24
|
+
originPriceUnitVisible?: boolean
|
|
25
|
+
tagsVisible?: boolean
|
|
26
|
+
locationVisible?: boolean
|
|
27
|
+
distanceVisible?: boolean
|
|
28
|
+
|
|
29
|
+
imageClass?: string
|
|
30
|
+
titleClass?: string
|
|
31
|
+
subTitleClass?: string
|
|
32
|
+
priceClass?: string
|
|
33
|
+
priceUnitClass?: string
|
|
34
|
+
priceSuffixClass?: string
|
|
35
|
+
originPriceClass?: string
|
|
36
|
+
originPriceUnitClass?: string
|
|
37
|
+
tagsClass?: string
|
|
38
|
+
tagsWrapperClass?: string
|
|
39
|
+
locationClass?: string
|
|
40
|
+
distanceClass?: string
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export const defaultLcbProductItemProps: LcbProductItemProps = {
|
|
44
|
+
layoutType: 'horizontal',
|
|
45
|
+
priceUnit: '¥',
|
|
46
|
+
originPriceUnit: '¥',
|
|
47
|
+
imageVisible: true,
|
|
48
|
+
titleVisible: true,
|
|
49
|
+
subTitleVisible: true,
|
|
50
|
+
priceVisible: true,
|
|
51
|
+
priceUnitVisible: true,
|
|
52
|
+
priceSuffixVisible: true,
|
|
53
|
+
originPriceVisible: true,
|
|
54
|
+
originPriceUnitVisible: true,
|
|
55
|
+
tagsVisible: true,
|
|
56
|
+
locationVisible: true,
|
|
57
|
+
distanceVisible: true,
|
|
14
58
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tplc/business",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.39",
|
|
4
4
|
"keywords": [
|
|
5
5
|
"业务组件"
|
|
6
6
|
],
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
},
|
|
12
12
|
"peerDependencies": {
|
|
13
13
|
"vue": ">=3.2.47",
|
|
14
|
-
"@tplc/wot": "0.1.
|
|
14
|
+
"@tplc/wot": "0.1.17"
|
|
15
15
|
},
|
|
16
16
|
"engines": {
|
|
17
17
|
"node": ">=18",
|
|
@@ -35,4 +35,14 @@ export declare const getProvinceCityArea: () => Promise<
|
|
|
35
35
|
}[]
|
|
36
36
|
}[]
|
|
37
37
|
>
|
|
38
|
+
export declare const getProvinceCity: () => Promise<
|
|
39
|
+
{
|
|
40
|
+
label: string
|
|
41
|
+
value: string
|
|
42
|
+
children: {
|
|
43
|
+
label: string
|
|
44
|
+
value: string
|
|
45
|
+
}[]
|
|
46
|
+
}[]
|
|
47
|
+
>
|
|
38
48
|
export {}
|
|
@@ -8,7 +8,12 @@ declare function __VLS_template(): {
|
|
|
8
8
|
default?(_: { text: string[] | undefined }): any
|
|
9
9
|
}
|
|
10
10
|
declare const __VLS_component: import('vue').DefineComponent<
|
|
11
|
-
__VLS_WithDefaults<
|
|
11
|
+
__VLS_WithDefaults<
|
|
12
|
+
__VLS_TypePropsToOption<__VLS_PublicProps>,
|
|
13
|
+
{
|
|
14
|
+
mode: string
|
|
15
|
+
}
|
|
16
|
+
>,
|
|
12
17
|
{},
|
|
13
18
|
unknown,
|
|
14
19
|
{},
|
|
@@ -23,13 +28,20 @@ declare const __VLS_component: import('vue').DefineComponent<
|
|
|
23
28
|
import('vue').PublicProps,
|
|
24
29
|
Readonly<
|
|
25
30
|
import('vue').ExtractPropTypes<
|
|
26
|
-
__VLS_WithDefaults<
|
|
31
|
+
__VLS_WithDefaults<
|
|
32
|
+
__VLS_TypePropsToOption<__VLS_PublicProps>,
|
|
33
|
+
{
|
|
34
|
+
mode: string
|
|
35
|
+
}
|
|
36
|
+
>
|
|
27
37
|
>
|
|
28
38
|
> & {
|
|
29
39
|
onConfirm?: ((payload: AreaOptions[]) => any) | undefined
|
|
30
40
|
'onUpdate:modelValue'?: ((modelValue: string[]) => any) | undefined
|
|
31
41
|
},
|
|
32
|
-
{
|
|
42
|
+
{
|
|
43
|
+
mode: 'city' | 'area'
|
|
44
|
+
},
|
|
33
45
|
{}
|
|
34
46
|
>
|
|
35
47
|
declare const _default: __VLS_WithTemplateSlots<
|
|
@@ -2,8 +2,10 @@ import { LcbListInfo } from '../../api'
|
|
|
2
2
|
import { LcbProductProps } from '../../../lcb-product/types'
|
|
3
3
|
export interface PageListProps {
|
|
4
4
|
emptyImage?: string
|
|
5
|
+
listType?: LcbProductProps['listType']
|
|
5
6
|
productProps?: LcbProductProps
|
|
6
7
|
}
|
|
7
8
|
export interface LcbFilterListProps extends PageListProps, LcbListInfo {
|
|
8
9
|
filter?: Record<string, any>
|
|
10
|
+
test?: any
|
|
9
11
|
}
|
|
@@ -1,19 +1,7 @@
|
|
|
1
1
|
import { LcbListProps } from './types'
|
|
2
2
|
import './index.scss'
|
|
3
3
|
declare const _default: import('vue').DefineComponent<
|
|
4
|
-
__VLS_WithDefaults<
|
|
5
|
-
__VLS_TypePropsToOption<LcbListProps>,
|
|
6
|
-
{
|
|
7
|
-
pageFilterType: string
|
|
8
|
-
border: boolean
|
|
9
|
-
styleMode: string
|
|
10
|
-
pageListProps: () => {
|
|
11
|
-
productProps: {
|
|
12
|
-
styleGroup: number
|
|
13
|
-
}
|
|
14
|
-
}
|
|
15
|
-
}
|
|
16
|
-
>,
|
|
4
|
+
__VLS_WithDefaults<__VLS_TypePropsToOption<LcbListProps>, any>,
|
|
17
5
|
{},
|
|
18
6
|
unknown,
|
|
19
7
|
{},
|
|
@@ -24,27 +12,14 @@ declare const _default: import('vue').DefineComponent<
|
|
|
24
12
|
string,
|
|
25
13
|
import('vue').PublicProps,
|
|
26
14
|
Readonly<
|
|
27
|
-
import('vue').ExtractPropTypes<
|
|
28
|
-
__VLS_WithDefaults<
|
|
29
|
-
__VLS_TypePropsToOption<LcbListProps>,
|
|
30
|
-
{
|
|
31
|
-
pageFilterType: string
|
|
32
|
-
border: boolean
|
|
33
|
-
styleMode: string
|
|
34
|
-
pageListProps: () => {
|
|
35
|
-
productProps: {
|
|
36
|
-
styleGroup: number
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
>
|
|
41
|
-
>
|
|
15
|
+
import('vue').ExtractPropTypes<__VLS_WithDefaults<__VLS_TypePropsToOption<LcbListProps>, any>>
|
|
42
16
|
>,
|
|
43
17
|
{
|
|
44
|
-
|
|
18
|
+
listType: 'horizontal' | 'list' | 'grid' | 'waterfall'
|
|
45
19
|
pageFilterType: string
|
|
46
|
-
|
|
20
|
+
border: boolean
|
|
47
21
|
styleMode: 'default' | 'plain'
|
|
22
|
+
pageListProps: import('./components/FilterList/type').PageListProps
|
|
48
23
|
},
|
|
49
24
|
{}
|
|
50
25
|
>
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import { PageListProps } from './components/FilterList/type'
|
|
2
|
+
import { LcbProductProps } from '../lcb-product/types'
|
|
2
3
|
export interface LcbListProps {
|
|
3
4
|
pageFilterType?: string
|
|
4
5
|
pageListProps?: PageListProps
|
|
5
6
|
border?: boolean
|
|
6
7
|
styleMode?: 'default' | 'plain'
|
|
8
|
+
listType?: LcbProductProps['listType']
|
|
7
9
|
}
|
|
8
10
|
export interface Option {
|
|
9
11
|
label: string
|
|
@@ -18,4 +20,6 @@ export interface FilterItemProps {
|
|
|
18
20
|
mode?: 'multiple' | 'single'
|
|
19
21
|
apiPath?: string
|
|
20
22
|
options?: Option[]
|
|
23
|
+
test?: 1
|
|
21
24
|
}
|
|
25
|
+
export declare const defaultLcbListProps: LcbListProps
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { LcbProductProps } from './types'
|
|
2
2
|
declare const _default: import('vue').DefineComponent<
|
|
3
|
-
__VLS_WithDefaults<__VLS_TypePropsToOption<LcbProductProps>,
|
|
3
|
+
__VLS_WithDefaults<__VLS_TypePropsToOption<LcbProductProps>, any>,
|
|
4
4
|
{},
|
|
5
5
|
unknown,
|
|
6
6
|
{},
|
|
@@ -11,9 +11,14 @@ declare const _default: import('vue').DefineComponent<
|
|
|
11
11
|
string,
|
|
12
12
|
import('vue').PublicProps,
|
|
13
13
|
Readonly<
|
|
14
|
-
import('vue').ExtractPropTypes<
|
|
14
|
+
import('vue').ExtractPropTypes<
|
|
15
|
+
__VLS_WithDefaults<__VLS_TypePropsToOption<LcbProductProps>, any>
|
|
16
|
+
>
|
|
15
17
|
>,
|
|
16
|
-
{
|
|
18
|
+
{
|
|
19
|
+
items: Record<string, any>[]
|
|
20
|
+
listType: 'list' | 'horizontal' | 'grid' | 'waterfall'
|
|
21
|
+
},
|
|
17
22
|
{}
|
|
18
23
|
>
|
|
19
24
|
export default _default
|
|
@@ -1,13 +1,5 @@
|
|
|
1
1
|
export interface LcbProductProps {
|
|
2
|
-
|
|
3
|
-
items?: Record<string, any>
|
|
4
|
-
marginHorizontal?: number
|
|
5
|
-
productStyle?: 'image' | 'flat' | 'card' | 'border'
|
|
6
|
-
productTitle?: 0 | 1 | 2
|
|
7
|
-
showTags?: boolean
|
|
8
|
-
showPrice?: boolean
|
|
9
|
-
showScribePrice?: boolean
|
|
10
|
-
showCart?: boolean
|
|
11
|
-
showLocation?: boolean
|
|
12
|
-
showCollection?: boolean
|
|
2
|
+
listType?: 'list' | 'horizontal' | 'grid' | 'waterfall'
|
|
3
|
+
items?: Record<string, any>[]
|
|
13
4
|
}
|
|
5
|
+
export declare const defaultLcbProductProps: LcbProductProps
|
|
@@ -1,13 +1,6 @@
|
|
|
1
1
|
import { LcbProductItemProps } from './types'
|
|
2
2
|
declare const _default: import('vue').DefineComponent<
|
|
3
|
-
__VLS_WithDefaults<
|
|
4
|
-
__VLS_TypePropsToOption<LcbProductItemProps>,
|
|
5
|
-
{
|
|
6
|
-
idx: number
|
|
7
|
-
picWidth: number
|
|
8
|
-
picHeight: number
|
|
9
|
-
}
|
|
10
|
-
>,
|
|
3
|
+
__VLS_WithDefaults<__VLS_TypePropsToOption<LcbProductItemProps>, LcbProductItemProps>,
|
|
11
4
|
{},
|
|
12
5
|
unknown,
|
|
13
6
|
{},
|
|
@@ -19,20 +12,45 @@ declare const _default: import('vue').DefineComponent<
|
|
|
19
12
|
import('vue').PublicProps,
|
|
20
13
|
Readonly<
|
|
21
14
|
import('vue').ExtractPropTypes<
|
|
22
|
-
__VLS_WithDefaults<
|
|
23
|
-
__VLS_TypePropsToOption<LcbProductItemProps>,
|
|
24
|
-
{
|
|
25
|
-
idx: number
|
|
26
|
-
picWidth: number
|
|
27
|
-
picHeight: number
|
|
28
|
-
}
|
|
29
|
-
>
|
|
15
|
+
__VLS_WithDefaults<__VLS_TypePropsToOption<LcbProductItemProps>, LcbProductItemProps>
|
|
30
16
|
>
|
|
31
17
|
>,
|
|
32
18
|
{
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
19
|
+
title: any
|
|
20
|
+
image: any
|
|
21
|
+
location: any
|
|
22
|
+
layoutType: 'vertical' | 'horizontal'
|
|
23
|
+
imageClass: string
|
|
24
|
+
subTitle: any
|
|
25
|
+
price: any
|
|
26
|
+
priceUnit: any
|
|
27
|
+
priceSuffix: any
|
|
28
|
+
originPrice: any
|
|
29
|
+
originPriceUnit: any
|
|
30
|
+
tags: any
|
|
31
|
+
distance: any
|
|
32
|
+
imageVisible: boolean
|
|
33
|
+
titleVisible: boolean
|
|
34
|
+
subTitleVisible: boolean
|
|
35
|
+
priceVisible: boolean
|
|
36
|
+
priceUnitVisible: boolean
|
|
37
|
+
priceSuffixVisible: boolean
|
|
38
|
+
originPriceVisible: boolean
|
|
39
|
+
originPriceUnitVisible: boolean
|
|
40
|
+
tagsVisible: boolean
|
|
41
|
+
locationVisible: boolean
|
|
42
|
+
distanceVisible: boolean
|
|
43
|
+
titleClass: string
|
|
44
|
+
subTitleClass: string
|
|
45
|
+
priceClass: string
|
|
46
|
+
priceUnitClass: string
|
|
47
|
+
priceSuffixClass: string
|
|
48
|
+
originPriceClass: string
|
|
49
|
+
originPriceUnitClass: string
|
|
50
|
+
tagsClass: string
|
|
51
|
+
tagsWrapperClass: string
|
|
52
|
+
locationClass: string
|
|
53
|
+
distanceClass: string
|
|
36
54
|
},
|
|
37
55
|
{}
|
|
38
56
|
>
|
|
@@ -1,13 +1,38 @@
|
|
|
1
1
|
export interface LcbProductItemProps {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
2
|
+
layoutType?: 'vertical' | 'horizontal'
|
|
3
|
+
image?: any
|
|
4
|
+
title?: any
|
|
5
|
+
subTitle?: any
|
|
6
|
+
price?: any
|
|
7
|
+
priceUnit?: any
|
|
8
|
+
priceSuffix?: any
|
|
9
|
+
originPrice?: any
|
|
10
|
+
originPriceUnit?: any
|
|
11
|
+
tags?: any
|
|
12
|
+
location?: any
|
|
13
|
+
distance?: any
|
|
14
|
+
imageVisible?: boolean
|
|
15
|
+
titleVisible?: boolean
|
|
16
|
+
subTitleVisible?: boolean
|
|
17
|
+
priceVisible?: boolean
|
|
18
|
+
priceUnitVisible?: boolean
|
|
19
|
+
priceSuffixVisible?: boolean
|
|
20
|
+
originPriceVisible?: boolean
|
|
21
|
+
originPriceUnitVisible?: boolean
|
|
22
|
+
tagsVisible?: boolean
|
|
23
|
+
locationVisible?: boolean
|
|
24
|
+
distanceVisible?: boolean
|
|
25
|
+
imageClass?: string
|
|
26
|
+
titleClass?: string
|
|
27
|
+
subTitleClass?: string
|
|
28
|
+
priceClass?: string
|
|
29
|
+
priceUnitClass?: string
|
|
30
|
+
priceSuffixClass?: string
|
|
31
|
+
originPriceClass?: string
|
|
32
|
+
originPriceUnitClass?: string
|
|
33
|
+
tagsClass?: string
|
|
34
|
+
tagsWrapperClass?: string
|
|
35
|
+
locationClass?: string
|
|
36
|
+
distanceClass?: string
|
|
13
37
|
}
|
|
38
|
+
export declare const defaultLcbProductItemProps: LcbProductItemProps
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import type { DefineComponent, Slot } from 'vue'
|
|
2
|
+
type ObjectLiteralWithPotentialObjectLiterals = Record<string, Record<string, any> | undefined>
|
|
3
|
+
type GenerateSlotsFromSlotMap<T extends ObjectLiteralWithPotentialObjectLiterals> = {
|
|
4
|
+
[K in keyof T]: Slot<T[K]>
|
|
5
|
+
}
|
|
6
|
+
export type DefineTemplateComponent<
|
|
7
|
+
Bindings extends Record<string, any>,
|
|
8
|
+
MapSlotNameToSlotProps extends ObjectLiteralWithPotentialObjectLiterals,
|
|
9
|
+
> = DefineComponent & {
|
|
10
|
+
new (): {
|
|
11
|
+
$slots: {
|
|
12
|
+
default: (
|
|
13
|
+
_: Bindings & {
|
|
14
|
+
$slots: GenerateSlotsFromSlotMap<MapSlotNameToSlotProps>
|
|
15
|
+
},
|
|
16
|
+
) => any
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
export type ReuseTemplateComponent<
|
|
21
|
+
Bindings extends Record<string, any>,
|
|
22
|
+
MapSlotNameToSlotProps extends ObjectLiteralWithPotentialObjectLiterals,
|
|
23
|
+
> = DefineComponent<Bindings> & {
|
|
24
|
+
new (): {
|
|
25
|
+
$slots: GenerateSlotsFromSlotMap<MapSlotNameToSlotProps>
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
export type ReusableTemplatePair<
|
|
29
|
+
Bindings extends Record<string, any>,
|
|
30
|
+
MapSlotNameToSlotProps extends ObjectLiteralWithPotentialObjectLiterals,
|
|
31
|
+
> = [
|
|
32
|
+
DefineTemplateComponent<Bindings, MapSlotNameToSlotProps>,
|
|
33
|
+
ReuseTemplateComponent<Bindings, MapSlotNameToSlotProps>,
|
|
34
|
+
] & {
|
|
35
|
+
define: DefineTemplateComponent<Bindings, MapSlotNameToSlotProps>
|
|
36
|
+
reuse: ReuseTemplateComponent<Bindings, MapSlotNameToSlotProps>
|
|
37
|
+
}
|
|
38
|
+
export interface CreateReusableTemplateOptions {
|
|
39
|
+
/**
|
|
40
|
+
* Inherit attrs from reuse component.
|
|
41
|
+
*
|
|
42
|
+
* @default true
|
|
43
|
+
*/
|
|
44
|
+
inheritAttrs?: boolean
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* This function creates `define` and `reuse` components in pair,
|
|
48
|
+
* It also allow to pass a generic to bind with type.
|
|
49
|
+
*
|
|
50
|
+
* @see https://vueuse.org/createReusableTemplate
|
|
51
|
+
*/
|
|
52
|
+
export declare function createReusableTemplate<
|
|
53
|
+
Bindings extends Record<string, any>,
|
|
54
|
+
MapSlotNameToSlotProps extends ObjectLiteralWithPotentialObjectLiterals = Record<
|
|
55
|
+
'default',
|
|
56
|
+
undefined
|
|
57
|
+
>,
|
|
58
|
+
>(options?: CreateReusableTemplateOptions): ReusableTemplatePair<Bindings, MapSlotNameToSlotProps>
|
|
59
|
+
export {}
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import type { DefineComponent, Slot } from 'vue'
|
|
2
|
+
import { defineComponent, shallowRef } from 'vue'
|
|
3
|
+
|
|
4
|
+
type ObjectLiteralWithPotentialObjectLiterals = Record<string, Record<string, any> | undefined>
|
|
5
|
+
|
|
6
|
+
type GenerateSlotsFromSlotMap<T extends ObjectLiteralWithPotentialObjectLiterals> = {
|
|
7
|
+
[K in keyof T]: Slot<T[K]>
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export type DefineTemplateComponent<
|
|
11
|
+
Bindings extends Record<string, any>,
|
|
12
|
+
MapSlotNameToSlotProps extends ObjectLiteralWithPotentialObjectLiterals,
|
|
13
|
+
> = DefineComponent & {
|
|
14
|
+
new (): {
|
|
15
|
+
$slots: {
|
|
16
|
+
default: (_: Bindings & { $slots: GenerateSlotsFromSlotMap<MapSlotNameToSlotProps> }) => any
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export type ReuseTemplateComponent<
|
|
22
|
+
Bindings extends Record<string, any>,
|
|
23
|
+
MapSlotNameToSlotProps extends ObjectLiteralWithPotentialObjectLiterals,
|
|
24
|
+
> = DefineComponent<Bindings> & {
|
|
25
|
+
new (): { $slots: GenerateSlotsFromSlotMap<MapSlotNameToSlotProps> }
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export type ReusableTemplatePair<
|
|
29
|
+
Bindings extends Record<string, any>,
|
|
30
|
+
MapSlotNameToSlotProps extends ObjectLiteralWithPotentialObjectLiterals,
|
|
31
|
+
> = [
|
|
32
|
+
DefineTemplateComponent<Bindings, MapSlotNameToSlotProps>,
|
|
33
|
+
ReuseTemplateComponent<Bindings, MapSlotNameToSlotProps>,
|
|
34
|
+
] & {
|
|
35
|
+
define: DefineTemplateComponent<Bindings, MapSlotNameToSlotProps>
|
|
36
|
+
reuse: ReuseTemplateComponent<Bindings, MapSlotNameToSlotProps>
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export interface CreateReusableTemplateOptions {
|
|
40
|
+
/**
|
|
41
|
+
* Inherit attrs from reuse component.
|
|
42
|
+
*
|
|
43
|
+
* @default true
|
|
44
|
+
*/
|
|
45
|
+
inheritAttrs?: boolean
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* This function creates `define` and `reuse` components in pair,
|
|
50
|
+
* It also allow to pass a generic to bind with type.
|
|
51
|
+
*
|
|
52
|
+
* @see https://vueuse.org/createReusableTemplate
|
|
53
|
+
*/
|
|
54
|
+
export function createReusableTemplate<
|
|
55
|
+
Bindings extends Record<string, any>,
|
|
56
|
+
MapSlotNameToSlotProps extends ObjectLiteralWithPotentialObjectLiterals = Record<
|
|
57
|
+
'default',
|
|
58
|
+
undefined
|
|
59
|
+
>,
|
|
60
|
+
>(
|
|
61
|
+
options: CreateReusableTemplateOptions = {},
|
|
62
|
+
): ReusableTemplatePair<Bindings, MapSlotNameToSlotProps> {
|
|
63
|
+
const { inheritAttrs = true } = options
|
|
64
|
+
|
|
65
|
+
const render = shallowRef<Slot | undefined>()
|
|
66
|
+
|
|
67
|
+
const define = defineComponent({
|
|
68
|
+
setup(_, { slots }) {
|
|
69
|
+
return () => {
|
|
70
|
+
render.value = slots.default
|
|
71
|
+
}
|
|
72
|
+
},
|
|
73
|
+
}) as unknown as DefineTemplateComponent<Bindings, MapSlotNameToSlotProps>
|
|
74
|
+
|
|
75
|
+
const reuse = defineComponent({
|
|
76
|
+
inheritAttrs,
|
|
77
|
+
setup(_, { attrs, slots }) {
|
|
78
|
+
return () => {
|
|
79
|
+
if (!render.value && process.env.NODE_ENV !== 'production')
|
|
80
|
+
throw new Error('[VueUse] Failed to find the definition of reusable template')
|
|
81
|
+
const vnode = render.value?.({ ...keysToCamelKebabCase(attrs), $slots: slots })
|
|
82
|
+
|
|
83
|
+
return inheritAttrs && vnode?.length === 1 ? vnode[0] : vnode
|
|
84
|
+
}
|
|
85
|
+
},
|
|
86
|
+
}) as unknown as ReuseTemplateComponent<Bindings, MapSlotNameToSlotProps>
|
|
87
|
+
|
|
88
|
+
return makeDestructurable({ define, reuse }, [define, reuse]) as any
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
function keysToCamelKebabCase(obj: Record<string, any>) {
|
|
92
|
+
const newObj: typeof obj = {}
|
|
93
|
+
for (const key in obj) newObj[camelize(key)] = obj[key]
|
|
94
|
+
return newObj
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* @see What the hack? https://antfu.me/posts/destructuring-with-object-or-array
|
|
98
|
+
*/
|
|
99
|
+
function makeDestructurable<T extends Record<string, unknown>, A extends readonly any[]>(
|
|
100
|
+
obj: T,
|
|
101
|
+
arr: A,
|
|
102
|
+
): T & A {
|
|
103
|
+
const clone = { ...obj }
|
|
104
|
+
Object.defineProperty(clone, Symbol.iterator, {
|
|
105
|
+
enumerable: false,
|
|
106
|
+
value() {
|
|
107
|
+
let index = 0
|
|
108
|
+
return {
|
|
109
|
+
next: () => ({
|
|
110
|
+
value: arr[index++],
|
|
111
|
+
done: index > arr.length,
|
|
112
|
+
}),
|
|
113
|
+
}
|
|
114
|
+
},
|
|
115
|
+
})
|
|
116
|
+
return clone as T & A
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
function camelize(str: string) {
|
|
120
|
+
return str.replace(/-(\w)/g, (_, c) => (c ? c.toUpperCase() : ''))
|
|
121
|
+
}
|