create-weapp-vite 1.3.2 → 1.3.3
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/dist/{chunk-CP2T5O3U.js → chunk-KDUDSVZ5.js} +2 -2
- package/dist/cli.cjs +2 -2
- package/dist/cli.js +1 -1
- package/dist/index.cjs +2 -2
- package/dist/index.js +1 -1
- package/package.json +1 -1
- package/templates/wevu-tdesign/README.md +5 -0
- package/templates/wevu-tdesign/components.d.ts +1 -1
- package/templates/wevu-tdesign/public/tabbar/ability-active.png +0 -0
- package/templates/wevu-tdesign/public/tabbar/ability.png +0 -0
- package/templates/wevu-tdesign/public/tabbar/data-active.png +0 -0
- package/templates/wevu-tdesign/public/tabbar/data.png +0 -0
- package/templates/wevu-tdesign/public/tabbar/form-active.png +0 -0
- package/templates/wevu-tdesign/public/tabbar/form.png +0 -0
- package/templates/wevu-tdesign/public/tabbar/home-active.png +0 -0
- package/templates/wevu-tdesign/public/tabbar/home.png +0 -0
- package/templates/wevu-tdesign/public/tabbar/list-active.png +0 -0
- package/templates/wevu-tdesign/public/tabbar/list.png +0 -0
- package/templates/wevu-tdesign/src/app.vue +60 -2
- package/templates/wevu-tdesign/src/components/EmptyState/index.vue +36 -0
- package/templates/wevu-tdesign/src/components/FilterBar/index.vue +63 -0
- package/templates/wevu-tdesign/src/components/FormRow/index.vue +43 -0
- package/templates/wevu-tdesign/src/components/FormStep/index.vue +48 -0
- package/templates/wevu-tdesign/src/components/KpiBoard/index.vue +146 -0
- package/templates/wevu-tdesign/src/components/QuickActionGrid/index.vue +90 -0
- package/templates/wevu-tdesign/src/components/ResultCard/index.vue +51 -0
- package/templates/wevu-tdesign/src/components/SectionTitle/index.vue +34 -0
- package/templates/wevu-tdesign/src/components/TrendCard/index.vue +101 -0
- package/templates/wevu-tdesign/src/pages/ability/index.vue +177 -0
- package/templates/wevu-tdesign/src/pages/data/index.vue +188 -0
- package/templates/wevu-tdesign/src/pages/form/index.vue +249 -0
- package/templates/wevu-tdesign/src/pages/index/index.vue +228 -126
- package/templates/wevu-tdesign/src/pages/list/index.vue +178 -0
- package/templates/wevu-tdesign/src/subpackages/ability/index.vue +106 -0
- package/templates/wevu-tdesign/src/subpackages/lab/index.vue +136 -0
- package/templates/wevu-tdesign/src/vite-env.d.ts +4 -0
- package/templates/wevu-tdesign/tsconfig.app.json +6 -1
- package/templates/wevu-tdesign/vite.config.ts +11 -1
- package/templates/wevu-tdesign/src/components/HelloWorld/index.vue +0 -23
|
@@ -5,10 +5,10 @@ import fs2 from "fs-extra";
|
|
|
5
5
|
import path2 from "pathe";
|
|
6
6
|
|
|
7
7
|
// ../weapp-vite/package.json
|
|
8
|
-
var version = "6.1.
|
|
8
|
+
var version = "6.1.7";
|
|
9
9
|
|
|
10
10
|
// ../wevu/package.json
|
|
11
|
-
var version2 = "1.0.
|
|
11
|
+
var version2 = "1.0.3";
|
|
12
12
|
|
|
13
13
|
// src/enums.ts
|
|
14
14
|
var TemplateName = /* @__PURE__ */ ((TemplateName2) => {
|
package/dist/cli.cjs
CHANGED
|
@@ -51,10 +51,10 @@ var import_fs_extra2 = __toESM(require("fs-extra"), 1);
|
|
|
51
51
|
var import_pathe2 = __toESM(require("pathe"), 1);
|
|
52
52
|
|
|
53
53
|
// ../weapp-vite/package.json
|
|
54
|
-
var version = "6.1.
|
|
54
|
+
var version = "6.1.7";
|
|
55
55
|
|
|
56
56
|
// ../wevu/package.json
|
|
57
|
-
var version2 = "1.0.
|
|
57
|
+
var version2 = "1.0.3";
|
|
58
58
|
|
|
59
59
|
// src/npm.ts
|
|
60
60
|
var import_node_https = __toESM(require("https"), 1);
|
package/dist/cli.js
CHANGED
package/dist/index.cjs
CHANGED
|
@@ -46,10 +46,10 @@ var import_fs_extra2 = __toESM(require("fs-extra"), 1);
|
|
|
46
46
|
var import_pathe2 = __toESM(require("pathe"), 1);
|
|
47
47
|
|
|
48
48
|
// ../weapp-vite/package.json
|
|
49
|
-
var version = "6.1.
|
|
49
|
+
var version = "6.1.7";
|
|
50
50
|
|
|
51
51
|
// ../wevu/package.json
|
|
52
|
-
var version2 = "1.0.
|
|
52
|
+
var version2 = "1.0.3";
|
|
53
53
|
|
|
54
54
|
// src/enums.ts
|
|
55
55
|
var TemplateName = /* @__PURE__ */ ((TemplateName2) => {
|
package/dist/index.js
CHANGED
package/package.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
// oxlint-disable
|
|
4
4
|
// ------
|
|
5
5
|
// Generated by weapp-vite autoImportComponents
|
|
6
|
-
import type { ComponentOptionsMixin, DefineComponent, PublicProps } from '
|
|
6
|
+
import type { ComponentOptionsMixin, DefineComponent, PublicProps } from 'wevu'
|
|
7
7
|
import type { ComponentProp } from 'weapp-vite/typed-components'
|
|
8
8
|
|
|
9
9
|
export {}
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -4,12 +4,65 @@ import { onHide, onLaunch, onShow } from 'wevu'
|
|
|
4
4
|
defineAppJson({
|
|
5
5
|
pages: [
|
|
6
6
|
'pages/index/index',
|
|
7
|
+
'pages/data/index',
|
|
8
|
+
'pages/form/index',
|
|
9
|
+
'pages/list/index',
|
|
10
|
+
'pages/ability/index',
|
|
7
11
|
],
|
|
8
12
|
window: {
|
|
9
|
-
navigationBarTitleText: '
|
|
10
|
-
navigationBarBackgroundColor: '#
|
|
13
|
+
navigationBarTitleText: 'Weapp Studio',
|
|
14
|
+
navigationBarBackgroundColor: '#2f2b5f',
|
|
11
15
|
navigationBarTextStyle: 'white',
|
|
16
|
+
backgroundTextStyle: 'dark',
|
|
12
17
|
},
|
|
18
|
+
tabBar: {
|
|
19
|
+
color: '#7a7aa0',
|
|
20
|
+
selectedColor: '#2f2b5f',
|
|
21
|
+
backgroundColor: '#ffffff',
|
|
22
|
+
borderStyle: 'white',
|
|
23
|
+
list: [
|
|
24
|
+
{
|
|
25
|
+
pagePath: 'pages/index/index',
|
|
26
|
+
text: '首页',
|
|
27
|
+
iconPath: 'tabbar/home.png',
|
|
28
|
+
selectedIconPath: 'tabbar/home-active.png',
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
pagePath: 'pages/data/index',
|
|
32
|
+
text: '数据',
|
|
33
|
+
iconPath: 'tabbar/data.png',
|
|
34
|
+
selectedIconPath: 'tabbar/data-active.png',
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
pagePath: 'pages/form/index',
|
|
38
|
+
text: '表单',
|
|
39
|
+
iconPath: 'tabbar/form.png',
|
|
40
|
+
selectedIconPath: 'tabbar/form-active.png',
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
pagePath: 'pages/list/index',
|
|
44
|
+
text: '清单',
|
|
45
|
+
iconPath: 'tabbar/list.png',
|
|
46
|
+
selectedIconPath: 'tabbar/list-active.png',
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
pagePath: 'pages/ability/index',
|
|
50
|
+
text: '能力',
|
|
51
|
+
iconPath: 'tabbar/ability.png',
|
|
52
|
+
selectedIconPath: 'tabbar/ability-active.png',
|
|
53
|
+
},
|
|
54
|
+
],
|
|
55
|
+
},
|
|
56
|
+
subPackages: [
|
|
57
|
+
{
|
|
58
|
+
root: 'subpackages/lab',
|
|
59
|
+
pages: ['index'],
|
|
60
|
+
},
|
|
61
|
+
{
|
|
62
|
+
root: 'subpackages/ability',
|
|
63
|
+
pages: ['index'],
|
|
64
|
+
},
|
|
65
|
+
],
|
|
13
66
|
style: 'v2',
|
|
14
67
|
componentFramework: 'glass-easel',
|
|
15
68
|
sitemapLocation: 'sitemap.json',
|
|
@@ -32,4 +85,9 @@ onLaunch(() => {
|
|
|
32
85
|
@tailwind base;
|
|
33
86
|
@tailwind components;
|
|
34
87
|
@tailwind utilities;
|
|
88
|
+
|
|
89
|
+
page {
|
|
90
|
+
font-family: 'HarmonyOS Sans', 'PingFang SC', 'Microsoft YaHei', sans-serif;
|
|
91
|
+
background-color: #f6f7fb;
|
|
92
|
+
}
|
|
35
93
|
</style>
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
const props = withDefaults(
|
|
3
|
+
defineProps<{
|
|
4
|
+
title: string
|
|
5
|
+
description?: string
|
|
6
|
+
actionText?: string
|
|
7
|
+
}>(),
|
|
8
|
+
{
|
|
9
|
+
description: '',
|
|
10
|
+
actionText: '',
|
|
11
|
+
},
|
|
12
|
+
)
|
|
13
|
+
|
|
14
|
+
const emit = defineEmits<{
|
|
15
|
+
(e: 'action'): void
|
|
16
|
+
}>()
|
|
17
|
+
|
|
18
|
+
defineComponentJson({
|
|
19
|
+
styleIsolation: 'apply-shared',
|
|
20
|
+
})
|
|
21
|
+
|
|
22
|
+
function onAction() {
|
|
23
|
+
emit('action')
|
|
24
|
+
}
|
|
25
|
+
</script>
|
|
26
|
+
|
|
27
|
+
<template>
|
|
28
|
+
<view class="rounded-[20rpx] bg-white p-[24rpx] shadow-[0_12rpx_28rpx_rgba(17,24,39,0.08)]">
|
|
29
|
+
<t-empty :title="title" :description="description" />
|
|
30
|
+
<view v-if="props.actionText" class="mt-[16rpx]">
|
|
31
|
+
<t-button block theme="primary" variant="outline" @tap="onAction">
|
|
32
|
+
{{ props.actionText }}
|
|
33
|
+
</t-button>
|
|
34
|
+
</view>
|
|
35
|
+
</view>
|
|
36
|
+
</template>
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import { computed } from 'wevu'
|
|
3
|
+
|
|
4
|
+
const emit = defineEmits<{
|
|
5
|
+
(e: 'update:query', value: string): void
|
|
6
|
+
(e: 'update:active', value: string): void
|
|
7
|
+
}>()
|
|
8
|
+
|
|
9
|
+
const props = defineProps({
|
|
10
|
+
query: { type: String, default: '' },
|
|
11
|
+
active: { type: String, default: 'all' },
|
|
12
|
+
filters: { type: Array, default: () => [] },
|
|
13
|
+
}) as {
|
|
14
|
+
query: string
|
|
15
|
+
active: string
|
|
16
|
+
filters: FilterItem[]
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
defineComponentJson({
|
|
20
|
+
styleIsolation: 'apply-shared',
|
|
21
|
+
})
|
|
22
|
+
|
|
23
|
+
interface FilterItem {
|
|
24
|
+
value: string
|
|
25
|
+
label: string
|
|
26
|
+
count?: number
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const filterItems = computed(() => (Array.isArray(props.filters) ? props.filters : []))
|
|
30
|
+
|
|
31
|
+
function onQueryChange(e: WechatMiniprogram.CustomEvent<{ value: string }>) {
|
|
32
|
+
emit('update:query', e.detail.value)
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function onSelect(value: string) {
|
|
36
|
+
emit('update:active', value)
|
|
37
|
+
}
|
|
38
|
+
</script>
|
|
39
|
+
|
|
40
|
+
<template>
|
|
41
|
+
<view class="rounded-[20rpx] bg-white p-[16rpx] shadow-[0_12rpx_28rpx_rgba(17,24,39,0.08)]">
|
|
42
|
+
<t-search
|
|
43
|
+
placeholder="搜索标题或负责人"
|
|
44
|
+
:value="query"
|
|
45
|
+
clearable
|
|
46
|
+
@change="onQueryChange"
|
|
47
|
+
/>
|
|
48
|
+
<view class="mt-[12rpx] flex flex-wrap gap-[12rpx]">
|
|
49
|
+
<t-check-tag
|
|
50
|
+
v-for="item in filterItems"
|
|
51
|
+
:key="item.value"
|
|
52
|
+
:checked="item.value === active"
|
|
53
|
+
content=""
|
|
54
|
+
@change="onSelect(item.value)"
|
|
55
|
+
>
|
|
56
|
+
{{ item.label }}
|
|
57
|
+
<text v-if="item.count !== undefined">
|
|
58
|
+
({{ item.count }})
|
|
59
|
+
</text>
|
|
60
|
+
</t-check-tag>
|
|
61
|
+
</view>
|
|
62
|
+
</view>
|
|
63
|
+
</template>
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import { computed } from 'wevu'
|
|
3
|
+
|
|
4
|
+
const props = withDefaults(
|
|
5
|
+
defineProps<{
|
|
6
|
+
label: string
|
|
7
|
+
align?: 'left' | 'center' | 'right'
|
|
8
|
+
description?: string
|
|
9
|
+
}>(),
|
|
10
|
+
{
|
|
11
|
+
align: 'left',
|
|
12
|
+
description: '',
|
|
13
|
+
},
|
|
14
|
+
)
|
|
15
|
+
|
|
16
|
+
defineComponentJson({
|
|
17
|
+
styleIsolation: 'apply-shared',
|
|
18
|
+
})
|
|
19
|
+
|
|
20
|
+
const labelClass = computed(() => {
|
|
21
|
+
if (props.align === 'right') {
|
|
22
|
+
return 'text-right'
|
|
23
|
+
}
|
|
24
|
+
if (props.align === 'center') {
|
|
25
|
+
return 'text-center'
|
|
26
|
+
}
|
|
27
|
+
return 'text-left'
|
|
28
|
+
})
|
|
29
|
+
</script>
|
|
30
|
+
|
|
31
|
+
<template>
|
|
32
|
+
<view class="flex flex-col gap-[8rpx]">
|
|
33
|
+
<view class="flex items-baseline justify-between gap-[12rpx]">
|
|
34
|
+
<text class="text-[22rpx] font-semibold text-[#1f1a3f]" :class="labelClass">
|
|
35
|
+
{{ label }}
|
|
36
|
+
</text>
|
|
37
|
+
<text v-if="description" class="text-[20rpx] text-[#8a8aa5]">
|
|
38
|
+
{{ description }}
|
|
39
|
+
</text>
|
|
40
|
+
</view>
|
|
41
|
+
<slot />
|
|
42
|
+
</view>
|
|
43
|
+
</template>
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
defineOptions({
|
|
3
|
+
options: {
|
|
4
|
+
multipleSlots: true,
|
|
5
|
+
},
|
|
6
|
+
})
|
|
7
|
+
|
|
8
|
+
withDefaults(
|
|
9
|
+
defineProps<{
|
|
10
|
+
step: number
|
|
11
|
+
title: string
|
|
12
|
+
subtitle?: string
|
|
13
|
+
active?: boolean
|
|
14
|
+
}>(),
|
|
15
|
+
{
|
|
16
|
+
subtitle: '',
|
|
17
|
+
active: false,
|
|
18
|
+
},
|
|
19
|
+
)
|
|
20
|
+
|
|
21
|
+
defineComponentJson({
|
|
22
|
+
styleIsolation: 'apply-shared',
|
|
23
|
+
})
|
|
24
|
+
</script>
|
|
25
|
+
|
|
26
|
+
<template>
|
|
27
|
+
<view class="rounded-[20rpx] bg-white p-[20rpx] shadow-[0_12rpx_28rpx_rgba(17,24,39,0.08)]">
|
|
28
|
+
<view class="flex items-center gap-[12rpx]">
|
|
29
|
+
<view
|
|
30
|
+
class="flex h-[36rpx] w-[36rpx] items-center justify-center rounded-full text-[20rpx] font-semibold"
|
|
31
|
+
:class="active ? 'bg-[#2f2b5f] text-white' : 'bg-[#eff1f6] text-[#5c5b7a]'"
|
|
32
|
+
>
|
|
33
|
+
{{ step }}
|
|
34
|
+
</view>
|
|
35
|
+
<view>
|
|
36
|
+
<text class="text-[26rpx] font-semibold text-[#1f1a3f]">
|
|
37
|
+
{{ title }}
|
|
38
|
+
</text>
|
|
39
|
+
<text v-if="subtitle" class="mt-[4rpx] block text-[20rpx] text-[#6f6b8a]">
|
|
40
|
+
{{ subtitle }}
|
|
41
|
+
</text>
|
|
42
|
+
</view>
|
|
43
|
+
</view>
|
|
44
|
+
<view class="mt-[16rpx]">
|
|
45
|
+
<slot />
|
|
46
|
+
</view>
|
|
47
|
+
</view>
|
|
48
|
+
</template>
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import { computed } from 'wevu'
|
|
3
|
+
|
|
4
|
+
defineOptions({
|
|
5
|
+
options: {
|
|
6
|
+
multipleSlots: true,
|
|
7
|
+
},
|
|
8
|
+
})
|
|
9
|
+
|
|
10
|
+
const props = defineProps({
|
|
11
|
+
title: { type: String, required: true },
|
|
12
|
+
subtitle: { type: String, default: '' },
|
|
13
|
+
items: { type: null, default: () => [] },
|
|
14
|
+
columns: { type: Number, default: 2 },
|
|
15
|
+
}) as {
|
|
16
|
+
title: string
|
|
17
|
+
subtitle?: string
|
|
18
|
+
items?: KpiItem[]
|
|
19
|
+
columns?: 2 | 3
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
defineComponentJson({
|
|
23
|
+
styleIsolation: 'apply-shared',
|
|
24
|
+
})
|
|
25
|
+
|
|
26
|
+
type KpiTone = 'positive' | 'negative' | 'neutral'
|
|
27
|
+
|
|
28
|
+
export interface KpiItem {
|
|
29
|
+
key?: string
|
|
30
|
+
label: string
|
|
31
|
+
value: string | number
|
|
32
|
+
unit?: string
|
|
33
|
+
delta?: number
|
|
34
|
+
footnote?: string
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
const cards = computed(() => {
|
|
38
|
+
const source = Array.isArray(props.items) ? props.items : []
|
|
39
|
+
return source.map((item, index) => ({
|
|
40
|
+
key: item.key ?? String(index),
|
|
41
|
+
item,
|
|
42
|
+
index,
|
|
43
|
+
tone: resolveTone(item.delta),
|
|
44
|
+
isLeading: index === 0,
|
|
45
|
+
}))
|
|
46
|
+
})
|
|
47
|
+
|
|
48
|
+
const gridClass = computed(() => (props.columns === 3 ? 'grid-cols-3' : 'grid-cols-2'))
|
|
49
|
+
|
|
50
|
+
function resolveTone(delta?: number): KpiTone {
|
|
51
|
+
if (delta === undefined || Number.isNaN(delta)) {
|
|
52
|
+
return 'neutral'
|
|
53
|
+
}
|
|
54
|
+
if (delta > 0) {
|
|
55
|
+
return 'positive'
|
|
56
|
+
}
|
|
57
|
+
if (delta < 0) {
|
|
58
|
+
return 'negative'
|
|
59
|
+
}
|
|
60
|
+
return 'neutral'
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
function formatDelta(delta?: number, unit = '') {
|
|
64
|
+
if (delta === undefined || Number.isNaN(delta)) {
|
|
65
|
+
return '--'
|
|
66
|
+
}
|
|
67
|
+
const sign = delta > 0 ? '+' : ''
|
|
68
|
+
return `${sign}${delta}${unit}`
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
function toneBadgeClass(tone: KpiTone) {
|
|
72
|
+
if (tone === 'positive') {
|
|
73
|
+
return 'bg-[#e7f7ee] text-[#1b7a3a]'
|
|
74
|
+
}
|
|
75
|
+
if (tone === 'negative') {
|
|
76
|
+
return 'bg-[#ffe9e9] text-[#b42318]'
|
|
77
|
+
}
|
|
78
|
+
return 'bg-[#edf1f7] text-[#64748b]'
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
function toneDotClass(tone: KpiTone) {
|
|
82
|
+
if (tone === 'positive') {
|
|
83
|
+
return 'bg-[#22c55e]'
|
|
84
|
+
}
|
|
85
|
+
if (tone === 'negative') {
|
|
86
|
+
return 'bg-[#ef4444]'
|
|
87
|
+
}
|
|
88
|
+
return 'bg-[#94a3b8]'
|
|
89
|
+
}
|
|
90
|
+
</script>
|
|
91
|
+
|
|
92
|
+
<template>
|
|
93
|
+
<view class="rounded-[24rpx] bg-white p-[20rpx] shadow-[0_18rpx_40rpx_rgba(17,24,39,0.08)]">
|
|
94
|
+
<view class="flex items-end justify-between">
|
|
95
|
+
<view>
|
|
96
|
+
<text class="text-[28rpx] font-semibold text-[#1f1a3f]">
|
|
97
|
+
{{ title }}
|
|
98
|
+
</text>
|
|
99
|
+
<text v-if="subtitle" class="mt-[6rpx] block text-[22rpx] text-[#6f6b8a]">
|
|
100
|
+
{{ subtitle }}
|
|
101
|
+
</text>
|
|
102
|
+
</view>
|
|
103
|
+
<slot name="action" />
|
|
104
|
+
</view>
|
|
105
|
+
<view class="mt-[16rpx] grid gap-[12rpx]" :class="gridClass">
|
|
106
|
+
<slot name="items" :items="cards">
|
|
107
|
+
<view v-for="card in cards" :key="card.key">
|
|
108
|
+
<view class="rounded-[18rpx] bg-[#f7f7fb] p-[16rpx]">
|
|
109
|
+
<view class="flex items-center justify-between">
|
|
110
|
+
<view class="flex items-center gap-[8rpx]">
|
|
111
|
+
<view class="h-[8rpx] w-[8rpx] rounded-full" :class="toneDotClass(card.tone)" />
|
|
112
|
+
<text class="text-[22rpx] text-[#61618a]">
|
|
113
|
+
{{ card.item.label }}
|
|
114
|
+
</text>
|
|
115
|
+
</view>
|
|
116
|
+
<view v-if="card.isLeading" class="rounded-full bg-[#fff3c2] px-[10rpx] py-[4rpx]">
|
|
117
|
+
<text class="text-[18rpx] font-semibold text-[#8a5200]">
|
|
118
|
+
HOT
|
|
119
|
+
</text>
|
|
120
|
+
</view>
|
|
121
|
+
</view>
|
|
122
|
+
<view class="mt-[10rpx] flex items-end justify-between">
|
|
123
|
+
<view class="flex items-baseline gap-[6rpx]">
|
|
124
|
+
<text class="text-[32rpx] font-bold text-[#1c1c3c]">
|
|
125
|
+
{{ card.item.value }}
|
|
126
|
+
</text>
|
|
127
|
+
<text v-if="card.item.unit" class="text-[20rpx] text-[#7a7aa0]">
|
|
128
|
+
{{ card.item.unit }}
|
|
129
|
+
</text>
|
|
130
|
+
</view>
|
|
131
|
+
<view class="rounded-full px-[10rpx] py-[4rpx]" :class="toneBadgeClass(card.tone)">
|
|
132
|
+
<text class="text-[20rpx] font-semibold">
|
|
133
|
+
{{ card.tone === 'positive' ? '↑' : card.tone === 'negative' ? '↓' : '→' }}
|
|
134
|
+
{{ formatDelta(card.item.delta, card.item.unit ?? '') }}
|
|
135
|
+
</text>
|
|
136
|
+
</view>
|
|
137
|
+
</view>
|
|
138
|
+
<text v-if="card.item.footnote" class="mt-[6rpx] block text-[20rpx] text-[#8a8aa5]">
|
|
139
|
+
{{ card.item.footnote }}
|
|
140
|
+
</text>
|
|
141
|
+
</view>
|
|
142
|
+
</view>
|
|
143
|
+
</slot>
|
|
144
|
+
</view>
|
|
145
|
+
</view>
|
|
146
|
+
</template>
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import { computed } from 'wevu'
|
|
3
|
+
|
|
4
|
+
const emit = defineEmits<{
|
|
5
|
+
(e: 'select', item: ActionItem): void
|
|
6
|
+
}>()
|
|
7
|
+
|
|
8
|
+
const props = defineProps({
|
|
9
|
+
title: { type: String, required: true },
|
|
10
|
+
subtitle: { type: String, default: '' },
|
|
11
|
+
items: { type: null, default: () => [] },
|
|
12
|
+
}) as {
|
|
13
|
+
title: string
|
|
14
|
+
subtitle?: string
|
|
15
|
+
items?: ActionItem[]
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
defineComponentJson({
|
|
19
|
+
styleIsolation: 'apply-shared',
|
|
20
|
+
})
|
|
21
|
+
|
|
22
|
+
interface ActionItem {
|
|
23
|
+
key: string
|
|
24
|
+
title: string
|
|
25
|
+
description?: string
|
|
26
|
+
icon?: string
|
|
27
|
+
tag?: string
|
|
28
|
+
tone?: 'brand' | 'neutral'
|
|
29
|
+
disabled?: boolean
|
|
30
|
+
path?: string
|
|
31
|
+
type?: 'tab' | 'sub'
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
const cards = computed(() => (Array.isArray(props.items) ? props.items : []))
|
|
35
|
+
|
|
36
|
+
function onSelect(item: ActionItem) {
|
|
37
|
+
if (item.disabled) {
|
|
38
|
+
return
|
|
39
|
+
}
|
|
40
|
+
emit('select', item)
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function toneClass(tone?: 'brand' | 'neutral') {
|
|
44
|
+
if (tone === 'brand') {
|
|
45
|
+
return 'bg-[#eef2ff] text-[#3534a5]'
|
|
46
|
+
}
|
|
47
|
+
return 'bg-[#f2f4f8] text-[#5c5b7a]'
|
|
48
|
+
}
|
|
49
|
+
</script>
|
|
50
|
+
|
|
51
|
+
<template>
|
|
52
|
+
<view class="rounded-[24rpx] bg-white p-[20rpx] shadow-[0_18rpx_40rpx_rgba(17,24,39,0.08)]">
|
|
53
|
+
<view class="flex items-end justify-between">
|
|
54
|
+
<view>
|
|
55
|
+
<text class="text-[28rpx] font-semibold text-[#1f1a3f]">
|
|
56
|
+
{{ title }}
|
|
57
|
+
</text>
|
|
58
|
+
<text v-if="subtitle" class="mt-[6rpx] block text-[22rpx] text-[#6f6b8a]">
|
|
59
|
+
{{ subtitle }}
|
|
60
|
+
</text>
|
|
61
|
+
</view>
|
|
62
|
+
</view>
|
|
63
|
+
<view class="mt-[16rpx] grid grid-cols-2 gap-[12rpx]">
|
|
64
|
+
<view
|
|
65
|
+
v-for="item in cards"
|
|
66
|
+
:key="item.key"
|
|
67
|
+
class="rounded-[18rpx] bg-[#f7f7fb] p-[16rpx]"
|
|
68
|
+
:class="item.disabled ? 'opacity-50' : 'opacity-100'"
|
|
69
|
+
@tap="onSelect(item)"
|
|
70
|
+
>
|
|
71
|
+
<view class="flex items-center justify-between">
|
|
72
|
+
<view class="flex items-center gap-[8rpx]">
|
|
73
|
+
<view class="flex h-[36rpx] w-[36rpx] items-center justify-center rounded-[12rpx]" :class="toneClass(item.tone)">
|
|
74
|
+
<t-icon :name="item.icon ?? 'app'" size="22" />
|
|
75
|
+
</view>
|
|
76
|
+
<text class="text-[24rpx] font-semibold text-[#1f1a3f]">
|
|
77
|
+
{{ item.title }}
|
|
78
|
+
</text>
|
|
79
|
+
</view>
|
|
80
|
+
<t-tag v-if="item.tag" size="small" theme="primary" variant="light">
|
|
81
|
+
{{ item.tag }}
|
|
82
|
+
</t-tag>
|
|
83
|
+
</view>
|
|
84
|
+
<text v-if="item.description" class="mt-[10rpx] block text-[20rpx] text-[#6f6b8a]">
|
|
85
|
+
{{ item.description }}
|
|
86
|
+
</text>
|
|
87
|
+
</view>
|
|
88
|
+
</view>
|
|
89
|
+
</view>
|
|
90
|
+
</template>
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import { computed } from 'wevu'
|
|
3
|
+
|
|
4
|
+
defineOptions({
|
|
5
|
+
options: {
|
|
6
|
+
multipleSlots: true,
|
|
7
|
+
},
|
|
8
|
+
})
|
|
9
|
+
|
|
10
|
+
const props = withDefaults(
|
|
11
|
+
defineProps<{
|
|
12
|
+
title: string
|
|
13
|
+
items?: ResultItem[]
|
|
14
|
+
}>(),
|
|
15
|
+
{
|
|
16
|
+
items: () => [],
|
|
17
|
+
},
|
|
18
|
+
)
|
|
19
|
+
|
|
20
|
+
defineComponentJson({
|
|
21
|
+
styleIsolation: 'apply-shared',
|
|
22
|
+
})
|
|
23
|
+
|
|
24
|
+
interface ResultItem {
|
|
25
|
+
label: string
|
|
26
|
+
value: string | number
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const rows = computed(() => props.items ?? [])
|
|
30
|
+
</script>
|
|
31
|
+
|
|
32
|
+
<template>
|
|
33
|
+
<view class="rounded-[20rpx] bg-white p-[20rpx] shadow-[0_12rpx_28rpx_rgba(17,24,39,0.08)]">
|
|
34
|
+
<view class="flex items-center justify-between">
|
|
35
|
+
<text class="text-[26rpx] font-semibold text-[#1f1a3f]">
|
|
36
|
+
{{ title }}
|
|
37
|
+
</text>
|
|
38
|
+
<slot name="action" />
|
|
39
|
+
</view>
|
|
40
|
+
<view class="mt-[12rpx] space-y-[10rpx]">
|
|
41
|
+
<view v-for="row in rows" :key="row.label" class="flex items-center justify-between">
|
|
42
|
+
<text class="text-[22rpx] text-[#6f6b8a]">
|
|
43
|
+
{{ row.label }}
|
|
44
|
+
</text>
|
|
45
|
+
<text class="text-[22rpx] font-semibold text-[#1f1a3f]">
|
|
46
|
+
{{ row.value }}
|
|
47
|
+
</text>
|
|
48
|
+
</view>
|
|
49
|
+
</view>
|
|
50
|
+
</view>
|
|
51
|
+
</template>
|