hy-app 0.2.18 → 0.3.1
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/components/hy-back-top/hy-back-top.vue +8 -6
- package/components/hy-config-provider/hy-config-provider.vue +1 -1
- package/components/hy-flex/hy-flex.vue +73 -0
- package/components/hy-flex/index.scss +8 -0
- package/components/hy-flex/typing.d.ts +23 -0
- package/components/hy-form/README.md +301 -0
- package/components/hy-form/hy-form.vue +259 -533
- package/components/hy-form/index.ts +5 -0
- package/components/hy-form/typing.d.ts +61 -77
- package/components/hy-form-group/hy-form-group.vue +464 -0
- package/components/hy-form-group/typing.d.ts +77 -0
- package/components/hy-form-item/hy-form-item.vue +201 -0
- package/components/hy-form-item/index.scss +41 -0
- package/components/hy-form-item/typing.d.ts +40 -0
- package/components/hy-input/hy-input.vue +10 -5
- package/components/hy-login/TheUserLogin.vue +82 -90
- package/components/hy-swipe-action/hy-swipe-action.vue +13 -6
- package/components/hy-swipe-action/typing.d.ts +1 -1
- package/components/hy-textarea/hy-textarea.vue +9 -7
- package/components/hy-textarea/typing.d.ts +1 -1
- package/components/index.ts +8 -2
- package/global.d.ts +4 -1
- package/libs/css/mixin.scss +2 -1
- package/package.json +2 -2
- package/theme.scss +5 -5
- package/utils/inspect.ts +33 -33
- package/utils/utils.ts +1 -19
- package/web-types.json +1 -1
- /package/components/{hy-form → hy-form-group}/index.scss +0 -0
- /package/components/{hy-form → hy-form-group}/props.ts +0 -0
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<view
|
|
3
|
+
class="hy-form-item"
|
|
4
|
+
:class="[`hy-form-item--${labelPosition}`, formContext.border && 'hy-border__bottom']"
|
|
5
|
+
>
|
|
6
|
+
<view v-if="label" class="hy-form-item__label" :style="labelStyle">
|
|
7
|
+
<text v-if="isRequired" class="hy-form-item__label--required">*</text>
|
|
8
|
+
{{ label }}
|
|
9
|
+
</view>
|
|
10
|
+
<view class="hy-form-item__content">
|
|
11
|
+
<slot></slot>
|
|
12
|
+
<view v-if="errorMessage" class="hy-form-item__error">
|
|
13
|
+
{{ errorMessage }}
|
|
14
|
+
</view>
|
|
15
|
+
</view>
|
|
16
|
+
</view>
|
|
17
|
+
</template>
|
|
18
|
+
|
|
19
|
+
<script lang="ts">
|
|
20
|
+
export default {
|
|
21
|
+
name: 'hy-form-item',
|
|
22
|
+
options: {
|
|
23
|
+
addGlobalClass: true,
|
|
24
|
+
virtualHost: true,
|
|
25
|
+
styleIsolation: 'shared',
|
|
26
|
+
},
|
|
27
|
+
}
|
|
28
|
+
</script>
|
|
29
|
+
|
|
30
|
+
<script setup lang="ts">
|
|
31
|
+
import { computed, inject, onMounted, onUnmounted, provide, ref } from 'vue'
|
|
32
|
+
import type { PropType } from 'vue'
|
|
33
|
+
import type { FormContext } from './typing'
|
|
34
|
+
import { addUnit } from '../../utils'
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* 表单组件子组件,需要搭配hy-form
|
|
38
|
+
* @displayName hy-form-item
|
|
39
|
+
*/
|
|
40
|
+
defineOptions({})
|
|
41
|
+
|
|
42
|
+
const props = defineProps({
|
|
43
|
+
/**
|
|
44
|
+
* 标签文本
|
|
45
|
+
*/
|
|
46
|
+
label: String,
|
|
47
|
+
/**
|
|
48
|
+
* 表单字段名
|
|
49
|
+
*/
|
|
50
|
+
prop: String,
|
|
51
|
+
/**
|
|
52
|
+
* 是否必填
|
|
53
|
+
*/
|
|
54
|
+
required: {
|
|
55
|
+
type: Boolean,
|
|
56
|
+
default: false,
|
|
57
|
+
},
|
|
58
|
+
/**
|
|
59
|
+
* 验证规则
|
|
60
|
+
*/
|
|
61
|
+
rules: Object as PropType<any>,
|
|
62
|
+
})
|
|
63
|
+
|
|
64
|
+
const emit = defineEmits<{
|
|
65
|
+
change: [value: any]
|
|
66
|
+
blur: [value: any]
|
|
67
|
+
}>()
|
|
68
|
+
|
|
69
|
+
// 注入表单上下文
|
|
70
|
+
const formContext = inject<FormContext>('formContext')
|
|
71
|
+
const formItem = {
|
|
72
|
+
// 处理子组件事件
|
|
73
|
+
handleChange(value: any) {
|
|
74
|
+
if (props.prop && formContext) {
|
|
75
|
+
formContext.setFieldValue(props.prop, value)
|
|
76
|
+
validate('change')
|
|
77
|
+
}
|
|
78
|
+
emit('change', value)
|
|
79
|
+
},
|
|
80
|
+
handleBlur(value: any) {
|
|
81
|
+
if (props.prop && formContext) {
|
|
82
|
+
validate('blur')
|
|
83
|
+
}
|
|
84
|
+
emit('blur', value)
|
|
85
|
+
},
|
|
86
|
+
}
|
|
87
|
+
provide('formItem', formItem)
|
|
88
|
+
|
|
89
|
+
// 当前组件的引用
|
|
90
|
+
const formItemRef = ref()
|
|
91
|
+
|
|
92
|
+
// 错误信息
|
|
93
|
+
const errorMessage = computed(() => {
|
|
94
|
+
if (!formContext || !props.prop) return ''
|
|
95
|
+
return formContext.errors[props.prop] || ''
|
|
96
|
+
})
|
|
97
|
+
|
|
98
|
+
// 是否必填
|
|
99
|
+
const isRequired = computed(() => {
|
|
100
|
+
if (props.required) return true
|
|
101
|
+
if (!formContext || !props.prop) return false
|
|
102
|
+
|
|
103
|
+
const fieldRules = formContext.rules.value?.[props.prop]
|
|
104
|
+
if (!fieldRules) return false
|
|
105
|
+
|
|
106
|
+
const rules = Array.isArray(fieldRules) ? fieldRules : [fieldRules]
|
|
107
|
+
return rules.some((rule) => rule.required)
|
|
108
|
+
})
|
|
109
|
+
|
|
110
|
+
// 标签样式
|
|
111
|
+
const labelStyle = computed(() => {
|
|
112
|
+
if (!formContext) return {}
|
|
113
|
+
|
|
114
|
+
const style: Record<string, any> = {}
|
|
115
|
+
|
|
116
|
+
if (formContext.labelWidth !== 'auto') {
|
|
117
|
+
style.width = addUnit(formContext.labelWidth)
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
if (formContext.labelAlign) {
|
|
121
|
+
style.textAlign = formContext.labelAlign
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
return style
|
|
125
|
+
})
|
|
126
|
+
|
|
127
|
+
// 标签位置
|
|
128
|
+
const labelPosition = computed(() => {
|
|
129
|
+
return formContext?.labelPosition || 'left'
|
|
130
|
+
})
|
|
131
|
+
|
|
132
|
+
// 监听表单数据变化
|
|
133
|
+
// watch(
|
|
134
|
+
// () => formContext?.formData[props.prop],
|
|
135
|
+
// (newVal) => {
|
|
136
|
+
// if (props.prop && formContext) {
|
|
137
|
+
// formContext.setFieldValue(props.prop, newVal)
|
|
138
|
+
// validate('change')
|
|
139
|
+
// }
|
|
140
|
+
// },
|
|
141
|
+
// { immediate: true },
|
|
142
|
+
// )
|
|
143
|
+
|
|
144
|
+
// 验证字段
|
|
145
|
+
const validate = (trigger?: 'blur' | 'change') => {
|
|
146
|
+
if (!formContext || !props.prop) return true
|
|
147
|
+
|
|
148
|
+
const value = formContext.getFieldValue(props.prop)
|
|
149
|
+
return formContext.validateField(props.prop, value, trigger)
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
// 重置字段
|
|
153
|
+
const resetField = () => {
|
|
154
|
+
if (!formContext || !props.prop) return
|
|
155
|
+
|
|
156
|
+
formContext.setFieldValue(props.prop, undefined)
|
|
157
|
+
formContext.validateField(props.prop, undefined)
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
// 清除验证
|
|
161
|
+
const clearValidate = () => {
|
|
162
|
+
if (!formContext || !props.prop) return
|
|
163
|
+
|
|
164
|
+
delete formContext.errors[props.prop]
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
// 组件挂载时注册到表单
|
|
168
|
+
onMounted(() => {
|
|
169
|
+
if (formContext) {
|
|
170
|
+
formContext.addFormItem({
|
|
171
|
+
props: props,
|
|
172
|
+
validate,
|
|
173
|
+
resetField,
|
|
174
|
+
clearValidate,
|
|
175
|
+
})
|
|
176
|
+
}
|
|
177
|
+
})
|
|
178
|
+
|
|
179
|
+
// 组件卸载时从表单中移除
|
|
180
|
+
onUnmounted(() => {
|
|
181
|
+
if (formContext) {
|
|
182
|
+
formContext.removeFormItem({
|
|
183
|
+
props: props,
|
|
184
|
+
validate,
|
|
185
|
+
resetField,
|
|
186
|
+
clearValidate,
|
|
187
|
+
})
|
|
188
|
+
}
|
|
189
|
+
})
|
|
190
|
+
|
|
191
|
+
// 暴露方法给父组件
|
|
192
|
+
defineExpose({
|
|
193
|
+
validate,
|
|
194
|
+
resetField,
|
|
195
|
+
clearValidate,
|
|
196
|
+
})
|
|
197
|
+
</script>
|
|
198
|
+
|
|
199
|
+
<style lang="scss" scoped>
|
|
200
|
+
@import './index.scss';
|
|
201
|
+
</style>
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
@use "../../theme.scss" as *;
|
|
2
|
+
@use "../../libs/css/mixin.scss" as *;
|
|
3
|
+
|
|
4
|
+
@include b(form-item) {
|
|
5
|
+
display: flex;
|
|
6
|
+
margin-bottom: 16px;
|
|
7
|
+
|
|
8
|
+
@include m(left) {
|
|
9
|
+
flex-direction: row;
|
|
10
|
+
align-items: flex-start;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
@include m(top) {
|
|
14
|
+
flex-direction: column;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
@include e(label) {
|
|
18
|
+
position: relative;
|
|
19
|
+
padding-right: 8px;
|
|
20
|
+
font-size: 14px;
|
|
21
|
+
color: $hy-text-color;
|
|
22
|
+
line-height: 2.5;
|
|
23
|
+
|
|
24
|
+
@include m(required) {
|
|
25
|
+
color: #ff4d4f;
|
|
26
|
+
margin-right: 2px;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
@include e(content) {
|
|
31
|
+
flex: 1;
|
|
32
|
+
min-width: 0;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
@include e(error) {
|
|
36
|
+
margin-top: 4px;
|
|
37
|
+
font-size: 12px;
|
|
38
|
+
color: #ff4d4f;
|
|
39
|
+
line-height: 1.5;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import HyFormSimpleProps from '../hy-form/typing'
|
|
2
|
+
|
|
3
|
+
export interface FormContext extends HyFormSimpleProps {
|
|
4
|
+
errors: Record<string, string>
|
|
5
|
+
addFormItem: (item: any) => void
|
|
6
|
+
removeFormItem: (item: any) => void
|
|
7
|
+
validateField: (field: string, value: any, trigger?: 'blur' | 'change') => boolean
|
|
8
|
+
setFieldValue: (field: string, value: any) => void
|
|
9
|
+
getFieldValue: (field: string) => any
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export interface FormItemContext {
|
|
13
|
+
/**
|
|
14
|
+
* 失去焦点触发表单校验
|
|
15
|
+
* */
|
|
16
|
+
handleBlur: (value: string | number) => void
|
|
17
|
+
/**
|
|
18
|
+
* 值改变触发表单校验
|
|
19
|
+
* */
|
|
20
|
+
handleChange: (value: string | number) => void
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export default interface HyFormItemProps {
|
|
24
|
+
/**
|
|
25
|
+
* 标签文本
|
|
26
|
+
*/
|
|
27
|
+
label?: string
|
|
28
|
+
/**
|
|
29
|
+
* 表单字段名
|
|
30
|
+
*/
|
|
31
|
+
prop?: string
|
|
32
|
+
/**
|
|
33
|
+
* 是否必填
|
|
34
|
+
*/
|
|
35
|
+
required?: boolean
|
|
36
|
+
/**
|
|
37
|
+
* 验证规则
|
|
38
|
+
*/
|
|
39
|
+
rules?: any
|
|
40
|
+
}
|
|
@@ -103,13 +103,15 @@ export default {
|
|
|
103
103
|
</script>
|
|
104
104
|
|
|
105
105
|
<script setup lang="ts">
|
|
106
|
-
import { computed, nextTick, ref, toRefs, watch, getCurrentInstance,
|
|
107
|
-
import type { CSSProperties } from 'vue'
|
|
106
|
+
import { computed, nextTick, ref, toRefs, watch, getCurrentInstance, inject } from 'vue'
|
|
107
|
+
import type { CSSProperties, PropType } from 'vue'
|
|
108
108
|
import HyIcon from '../hy-icon/hy-icon.vue'
|
|
109
109
|
import { addUnit, formatObject } from '../../utils'
|
|
110
110
|
import { IconConfig } from '../../config'
|
|
111
111
|
import type { IInputEmits } from './typing'
|
|
112
|
-
import HyIconProps from '
|
|
112
|
+
import type HyIconProps from '../hy-icon/typing'
|
|
113
|
+
import { FormItemContext } from '@/package/components/hy-form-item/typing'
|
|
114
|
+
import { TextAlign } from 'csstype'
|
|
113
115
|
|
|
114
116
|
/**
|
|
115
117
|
* 为一个输入框,利用它可以快速实现表单验证,输入内容,下拉选择等功能。
|
|
@@ -236,7 +238,7 @@ const props = defineProps({
|
|
|
236
238
|
* @values left,center,right
|
|
237
239
|
* */
|
|
238
240
|
inputAlign: {
|
|
239
|
-
type: String
|
|
241
|
+
type: String as PropType<TextAlign>,
|
|
240
242
|
default: 'left',
|
|
241
243
|
},
|
|
242
244
|
/** 输入框字体的大小 */
|
|
@@ -303,6 +305,7 @@ const {
|
|
|
303
305
|
placeholderStyle,
|
|
304
306
|
} = toRefs(props)
|
|
305
307
|
const emit = defineEmits<IInputEmits>()
|
|
308
|
+
const formItem = inject<FormItemContext>('formItem')
|
|
306
309
|
|
|
307
310
|
const instance = getCurrentInstance()
|
|
308
311
|
// 清除操作
|
|
@@ -424,8 +427,9 @@ const onInput = (e: any) => {
|
|
|
424
427
|
/**
|
|
425
428
|
* @description 输入框失去焦点时触发
|
|
426
429
|
* */
|
|
427
|
-
const onBlur = (event:
|
|
430
|
+
const onBlur = (event: any) => {
|
|
428
431
|
emit('blur', event.detail.value)
|
|
432
|
+
formItem.handleBlur(event.detail.value)
|
|
429
433
|
// H5端的blur会先于点击清除控件的点击click事件触发,导致focused
|
|
430
434
|
// 瞬间为false,从而隐藏了清除控件而无法被点击到
|
|
431
435
|
setTimeout(() => {
|
|
@@ -466,6 +470,7 @@ const valueChange = (value: string | number, isOut = false) => {
|
|
|
466
470
|
// 标识value值的变化是由内部引起的
|
|
467
471
|
changeFromInner.value = true
|
|
468
472
|
emit('change', value)
|
|
473
|
+
formItem.handleChange(value)
|
|
469
474
|
|
|
470
475
|
emit('update:modelValue', value)
|
|
471
476
|
}
|
|
@@ -21,52 +21,52 @@
|
|
|
21
21
|
</template>
|
|
22
22
|
|
|
23
23
|
<script setup lang="ts">
|
|
24
|
-
import { ref, reactive, onMounted, computed } from
|
|
25
|
-
import { onHide } from
|
|
26
|
-
import { storeToRefs } from
|
|
27
|
-
import { useUserInfo } from
|
|
28
|
-
import { decryptData, encryptData } from
|
|
29
|
-
import { FormTypeEnum } from
|
|
30
|
-
import { IconConfig } from
|
|
31
|
-
import type { UserLoginInfoVo } from
|
|
24
|
+
import { ref, reactive, onMounted, computed } from 'vue'
|
|
25
|
+
import { onHide } from '@dcloudio/uni-app'
|
|
26
|
+
import { storeToRefs } from 'pinia'
|
|
27
|
+
import { useUserInfo } from '../../store'
|
|
28
|
+
import { decryptData, encryptData } from '../../utils'
|
|
29
|
+
import { FormTypeEnum } from '../../typing'
|
|
30
|
+
import { IconConfig } from '../../config'
|
|
31
|
+
import type { UserLoginInfoVo } from './typing'
|
|
32
32
|
|
|
33
33
|
// 组件
|
|
34
|
-
import HyCheckbox from
|
|
35
|
-
import HyForm from
|
|
34
|
+
import HyCheckbox from '../hy-checkbox/hy-checkbox.vue'
|
|
35
|
+
import HyForm from '@/package/components/hy-form-group/hy-form-group.vue'
|
|
36
36
|
|
|
37
37
|
interface IProps {
|
|
38
|
-
themeColor: string
|
|
39
|
-
prefix: string
|
|
40
|
-
isShowPwd: boolean
|
|
41
|
-
userPlaceholder: string
|
|
42
|
-
pwdPlaceholder: string
|
|
43
|
-
customUserValidator: Record<string, any
|
|
44
|
-
customPwdValidator: Record<string, any
|
|
45
|
-
userNumValidator: Record<string, any
|
|
46
|
-
pwdNumValidator: Record<string, any
|
|
38
|
+
themeColor: string
|
|
39
|
+
prefix: string
|
|
40
|
+
isShowPwd: boolean
|
|
41
|
+
userPlaceholder: string
|
|
42
|
+
pwdPlaceholder: string
|
|
43
|
+
customUserValidator: Record<string, any>
|
|
44
|
+
customPwdValidator: Record<string, any>
|
|
45
|
+
userNumValidator: Record<string, any>
|
|
46
|
+
pwdNumValidator: Record<string, any>
|
|
47
47
|
}
|
|
48
48
|
|
|
49
49
|
const props = withDefaults(defineProps<IProps>(), {
|
|
50
|
-
themeColor:
|
|
51
|
-
prefix:
|
|
50
|
+
themeColor: '',
|
|
51
|
+
prefix: 'hy',
|
|
52
52
|
isShowPwd: false,
|
|
53
|
-
userPlaceholder:
|
|
54
|
-
pwdPlaceholder:
|
|
53
|
+
userPlaceholder: '',
|
|
54
|
+
pwdPlaceholder: '',
|
|
55
55
|
customUserValidator: () => ({}),
|
|
56
56
|
customPwdValidator: () => ({}),
|
|
57
57
|
userNumValidator: () => ({}),
|
|
58
58
|
pwdNumValidator: () => ({}),
|
|
59
|
-
})
|
|
60
|
-
const emit = defineEmits([
|
|
61
|
-
const userInfoStore = useUserInfo()
|
|
62
|
-
const { userForm, choiceList, rememberPsw } = storeToRefs(userInfoStore)
|
|
59
|
+
})
|
|
60
|
+
const emit = defineEmits(['handleHistory', 'handleCheckbox'])
|
|
61
|
+
const userInfoStore = useUserInfo()
|
|
62
|
+
const { userForm, choiceList, rememberPsw } = storeToRefs(userInfoStore)
|
|
63
63
|
|
|
64
|
-
const showChoice = ref<boolean>(false)
|
|
65
|
-
const showPwd = ref<boolean>(false)
|
|
64
|
+
const showChoice = ref<boolean>(false)
|
|
65
|
+
const showPwd = ref<boolean>(false)
|
|
66
66
|
const userColumns = computed(() => [
|
|
67
67
|
{
|
|
68
|
-
field:
|
|
69
|
-
label:
|
|
68
|
+
field: 'userName',
|
|
69
|
+
label: '',
|
|
70
70
|
type: FormTypeEnum.TEXT,
|
|
71
71
|
input: {
|
|
72
72
|
clearable: true,
|
|
@@ -76,20 +76,18 @@ const userColumns = computed(() => [
|
|
|
76
76
|
color: props.themeColor,
|
|
77
77
|
},
|
|
78
78
|
suffixIcon: {
|
|
79
|
-
name: showChoice.value
|
|
80
|
-
? IconConfig.ARROW_UP_FILL
|
|
81
|
-
: IconConfig.ARROW_DOWN_FILL,
|
|
79
|
+
name: showChoice.value ? IconConfig.ARROW_UP_FILL : IconConfig.ARROW_DOWN_FILL,
|
|
82
80
|
color: props.themeColor,
|
|
83
81
|
},
|
|
84
82
|
onSuffix: () => {
|
|
85
|
-
showChoice.value = !showChoice.value
|
|
83
|
+
showChoice.value = !showChoice.value
|
|
86
84
|
},
|
|
87
85
|
},
|
|
88
86
|
rules: [props.customUserValidator, props.userNumValidator],
|
|
89
87
|
},
|
|
90
88
|
{
|
|
91
|
-
field:
|
|
92
|
-
label:
|
|
89
|
+
field: 'password',
|
|
90
|
+
label: '',
|
|
93
91
|
type: showPwd.value ? FormTypeEnum.TEXT : FormTypeEnum.PASSWORD,
|
|
94
92
|
input: {
|
|
95
93
|
clearable: true,
|
|
@@ -103,22 +101,22 @@ const userColumns = computed(() => [
|
|
|
103
101
|
color: props.themeColor,
|
|
104
102
|
},
|
|
105
103
|
onSuffix: () => {
|
|
106
|
-
showPwd.value = !showPwd.value
|
|
104
|
+
showPwd.value = !showPwd.value
|
|
107
105
|
},
|
|
108
106
|
},
|
|
109
107
|
rules: [props.customUserValidator, props.pwdNumValidator],
|
|
110
108
|
},
|
|
111
|
-
])
|
|
112
|
-
const rememberList = reactive([{ label:
|
|
113
|
-
const form_1Ref = ref<InstanceType<typeof HyForm>>()
|
|
109
|
+
])
|
|
110
|
+
const rememberList = reactive([{ label: '记住密码', value: 1 }])
|
|
111
|
+
const form_1Ref = ref<InstanceType<typeof HyForm>>()
|
|
114
112
|
// 效验用户名和密码
|
|
115
113
|
const userRules = reactive({
|
|
116
114
|
userName: [
|
|
117
115
|
{
|
|
118
116
|
required: true,
|
|
119
|
-
message:
|
|
117
|
+
message: '请先输入账号',
|
|
120
118
|
// 可以单个或者同时写两个触发验证方式
|
|
121
|
-
trigger: [
|
|
119
|
+
trigger: ['blur', 'change'],
|
|
122
120
|
},
|
|
123
121
|
props.customUserValidator,
|
|
124
122
|
props.userNumValidator,
|
|
@@ -126,44 +124,44 @@ const userRules = reactive({
|
|
|
126
124
|
password: [
|
|
127
125
|
{
|
|
128
126
|
required: true,
|
|
129
|
-
message:
|
|
127
|
+
message: '请输入密码',
|
|
130
128
|
// 可以单个或者同时写两个触发验证方式
|
|
131
|
-
trigger: [
|
|
129
|
+
trigger: ['blur', 'change'],
|
|
132
130
|
},
|
|
133
131
|
props.pwdNumValidator,
|
|
134
132
|
props.customPwdValidator,
|
|
135
133
|
],
|
|
136
|
-
})
|
|
137
|
-
const rememberPassword = ref(false)
|
|
138
|
-
const account = uni.getStorageSync(`${props.prefix}_account`)
|
|
139
|
-
const accountList = uni.getStorageSync(`${props.prefix}_choiceList`)
|
|
134
|
+
})
|
|
135
|
+
const rememberPassword = ref(false)
|
|
136
|
+
const account = uni.getStorageSync(`${props.prefix}_account`)
|
|
137
|
+
const accountList = uni.getStorageSync(`${props.prefix}_choiceList`)
|
|
140
138
|
|
|
141
139
|
onMounted(() => {
|
|
142
|
-
if (!account) return
|
|
143
|
-
const result = decryptData(account)
|
|
144
|
-
console.log(result)
|
|
140
|
+
if (!account) return
|
|
141
|
+
const result = decryptData(account)
|
|
142
|
+
console.log(result)
|
|
145
143
|
//有缓存就赋值给文本没有就清空
|
|
146
|
-
rememberPsw.value = result?.rememberPsw
|
|
144
|
+
rememberPsw.value = result?.rememberPsw
|
|
147
145
|
//获取缓存的账号和密码
|
|
148
|
-
userForm.value.userName = result?.userName
|
|
149
|
-
userForm.value.password = result?.password
|
|
146
|
+
userForm.value.userName = result?.userName
|
|
147
|
+
userForm.value.password = result?.password
|
|
150
148
|
|
|
151
149
|
if (accountList) {
|
|
152
|
-
choiceList.value = decryptData(accountList) as UserLoginInfoVo[]
|
|
150
|
+
choiceList.value = decryptData(accountList) as UserLoginInfoVo[]
|
|
153
151
|
}
|
|
154
|
-
})
|
|
152
|
+
})
|
|
155
153
|
|
|
156
154
|
onHide(() => {
|
|
157
155
|
// if (!account) return;
|
|
158
156
|
//获取缓存的账号和密码
|
|
159
|
-
const { userName, password } = decryptData(account)
|
|
157
|
+
const { userName, password } = decryptData(account)
|
|
160
158
|
if (choiceList.value.length) {
|
|
161
159
|
// 过滤数判断是否有一样的账号
|
|
162
160
|
const filterArr = choiceList.value.filter((item) => {
|
|
163
|
-
return item.user === userName
|
|
164
|
-
})
|
|
161
|
+
return item.user === userName
|
|
162
|
+
})
|
|
165
163
|
// 有一样的账号退出函数不执行下面的
|
|
166
|
-
if (filterArr.length) return
|
|
164
|
+
if (filterArr.length) return
|
|
167
165
|
}
|
|
168
166
|
// 判断是否有保存账号和密码
|
|
169
167
|
if (userName && password) {
|
|
@@ -171,17 +169,14 @@ onHide(() => {
|
|
|
171
169
|
choiceList.value.unshift({
|
|
172
170
|
user: userName,
|
|
173
171
|
pwd: password,
|
|
174
|
-
})
|
|
172
|
+
})
|
|
175
173
|
// 数组最多只放三个账号
|
|
176
174
|
if (choiceList.value.length >= 5) {
|
|
177
|
-
choiceList.value.splice(5, 1)
|
|
175
|
+
choiceList.value.splice(5, 1)
|
|
178
176
|
}
|
|
179
|
-
uni.setStorageSync(
|
|
180
|
-
`${props.prefix}_choiceList`,
|
|
181
|
-
encryptData(choiceList.value),
|
|
182
|
-
);
|
|
177
|
+
uni.setStorageSync(`${props.prefix}_choiceList`, encryptData(choiceList.value))
|
|
183
178
|
}
|
|
184
|
-
})
|
|
179
|
+
})
|
|
185
180
|
|
|
186
181
|
/**
|
|
187
182
|
* 登录效验
|
|
@@ -191,30 +186,30 @@ const loginFn = () => {
|
|
|
191
186
|
form_1Ref.value
|
|
192
187
|
?.handleSubmit()
|
|
193
188
|
.then((res) => {
|
|
194
|
-
resolve(
|
|
189
|
+
resolve('success' + res)
|
|
195
190
|
})
|
|
196
191
|
.catch((err) => {
|
|
197
|
-
reject(
|
|
198
|
-
})
|
|
199
|
-
})
|
|
200
|
-
}
|
|
192
|
+
reject('error' + err)
|
|
193
|
+
})
|
|
194
|
+
})
|
|
195
|
+
}
|
|
201
196
|
|
|
202
197
|
/**
|
|
203
198
|
* 勾选是否记住密码
|
|
204
199
|
* */
|
|
205
200
|
const checkboxChange = () => {
|
|
206
|
-
emit(
|
|
207
|
-
}
|
|
201
|
+
emit('handleCheckbox', rememberPassword.value)
|
|
202
|
+
}
|
|
208
203
|
|
|
209
204
|
/**
|
|
210
205
|
* 选择历史账号
|
|
211
206
|
* */
|
|
212
207
|
const btnChoiceClick = (index: number) => {
|
|
213
|
-
showChoice.value = false
|
|
214
|
-
userForm.value.name = choiceList.value[index].user
|
|
215
|
-
userForm.value.pwd = choiceList.value[index].pwd
|
|
216
|
-
emit(
|
|
217
|
-
}
|
|
208
|
+
showChoice.value = false
|
|
209
|
+
userForm.value.name = choiceList.value[index].user
|
|
210
|
+
userForm.value.pwd = choiceList.value[index].pwd
|
|
211
|
+
emit('handleHistory')
|
|
212
|
+
}
|
|
218
213
|
|
|
219
214
|
/**
|
|
220
215
|
* 长按操作历史账户
|
|
@@ -224,21 +219,18 @@ const btnChoiceClick = (index: number) => {
|
|
|
224
219
|
const extensionFun = (index: number, username: string) => {
|
|
225
220
|
switch (index) {
|
|
226
221
|
case 0:
|
|
227
|
-
const i = choiceList.value.findIndex((item) => item.user === username)
|
|
228
|
-
choiceList.value.splice(i, 1)
|
|
229
|
-
uni.setStorageSync(
|
|
230
|
-
|
|
231
|
-
encryptData(choiceList.value),
|
|
232
|
-
);
|
|
233
|
-
break;
|
|
222
|
+
const i = choiceList.value.findIndex((item) => item.user === username)
|
|
223
|
+
choiceList.value.splice(i, 1)
|
|
224
|
+
uni.setStorageSync(`${props.prefix}_choiceList`, encryptData(choiceList.value))
|
|
225
|
+
break
|
|
234
226
|
default:
|
|
235
|
-
break
|
|
227
|
+
break
|
|
236
228
|
}
|
|
237
|
-
}
|
|
229
|
+
}
|
|
238
230
|
|
|
239
231
|
defineExpose({
|
|
240
232
|
loginFn,
|
|
241
|
-
})
|
|
233
|
+
})
|
|
242
234
|
</script>
|
|
243
235
|
|
|
244
236
|
<style lang="scss" scoped>
|
|
@@ -28,8 +28,8 @@
|
|
|
28
28
|
<view v-if="!slots.left" class="hy-swipe-action--right__action">
|
|
29
29
|
<view
|
|
30
30
|
class="hy-swipe-action--right__action-btn"
|
|
31
|
-
:style="item.style"
|
|
32
31
|
v-for="(item, i) in options"
|
|
32
|
+
:style="item.style"
|
|
33
33
|
@tap.stop="onActiveClick(item, i)"
|
|
34
34
|
>
|
|
35
35
|
{{ item.text }}
|
|
@@ -61,10 +61,15 @@ import {
|
|
|
61
61
|
ref,
|
|
62
62
|
watch,
|
|
63
63
|
useSlots,
|
|
64
|
-
PropType,
|
|
64
|
+
type PropType,
|
|
65
65
|
} from 'vue'
|
|
66
|
-
import type {
|
|
67
|
-
|
|
66
|
+
import type {
|
|
67
|
+
ISwipeActionEmits,
|
|
68
|
+
SwipeActionStatus,
|
|
69
|
+
SwipeActionPosition,
|
|
70
|
+
SwipeActionReason,
|
|
71
|
+
SwipeActionOptionsVo,
|
|
72
|
+
} from './typing'
|
|
68
73
|
import { useTouch } from '../../composables'
|
|
69
74
|
import { closeOther, pushToQueue, removeFromQueue } from './index'
|
|
70
75
|
import { getRect, guid } from '../../utils'
|
|
@@ -81,7 +86,7 @@ const props = defineProps({
|
|
|
81
86
|
* 滑动按钮的状态,使用v-model进行双向绑定。
|
|
82
87
|
* @values left,close,right
|
|
83
88
|
* */
|
|
84
|
-
modelValue: String
|
|
89
|
+
modelValue: String as PropType<SwipeActionStatus>,
|
|
85
90
|
/** 是否禁用滑动操作 */
|
|
86
91
|
disabled: {
|
|
87
92
|
type: Boolean,
|
|
@@ -94,7 +99,7 @@ const props = defineProps({
|
|
|
94
99
|
},
|
|
95
100
|
/** 右侧按钮内容 */
|
|
96
101
|
options: {
|
|
97
|
-
type: Array as unknown as PropType<
|
|
102
|
+
type: Array as unknown as PropType<SwipeActionOptionsVo[]>,
|
|
98
103
|
default: () => [
|
|
99
104
|
{
|
|
100
105
|
text: '收藏',
|
|
@@ -115,6 +120,8 @@ const props = defineProps({
|
|
|
115
120
|
type: Number,
|
|
116
121
|
default: 300,
|
|
117
122
|
},
|
|
123
|
+
/** 关闭滑动按钮前的钩子函数 */
|
|
124
|
+
beforeClose: Function,
|
|
118
125
|
})
|
|
119
126
|
const emit = defineEmits<ISwipeActionEmits>()
|
|
120
127
|
const leftClass = `hy-swipe-action--left--${guid()}`
|