hy-app 0.3.1 → 0.3.2
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/README.md +6 -3
- package/common/shakeService.ts +31 -29
- package/components/avatar.zip +0 -0
- package/components/hy-action-sheet/hy-action-sheet.vue +71 -46
- package/components/hy-address-picker/hy-address-picker.vue +94 -83
- package/components/hy-avatar/hy-avatar.vue +84 -85
- package/components/hy-badge/hy-badge.vue +47 -46
- package/components/hy-button/hy-button.vue +117 -93
- package/components/hy-calendar/hy-calendar.vue +168 -160
- package/components/hy-card/hy-card.vue +50 -43
- package/components/hy-card/typing.d.ts +33 -32
- package/components/hy-cell/hy-cell.vue +73 -51
- package/components/hy-check-button/hy-check-button.vue +54 -47
- package/components/hy-checkbox/hy-checkbox.vue +97 -105
- package/components/hy-code-input/hy-code-input.vue +80 -89
- package/components/hy-config-provider/hy-config-provider.vue +19 -20
- package/components/hy-count-down/hy-count-down.vue +66 -67
- package/components/hy-count-to/hy-count-to.vue +105 -99
- package/components/hy-count-to/typing.d.ts +13 -12
- package/components/hy-datetime-picker/hy-datetime-picker.vue +261 -253
- package/components/hy-datetime-picker/typing.d.ts +42 -40
- package/components/hy-divider/hy-divider.vue +68 -73
- package/components/hy-dropdown/hy-dropdown.vue +20 -19
- package/components/hy-dropdown-item/hy-dropdown-item.vue +66 -61
- package/components/hy-dropdown-item/typing.d.ts +9 -9
- package/components/hy-empty/hy-empty.vue +42 -42
- package/components/hy-flex/hy-flex.vue +52 -26
- package/components/hy-float-button/hy-float-button.vue +218 -210
- package/components/hy-folding-panel/hy-folding-panel.vue +32 -33
- package/components/hy-form/hy-form.vue +264 -259
- package/components/hy-grid/hy-grid.vue +44 -43
- package/components/hy-icon/hy-icon.vue +61 -67
- package/components/hy-image/hy-image.vue +112 -88
- package/components/hy-image/typing.d.ts +27 -23
- package/components/hy-input/hy-input.vue +157 -127
- package/components/hy-input/typing.d.ts +53 -47
- package/components/hy-line/hy-line.vue +26 -26
- package/components/hy-line-progress/hy-line-progress.vue +42 -35
- package/components/hy-list/hy-list.vue +76 -85
- package/components/hy-loading/hy-loading.vue +26 -23
- package/components/hy-menu/hy-menu.vue +48 -43
- package/components/hy-menu/typing.d.ts +18 -17
- package/components/hy-modal/hy-modal.vue +39 -35
- package/components/hy-navbar/hy-navbar.vue +25 -25
- package/components/hy-navbar/typing.d.ts +24 -22
- package/components/hy-notice-bar/hy-notice-bar.vue +26 -27
- package/components/hy-notify/hy-notify.vue +53 -53
- package/components/hy-number-step/hy-number-step.vue +134 -146
- package/components/hy-number-step/typing.d.ts +35 -35
- package/components/hy-overlay/hy-overlay.vue +23 -21
- package/components/hy-pagination/hy-pagination.vue +41 -36
- package/components/hy-picker/hy-picker.vue +184 -154
- package/components/hy-picker/typing.d.ts +39 -39
- package/components/hy-popover/hy-popover.vue +97 -77
- package/components/hy-popup/hy-popup.vue +107 -98
- package/components/hy-price/hy-price.vue +38 -34
- package/components/hy-qrcode/hy-qrcode.vue +50 -51
- package/components/hy-radio/hy-radio.vue +101 -113
- package/components/hy-rate/hy-rate.vue +107 -88
- package/components/hy-read-more/hy-read-more.vue +64 -49
- package/components/hy-scroll-list/hy-scroll-list.vue +45 -48
- package/components/hy-search/hy-search.vue +73 -66
- package/components/hy-search/typing.d.ts +36 -35
- package/components/hy-signature/hy-signature.vue +282 -240
- package/components/hy-slider/hy-slider.vue +195 -153
- package/components/hy-slider/typing.d.ts +21 -21
- package/components/hy-steps/hy-steps.vue +118 -90
- package/components/hy-steps/index.scss +31 -21
- package/components/hy-submit-bar/hy-submit-bar.vue +61 -70
- package/components/hy-subsection/hy-subsection.vue +99 -102
- package/components/hy-subsection/typing.d.ts +19 -19
- package/components/hy-swipe-action/hy-swipe-action.vue +131 -118
- package/components/hy-swiper/hy-swiper.vue +85 -71
- package/components/hy-switch/hy-switch.vue +67 -72
- package/components/hy-switch/typing.d.ts +21 -19
- package/components/hy-tabs/hy-tabs.vue +168 -113
- package/components/hy-tag/hy-tag.vue +90 -86
- package/components/hy-tag/typing.d.ts +26 -21
- package/components/hy-text/hy-text.vue +119 -111
- package/components/hy-textarea/hy-textarea.vue +100 -93
- package/components/hy-textarea/typing.d.ts +36 -31
- package/components/hy-toast/hy-toast.vue +77 -67
- package/components/hy-tooltip/hy-tooltip.vue +109 -91
- package/components/hy-transition/hy-transition.vue +62 -66
- package/components/hy-upload/hy-upload.vue +294 -152
- package/components/hy-upload/typing.d.ts +41 -36
- package/components/hy-warn/hy-warn.vue +34 -27
- package/components/hy-waterfall/hy-waterfall.vue +83 -74
- package/components/hy-watermark/hy-watermark.vue +134 -115
- package/composables/usePopover.ts +236 -221
- package/composables/useQueue.ts +53 -52
- package/package.json +2 -2
- package/store/index.ts +9 -1
- package/typing/index.ts +0 -1
- package/typing/modules/common.d.ts +0 -2
- package/web-types.json +1 -1
package/README.md
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
|
-
##
|
|
2
|
-
[
|
|
3
|
-
[
|
|
1
|
+
## 在线使用文档地址
|
|
2
|
+
[华玥组件库文档(需要翻墙)](https://hy-component-docs.vercel.app/)
|
|
3
|
+
[华玥组件库文档(国内地址)](https://www.gxh151.top)
|
|
4
|
+
|
|
5
|
+
## H5测试页面地址
|
|
6
|
+
[华玥组件库dome(需要翻墙)](https://hy-design-uni.vercel.app/#/)
|
|
4
7
|
|
|
5
8
|
## 安装教程
|
|
6
9
|
|
package/common/shakeService.ts
CHANGED
|
@@ -1,60 +1,62 @@
|
|
|
1
1
|
// src/composables/useShakeService.ts
|
|
2
|
-
import { ref
|
|
3
|
-
import {
|
|
2
|
+
import { ref } from "vue";
|
|
3
|
+
import type { Ref } from "vue";
|
|
4
|
+
import { debounce } from "../utils";
|
|
4
5
|
|
|
5
6
|
interface Acceleration {
|
|
6
|
-
x: number
|
|
7
|
-
y: number
|
|
8
|
-
z: number
|
|
7
|
+
x: number;
|
|
8
|
+
y: number;
|
|
9
|
+
z: number;
|
|
9
10
|
}
|
|
10
11
|
|
|
11
12
|
export function useShakeService(shakeThreshold: number = 30) {
|
|
12
|
-
const lastAcceleration: Ref<Acceleration> = ref({ x: 0, y: 0, z: 0 })
|
|
13
|
-
const lastTime: Ref<number> = ref(Date.now())
|
|
14
|
-
const shakeCallback: Ref<null | (() => void)> = ref(null)
|
|
13
|
+
const lastAcceleration: Ref<Acceleration> = ref({ x: 0, y: 0, z: 0 });
|
|
14
|
+
const lastTime: Ref<number> = ref(Date.now());
|
|
15
|
+
const shakeCallback: Ref<null | (() => void)> = ref(null);
|
|
15
16
|
|
|
16
17
|
const startShakeListener = (callback: () => void): void => {
|
|
17
|
-
shakeCallback.value = callback
|
|
18
|
+
shakeCallback.value = callback;
|
|
18
19
|
uni.startAccelerometer({
|
|
19
20
|
success: () => {
|
|
20
|
-
uni.onAccelerometerChange(handleShake)
|
|
21
|
+
uni.onAccelerometerChange(handleShake);
|
|
21
22
|
},
|
|
22
23
|
fail: (err: any) => {
|
|
23
|
-
console.error(
|
|
24
|
+
console.error("加速度传感器启动失败", err.errMsg);
|
|
24
25
|
},
|
|
25
|
-
})
|
|
26
|
-
}
|
|
26
|
+
});
|
|
27
|
+
};
|
|
27
28
|
|
|
28
29
|
const stopShakeListener = (): void => {
|
|
29
30
|
uni.stopAccelerometer().then(
|
|
30
31
|
(res) => {
|
|
31
|
-
uni.offAccelerometerChange(handleShake)
|
|
32
|
+
uni.offAccelerometerChange(handleShake);
|
|
32
33
|
},
|
|
33
|
-
(err) => console.error(
|
|
34
|
-
)
|
|
35
|
-
}
|
|
34
|
+
(err) => console.error("加速度传感器关闭失败", err.errMsg),
|
|
35
|
+
);
|
|
36
|
+
};
|
|
36
37
|
|
|
37
38
|
const handleShake = (res: Acceleration): void => {
|
|
38
|
-
const acceleration = res
|
|
39
|
-
const currentTime = Date.now()
|
|
40
|
-
const timeDiff = (currentTime - lastTime.value) / 1000 // 转换为秒
|
|
39
|
+
const acceleration = res;
|
|
40
|
+
const currentTime = Date.now();
|
|
41
|
+
const timeDiff = (currentTime - lastTime.value) / 1000; // 转换为秒
|
|
41
42
|
|
|
42
43
|
// 计算加速度的欧几里得距离
|
|
43
|
-
const deltaX = acceleration.x - lastAcceleration.value.x
|
|
44
|
-
const deltaY = acceleration.y - lastAcceleration.value.y
|
|
45
|
-
const deltaZ = acceleration.z - lastAcceleration.value.z
|
|
46
|
-
const speed =
|
|
44
|
+
const deltaX = acceleration.x - lastAcceleration.value.x;
|
|
45
|
+
const deltaY = acceleration.y - lastAcceleration.value.y;
|
|
46
|
+
const deltaZ = acceleration.z - lastAcceleration.value.z;
|
|
47
|
+
const speed =
|
|
48
|
+
Math.sqrt(deltaX * deltaX + deltaY * deltaY + deltaZ * deltaZ) / timeDiff;
|
|
47
49
|
|
|
48
50
|
if (speed > shakeThreshold && shakeCallback.value) {
|
|
49
|
-
debounce(shakeCallback.value, 500)
|
|
51
|
+
debounce(shakeCallback.value, 500);
|
|
50
52
|
}
|
|
51
53
|
|
|
52
|
-
lastAcceleration.value = acceleration
|
|
53
|
-
lastTime.value = currentTime
|
|
54
|
-
}
|
|
54
|
+
lastAcceleration.value = acceleration;
|
|
55
|
+
lastTime.value = currentTime;
|
|
56
|
+
};
|
|
55
57
|
|
|
56
58
|
return {
|
|
57
59
|
startShakeListener,
|
|
58
60
|
stopShakeListener,
|
|
59
|
-
}
|
|
61
|
+
};
|
|
60
62
|
}
|
|
Binary file
|
|
@@ -20,7 +20,10 @@
|
|
|
20
20
|
} ${customStyle}`"
|
|
21
21
|
>
|
|
22
22
|
<!-- 标题 -->
|
|
23
|
-
<view
|
|
23
|
+
<view
|
|
24
|
+
v-if="title"
|
|
25
|
+
:class="`hy-action-sheet__header ${customHeaderClass}`"
|
|
26
|
+
>
|
|
24
27
|
{{ title }}
|
|
25
28
|
<HyIcon
|
|
26
29
|
customClass="hy-action-sheet__close"
|
|
@@ -43,8 +46,13 @@
|
|
|
43
46
|
@click="onSelect(rowIndex, 'action')"
|
|
44
47
|
>
|
|
45
48
|
<HyLoading :show="!!action?.loading" mode="circle" />
|
|
46
|
-
<view v-if="!action?.loading" class="hy-action-sheet__name">{{
|
|
47
|
-
|
|
49
|
+
<view v-if="!action?.loading" class="hy-action-sheet__name">{{
|
|
50
|
+
action?.name
|
|
51
|
+
}}</view>
|
|
52
|
+
<view
|
|
53
|
+
v-if="!action?.loading && action?.sub"
|
|
54
|
+
class="hy-action-sheet__subname"
|
|
55
|
+
>
|
|
48
56
|
{{ action?.sub }}
|
|
49
57
|
</view>
|
|
50
58
|
</button>
|
|
@@ -65,8 +73,13 @@
|
|
|
65
73
|
class="hy-action-sheet__panel"
|
|
66
74
|
@click="onSelect(rowIndex, 'panels', colIndex)"
|
|
67
75
|
>
|
|
68
|
-
<image
|
|
69
|
-
|
|
76
|
+
<image
|
|
77
|
+
class="hy-action-sheet__panel-img"
|
|
78
|
+
:src="(col as any).iconUrl"
|
|
79
|
+
/>
|
|
80
|
+
<view class="hy-action-sheet__panel-title">{{
|
|
81
|
+
(col as any).name
|
|
82
|
+
}}</view>
|
|
70
83
|
</view>
|
|
71
84
|
</view>
|
|
72
85
|
</view>
|
|
@@ -90,32 +103,38 @@
|
|
|
90
103
|
</HyPopup>
|
|
91
104
|
</view>
|
|
92
105
|
</template>
|
|
106
|
+
|
|
93
107
|
<script lang="ts">
|
|
94
108
|
export default {
|
|
95
|
-
name:
|
|
109
|
+
name: "hy-action-sheet",
|
|
96
110
|
options: {
|
|
97
111
|
addGlobalClass: true,
|
|
98
112
|
virtualHost: true,
|
|
99
|
-
styleIsolation:
|
|
113
|
+
styleIsolation: "shared",
|
|
100
114
|
},
|
|
101
|
-
}
|
|
115
|
+
};
|
|
102
116
|
</script>
|
|
103
117
|
|
|
104
118
|
<script lang="ts" setup>
|
|
119
|
+
import { watch, ref } from "vue";
|
|
120
|
+
import type { PropType, CSSProperties } from "vue";
|
|
121
|
+
import { isArray } from "../../utils";
|
|
122
|
+
import type {
|
|
123
|
+
IActionSheetPanel,
|
|
124
|
+
IActionSheetEmits,
|
|
125
|
+
IActionSheetAction,
|
|
126
|
+
} from "./typing";
|
|
127
|
+
// 组件
|
|
128
|
+
import HyIcon from "../hy-icon/hy-icon.vue";
|
|
129
|
+
import HyPopup from "../hy-popup/hy-popup.vue";
|
|
130
|
+
import HyLoading from "../hy-loading/hy-loading.vue";
|
|
131
|
+
import HyButton from "../hy-button/hy-button.vue";
|
|
132
|
+
|
|
105
133
|
/**
|
|
106
134
|
* 本组件用于从底部弹出一个操作菜单,供用户选择并返回结果。本组件功能类似于uni的uni.showActionSheetAPI,配置更加灵活,所有平台都表现一致。
|
|
107
135
|
* @displayName hy-action-sheet
|
|
108
136
|
*/
|
|
109
|
-
defineOptions({})
|
|
110
|
-
import { watch, ref, PropType, type CSSProperties } from 'vue'
|
|
111
|
-
import { isArray } from '../../utils'
|
|
112
|
-
import { IActionSheetPanel, IActionSheetEmits, IActionSheetAction } from './typing.d.ts'
|
|
113
|
-
|
|
114
|
-
// 组件
|
|
115
|
-
import HyIcon from '../hy-icon/hy-icon.vue'
|
|
116
|
-
import HyPopup from '../hy-popup/hy-popup.vue'
|
|
117
|
-
import HyLoading from '../hy-loading/hy-loading.vue'
|
|
118
|
-
import HyButton from '../hy-button/hy-button.vue'
|
|
137
|
+
defineOptions({});
|
|
119
138
|
|
|
120
139
|
// const props = withDefaults(defineProps<HyActionSheetProps>(), defaultProps)
|
|
121
140
|
const props = defineProps({
|
|
@@ -129,14 +148,14 @@ const props = defineProps({
|
|
|
129
148
|
actions: {
|
|
130
149
|
type: Array as PropType<IActionSheetAction[]>,
|
|
131
150
|
default() {
|
|
132
|
-
return []
|
|
151
|
+
return [];
|
|
133
152
|
},
|
|
134
153
|
},
|
|
135
154
|
/** 自定义面板项,可以为字符串数组,也可以为对象数组,如果为二维数组,则为多行展示 */
|
|
136
155
|
panels: {
|
|
137
156
|
type: Array as PropType<Array<IActionSheetPanel | IActionSheetPanel[]>>,
|
|
138
157
|
default() {
|
|
139
|
-
return []
|
|
158
|
+
return [];
|
|
140
159
|
},
|
|
141
160
|
},
|
|
142
161
|
/** 操作菜单是否展示 */
|
|
@@ -152,7 +171,7 @@ const props = defineProps({
|
|
|
152
171
|
* */
|
|
153
172
|
titleAlign: {
|
|
154
173
|
type: String,
|
|
155
|
-
default:
|
|
174
|
+
default: "center",
|
|
156
175
|
},
|
|
157
176
|
/** 取消按钮的提示文字,不为空时显示按钮 */
|
|
158
177
|
cancelText: String,
|
|
@@ -187,71 +206,77 @@ const props = defineProps({
|
|
|
187
206
|
customClass: String,
|
|
188
207
|
/** 自定义标题类名 */
|
|
189
208
|
customHeaderClass: String,
|
|
190
|
-
})
|
|
191
|
-
const emit = defineEmits<IActionSheetEmits>()
|
|
209
|
+
});
|
|
210
|
+
const emit = defineEmits<IActionSheetEmits>();
|
|
192
211
|
|
|
193
|
-
const formatPanels = ref<Array<IActionSheetPanel> | Array<IActionSheetPanel[]>>(
|
|
194
|
-
|
|
212
|
+
const formatPanels = ref<Array<IActionSheetPanel> | Array<IActionSheetPanel[]>>(
|
|
213
|
+
[],
|
|
214
|
+
);
|
|
215
|
+
const showPopup = ref<boolean>(false);
|
|
195
216
|
|
|
196
|
-
watch(() => props.panels, computedValue, { deep: true, immediate: true })
|
|
217
|
+
watch(() => props.panels, computedValue, { deep: true, immediate: true });
|
|
197
218
|
|
|
198
219
|
watch(
|
|
199
220
|
() => props.modelValue,
|
|
200
221
|
(newValue) => {
|
|
201
|
-
showPopup.value = newValue
|
|
222
|
+
showPopup.value = newValue;
|
|
202
223
|
},
|
|
203
224
|
{ deep: true, immediate: true },
|
|
204
|
-
)
|
|
225
|
+
);
|
|
205
226
|
|
|
206
227
|
function isPanelArray() {
|
|
207
|
-
return props.panels.length && !isArray(props.panels[0])
|
|
228
|
+
return props.panels.length && !isArray(props.panels[0]);
|
|
208
229
|
}
|
|
209
230
|
function computedValue() {
|
|
210
231
|
formatPanels.value = isPanelArray()
|
|
211
232
|
? [props.panels as IActionSheetPanel[]]
|
|
212
|
-
: (props.panels as IActionSheetPanel[][])
|
|
233
|
+
: (props.panels as IActionSheetPanel[][]);
|
|
213
234
|
}
|
|
214
235
|
|
|
215
|
-
function onSelect(
|
|
216
|
-
|
|
236
|
+
function onSelect(
|
|
237
|
+
rowIndex: number,
|
|
238
|
+
type: "action" | "panels",
|
|
239
|
+
colIndex?: number,
|
|
240
|
+
) {
|
|
241
|
+
if (type === "action") {
|
|
217
242
|
if (props.actions[rowIndex].disabled || props.actions[rowIndex].loading) {
|
|
218
|
-
return
|
|
243
|
+
return;
|
|
219
244
|
}
|
|
220
|
-
emit(
|
|
245
|
+
emit("select", {
|
|
221
246
|
item: props.actions[rowIndex],
|
|
222
247
|
index: rowIndex,
|
|
223
|
-
})
|
|
248
|
+
});
|
|
224
249
|
} else if (isPanelArray()) {
|
|
225
|
-
emit(
|
|
250
|
+
emit("select", {
|
|
226
251
|
item: props.panels[Number(colIndex)],
|
|
227
252
|
index: colIndex,
|
|
228
|
-
})
|
|
253
|
+
});
|
|
229
254
|
} else {
|
|
230
|
-
emit(
|
|
255
|
+
emit("select", {
|
|
231
256
|
item: (props.panels as IActionSheetPanel[][])[rowIndex][Number(colIndex)],
|
|
232
257
|
rowIndex,
|
|
233
258
|
colIndex,
|
|
234
|
-
})
|
|
259
|
+
});
|
|
235
260
|
}
|
|
236
261
|
if (props.closeOnClickAction) {
|
|
237
|
-
onClose()
|
|
262
|
+
onClose();
|
|
238
263
|
}
|
|
239
264
|
}
|
|
240
265
|
function handleCancel() {
|
|
241
|
-
emit(
|
|
242
|
-
onClose()
|
|
266
|
+
emit("cancel");
|
|
267
|
+
onClose();
|
|
243
268
|
}
|
|
244
269
|
function onClose() {
|
|
245
|
-
emit(
|
|
246
|
-
emit(
|
|
270
|
+
emit("update:modelValue", false);
|
|
271
|
+
emit("close");
|
|
247
272
|
}
|
|
248
273
|
function onOpen() {
|
|
249
|
-
emit(
|
|
274
|
+
emit("open");
|
|
250
275
|
}
|
|
251
276
|
</script>
|
|
252
277
|
|
|
253
278
|
<style lang="scss" scoped>
|
|
254
|
-
@import
|
|
279
|
+
@import "./index.scss";
|
|
255
280
|
.hy-action-sheet__header {
|
|
256
281
|
text-align: v-bind(titleAlign);
|
|
257
282
|
}
|
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<view class="hy-address-picker">
|
|
3
|
-
<view
|
|
3
|
+
<view
|
|
4
|
+
v-if="hasInput"
|
|
5
|
+
class="hy-address-picker__has-input"
|
|
6
|
+
@tap="onShowByClickInput"
|
|
7
|
+
>
|
|
4
8
|
<!-- @slot 自定义输入框 -->
|
|
5
9
|
<slot name="trigger" :value="inputValue">
|
|
6
10
|
<HyInput
|
|
@@ -18,7 +22,9 @@
|
|
|
18
22
|
:placeholder="input?.placeholder || '请选择地址'"
|
|
19
23
|
:placeholderStyle="input?.placeholderStyle"
|
|
20
24
|
:placeholderClass="input?.placeholderClass"
|
|
21
|
-
:customStyle="
|
|
25
|
+
:customStyle="
|
|
26
|
+
Object.assign({ 'pointer-events': 'none' }, input?.customStyle)
|
|
27
|
+
"
|
|
22
28
|
></HyInput>
|
|
23
29
|
<view class="input-cover"></view>
|
|
24
30
|
</slot>
|
|
@@ -61,28 +67,30 @@
|
|
|
61
67
|
|
|
62
68
|
<script lang="ts">
|
|
63
69
|
export default {
|
|
64
|
-
name:
|
|
70
|
+
name: "hy-address-picker",
|
|
65
71
|
options: {
|
|
66
72
|
addGlobalClass: true,
|
|
67
73
|
virtualHost: true,
|
|
68
|
-
styleIsolation:
|
|
74
|
+
styleIsolation: "shared",
|
|
69
75
|
},
|
|
70
|
-
}
|
|
76
|
+
};
|
|
71
77
|
</script>
|
|
72
78
|
|
|
73
79
|
<script setup lang="ts">
|
|
80
|
+
import { onMounted, ref, toRefs } from "vue";
|
|
81
|
+
import type { PropType, CSSProperties } from "vue";
|
|
82
|
+
import type { IAddressPickerEmits } from "./typing";
|
|
83
|
+
import address from "../../utils/address.json";
|
|
84
|
+
import type HyInputProps from "../hy-input/typing";
|
|
85
|
+
// 组件
|
|
86
|
+
import HyInput from "../hy-input/hy-input.vue";
|
|
87
|
+
import HyPicker from "../hy-picker/hy-picker.vue";
|
|
88
|
+
|
|
74
89
|
/**
|
|
75
90
|
* 此选择器用于选择地址
|
|
76
91
|
* @displayName hy-address-picker
|
|
77
92
|
*/
|
|
78
|
-
defineOptions({})
|
|
79
|
-
import { type CSSProperties, onMounted, PropType, ref, toRefs } from 'vue'
|
|
80
|
-
import type { IAddressPickerEmits } from './typing'
|
|
81
|
-
import address from '../../utils/address.json'
|
|
82
|
-
import type HyInputProps from '../hy-input/typing'
|
|
83
|
-
// 组件
|
|
84
|
-
import HyInput from '../hy-input/hy-input.vue'
|
|
85
|
-
import HyPicker from '../hy-picker/hy-picker.vue'
|
|
93
|
+
defineOptions({});
|
|
86
94
|
|
|
87
95
|
// const props = withDefaults(defineProps<IProps>(), defaultProps)
|
|
88
96
|
const props = defineProps({
|
|
@@ -97,7 +105,7 @@ const props = defineProps({
|
|
|
97
105
|
* */
|
|
98
106
|
popupMode: {
|
|
99
107
|
type: String,
|
|
100
|
-
default:
|
|
108
|
+
default: "bottom",
|
|
101
109
|
},
|
|
102
110
|
/** 是否显示顶部的操作栏 */
|
|
103
111
|
showToolbar: {
|
|
@@ -114,7 +122,7 @@ const props = defineProps({
|
|
|
114
122
|
/** 字符串截取数组条件 */
|
|
115
123
|
separator: {
|
|
116
124
|
type: String,
|
|
117
|
-
default:
|
|
125
|
+
default: " ",
|
|
118
126
|
},
|
|
119
127
|
/** 是否显示加载中状态 */
|
|
120
128
|
loading: {
|
|
@@ -129,22 +137,22 @@ const props = defineProps({
|
|
|
129
137
|
/** 取消按钮的文字 */
|
|
130
138
|
cancelText: {
|
|
131
139
|
type: String,
|
|
132
|
-
default:
|
|
140
|
+
default: "取消",
|
|
133
141
|
},
|
|
134
142
|
/** 确认按钮的文字 */
|
|
135
143
|
confirmText: {
|
|
136
144
|
type: String,
|
|
137
|
-
default:
|
|
145
|
+
default: "确认",
|
|
138
146
|
},
|
|
139
147
|
/** 取消按钮的颜色 */
|
|
140
148
|
cancelColor: {
|
|
141
149
|
type: String,
|
|
142
|
-
default:
|
|
150
|
+
default: "#909193",
|
|
143
151
|
},
|
|
144
152
|
/** 确认按钮的颜色 */
|
|
145
153
|
confirmColor: {
|
|
146
154
|
type: String,
|
|
147
|
-
default:
|
|
155
|
+
default: "#3c9cff",
|
|
148
156
|
},
|
|
149
157
|
/** 每列中可见选项的数量 */
|
|
150
158
|
visibleItemCount: {
|
|
@@ -178,88 +186,91 @@ const props = defineProps({
|
|
|
178
186
|
customStyle: {
|
|
179
187
|
type: Object as PropType<CSSProperties>,
|
|
180
188
|
},
|
|
181
|
-
})
|
|
182
|
-
const { show, modelValue, hasInput, input, separator, closeOnClickOverlay } =
|
|
183
|
-
|
|
189
|
+
});
|
|
190
|
+
const { show, modelValue, hasInput, input, separator, closeOnClickOverlay } =
|
|
191
|
+
toRefs(props);
|
|
192
|
+
const emit = defineEmits<IAddressPickerEmits>();
|
|
184
193
|
|
|
185
194
|
// 原来的日期选择器不方便,这里增加一个hasInput选项支持类似element的自带输入框的功能。
|
|
186
|
-
const inputValue = ref<string>(
|
|
187
|
-
const showByClickInput = ref<boolean>(false) // 是否在hasInput模式下显示日期选择
|
|
188
|
-
const columns = ref<any[]>([])
|
|
189
|
-
const uPickerRef = ref<InstanceType<typeof HyPicker> | null>()
|
|
190
|
-
const defaultIndex = ref<number[]>([])
|
|
195
|
+
const inputValue = ref<string>(""); // 表单显示值
|
|
196
|
+
const showByClickInput = ref<boolean>(false); // 是否在hasInput模式下显示日期选择
|
|
197
|
+
const columns = ref<any[]>([]);
|
|
198
|
+
const uPickerRef = ref<InstanceType<typeof HyPicker> | null>();
|
|
199
|
+
const defaultIndex = ref<number[]>([]);
|
|
191
200
|
|
|
192
201
|
function normalizeCityName(city: string) {
|
|
193
202
|
// 定义常见的后缀
|
|
194
|
-
const suffixes = [
|
|
203
|
+
const suffixes = ["市", "省", "自治区", "特别行政区", "县", "区"];
|
|
195
204
|
suffixes.forEach((suffix) => {
|
|
196
205
|
if (city.endsWith(suffix)) {
|
|
197
|
-
city = city.slice(0, -suffix.length)
|
|
206
|
+
city = city.slice(0, -suffix.length);
|
|
198
207
|
}
|
|
199
|
-
})
|
|
200
|
-
return city
|
|
208
|
+
});
|
|
209
|
+
return city;
|
|
201
210
|
}
|
|
202
211
|
/**
|
|
203
212
|
* @description 判断城市是否相等
|
|
204
213
|
* */
|
|
205
214
|
const areCitiesEqual = (city1: string, city2: string) => {
|
|
206
|
-
const normalizedCity1 = normalizeCityName(city1)
|
|
207
|
-
const normalizedCity2 = normalizeCityName(city2)
|
|
208
|
-
return normalizedCity1 === normalizedCity2
|
|
209
|
-
}
|
|
215
|
+
const normalizedCity1 = normalizeCityName(city1);
|
|
216
|
+
const normalizedCity2 = normalizeCityName(city2);
|
|
217
|
+
return normalizedCity1 === normalizedCity2;
|
|
218
|
+
};
|
|
210
219
|
/**
|
|
211
220
|
* @description 更新各列的值
|
|
212
221
|
* */
|
|
213
222
|
const updateColumnValue = (value: string) => {
|
|
214
|
-
let provinceIndex, cityIndex, countyIndex
|
|
223
|
+
let provinceIndex, cityIndex, countyIndex;
|
|
215
224
|
// 判断是初始化有数据就找到对应索引,无数据默认索引为0
|
|
216
225
|
if (value) {
|
|
217
|
-
const addressArr = value.split(separator.value)
|
|
226
|
+
const addressArr = value.split(separator.value);
|
|
218
227
|
// 查出省索引
|
|
219
|
-
provinceIndex = address.findIndex((item) =>
|
|
228
|
+
provinceIndex = address.findIndex((item) =>
|
|
229
|
+
areCitiesEqual(item.name, addressArr[0]),
|
|
230
|
+
);
|
|
220
231
|
// 查出市索引
|
|
221
232
|
cityIndex = address[provinceIndex].areas.findIndex((item) =>
|
|
222
233
|
areCitiesEqual(item.name, addressArr[1]),
|
|
223
|
-
)
|
|
234
|
+
);
|
|
224
235
|
|
|
225
236
|
// 查出县/区索引
|
|
226
|
-
countyIndex = address[provinceIndex].areas[cityIndex].areas.findIndex(
|
|
227
|
-
areCitiesEqual(item.name, addressArr[2]),
|
|
228
|
-
)
|
|
237
|
+
countyIndex = address[provinceIndex].areas[cityIndex].areas.findIndex(
|
|
238
|
+
(item) => areCitiesEqual(item.name, addressArr[2]),
|
|
239
|
+
);
|
|
229
240
|
} else {
|
|
230
|
-
provinceIndex = 0
|
|
231
|
-
cityIndex = 0
|
|
232
|
-
countyIndex = 0
|
|
241
|
+
provinceIndex = 0;
|
|
242
|
+
cityIndex = 0;
|
|
243
|
+
countyIndex = 0;
|
|
233
244
|
}
|
|
234
245
|
// 省级数组
|
|
235
246
|
const provinceData = address.map((item) => ({
|
|
236
247
|
name: item.name,
|
|
237
248
|
code: item.code,
|
|
238
|
-
}))
|
|
249
|
+
}));
|
|
239
250
|
// 市级数组
|
|
240
251
|
const cityData = address[provinceIndex].areas.map((item) => ({
|
|
241
252
|
name: item.name,
|
|
242
253
|
code: item.code,
|
|
243
|
-
}))
|
|
254
|
+
}));
|
|
244
255
|
// 县/区级数组
|
|
245
|
-
const areaData = address[provinceIndex].areas[cityIndex].areas
|
|
256
|
+
const areaData = address[provinceIndex].areas[cityIndex].areas;
|
|
246
257
|
|
|
247
258
|
// 默认索引
|
|
248
|
-
defaultIndex.value = [provinceIndex, cityIndex, countyIndex]
|
|
259
|
+
defaultIndex.value = [provinceIndex, cityIndex, countyIndex];
|
|
249
260
|
// 列表
|
|
250
|
-
columns.value = [provinceData, cityData, areaData]
|
|
251
|
-
}
|
|
261
|
+
columns.value = [provinceData, cityData, areaData];
|
|
262
|
+
};
|
|
252
263
|
|
|
253
264
|
const init = () => {
|
|
254
265
|
// 获取当前值
|
|
255
|
-
inputValue.value = modelValue.value
|
|
266
|
+
inputValue.value = modelValue.value;
|
|
256
267
|
// 更新列表
|
|
257
|
-
updateColumnValue(modelValue.value)
|
|
258
|
-
}
|
|
268
|
+
updateColumnValue(modelValue.value);
|
|
269
|
+
};
|
|
259
270
|
|
|
260
271
|
onMounted(() => {
|
|
261
|
-
init()
|
|
262
|
-
})
|
|
272
|
+
init();
|
|
273
|
+
});
|
|
263
274
|
|
|
264
275
|
/**
|
|
265
276
|
* @description 关闭选择器
|
|
@@ -267,74 +278,74 @@ onMounted(() => {
|
|
|
267
278
|
const close = () => {
|
|
268
279
|
if (closeOnClickOverlay.value) {
|
|
269
280
|
if (hasInput.value) {
|
|
270
|
-
showByClickInput.value = false
|
|
281
|
+
showByClickInput.value = false;
|
|
271
282
|
}
|
|
272
|
-
emit(
|
|
283
|
+
emit("close");
|
|
273
284
|
}
|
|
274
|
-
}
|
|
285
|
+
};
|
|
275
286
|
|
|
276
287
|
/**
|
|
277
288
|
* @description 点击工具栏的取消按钮
|
|
278
289
|
* */
|
|
279
290
|
const cancel = () => {
|
|
280
291
|
if (hasInput.value) {
|
|
281
|
-
showByClickInput.value = false
|
|
292
|
+
showByClickInput.value = false;
|
|
282
293
|
}
|
|
283
|
-
emit(
|
|
284
|
-
}
|
|
294
|
+
emit("cancel");
|
|
295
|
+
};
|
|
285
296
|
|
|
286
297
|
/**
|
|
287
298
|
* @description 点击工具栏的确定按钮
|
|
288
299
|
* */
|
|
289
300
|
const confirm = ({ value }: { value: Record<string, any>[] }) => {
|
|
290
|
-
inputValue.value = value.map((item) => item.name).join(separator.value)
|
|
301
|
+
inputValue.value = value.map((item) => item.name).join(separator.value);
|
|
291
302
|
|
|
292
|
-
showByClickInput.value = false
|
|
293
|
-
emit(
|
|
294
|
-
emit(
|
|
303
|
+
showByClickInput.value = false;
|
|
304
|
+
emit("update:modelValue", inputValue.value);
|
|
305
|
+
emit("confirm", {
|
|
295
306
|
value: inputValue.value,
|
|
296
|
-
})
|
|
297
|
-
}
|
|
307
|
+
});
|
|
308
|
+
};
|
|
298
309
|
|
|
299
310
|
/**
|
|
300
311
|
* @description 列发生变化时触发
|
|
301
312
|
* */
|
|
302
313
|
const change = (e: any) => {
|
|
303
|
-
const { columnIndex, index, indexs } = e
|
|
314
|
+
const { columnIndex, index, indexs } = e;
|
|
304
315
|
//如果改变的是第一列
|
|
305
316
|
if (columnIndex === 0) {
|
|
306
317
|
const children1 = address[index].areas.map((item) => {
|
|
307
|
-
return { name: item.name, code: item.code }
|
|
308
|
-
})
|
|
309
|
-
uPickerRef.value?.setColumnValues(1, children1)
|
|
318
|
+
return { name: item.name, code: item.code };
|
|
319
|
+
});
|
|
320
|
+
uPickerRef.value?.setColumnValues(1, children1);
|
|
310
321
|
//更换 第二列数据
|
|
311
322
|
const children2 = address[index].areas[indexs[1]].areas.map((item) => ({
|
|
312
323
|
...item,
|
|
313
|
-
}))
|
|
314
|
-
uPickerRef.value?.setColumnValues(2, children2)
|
|
324
|
+
}));
|
|
325
|
+
uPickerRef.value?.setColumnValues(2, children2);
|
|
315
326
|
//更换 第三列数据
|
|
316
327
|
}
|
|
317
328
|
if (columnIndex === 1) {
|
|
318
329
|
//如果改变的是第二列
|
|
319
330
|
const children3 = address[indexs[0]].areas[indexs[1]].areas.map((item) => ({
|
|
320
331
|
...item,
|
|
321
|
-
}))
|
|
322
|
-
uPickerRef.value?.setColumnValues(2, children3)
|
|
332
|
+
}));
|
|
333
|
+
uPickerRef.value?.setColumnValues(2, children3);
|
|
323
334
|
}
|
|
324
335
|
|
|
325
336
|
// 发出change时间,value为当前选中的时间戳
|
|
326
|
-
emit(
|
|
337
|
+
emit("change", {
|
|
327
338
|
...e,
|
|
328
|
-
})
|
|
329
|
-
}
|
|
339
|
+
});
|
|
340
|
+
};
|
|
330
341
|
|
|
331
342
|
const onShowByClickInput = () => {
|
|
332
|
-
if (!input
|
|
333
|
-
showByClickInput.value = !showByClickInput.value
|
|
343
|
+
if (!props.input?.disabled) {
|
|
344
|
+
showByClickInput.value = !showByClickInput.value;
|
|
334
345
|
}
|
|
335
|
-
}
|
|
346
|
+
};
|
|
336
347
|
</script>
|
|
337
348
|
|
|
338
349
|
<style lang="scss" scoped>
|
|
339
|
-
@import
|
|
350
|
+
@import "./index.scss";
|
|
340
351
|
</style>
|