create-weapp-vite 2.3.14 → 2.3.16

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 (80) hide show
  1. package/dist/cli.js +1 -1
  2. package/dist/index.js +1 -1
  3. package/dist/{src-JolaD7Ia.js → src-C8kzMXK7.js} +11 -7
  4. package/package.json +1 -1
  5. package/templates/default/.vscode/extensions.json +2 -1
  6. package/templates/default/package.json +3 -0
  7. package/templates/lib/.vscode/extensions.json +2 -1
  8. package/templates/lib/package.json +4 -1
  9. package/templates/plugin/.vscode/extensions.json +7 -0
  10. package/templates/plugin/package.json +3 -0
  11. package/templates/tailwindcss/.vscode/extensions.json +2 -1
  12. package/templates/tailwindcss/package.json +3 -0
  13. package/templates/tdesign/.vscode/extensions.json +2 -1
  14. package/templates/tdesign/package.json +3 -0
  15. package/templates/vant/.vscode/extensions.json +2 -1
  16. package/templates/vant/package.json +3 -0
  17. package/templates/wevu/.vscode/extensions.json +2 -1
  18. package/templates/wevu/README.md +3 -3
  19. package/templates/wevu/package.json +4 -1
  20. package/templates/wevu/src/app.vue +1 -60
  21. package/templates/wevu/src/pages/index/index.vue +26 -194
  22. package/templates/wevu/src/pages/layouts/index.vue +0 -18
  23. package/templates/wevu/weapp-vite.config.ts +0 -7
  24. package/templates/wevu-tdesign/.vscode/extensions.json +2 -1
  25. package/templates/wevu-tdesign/README.md +3 -6
  26. package/templates/wevu-tdesign/package.json +4 -1
  27. package/templates/wevu-tdesign/project.private.config.json +0 -66
  28. package/templates/wevu-tdesign/src/app.vue +1 -73
  29. package/templates/wevu-tdesign/src/pages/index/index.vue +19 -362
  30. package/templates/wevu/src/components/InfoPanel/index.vue +0 -52
  31. package/templates/wevu/src/components/StatusPill/index.vue +0 -42
  32. package/templates/wevu/src/packageA/pages/workspace/index.vue +0 -137
  33. package/templates/wevu/src/packageB/pages/settings/index.vue +0 -131
  34. package/templates/wevu/src/pages/overview/index.vue +0 -149
  35. package/templates/wevu-tdesign/public/tabbar/ability-active.png +0 -0
  36. package/templates/wevu-tdesign/public/tabbar/ability.png +0 -0
  37. package/templates/wevu-tdesign/public/tabbar/data-active.png +0 -0
  38. package/templates/wevu-tdesign/public/tabbar/data.png +0 -0
  39. package/templates/wevu-tdesign/public/tabbar/form-active.png +0 -0
  40. package/templates/wevu-tdesign/public/tabbar/form.png +0 -0
  41. package/templates/wevu-tdesign/public/tabbar/home-active.png +0 -0
  42. package/templates/wevu-tdesign/public/tabbar/home.png +0 -0
  43. package/templates/wevu-tdesign/public/tabbar/list-active.png +0 -0
  44. package/templates/wevu-tdesign/public/tabbar/list.png +0 -0
  45. package/templates/wevu-tdesign/src/components/EmptyState/index.vue +0 -36
  46. package/templates/wevu-tdesign/src/components/FilterBar/index.vue +0 -64
  47. package/templates/wevu-tdesign/src/components/FormRow/index.vue +0 -43
  48. package/templates/wevu-tdesign/src/components/FormStep/index.vue +0 -48
  49. package/templates/wevu-tdesign/src/components/KpiBoard/index.vue +0 -145
  50. package/templates/wevu-tdesign/src/components/QuickActionGrid/index.vue +0 -79
  51. package/templates/wevu-tdesign/src/components/ResultCard/index.vue +0 -51
  52. package/templates/wevu-tdesign/src/components/SectionTitle/index.vue +0 -34
  53. package/templates/wevu-tdesign/src/components/TrendCard/index.vue +0 -101
  54. package/templates/wevu-tdesign/src/components/VirtualHostClassDemo/BrokenCard.vue +0 -46
  55. package/templates/wevu-tdesign/src/components/VirtualHostClassDemo/FixedExternalClassCard.vue +0 -50
  56. package/templates/wevu-tdesign/src/components/VirtualHostClassDemo/RecommendedCard.vue +0 -53
  57. package/templates/wevu-tdesign/src/hooks/useDialog.ts +0 -205
  58. package/templates/wevu-tdesign/src/hooks/useFormBinder.ts +0 -17
  59. package/templates/wevu-tdesign/src/hooks/useLayoutFeedbackBridge.ts +0 -17
  60. package/templates/wevu-tdesign/src/hooks/usePullDownRefresh.ts +0 -12
  61. package/templates/wevu-tdesign/src/hooks/useToast.ts +0 -100
  62. package/templates/wevu-tdesign/src/layouts/admin.vue +0 -41
  63. package/templates/wevu-tdesign/src/layouts/default.vue +0 -23
  64. package/templates/wevu-tdesign/src/pages/ability/index.vue +0 -164
  65. package/templates/wevu-tdesign/src/pages/data/index.vue +0 -189
  66. package/templates/wevu-tdesign/src/pages/form/index.vue +0 -271
  67. package/templates/wevu-tdesign/src/pages/layout-feedback/components/FeedbackCallerCard.vue +0 -79
  68. package/templates/wevu-tdesign/src/pages/layout-feedback/index.vue +0 -211
  69. package/templates/wevu-tdesign/src/pages/layout-store/index.vue +0 -127
  70. package/templates/wevu-tdesign/src/pages/layouts/index.vue +0 -120
  71. package/templates/wevu-tdesign/src/pages/list/index.vue +0 -146
  72. package/templates/wevu-tdesign/src/stores/layoutInteractionDemo.ts +0 -129
  73. package/templates/wevu-tdesign/src/subpackages/ability/index.vue +0 -103
  74. package/templates/wevu-tdesign/src/subpackages/lab/class-binding/index.vue +0 -440
  75. package/templates/wevu-tdesign/src/subpackages/lab/index.vue +0 -169
  76. package/templates/wevu-tdesign/src/subpackages/lab/virtual-host-class/index.vue +0 -94
  77. package/templates/wevu-tdesign/src/types/action.ts +0 -14
  78. package/templates/wevu-tdesign/src/types/list.ts +0 -17
  79. package/templates/wevu-tdesign/src/utils/changeEvent.ts +0 -53
  80. package/templates/wevu-tdesign/src/utils/listFilters.ts +0 -34
@@ -1,211 +0,0 @@
1
- <script setup lang="ts">
2
- import { computed, getCurrentInstance, ref, resolveLayoutHost } from 'wevu'
3
- import SectionTitle from '@/components/SectionTitle/index.vue'
4
- import { useDialog } from '@/hooks/useDialog'
5
- import { LAYOUT_DIALOG_BRIDGE_KEY, LAYOUT_TOAST_BRIDGE_KEY } from '@/hooks/useLayoutFeedbackBridge'
6
- import { useToast } from '@/hooks/useToast'
7
- import FeedbackCallerCard from './components/FeedbackCallerCard.vue'
8
-
9
- definePageJson({
10
- navigationBarTitleText: 'Layout 通信演示',
11
- backgroundColor: '#f6f7fb',
12
- })
13
-
14
- const pageInstance = getCurrentInstance<any>()
15
- const { showToast } = useToast({ duration: 1400 })
16
- const { alert, confirm } = useDialog()
17
- const actionSeed = ref(0)
18
- const actionLogs = ref<string[]>([
19
- '页面与子组件都会直接调用 useToast() / useDialog(),由 layout 统一承载宿主。',
20
- ])
21
-
22
- const bridgeStatus = computed(() => {
23
- const toastHost = resolveLayoutHost(LAYOUT_TOAST_BRIDGE_KEY, { context: pageInstance })
24
- const dialogHost = resolveLayoutHost(LAYOUT_DIALOG_BRIDGE_KEY, { context: pageInstance })
25
-
26
- return [
27
- {
28
- key: 'toast',
29
- title: 'Toast Host',
30
- description: toastHost ? '已解析到 layout 内的 t-toast 实例。' : '尚未解析到 toast 宿主。',
31
- ready: Boolean(toastHost),
32
- },
33
- {
34
- key: 'dialog',
35
- title: 'Dialog Host',
36
- description: dialogHost ? '已解析到 layout 内的 t-dialog 实例。' : '尚未解析到 dialog 宿主。',
37
- ready: Boolean(dialogHost),
38
- },
39
- ]
40
- })
41
-
42
- function pushLog(message: string) {
43
- actionLogs.value = [`${new Date().toLocaleTimeString()} ${message}`, ...actionLogs.value].slice(0, 8)
44
- }
45
-
46
- function onChildReport(message: string) {
47
- pushLog(message)
48
- }
49
-
50
- function nextLabel(prefix: string) {
51
- actionSeed.value += 1
52
- return `${prefix} #${actionSeed.value}`
53
- }
54
-
55
- function triggerPageToast() {
56
- const label = nextLabel('页面 Toast')
57
- showToast(`${label} 已通过 layout 宿主触发`)
58
- pushLog(`${label} 已触发`)
59
- }
60
-
61
- function triggerPageAlert() {
62
- const label = nextLabel('页面 Alert')
63
- void alert({
64
- title: label,
65
- content: '这是页面直接调用 useDialog() 后,由 layout 内 t-dialog 承载的弹窗。',
66
- confirmBtn: '知道了',
67
- }).then(() => {
68
- pushLog(`${label} 已确认`)
69
- })
70
- }
71
-
72
- function triggerPageConfirm() {
73
- const label = nextLabel('页面 Confirm')
74
- void confirm({
75
- title: label,
76
- content: '确认后会写入日志,方便观察页面与 layout 宿主之间的通信。',
77
- confirmBtn: '确认',
78
- cancelBtn: '取消',
79
- }).then(() => {
80
- pushLog(`${label} 点击确认`)
81
- }).catch(() => {
82
- pushLog(`${label} 点击取消`)
83
- })
84
- }
85
-
86
- function inspectDialogHostE2E() {
87
- const dialogHost = resolveLayoutHost<any>(LAYOUT_DIALOG_BRIDGE_KEY, { context: pageInstance })
88
- return {
89
- hasHost: Boolean(dialogHost),
90
- visible: dialogHost?.data?.visible ?? dialogHost?.properties?.visible ?? null,
91
- hasOnConfirm: typeof dialogHost?._onConfirm === 'function',
92
- hasOnCancel: typeof dialogHost?._onCancel === 'function',
93
- hasNativeConfirm: typeof dialogHost?.onConfirm === 'function',
94
- hasNativeCancel: typeof dialogHost?.onCancel === 'function',
95
- title: dialogHost?.data?.title ?? dialogHost?.properties?.title ?? '',
96
- confirmBtn: dialogHost?.data?._confirm?.content ?? dialogHost?.properties?.confirmBtn ?? '',
97
- cancelBtn: dialogHost?.data?._cancel?.content ?? dialogHost?.properties?.cancelBtn ?? '',
98
- }
99
- }
100
-
101
- async function runPageAlertCloseE2E() {
102
- triggerPageAlert()
103
- await new Promise(resolve => setTimeout(resolve, 120))
104
- return inspectDialogHostE2E()
105
- }
106
-
107
- async function runPageConfirmOpenE2E() {
108
- triggerPageConfirm()
109
- await new Promise(resolve => setTimeout(resolve, 120))
110
- return inspectDialogHostE2E()
111
- }
112
-
113
- function getLayoutFeedbackLogsE2E() {
114
- return actionLogs.value.slice()
115
- }
116
-
117
- async function runDialogHostConfirmE2E() {
118
- const dialogHost = resolveLayoutHost<any>(LAYOUT_DIALOG_BRIDGE_KEY, { context: pageInstance })
119
- dialogHost?.onConfirm?.()
120
- await new Promise(resolve => setTimeout(resolve, 60))
121
- return inspectDialogHostE2E()
122
- }
123
-
124
- async function runDialogHostCancelE2E() {
125
- const dialogHost = resolveLayoutHost<any>(LAYOUT_DIALOG_BRIDGE_KEY, { context: pageInstance })
126
- dialogHost?.onCancel?.()
127
- await new Promise(resolve => setTimeout(resolve, 60))
128
- return inspectDialogHostE2E()
129
- }
130
-
131
- void inspectDialogHostE2E
132
- void runPageAlertCloseE2E
133
- void runPageConfirmOpenE2E
134
- void getLayoutFeedbackLogsE2E
135
- void runDialogHostConfirmE2E
136
- void runDialogHostCancelE2E
137
- </script>
138
-
139
- <template>
140
- <view class="min-h-screen bg-[#f6f7fb] px-[28rpx] pb-[88rpx] pt-[24rpx] text-[#1c1c3c]">
141
- <view class="rounded-[28rpx] bg-linear-to-br from-[#eef2ff] via-[#ffffff] to-[#ede9fe] p-[20rpx] shadow-[0_18rpx_40rpx_rgba(17,24,39,0.06)]">
142
- <SectionTitle title="Layout 反馈宿主通信" subtitle="页面与子组件都直接调用 hooks,由 layout 持有 toast / dialog 组件实例" />
143
- <text class="mt-[12rpx] block text-[22rpx] leading-[1.7] text-[#5b5b7b]">
144
- 推荐用法是业务侧只关心 useToast() / useDialog(),layout 负责注册宿主;页面和组件都不需要关心 id、selector,也不需要直接拿 layout 实例。
145
- </text>
146
- </view>
147
-
148
- <view class="mt-[18rpx] rounded-[24rpx] bg-white p-[20rpx] shadow-[0_18rpx_40rpx_rgba(17,24,39,0.08)]">
149
- <SectionTitle title="Bridge 状态" subtitle="当前页面是否成功解析到 layout 宿主" />
150
- <view class="mt-[16rpx] flex flex-col gap-[12rpx]">
151
- <view
152
- v-for="item in bridgeStatus"
153
- :key="item.key"
154
- class="rounded-[18rpx] bg-[#f7f7fb] p-[16rpx]"
155
- >
156
- <view class="flex items-center justify-between">
157
- <text class="text-[24rpx] font-semibold text-[#1f1a3f]">
158
- {{ item.title }}
159
- </text>
160
- <t-tag :theme="item.ready ? 'success' : 'warning'" size="small" variant="light">
161
- {{ item.ready ? 'Ready' : 'Pending' }}
162
- </t-tag>
163
- </view>
164
- <text class="mt-[8rpx] block text-[20rpx] leading-[1.7] text-[#6f6b8a]">
165
- {{ item.description }}
166
- </text>
167
- </view>
168
- </view>
169
- </view>
170
-
171
- <view class="mt-[18rpx] rounded-[24rpx] bg-white p-[20rpx] shadow-[0_18rpx_40rpx_rgba(17,24,39,0.08)]">
172
- <SectionTitle title="页面直接调用" subtitle="页面本身直接触发 layout 内的 toast / dialog 方法" />
173
- <view class="mt-[16rpx] flex flex-col gap-[12rpx]">
174
- <view id="layout-feedback-page-toast-trigger">
175
- <t-button block theme="primary" @tap="triggerPageToast">
176
- 页面触发 Toast
177
- </t-button>
178
- </view>
179
- <view id="layout-feedback-page-alert-trigger">
180
- <t-button block theme="primary" variant="outline" @tap="triggerPageAlert">
181
- 页面触发 Alert
182
- </t-button>
183
- </view>
184
- <view id="layout-feedback-page-confirm-trigger">
185
- <t-button block theme="danger" variant="outline" @tap="triggerPageConfirm">
186
- 页面触发 Confirm
187
- </t-button>
188
- </view>
189
- </view>
190
- </view>
191
-
192
- <view class="mt-[18rpx]">
193
- <FeedbackCallerCard :on-report="onChildReport" />
194
- </view>
195
-
196
- <view class="mt-[18rpx] rounded-[24rpx] bg-white p-[20rpx] shadow-[0_18rpx_40rpx_rgba(17,24,39,0.08)]">
197
- <SectionTitle title="通信日志" subtitle="观察页面与子组件调用 layout 宿主后的反馈结果" />
198
- <view class="mt-[16rpx] flex flex-col gap-[10rpx]">
199
- <view
200
- v-for="(item, index) in actionLogs"
201
- :key="`${item}-${index}`"
202
- class="rounded-[16rpx] bg-[#f7f7fb] px-[16rpx] py-[14rpx]"
203
- >
204
- <text class="block text-[20rpx] leading-[1.7] text-[#4c4b6c]">
205
- {{ item }}
206
- </text>
207
- </view>
208
- </view>
209
- </view>
210
- </view>
211
- </template>
@@ -1,127 +0,0 @@
1
- <script setup lang="ts">
2
- import { onUnload, setPageLayout, storeToRefs, watch } from 'wevu'
3
- import SectionTitle from '@/components/SectionTitle/index.vue'
4
- import { useLayoutInteractionDemoStore } from '@/stores/layoutInteractionDemo'
5
-
6
- definePageJson({
7
- navigationBarTitleText: 'Store 调用 Layout',
8
- backgroundColor: '#f6f7fb',
9
- })
10
-
11
- const store = useLayoutInteractionDemoStore()
12
- const { activeLayout, adminLayoutProps, commandStatus, lastResult, logs } = storeToRefs(store)
13
-
14
- watch([activeLayout, adminLayoutProps], ([layout, props]) => {
15
- if (layout === 'admin') {
16
- setPageLayout('admin', props)
17
- return
18
- }
19
- setPageLayout('default')
20
- }, { immediate: true })
21
-
22
- function useDefaultLayout() {
23
- store.setLayout('default')
24
- }
25
-
26
- function useAdminLayout() {
27
- store.setLayout('admin')
28
- }
29
-
30
- function openToastByStore() {
31
- store.triggerToast()
32
- }
33
-
34
- function openAlertByStore() {
35
- store.triggerAlert()
36
- }
37
-
38
- function openConfirmByStore() {
39
- store.triggerConfirm()
40
- }
41
-
42
- function clearLogs() {
43
- store.resetLogs()
44
- }
45
-
46
- onUnload(() => {
47
- setPageLayout('default')
48
- })
49
- </script>
50
-
51
- <template>
52
- <view class="min-h-screen bg-[#f6f7fb] px-[28rpx] pb-[88rpx] pt-[24rpx] text-[#1c1c3c]">
53
- <view class="rounded-[28rpx] bg-linear-to-br from-[#e8f1ff] via-[#ffffff] to-[#eef2ff] p-[20rpx] shadow-[0_18rpx_40rpx_rgba(17,24,39,0.06)]">
54
- <SectionTitle title="Store 驱动 Layout 交互" subtitle="wevu/store 发起意图,页面上下文消费后命中 layout 内的 toast / dialog 宿主" />
55
- <text class="mt-[12rpx] block text-[22rpx] leading-[1.7] text-[#5b5b7b]">
56
- 推荐边界是 store 只保存布局状态和交互意图,真正调用 useToast() / useDialog() / setPageLayout() 仍由页面执行,这样不会把 page runtime hook 直接塞进 store。
57
- </text>
58
- </view>
59
-
60
- <view class="mt-[18rpx] rounded-[24rpx] bg-white p-[20rpx] shadow-[0_18rpx_40rpx_rgba(17,24,39,0.08)]">
61
- <SectionTitle title="当前状态" subtitle="观察 store 对布局和宿主交互的描述" />
62
- <view class="mt-[16rpx] flex flex-col gap-[12rpx]">
63
- <view class="rounded-[18rpx] bg-[#f7f7fb] p-[16rpx]">
64
- <text class="text-[24rpx] font-semibold text-[#1f1a3f]">
65
- 当前布局:{{ activeLayout }}
66
- </text>
67
- <text class="mt-[8rpx] block text-[20rpx] leading-[1.7] text-[#6f6b8a]">
68
- command 状态:{{ commandStatus }}
69
- </text>
70
- </view>
71
- <view class="rounded-[18rpx] bg-[#f7f7fb] p-[16rpx]">
72
- <text class="text-[24rpx] font-semibold text-[#1f1a3f]">
73
- 最近结果
74
- </text>
75
- <text class="mt-[8rpx] block text-[20rpx] leading-[1.7] text-[#6f6b8a]">
76
- {{ lastResult }}
77
- </text>
78
- </view>
79
- </view>
80
- </view>
81
-
82
- <view class="mt-[18rpx] rounded-[24rpx] bg-white p-[20rpx] shadow-[0_18rpx_40rpx_rgba(17,24,39,0.08)]">
83
- <SectionTitle title="切换 Layout" subtitle="store 修改布局状态,页面 watch 后调用 setPageLayout()" />
84
- <view class="mt-[16rpx] flex flex-col gap-[12rpx]">
85
- <t-button block theme="primary" @tap="useDefaultLayout">
86
- Store 切到 default 布局
87
- </t-button>
88
- <t-button block theme="primary" variant="outline" @tap="useAdminLayout">
89
- Store 切到 admin 布局
90
- </t-button>
91
- </view>
92
- </view>
93
-
94
- <view class="mt-[18rpx] rounded-[24rpx] bg-white p-[20rpx] shadow-[0_18rpx_40rpx_rgba(17,24,39,0.08)]">
95
- <SectionTitle title="触发 Layout 宿主" subtitle="store 直接调用 toast / dialog,命中当前 layout 内的反馈宿主" />
96
- <view class="mt-[16rpx] flex flex-col gap-[12rpx]">
97
- <t-button block theme="primary" @tap="openToastByStore">
98
- Store 触发 Toast
99
- </t-button>
100
- <t-button block theme="primary" variant="outline" @tap="openAlertByStore">
101
- Store 触发 Alert
102
- </t-button>
103
- <t-button block theme="danger" variant="outline" @tap="openConfirmByStore">
104
- Store 触发 Confirm
105
- </t-button>
106
- </view>
107
- </view>
108
-
109
- <view class="mt-[18rpx] rounded-[24rpx] bg-white p-[20rpx] shadow-[0_18rpx_40rpx_rgba(17,24,39,0.08)]">
110
- <SectionTitle title="通信日志" subtitle="记录 store 发出的布局切换与交互命令" />
111
- <t-button class="mt-[16rpx]" size="small" theme="default" variant="outline" @tap="clearLogs">
112
- 清空日志
113
- </t-button>
114
- <view class="mt-[16rpx] flex flex-col gap-[10rpx]">
115
- <view
116
- v-for="(item, index) in logs"
117
- :key="`${item}-${index}`"
118
- class="rounded-[16rpx] bg-[#f7f7fb] px-[16rpx] py-[14rpx]"
119
- >
120
- <text class="block text-[20rpx] leading-[1.7] text-[#4c4b6c]">
121
- {{ item }}
122
- </text>
123
- </view>
124
- </view>
125
- </view>
126
- </view>
127
- </template>
@@ -1,120 +0,0 @@
1
- <script setup lang="ts">
2
- import { ref, setPageLayout } from 'wevu'
3
- import { wpi } from 'wevu/api'
4
-
5
- import SectionTitle from '@/components/SectionTitle/index.vue'
6
- import { useToast } from '@/hooks/useToast'
7
-
8
- definePageJson({
9
- navigationBarTitleText: '布局',
10
- backgroundColor: '#f6f7fb',
11
- })
12
-
13
- const { showToast } = useToast()
14
- const currentLayout = ref<'default' | 'admin' | 'none'>('default')
15
-
16
- const cards = [
17
- {
18
- key: 'default',
19
- title: 'default 布局',
20
- desc: '页面未声明 layout 时,会自动命中 src/layouts/default.vue。',
21
- },
22
- {
23
- key: 'admin',
24
- title: 'admin 布局',
25
- desc: '通过 setPageLayout(\'admin\') 切换到命名布局,并把 title/subtitle 作为 props 传给布局组件。',
26
- },
27
- {
28
- key: 'none',
29
- title: '关闭布局',
30
- desc: '通过 setPageLayout(false) 临时移除页面壳,用于沉浸式页或特殊根结构。',
31
- },
32
- ]
33
-
34
- function applyDefaultLayout() {
35
- currentLayout.value = 'default'
36
- setPageLayout('default')
37
- showToast('已切回 default 布局')
38
- }
39
-
40
- function applyAdminLayout() {
41
- currentLayout.value = 'admin'
42
- setPageLayout('admin', {
43
- title: 'Studio Admin',
44
- subtitle: '这个标题来自 setPageLayout() 运行时传入的 props。',
45
- })
46
- showToast('已切换到 admin 布局')
47
- }
48
-
49
- function clearLayout() {
50
- currentLayout.value = 'none'
51
- setPageLayout(false)
52
- showToast('已关闭布局')
53
- }
54
-
55
- async function openLayoutFeedbackDemo() {
56
- await wpi.navigateTo({
57
- url: '/pages/layout-feedback/index',
58
- })
59
- }
60
-
61
- async function openLayoutStoreDemo() {
62
- await wpi.navigateTo({
63
- url: '/pages/layout-store/index',
64
- })
65
- }
66
- </script>
67
-
68
- <template>
69
- <view class="min-h-screen bg-[#f6f7fb] px-[28rpx] pb-[88rpx] pt-[24rpx] text-[#1c1c3c]">
70
- <view class="rounded-[28rpx] bg-linear-to-br from-[#eef2ff] via-[#ffffff] to-[#ede9fe] p-[20rpx] shadow-[0_18rpx_40rpx_rgba(17,24,39,0.06)]">
71
- <SectionTitle title="页面布局能力" subtitle="基础模板已接入 src/layouts 目录约定" />
72
- <text class="mt-[12rpx] block text-[22rpx] leading-[1.7] text-[#5b5b7b]">
73
- 当前状态:{{ currentLayout }}。可在 default、admin 与 false 三种模式之间切换,用来承接后台页、运营页或沉浸式页面。
74
- </text>
75
- </view>
76
-
77
- <view class="mt-[18rpx] flex flex-col gap-[14rpx]">
78
- <view
79
- v-for="item in cards"
80
- :key="item.key"
81
- class="rounded-[24rpx] bg-white p-[20rpx] shadow-[0_18rpx_40rpx_rgba(17,24,39,0.08)]"
82
- >
83
- <text class="text-[28rpx] font-semibold text-[#1f1a3f]">
84
- {{ item.title }}
85
- </text>
86
- <text class="mt-[10rpx] block text-[22rpx] leading-[1.7] text-[#6f6b8a]">
87
- {{ item.desc }}
88
- </text>
89
- </view>
90
- </view>
91
-
92
- <view class="mt-[18rpx] rounded-[24rpx] bg-white p-[20rpx] shadow-[0_18rpx_40rpx_rgba(17,24,39,0.08)]">
93
- <SectionTitle title="切换布局" subtitle="运行时调用 setPageLayout()" />
94
- <view class="mt-[14rpx] flex flex-col gap-[12rpx]">
95
- <t-button block theme="primary" @tap="applyDefaultLayout">
96
- 使用 default 布局
97
- </t-button>
98
- <t-button block theme="primary" variant="outline" @tap="applyAdminLayout">
99
- 切到 admin 布局
100
- </t-button>
101
- <t-button block theme="danger" variant="outline" @tap="clearLayout">
102
- 关闭布局
103
- </t-button>
104
- </view>
105
- </view>
106
-
107
- <view class="mt-[18rpx] rounded-[24rpx] bg-white p-[20rpx] shadow-[0_18rpx_40rpx_rgba(17,24,39,0.08)]">
108
- <SectionTitle title="通信演示" subtitle="查看页面/组件如何直接使用 layout 里的反馈宿主" />
109
- <text class="mt-[12rpx] block text-[22rpx] leading-[1.7] text-[#6f6b8a]">
110
- 演示页会同时展示页面调用和子组件调用,它们都只依赖 useToast() / useDialog(),不会直接操作 layout 实例。
111
- </text>
112
- <t-button class="mt-[16rpx]" block theme="primary" variant="outline" @tap="openLayoutFeedbackDemo">
113
- 打开 Layout 通信演示
114
- </t-button>
115
- <t-button class="mt-[12rpx]" block theme="primary" variant="outline" @tap="openLayoutStoreDemo">
116
- 打开 Store 驱动 Layout 演示
117
- </t-button>
118
- </view>
119
- </view>
120
- </template>
@@ -1,146 +0,0 @@
1
- <script setup lang="ts">
2
- import type { ListItem, StatusFilter, StatusFilterValue } from '@/types/list'
3
-
4
- import { computed, ref, watch } from 'wevu'
5
- import EmptyState from '@/components/EmptyState/index.vue'
6
- import FilterBar from '@/components/FilterBar/index.vue'
7
- import SectionTitle from '@/components/SectionTitle/index.vue'
8
- import { usePullDownRefresh } from '@/hooks/usePullDownRefresh'
9
- import { useToast } from '@/hooks/useToast'
10
- import { buildStatusFilters, filterListItems } from '@/utils/listFilters'
11
-
12
- definePageJson({
13
- navigationBarTitleText: '清单',
14
- backgroundColor: '#f6f7fb',
15
- enablePullDownRefresh: true,
16
- })
17
-
18
- const { showToast } = useToast({ duration: 1000 })
19
-
20
- const query = ref('')
21
- const activeStatus = ref<StatusFilterValue>('all')
22
- const loading = ref(true)
23
-
24
- const items = ref<ListItem[]>([
25
- {
26
- id: 1,
27
- title: '门店会员激活方案',
28
- owner: '王凯',
29
- status: 'processing',
30
- deadline: '今日 18:00',
31
- priority: 'P0',
32
- },
33
- {
34
- id: 2,
35
- title: '社群内容排期',
36
- owner: '林鹤',
37
- status: 'pending',
38
- deadline: '明日 12:00',
39
- priority: 'P1',
40
- },
41
- {
42
- id: 3,
43
- title: '新客任务提醒',
44
- owner: '陈一',
45
- status: 'done',
46
- deadline: '已完成',
47
- priority: 'P2',
48
- },
49
- {
50
- id: 4,
51
- title: '客服脚本优化',
52
- owner: '韩逸',
53
- status: 'processing',
54
- deadline: '周五 20:00',
55
- priority: 'P1',
56
- },
57
- ])
58
-
59
- const statusFilters = ref<StatusFilter[]>([])
60
-
61
- function rebuildStatusFilters() {
62
- statusFilters.value = buildStatusFilters(items.value)
63
- }
64
-
65
- rebuildStatusFilters()
66
- watch(items, rebuildStatusFilters, { deep: true })
67
-
68
- const filteredItems = computed(() =>
69
- filterListItems(items.value, query.value, activeStatus.value),
70
- )
71
-
72
- const hasEmpty = computed(() => !loading.value && filteredItems.value.length === 0)
73
-
74
- function reload() {
75
- loading.value = true
76
- setTimeout(() => {
77
- loading.value = false
78
- showToast('列表已刷新')
79
- }, 600)
80
- }
81
-
82
- function onAction(item: (typeof items.value)[number]) {
83
- showToast(`打开「${item.title}」详情`)
84
- }
85
-
86
- usePullDownRefresh(reload)
87
-
88
- reload()
89
- </script>
90
-
91
- <template>
92
- <view class="min-h-screen bg-[#f6f7fb] px-[28rpx] pb-[88rpx] pt-[24rpx] text-[#1c1c3c]">
93
- <view class="rounded-[28rpx] bg-linear-to-br from-[#fdf2f8] via-[#fff7fb] to-[#ffffff] p-[20rpx]">
94
- <SectionTitle title="任务清单" subtitle="筛选、搜索与分页反馈" />
95
- <view class="mt-[12rpx]">
96
- <FilterBar v-model:query="query" v-model:active="activeStatus" :filters="statusFilters" />
97
- </view>
98
- </view>
99
-
100
- <view v-if="loading" class="mt-[20rpx] flex flex-col items-center gap-[12rpx] rounded-[24rpx] bg-white p-[24rpx]">
101
- <t-loading theme="circular" size="40" />
102
- <text class="text-[22rpx] text-[#6f6b8a]">
103
- 正在同步数据...
104
- </text>
105
- </view>
106
-
107
- <view v-else class="mt-[20rpx] space-y-[14rpx]">
108
- <view v-for="item in filteredItems" :key="item.id" class="rounded-[20rpx] bg-white p-[18rpx] shadow-[0_12rpx_28rpx_rgba(17,24,39,0.08)]">
109
- <view class="flex items-start justify-between">
110
- <view>
111
- <text class="text-[26rpx] font-semibold text-[#1f1a3f]">
112
- {{ item.title }}
113
- </text>
114
- <text class="mt-[6rpx] block text-[22rpx] text-[#6f6b8a]">
115
- 负责人:{{ item.owner }} · 截止 {{ item.deadline }}
116
- </text>
117
- </view>
118
- <t-tag
119
- size="small"
120
- :theme="item.status === 'done' ? 'success' : item.status === 'processing' ? 'primary' : 'warning'"
121
- variant="light"
122
- >
123
- {{ item.status === 'done' ? '已完成' : item.status === 'processing' ? '进行中' : '待启动' }}
124
- </t-tag>
125
- </view>
126
- <view class="mt-[12rpx] flex items-center justify-between">
127
- <view class="flex items-center gap-[8rpx]">
128
- <t-tag size="small" theme="primary" variant="outline">
129
- {{ item.priority }}
130
- </t-tag>
131
- <text class="text-[20rpx] text-[#7a7aa0]">
132
- 进度跟进
133
- </text>
134
- </view>
135
- <t-button size="small" theme="primary" variant="outline" @tap="onAction(item)">
136
- 查看
137
- </t-button>
138
- </view>
139
- </view>
140
- </view>
141
-
142
- <view v-if="hasEmpty" class="mt-[20rpx]">
143
- <EmptyState title="暂无匹配任务" description="调整筛选条件或刷新数据" action-text="重新加载" @action="reload" />
144
- </view>
145
- </view>
146
- </template>