wui-components-v2 1.1.69 → 1.1.71

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 (117) hide show
  1. package/api/core/index.ts +74 -74
  2. package/api/feishu.ts +20 -20
  3. package/api/index.ts +4 -4
  4. package/api/login.ts +51 -51
  5. package/api/menu.ts +45 -45
  6. package/api/page.ts +114 -114
  7. package/api/sys.ts +12 -12
  8. package/api/tree.ts +28 -28
  9. package/components/action-popup/action-popup.vue +116 -116
  10. package/components/add-address-list/add-address-list.vue +187 -187
  11. package/components/add-address-page/add-address-page.vue +77 -77
  12. package/components/add-address-page/config.ts +297 -297
  13. package/components/audio-play/audio-play.vue +220 -220
  14. package/components/batch-upload-file/batch-upload-file.vue +75 -75
  15. package/components/card-botom-buttons/card-botom-buttons.vue +279 -279
  16. package/components/custom-date-picker/custom-date-picker.vue +106 -106
  17. package/components/custom-select-picker/custom-select-picker.vue +95 -95
  18. package/components/demo-block/demo-block.vue +63 -63
  19. package/components/demo-card/demo-card.vue +44 -44
  20. package/components/detail-popup/detail-popup.vue +99 -99
  21. package/components/evaluation-page/evaluation-page.vue +196 -196
  22. package/components/fold-card/fold-card.vue +171 -171
  23. package/components/form-control/form-control.vue +661 -661
  24. package/components/global-loading/GlobalLoading.md +366 -366
  25. package/components/global-loading/global-loading.vue +55 -55
  26. package/components/global-message/GlobalMessage.md +570 -570
  27. package/components/global-message/global-message.vue +68 -68
  28. package/components/global-toast/GlobalToast.md +261 -261
  29. package/components/global-toast/global-toast.vue +56 -56
  30. package/components/label-value/label-value.vue +144 -144
  31. package/components/label-value/open-value-more.vue +56 -56
  32. package/components/list-top-buttons/list-top-buttons.vue +19 -19
  33. package/components/loading/loading.vue +5 -5
  34. package/components/login-form/login-form.vue +126 -126
  35. package/components/login-form-box/login-form-box.vue +65 -65
  36. package/components/mulselect-picker/mulselect-picker.vue +86 -86
  37. package/components/phone-login-form/phone-login-form.vue +204 -204
  38. package/components/privacy-popup/privacy-popup.vue +191 -191
  39. package/components/product-card/product-card.vue +201 -201
  40. package/components/scan-input/scan-input.vue +406 -406
  41. package/components/search/search.vue +128 -128
  42. package/components/select-col-picker/select-col-picker.vue +168 -168
  43. package/components/tab-search/tab-search.vue +73 -73
  44. package/components/tree-select/components/TreeNode.vue +200 -200
  45. package/components/tree-select/components/index.vue +471 -471
  46. package/components/tree-select/components/tree-select.vue +56 -56
  47. package/components/tree-select/index.vue +93 -93
  48. package/components/user-choose/user-choose.vue +169 -151
  49. package/components/video-play/video-play.vue +56 -56
  50. package/components/wui-auto-update-component/wui-auto-update-component.vue +132 -132
  51. package/components/wui-default/wui-default.vue +49 -49
  52. package/components/wui-details-page/wui-details-page.vue +147 -147
  53. package/components/wui-edit-page/wui-edit-page-copy.vue +757 -757
  54. package/components/wui-edit-page/wui-edit-page.vue +793 -793
  55. package/components/wui-enume-select-control/wui-enume-select-control.vue +92 -92
  56. package/components/wui-list/wui-list.vue +235 -235
  57. package/components/wui-login/wui-login.vue +43 -43
  58. package/components/wui-login1/wui-login.vue +41 -41
  59. package/components/wui-menus/wui-menus-top.vue +137 -137
  60. package/components/wui-menus/wui-menus-top1.vue +8 -8
  61. package/components/wui-menus/wui-menus.vue +247 -247
  62. package/components/wui-menus1/components/banner-carousel.vue +320 -320
  63. package/components/wui-menus1/components/navbar.vue +43 -43
  64. package/components/wui-menus1/components/quick-panel.vue +55 -55
  65. package/components/wui-menus1/components/search-bar.vue +49 -49
  66. package/components/wui-menus1/components/section-menus.vue +208 -208
  67. package/components/wui-menus1/wui-menus-top.vue +718 -718
  68. package/components/wui-menus1/wui-menus-top1.vue +398 -398
  69. package/components/wui-menus1/wui-menus.vue +564 -564
  70. package/components/wui-notify-info/notify-handle.vue +53 -53
  71. package/components/wui-notify-info/wui-notify-info.vue +280 -280
  72. package/components/wui-scan-binding-sensor/wui-scan-binding-sensor.vue +75 -75
  73. package/components/wui-search-history-babbar/components/SearchBar.vue +70 -70
  74. package/components/wui-search-history-babbar/wui-search-history-babbar.vue +204 -204
  75. package/components/wui-select-list/wui-select-list.vue +310 -310
  76. package/components/wui-select-popup/wui-select-popup.vue +613 -612
  77. package/components/wui-system-settings/wui-system-settings.vue +144 -144
  78. package/components/wui-tabbar/wui-tabbar.vue +106 -106
  79. package/components/wui-tree-page/components/tree-item.vue +238 -238
  80. package/components/wui-tree-page/wui-tree-page.vue +297 -297
  81. package/components/wui-update-component/wui-update-component.vue +221 -221
  82. package/components/wui-user/wui-user.vue +202 -202
  83. package/composables/types/theme.ts +65 -65
  84. package/composables/types/user.ts +5 -5
  85. package/composables/useColorGenerator.ts +221 -221
  86. package/composables/useCompanyFieldFilter.ts +91 -91
  87. package/composables/useEnumes.ts +43 -43
  88. package/composables/useEventBus.ts +37 -37
  89. package/composables/useGlobalLoading.ts +47 -47
  90. package/composables/useGlobalMessage.ts +53 -53
  91. package/composables/useGlobalToast.ts +63 -63
  92. package/composables/useLocale.ts +54 -54
  93. package/composables/useManualTheme.ts +179 -179
  94. package/composables/useMenus.ts +193 -193
  95. package/composables/useSectionMenus.ts +120 -120
  96. package/composables/useTabbar.ts +50 -50
  97. package/composables/useTheme.ts +74 -74
  98. package/composables/useUser.ts +24 -24
  99. package/index.d.ts +90 -90
  100. package/index.ts +83 -83
  101. package/package.json +24 -24
  102. package/static/iconfont/iconfont.css +63 -63
  103. package/store/language.ts +151 -151
  104. package/store/manualThemeStore.ts +143 -143
  105. package/store/persist.ts +41 -41
  106. package/store/themeStore.ts +74 -74
  107. package/store/userStore.ts +22 -22
  108. package/styles/dark-mode.css +523 -523
  109. package/styles/dark-mode.min.css +1 -1
  110. package/styles/dark-mode.scss +498 -498
  111. package/type.ts +154 -154
  112. package/utils/control-tree.ts +353 -353
  113. package/utils/control-type-supportor.ts +148 -148
  114. package/utils/eventBus.ts +36 -36
  115. package/utils/idata-scan.ts +99 -99
  116. package/utils/index.ts +979 -979
  117. package/utils/rsaEncrypt.ts +10 -10
package/api/tree.ts CHANGED
@@ -1,28 +1,28 @@
1
- import req from './core/index'
2
- // 树列表页面详细配置
3
- export function treeConfigApi(sourceId: string) {
4
- return req({
5
- url: `/v3/ttmpl/config?sourceId=${sourceId}`,
6
- })
7
- }
8
-
9
- // 树数据
10
- export function treeDataApi(sourceId: string) {
11
- return req({
12
- url: `/v3/ttmpl/root-data?sourceId=${sourceId}`,
13
- })
14
- }
15
- // 树节点数据
16
- export function treeNodeDataApi(sourceId: string, mainCode?: string) {
17
- return req({
18
- url: `/v3/ltmpl/top-data?sourceId=${sourceId}&mainCode=${mainCode}`,
19
- })
20
- }
21
-
22
- // 删除树节点
23
- export function treeNodeDeleteApi(sourceId: string, codes: string) {
24
- return req({
25
- url: `/v3/ltmpl/data?sourceId=${sourceId}&codes=${codes}`,
26
- method: 'DELETE',
27
- })
28
- }
1
+ import req from './core/index'
2
+ // 树列表页面详细配置
3
+ export function treeConfigApi(sourceId: string) {
4
+ return req({
5
+ url: `/v3/ttmpl/config?sourceId=${sourceId}`,
6
+ })
7
+ }
8
+
9
+ // 树数据
10
+ export function treeDataApi(sourceId: string) {
11
+ return req({
12
+ url: `/v3/ttmpl/root-data?sourceId=${sourceId}`,
13
+ })
14
+ }
15
+ // 树节点数据
16
+ export function treeNodeDataApi(sourceId: string, mainCode?: string) {
17
+ return req({
18
+ url: `/v3/ltmpl/top-data?sourceId=${sourceId}&mainCode=${mainCode}`,
19
+ })
20
+ }
21
+
22
+ // 删除树节点
23
+ export function treeNodeDeleteApi(sourceId: string, codes: string) {
24
+ return req({
25
+ url: `/v3/ltmpl/data?sourceId=${sourceId}&codes=${codes}`,
26
+ method: 'DELETE',
27
+ })
28
+ }
@@ -1,116 +1,116 @@
1
- <script setup lang="ts">
2
- import { computed, defineEmits, defineOptions, defineProps, ref } from 'vue'
3
- import type { Enums, Groups } from '../../type'
4
- import formControl from '../form-control/form-control.vue'
5
- import { actionDataSave } from '../../api/page'
6
- import { useGlobalToast } from '../../composables/useGlobalToast'
7
-
8
- defineOptions({
9
- name: 'ActionPopup',
10
- })
11
- const props = defineProps<{
12
- fieldGroup?: Groups
13
- show: boolean
14
- code: string
15
- zpaging: any
16
- enumColumn?: Enums
17
- /** 提交成功后跳转的自定义页面路径,不传则默认刷新 */
18
- successUrl?: string
19
- }>()
20
- const emits = defineEmits(['update:show'])
21
- const btnLoading = ref(false)
22
- const toast = useGlobalToast()
23
- const formControlRef = ref()
24
- // 显示开关
25
- const show = computed({
26
- get() {
27
- return props.show
28
- },
29
- set(value: boolean) {
30
- emits('update:show', value)
31
- },
32
- })
33
-
34
- // 格式化文件数据为后端期望的 JSON 字符串
35
- function formatFileData(data: Record<string, any>) {
36
- const result = { ...data }
37
- for (const key in result) {
38
- if (result[key]?.response) {
39
- const fileObj = result[key]
40
- const res = typeof fileObj.response === 'string' ? JSON.parse(fileObj.response) : fileObj.response
41
- result[key] = JSON.stringify({
42
- valid: fileObj.disabled ? 'old' : 'new',
43
- fileKey: res.fileKey,
44
- fileName: fileObj.name,
45
- })
46
- }
47
- }
48
- return result
49
- }
50
-
51
- // 提交数据
52
- async function action() {
53
- btnLoading.value = true
54
- if (!props.fieldGroup?.id) {
55
- return toast.warning({ msg: '无sourceId' })
56
- }
57
- try {
58
- const data = await formControlRef.value.submit()
59
- await actionDataSave(props.fieldGroup?.id || '', props.code, formatFileData(data))
60
- btnLoading.value = false
61
- show.value = false
62
- toast.success({ msg: '操作成功!' })
63
- // 如果传了 successUrl,跳转到自定义页面;否则默认刷新
64
- if (props.successUrl) {
65
- uni.navigateTo({ url: props.successUrl })
66
- } else {
67
- props.zpaging.reload()
68
- }
69
- } catch (error: any) {
70
- btnLoading.value = false
71
- toast.error(error)
72
- }
73
- }
74
- </script>
75
-
76
- <template>
77
- <wd-popup
78
- v-model="show"
79
- position="bottom"
80
- closable
81
- :z-index="999999"
82
- @close="
83
- () => {
84
- show = false
85
- }
86
- "
87
- >
88
- <view class="h-50vh w-100vw bg-white dark:bg-[var(--wot-dark-background)]">
89
- <view class="h-44px bg-white dark:bg-[var(--wot-dark-background)]" />
90
- <view class="w-[calc(100%-44px)] overflow-auto bg-white dark:bg-[var(--wot-dark-background)]">
91
- <formControl
92
- v-if="props.fieldGroup"
93
- ref="formControlRef"
94
- :field-group="props.fieldGroup"
95
- :enum-column="enumColumn"
96
- />
97
- <view class="h-44px bg-white dark:bg-[var(--wot-dark-background)]" />
98
- <view
99
- class="fixed bottom-0 left-0 right-0 box-border w-100% flex p-2 bg-white dark:bg-[var(--wot-dark-background)]"
100
- >
101
- <wd-button
102
- :loading="btnLoading"
103
- custom-class="flex-1"
104
- @click="
105
- () => {
106
- action()
107
- }
108
- "
109
- >
110
- 提交
111
- </wd-button>
112
- </view>
113
- </view>
114
- </view>
115
- </wd-popup>
116
- </template>
1
+ <script setup lang="ts">
2
+ import { computed, defineEmits, defineOptions, defineProps, ref } from 'vue'
3
+ import type { Enums, Groups } from '../../type'
4
+ import formControl from '../form-control/form-control.vue'
5
+ import { actionDataSave } from '../../api/page'
6
+ import { useGlobalToast } from '../../composables/useGlobalToast'
7
+
8
+ defineOptions({
9
+ name: 'ActionPopup',
10
+ })
11
+ const props = defineProps<{
12
+ fieldGroup?: Groups
13
+ show: boolean
14
+ code: string
15
+ zpaging: any
16
+ enumColumn?: Enums
17
+ /** 提交成功后跳转的自定义页面路径,不传则默认刷新 */
18
+ successUrl?: string
19
+ }>()
20
+ const emits = defineEmits(['update:show'])
21
+ const btnLoading = ref(false)
22
+ const toast = useGlobalToast()
23
+ const formControlRef = ref()
24
+ // 显示开关
25
+ const show = computed({
26
+ get() {
27
+ return props.show
28
+ },
29
+ set(value: boolean) {
30
+ emits('update:show', value)
31
+ },
32
+ })
33
+
34
+ // 格式化文件数据为后端期望的 JSON 字符串
35
+ function formatFileData(data: Record<string, any>) {
36
+ const result = { ...data }
37
+ for (const key in result) {
38
+ if (result[key]?.response) {
39
+ const fileObj = result[key]
40
+ const res = typeof fileObj.response === 'string' ? JSON.parse(fileObj.response) : fileObj.response
41
+ result[key] = JSON.stringify({
42
+ valid: fileObj.disabled ? 'old' : 'new',
43
+ fileKey: res.fileKey,
44
+ fileName: fileObj.name,
45
+ })
46
+ }
47
+ }
48
+ return result
49
+ }
50
+
51
+ // 提交数据
52
+ async function action() {
53
+ btnLoading.value = true
54
+ if (!props.fieldGroup?.id) {
55
+ return toast.warning({ msg: '无sourceId' })
56
+ }
57
+ try {
58
+ const data = await formControlRef.value.submit()
59
+ await actionDataSave(props.fieldGroup?.id || '', props.code, formatFileData(data))
60
+ btnLoading.value = false
61
+ show.value = false
62
+ toast.success({ msg: '操作成功!' })
63
+ // 如果传了 successUrl,跳转到自定义页面;否则默认刷新
64
+ if (props.successUrl) {
65
+ uni.navigateTo({ url: props.successUrl })
66
+ } else {
67
+ props.zpaging.reload()
68
+ }
69
+ } catch (error: any) {
70
+ btnLoading.value = false
71
+ toast.error(error)
72
+ }
73
+ }
74
+ </script>
75
+
76
+ <template>
77
+ <wd-popup
78
+ v-model="show"
79
+ position="bottom"
80
+ closable
81
+ :z-index="999999"
82
+ @close="
83
+ () => {
84
+ show = false
85
+ }
86
+ "
87
+ >
88
+ <view class="h-50vh w-100vw bg-white dark:bg-[var(--wot-dark-background)]">
89
+ <view class="h-44px bg-white dark:bg-[var(--wot-dark-background)]" />
90
+ <view class="w-[calc(100%-44px)] overflow-auto bg-white dark:bg-[var(--wot-dark-background)]">
91
+ <formControl
92
+ v-if="props.fieldGroup"
93
+ ref="formControlRef"
94
+ :field-group="props.fieldGroup"
95
+ :enum-column="enumColumn"
96
+ />
97
+ <view class="h-44px bg-white dark:bg-[var(--wot-dark-background)]" />
98
+ <view
99
+ class="fixed bottom-0 left-0 right-0 box-border w-100% flex p-2 bg-white dark:bg-[var(--wot-dark-background)]"
100
+ >
101
+ <wd-button
102
+ :loading="btnLoading"
103
+ custom-class="flex-1"
104
+ @click="
105
+ () => {
106
+ action()
107
+ }
108
+ "
109
+ >
110
+ 提交
111
+ </wd-button>
112
+ </view>
113
+ </view>
114
+ </view>
115
+ </wd-popup>
116
+ </template>
@@ -1,187 +1,187 @@
1
- <script setup>
2
- import { computed, onMounted, ref } from 'vue'
3
- import { useGlobalMessage } from '@/core-components/composables/useGlobalMessage'
4
-
5
- defineOptions({
6
- name: 'AddAddressList',
7
- })
8
- const { addAddressPath } = defineProps({
9
- addAddressPath: {
10
- type: String,
11
- default: '',
12
- },
13
- })
14
-
15
- function addAddress() {
16
- uni.navigateTo({
17
- url: addAddressPath,
18
- })
19
- }
20
-
21
- // 搜索关键词
22
- const keyword = ref('')
23
- // 分页配置
24
- const page = ref(1)
25
- const pageSize = ref(5)
26
- const isNoMore = ref(false)
27
- const loadingText = ref('上拉加载更多')
28
-
29
- // 全部数据源
30
- const allAddressList = ref([])
31
- // 页面展示列表
32
- const showList = ref([])
33
-
34
- // 模拟后端批量数据
35
- function mockAllData() {
36
- const arr = []
37
- for (let i = 1; i <= 30; i++) {
38
- arr.push({
39
- name: `用户${i}`,
40
- phone: `138${String(i).padStart(8, '0')}`,
41
- address: `测试地址${i}号 某某小区${i}栋${i}单元`,
42
- })
43
- }
44
- allAddressList.value = arr
45
- }
46
-
47
- // 分页截取数据
48
- function getPageData() {
49
- const start = (page.value - 1) * pageSize.value
50
- const end = page.value * pageSize.value
51
- return allAddressList.value.slice(start, end)
52
- }
53
-
54
- // 加载更多
55
- function loadMore() {
56
- if (isNoMore.value)
57
- return
58
- loadingText.value = '加载中...'
59
- // 模拟接口延迟
60
- setTimeout(() => {
61
- const newData = getPageData()
62
- if (newData.length === 0) {
63
- isNoMore.value = true
64
- loadingText.value = '没有更多了'
65
- return
66
- }
67
- showList.value.push(...newData)
68
- page.value++
69
- loadingText.value = '上拉加载更多'
70
- }, 600)
71
- }
72
-
73
- // 搜索过滤
74
- const filterList = computed(() => {
75
- if (!keyword.value)
76
- return showList.value
77
- return showList.value.filter(item =>
78
- item.name.includes(keyword.value)
79
- || item.phone.includes(keyword.value)
80
- || item.address.includes(keyword.value),
81
- )
82
- })
83
-
84
- // 返回
85
- const goBack = () => history.back()
86
- // 编辑
87
- function editAddress() {}
88
- // 删除
89
- function deleteAddress(idx) {
90
- uni.showModal({
91
- title: '提示',
92
- content: '确定删除该地址?',
93
- success: (res) => {
94
- if (res.confirm)
95
- showList.value.splice(idx, 1)
96
- },
97
- })
98
- }
99
- function selectAddress(item) {
100
- console.log('item', item)
101
- uni.$emit('addressListBack', {...item,id:1111})
102
- uni.navigateBack({
103
- delta: 1,
104
- })
105
- }
106
-
107
- onMounted(() => {
108
- mockAllData()
109
- loadMore()
110
- })
111
- </script>
112
-
113
- <template>
114
- <view class="min-h-screen bg-gray-50 pb-20">
115
- <!-- 搜索框 -->
116
- <view class="p-4">
117
- <view class="flex items-center rounded-full bg-gray-100 px-4 py-2">
118
- <svg class="mr-2 h-4 w-4 text-gray-400" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
119
- <circle cx="11" cy="11" r="7" />
120
- <path d="M16 16l4 4" stroke-linecap="round" />
121
- </svg>
122
- <input
123
- v-model="keyword"
124
- type="text"
125
- placeholder="请输入姓名/手机号/公司名称"
126
- class="flex-1 bg-transparent text-sm text-gray-700 outline-none placeholder-gray-400"
127
- >
128
- </view>
129
- </view>
130
-
131
- <!-- 列表区域 开启滚动监听 -->
132
- <view
133
- class="overflow-y-auto px-4 space-y-3"
134
- @scrolltolower="loadMore"
135
- >
136
- <view
137
- v-for="(item, index) in showList"
138
- :key="index"
139
- class="rounded-lg bg-white p-4 shadow-sm"
140
- @click="selectAddress(item)"
141
- >
142
- <view class="mb-2 flex items-center">
143
- <text class="mr-3 text-gray-900 font-medium">
144
- {{ item.name }}
145
- </text>
146
- <text class="text-sm text-gray-500">
147
- {{ item.phone }}
148
- </text>
149
- </view>
150
- <text class="mb-3 block text-sm text-gray-500 leading-relaxed">
151
- {{ item.address }}
152
- </text>
153
- <view class="flex justify-end text-sm space-x-6">
154
- <view class="flex items-center text-gray-500" @click="editAddress(item, index)">
155
- <svg class="mr-1 h-4 w-4" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
156
- <path d="M12 20h9M16.5 3.5a2.121 2.121 0 013 3L7 19l-4 1 1-4L16.5 3.5z" />
157
- </svg>
158
- 编辑
159
- </view>
160
- <view class="flex items-center text-gray-500" @click="deleteAddress(index)">
161
- <svg class="mr-1 h-4 w-4" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
162
- <path d="M3 6h18M8 6V4a2 2 0 012-2h4a2 2 0 012 2v2M10 11v6M14 11v6M5 6h14v14a2 2 0 01-2 2H7a2 2 0 01-2-2V6z" />
163
- </svg>
164
- 删除
165
- </view>
166
- </view>
167
- </view>
168
-
169
- <!-- 加载提示 -->
170
- <view class="py-4 text-center text-sm text-gray-400">
171
- {{ loadingText }}
172
- </view>
173
- </view>
174
-
175
- <!-- 底部新增按钮 -->
176
- <view
177
- class="fixed bottom-6 left-1/2 h-12 w-11/12 flex items-center justify-center rounded-full bg-blue-500 text-white font-medium -translate-x-1/2"
178
- @click="addAddress"
179
- >
180
- 新增地址
181
- </view>
182
- </view>
183
- </template>
184
-
185
- <style scoped>
186
-
187
- </style>
1
+ <script setup>
2
+ import { computed, onMounted, ref } from 'vue'
3
+ import { useGlobalMessage } from '@/core-components/composables/useGlobalMessage'
4
+
5
+ defineOptions({
6
+ name: 'AddAddressList',
7
+ })
8
+ const { addAddressPath } = defineProps({
9
+ addAddressPath: {
10
+ type: String,
11
+ default: '',
12
+ },
13
+ })
14
+
15
+ function addAddress() {
16
+ uni.navigateTo({
17
+ url: addAddressPath,
18
+ })
19
+ }
20
+
21
+ // 搜索关键词
22
+ const keyword = ref('')
23
+ // 分页配置
24
+ const page = ref(1)
25
+ const pageSize = ref(5)
26
+ const isNoMore = ref(false)
27
+ const loadingText = ref('上拉加载更多')
28
+
29
+ // 全部数据源
30
+ const allAddressList = ref([])
31
+ // 页面展示列表
32
+ const showList = ref([])
33
+
34
+ // 模拟后端批量数据
35
+ function mockAllData() {
36
+ const arr = []
37
+ for (let i = 1; i <= 30; i++) {
38
+ arr.push({
39
+ name: `用户${i}`,
40
+ phone: `138${String(i).padStart(8, '0')}`,
41
+ address: `测试地址${i}号 某某小区${i}栋${i}单元`,
42
+ })
43
+ }
44
+ allAddressList.value = arr
45
+ }
46
+
47
+ // 分页截取数据
48
+ function getPageData() {
49
+ const start = (page.value - 1) * pageSize.value
50
+ const end = page.value * pageSize.value
51
+ return allAddressList.value.slice(start, end)
52
+ }
53
+
54
+ // 加载更多
55
+ function loadMore() {
56
+ if (isNoMore.value)
57
+ return
58
+ loadingText.value = '加载中...'
59
+ // 模拟接口延迟
60
+ setTimeout(() => {
61
+ const newData = getPageData()
62
+ if (newData.length === 0) {
63
+ isNoMore.value = true
64
+ loadingText.value = '没有更多了'
65
+ return
66
+ }
67
+ showList.value.push(...newData)
68
+ page.value++
69
+ loadingText.value = '上拉加载更多'
70
+ }, 600)
71
+ }
72
+
73
+ // 搜索过滤
74
+ const filterList = computed(() => {
75
+ if (!keyword.value)
76
+ return showList.value
77
+ return showList.value.filter(item =>
78
+ item.name.includes(keyword.value)
79
+ || item.phone.includes(keyword.value)
80
+ || item.address.includes(keyword.value),
81
+ )
82
+ })
83
+
84
+ // 返回
85
+ const goBack = () => history.back()
86
+ // 编辑
87
+ function editAddress() {}
88
+ // 删除
89
+ function deleteAddress(idx) {
90
+ uni.showModal({
91
+ title: '提示',
92
+ content: '确定删除该地址?',
93
+ success: (res) => {
94
+ if (res.confirm)
95
+ showList.value.splice(idx, 1)
96
+ },
97
+ })
98
+ }
99
+ function selectAddress(item) {
100
+ console.log('item', item)
101
+ uni.$emit('addressListBack', {...item,id:1111})
102
+ uni.navigateBack({
103
+ delta: 1,
104
+ })
105
+ }
106
+
107
+ onMounted(() => {
108
+ mockAllData()
109
+ loadMore()
110
+ })
111
+ </script>
112
+
113
+ <template>
114
+ <view class="min-h-screen bg-gray-50 pb-20">
115
+ <!-- 搜索框 -->
116
+ <view class="p-4">
117
+ <view class="flex items-center rounded-full bg-gray-100 px-4 py-2">
118
+ <svg class="mr-2 h-4 w-4 text-gray-400" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
119
+ <circle cx="11" cy="11" r="7" />
120
+ <path d="M16 16l4 4" stroke-linecap="round" />
121
+ </svg>
122
+ <input
123
+ v-model="keyword"
124
+ type="text"
125
+ placeholder="请输入姓名/手机号/公司名称"
126
+ class="flex-1 bg-transparent text-sm text-gray-700 outline-none placeholder-gray-400"
127
+ >
128
+ </view>
129
+ </view>
130
+
131
+ <!-- 列表区域 开启滚动监听 -->
132
+ <view
133
+ class="overflow-y-auto px-4 space-y-3"
134
+ @scrolltolower="loadMore"
135
+ >
136
+ <view
137
+ v-for="(item, index) in showList"
138
+ :key="index"
139
+ class="rounded-lg bg-white p-4 shadow-sm"
140
+ @click="selectAddress(item)"
141
+ >
142
+ <view class="mb-2 flex items-center">
143
+ <text class="mr-3 text-gray-900 font-medium">
144
+ {{ item.name }}
145
+ </text>
146
+ <text class="text-sm text-gray-500">
147
+ {{ item.phone }}
148
+ </text>
149
+ </view>
150
+ <text class="mb-3 block text-sm text-gray-500 leading-relaxed">
151
+ {{ item.address }}
152
+ </text>
153
+ <view class="flex justify-end text-sm space-x-6">
154
+ <view class="flex items-center text-gray-500" @click="editAddress(item, index)">
155
+ <svg class="mr-1 h-4 w-4" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
156
+ <path d="M12 20h9M16.5 3.5a2.121 2.121 0 013 3L7 19l-4 1 1-4L16.5 3.5z" />
157
+ </svg>
158
+ 编辑
159
+ </view>
160
+ <view class="flex items-center text-gray-500" @click="deleteAddress(index)">
161
+ <svg class="mr-1 h-4 w-4" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
162
+ <path d="M3 6h18M8 6V4a2 2 0 012-2h4a2 2 0 012 2v2M10 11v6M14 11v6M5 6h14v14a2 2 0 01-2 2H7a2 2 0 01-2-2V6z" />
163
+ </svg>
164
+ 删除
165
+ </view>
166
+ </view>
167
+ </view>
168
+
169
+ <!-- 加载提示 -->
170
+ <view class="py-4 text-center text-sm text-gray-400">
171
+ {{ loadingText }}
172
+ </view>
173
+ </view>
174
+
175
+ <!-- 底部新增按钮 -->
176
+ <view
177
+ class="fixed bottom-6 left-1/2 h-12 w-11/12 flex items-center justify-center rounded-full bg-blue-500 text-white font-medium -translate-x-1/2"
178
+ @click="addAddress"
179
+ >
180
+ 新增地址
181
+ </view>
182
+ </view>
183
+ </template>
184
+
185
+ <style scoped>
186
+
187
+ </style>