Merge branch 'dev' of github.com:jetlinks/jetlinks-ui-vue into dev
This commit is contained in:
commit
fed499e18c
|
@ -11,6 +11,7 @@ declare module '@vue/runtime-core' {
|
||||||
AButton: typeof import('ant-design-vue/es')['Button']
|
AButton: typeof import('ant-design-vue/es')['Button']
|
||||||
ACard: typeof import('ant-design-vue/es')['Card']
|
ACard: typeof import('ant-design-vue/es')['Card']
|
||||||
ACheckbox: typeof import('ant-design-vue/es')['Checkbox']
|
ACheckbox: typeof import('ant-design-vue/es')['Checkbox']
|
||||||
|
ACheckboxGroup: typeof import('ant-design-vue/es')['CheckboxGroup']
|
||||||
ACol: typeof import('ant-design-vue/es')['Col']
|
ACol: typeof import('ant-design-vue/es')['Col']
|
||||||
ADatePicker: typeof import('ant-design-vue/es')['DatePicker']
|
ADatePicker: typeof import('ant-design-vue/es')['DatePicker']
|
||||||
ADivider: typeof import('ant-design-vue/es')['Divider']
|
ADivider: typeof import('ant-design-vue/es')['Divider']
|
||||||
|
@ -23,15 +24,19 @@ declare module '@vue/runtime-core' {
|
||||||
AModal: typeof import('ant-design-vue/es')['Modal']
|
AModal: typeof import('ant-design-vue/es')['Modal']
|
||||||
APagination: typeof import('ant-design-vue/es')['Pagination']
|
APagination: typeof import('ant-design-vue/es')['Pagination']
|
||||||
APopconfirm: typeof import('ant-design-vue/es')['Popconfirm']
|
APopconfirm: typeof import('ant-design-vue/es')['Popconfirm']
|
||||||
|
ARadioGroup: typeof import('ant-design-vue/es')['RadioGroup']
|
||||||
ARow: typeof import('ant-design-vue/es')['Row']
|
ARow: typeof import('ant-design-vue/es')['Row']
|
||||||
ASelect: typeof import('ant-design-vue/es')['Select']
|
ASelect: typeof import('ant-design-vue/es')['Select']
|
||||||
ASpace: typeof import('ant-design-vue/es')['Space']
|
ASpace: typeof import('ant-design-vue/es')['Space']
|
||||||
ASpin: typeof import('ant-design-vue/es')['Spin']
|
ASpin: typeof import('ant-design-vue/es')['Spin']
|
||||||
|
ASwitch: typeof import('ant-design-vue/es')['Switch']
|
||||||
ATable: typeof import('ant-design-vue/es')['Table']
|
ATable: typeof import('ant-design-vue/es')['Table']
|
||||||
ATabPane: typeof import('ant-design-vue/es')['TabPane']
|
ATabPane: typeof import('ant-design-vue/es')['TabPane']
|
||||||
ATabs: typeof import('ant-design-vue/es')['Tabs']
|
ATabs: typeof import('ant-design-vue/es')['Tabs']
|
||||||
|
ATimePicker: typeof import('ant-design-vue/es')['TimePicker']
|
||||||
ATooltip: typeof import('ant-design-vue/es')['Tooltip']
|
ATooltip: typeof import('ant-design-vue/es')['Tooltip']
|
||||||
ATree: typeof import('ant-design-vue/es')['Tree']
|
ATree: typeof import('ant-design-vue/es')['Tree']
|
||||||
|
ATreeSelect: typeof import('ant-design-vue/es')['TreeSelect']
|
||||||
AUpload: typeof import('ant-design-vue/es')['Upload']
|
AUpload: typeof import('ant-design-vue/es')['Upload']
|
||||||
BadgeStatus: typeof import('./src/components/BadgeStatus/index.vue')['default']
|
BadgeStatus: typeof import('./src/components/BadgeStatus/index.vue')['default']
|
||||||
CardBox: typeof import('./src/components/CardBox/index.vue')['default']
|
CardBox: typeof import('./src/components/CardBox/index.vue')['default']
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
import { get } from '@/utils/request'
|
import { get, post } from '@/utils/request'
|
||||||
|
|
||||||
// 三方应用账户信息
|
// 三方应用账户信息
|
||||||
export const applicationInfo = (code: string) => get(`/application/sso/bind-code/${code}`)
|
export const applicationInfo = (code: string): any => get(`/application/sso/bind-code/${code}`)
|
||||||
|
// 立即绑定
|
||||||
|
export const bindAccount = (code: string): any => post(`/application/sso/me/bind/${code}`)
|
|
@ -1,11 +1,252 @@
|
||||||
<template>
|
<template>
|
||||||
<div class=''>
|
<div class='JForm-content'>
|
||||||
|
<a-form
|
||||||
|
ref='form'
|
||||||
|
v-bind='props'
|
||||||
|
:model='formData.data'
|
||||||
|
layout='vertical'
|
||||||
|
>
|
||||||
|
<a-row :type='rowType'>
|
||||||
|
<a-col v-for='item in formOptions.data' :key='item.key' :span='item.span'>
|
||||||
|
<a-form-item
|
||||||
|
:name='item.name'
|
||||||
|
:required='item.required'
|
||||||
|
:rules='item.rules'
|
||||||
|
:noStyle='item.noStyle'
|
||||||
|
>
|
||||||
|
<template #label>
|
||||||
|
<span>{{ item.title }}</span>
|
||||||
|
<a-tooltip :title='item.tooltip'>
|
||||||
|
<QuestionCircleOutlined v-if='!!item.tooltip' style='margin-left: 4px; color: rgba(0,0,0,.45) ' />
|
||||||
|
</a-tooltip>
|
||||||
|
</template>
|
||||||
|
<a-input
|
||||||
|
v-if='item.component === componentType.input'
|
||||||
|
v-bind='item.componentProps'
|
||||||
|
v-model:value='formData.data[item.name]'
|
||||||
|
/>
|
||||||
|
<a-select
|
||||||
|
v-else-if='item.component === componentType.select'
|
||||||
|
v-bind='item.componentProps'
|
||||||
|
v-model:value='formData.data[item.name]'
|
||||||
|
:options='item.options'
|
||||||
|
/>
|
||||||
|
<a-inputnumber
|
||||||
|
v-else-if='item.component === componentType.inputNumber'
|
||||||
|
v-bind='item.componentProps'
|
||||||
|
v-model:value='formData.data[item.name]'
|
||||||
|
/>
|
||||||
|
<a-input-password
|
||||||
|
v-else-if='item.component === componentType.password'
|
||||||
|
v-bind='item.componentProps'
|
||||||
|
v-model:value='formData.data[item.name]'
|
||||||
|
/>
|
||||||
|
<a-switch
|
||||||
|
v-else-if='item.component === componentType.switch'
|
||||||
|
v-bind='item.componentProps'
|
||||||
|
v-model:checked='formData.data[item.name]'
|
||||||
|
/>
|
||||||
|
<a-radio-group
|
||||||
|
v-else-if='item.component === componentType.radio'
|
||||||
|
v-bind='item.componentProps'
|
||||||
|
v-model:value='formData.data[item.name]'
|
||||||
|
/>
|
||||||
|
<a-checkbox-group
|
||||||
|
v-else-if='item.component === componentType.checkbox'
|
||||||
|
v-bind='item.componentProps'
|
||||||
|
v-model:value='formData.data[item.name]'
|
||||||
|
:options='item.options'
|
||||||
|
/>
|
||||||
|
<a-time-picker
|
||||||
|
v-else-if='item.component === componentType.time'
|
||||||
|
v-bind='item.componentProps'
|
||||||
|
v-model:value='formData.data[item.name]'
|
||||||
|
/>
|
||||||
|
<a-date-picker
|
||||||
|
v-else-if='item.component === componentType.date'
|
||||||
|
v-bind='item.componentProps'
|
||||||
|
v-model:value='formData.data[item.name]'
|
||||||
|
/>
|
||||||
|
<a-tree-select
|
||||||
|
v-else-if='item.component === componentType.tree'
|
||||||
|
v-bind='item.componentProps'
|
||||||
|
v-model:value='formData.data[item.name]'
|
||||||
|
:tree-data='item.options'
|
||||||
|
/>
|
||||||
|
<a-upload
|
||||||
|
v-else-if='item.component === componentType.upload'
|
||||||
|
v-bind='item.componentProps'
|
||||||
|
v-model:value='formData.data[item.name]'
|
||||||
|
/>
|
||||||
|
<component
|
||||||
|
v-else
|
||||||
|
:is='item.component'
|
||||||
|
v-bind='item.componentProps'
|
||||||
|
v-model:value='formData.data[item.name]'
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
</a-col>
|
||||||
|
</a-row>
|
||||||
|
</a-form>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup type='ts' name='FormBuilder'>
|
<script setup lang='ts' name='FormBuilder'>
|
||||||
const data = reactive({})
|
import type { Options, OptionsItem, OptionsComponent } from './index.modules'
|
||||||
|
import { PropType } from 'vue'
|
||||||
|
import { get, isArray, isString, pick, set } from 'lodash-es'
|
||||||
|
import { formProps } from 'ant-design-vue/es/form'
|
||||||
|
import componentType from './util'
|
||||||
|
import {
|
||||||
|
QuestionCircleOutlined
|
||||||
|
} from '@ant-design/icons-vue';
|
||||||
|
|
||||||
|
const form = ref()
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
...formProps,
|
||||||
|
options: {
|
||||||
|
type: Object as PropType<Options>,
|
||||||
|
default: () => []
|
||||||
|
},
|
||||||
|
initValue: {
|
||||||
|
type: Object,
|
||||||
|
default: () => ({})
|
||||||
|
},
|
||||||
|
column: {
|
||||||
|
type: Number,
|
||||||
|
default: 1
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
// 表单数据
|
||||||
|
const formData = reactive({
|
||||||
|
data: {}
|
||||||
|
})
|
||||||
|
|
||||||
|
const formOptions = reactive<{ data: OptionsComponent[]}>({
|
||||||
|
data: []
|
||||||
|
}) // 表单Item
|
||||||
|
|
||||||
|
const rowType = ref<string | undefined>(undefined)
|
||||||
|
|
||||||
|
const calculateItemSpan = (span?: number | string) => {
|
||||||
|
const itemSpan = 24 / props.column
|
||||||
|
if (!span) return itemSpan
|
||||||
|
|
||||||
|
if (isString(span) && span.includes('px')) {
|
||||||
|
rowType.value = 'flex'
|
||||||
|
} else {
|
||||||
|
return span
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据传入的表单options生成表单
|
||||||
|
* @param data {Options}
|
||||||
|
* @param parentKey
|
||||||
|
*/
|
||||||
|
const handleFormData = (data: Options, parentKey: Array<string> = []): any => {
|
||||||
|
const cacheModel: any = {}
|
||||||
|
|
||||||
|
Object.keys(data).forEach(async (key) => {
|
||||||
|
const optionItem = data[key]
|
||||||
|
const _key = [...parentKey, key]
|
||||||
|
if ('type' in optionItem && optionItem.type === 'Object') {
|
||||||
|
const dataModel = handleFormData(optionItem.properties, _key)
|
||||||
|
cacheModel[key] = dataModel
|
||||||
|
} else if (!('visible' in optionItem) || ('visible' in optionItem && optionItem.visible !== true)){
|
||||||
|
// 处理默认值以及原始值
|
||||||
|
const keyValue = get(formData.data, _key)
|
||||||
|
let _options: any[] = []
|
||||||
|
|
||||||
|
if (keyValue) { // 当前值在formModel中
|
||||||
|
cacheModel[key] = keyValue
|
||||||
|
} else {
|
||||||
|
cacheModel[key] = (optionItem as OptionsItem).default
|
||||||
|
}
|
||||||
|
// 处理options
|
||||||
|
if ('options' in optionItem) {
|
||||||
|
_options = optionItem.options!
|
||||||
|
}
|
||||||
|
// 处理 onSearch 请求
|
||||||
|
if ('onSearch' in optionItem) {
|
||||||
|
const data = await optionItem.onSearch!()
|
||||||
|
if (data) {
|
||||||
|
_options = data
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const optionsItemProps = pick(optionItem, ['componentProps', 'title', 'component', 'rules', 'required', 'hidden', 'tooltip', 'noStyle'])
|
||||||
|
//
|
||||||
|
formOptions.data.push({
|
||||||
|
...optionsItemProps,
|
||||||
|
name: _key,
|
||||||
|
options: _options,
|
||||||
|
key: isArray(_key) ? _key.toString() : _key,
|
||||||
|
span: calculateItemSpan((optionItem as OptionsItem).span)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
return cacheModel
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 重置表单
|
||||||
|
*/
|
||||||
|
const resetModel = () => {
|
||||||
|
form.value.resetFields()
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 验证并提交表单
|
||||||
|
*/
|
||||||
|
const formValidate = () => {
|
||||||
|
return new Promise((res, rej) => {
|
||||||
|
form.value.validate().then(() => {
|
||||||
|
res(formData.data)
|
||||||
|
}).catch((err: any) => {
|
||||||
|
rej(err)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* 改变单个值
|
||||||
|
*/
|
||||||
|
const setItemValue = (key: string | (string | number)[], value: any) => {
|
||||||
|
set(formData.data, key, value)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 修改整个表单值
|
||||||
|
* @param data
|
||||||
|
*/
|
||||||
|
const setData = (data: any) => {
|
||||||
|
formData.data = data
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (props.initValue) {
|
||||||
|
formData.data = props.initValue
|
||||||
|
}
|
||||||
|
|
||||||
|
formData.data = handleFormData(props.options)
|
||||||
|
|
||||||
|
watch(props.options, (newValue: any) => {
|
||||||
|
formOptions.data = []
|
||||||
|
formData.data = handleFormData(newValue)
|
||||||
|
})
|
||||||
|
|
||||||
|
watch(props.initValue, (newValue: any) => {
|
||||||
|
formData.data = newValue
|
||||||
|
})
|
||||||
|
|
||||||
|
defineExpose({
|
||||||
|
resetModel,
|
||||||
|
formValidate,
|
||||||
|
setItemValue,
|
||||||
|
setData
|
||||||
|
})
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
|
|
|
@ -0,0 +1,40 @@
|
||||||
|
import type { FormProps } from 'ant-design-vue/es/form'
|
||||||
|
|
||||||
|
export interface OptionsComponent {
|
||||||
|
/** FormItem title **/
|
||||||
|
title?: string
|
||||||
|
/** 组件名称 **/
|
||||||
|
component?: string
|
||||||
|
/** 组件Props **/
|
||||||
|
componentProps?: any
|
||||||
|
/** 组件Options **/
|
||||||
|
options?: any[]
|
||||||
|
name?: any
|
||||||
|
[name: string]: any
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface OptionsItem extends OptionsComponent{
|
||||||
|
/** 内置查询,会覆盖options **/
|
||||||
|
onSearch?: () => Promise<any>
|
||||||
|
default?: any
|
||||||
|
/** 隐藏Item,值不会进入到FormModel中 **/
|
||||||
|
visible?: boolean
|
||||||
|
/** 表单隐藏域 **/
|
||||||
|
hidden?: boolean,
|
||||||
|
span?: number | string
|
||||||
|
rules?: FormProps.rules
|
||||||
|
required?: boolean
|
||||||
|
tooltip?: string
|
||||||
|
noStyle?: boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
interface ObjectTypes {
|
||||||
|
type: 'Object'
|
||||||
|
properties: {
|
||||||
|
[name: string]: OptionsItem
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface Options extends FormProps {
|
||||||
|
[name: string]: ObjectTypes | OptionsItem
|
||||||
|
}
|
|
@ -1,3 +1,4 @@
|
||||||
import FormBuilder from './FormBuilder.vue'
|
import FormBuilder from './FormBuilder.vue'
|
||||||
|
export { default as componentType } from './util'
|
||||||
|
|
||||||
export default FormBuilder
|
export default FormBuilder
|
|
@ -0,0 +1,15 @@
|
||||||
|
const optionComponentType = {
|
||||||
|
input: 'input',
|
||||||
|
inputNumber: 'inputNumber',
|
||||||
|
password: 'password',
|
||||||
|
switch: 'switch',
|
||||||
|
radio: 'radio',
|
||||||
|
checkbox: 'checkbox',
|
||||||
|
time: 'time',
|
||||||
|
date: 'date',
|
||||||
|
treeSelect: 'treeSelect',
|
||||||
|
upload: 'upload',
|
||||||
|
tree: 'tree',
|
||||||
|
select: 'select'
|
||||||
|
}
|
||||||
|
export default optionComponentType
|
|
@ -0,0 +1,4 @@
|
||||||
|
.ant-form-item-required:before {
|
||||||
|
position: absolute;
|
||||||
|
right: -12px;
|
||||||
|
}
|
|
@ -4,7 +4,7 @@
|
||||||
<div class="content">
|
<div class="content">
|
||||||
<div class="title">第三方账户绑定</div>
|
<div class="title">第三方账户绑定</div>
|
||||||
<!-- 已登录-绑定三方账号 -->
|
<!-- 已登录-绑定三方账号 -->
|
||||||
<template v-if="false">
|
<template v-if="!token">
|
||||||
<div class="info">
|
<div class="info">
|
||||||
<a-card style="width: 280px">
|
<a-card style="width: 280px">
|
||||||
<template #title>
|
<template #title>
|
||||||
|
@ -28,14 +28,21 @@
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<div class="info-body">
|
<div class="info-body">
|
||||||
<img :src="getImage('/bind/wechat-webapp.png')" />
|
<img
|
||||||
|
:src="
|
||||||
|
accountInfo?.avatar ||
|
||||||
|
getImage('/bind/wechat-webapp.png')
|
||||||
|
"
|
||||||
|
/>
|
||||||
<p>用户名:-</p>
|
<p>用户名:-</p>
|
||||||
<p>名称:微信昵称</p>
|
<p>名称:{{ accountInfo?.name || '-' }}</p>
|
||||||
</div>
|
</div>
|
||||||
</a-card>
|
</a-card>
|
||||||
</div>
|
</div>
|
||||||
<div class="btn">
|
<div class="btn">
|
||||||
<a-button type="primary">立即绑定</a-button>
|
<a-button type="primary" @click="handleBind"
|
||||||
|
>立即绑定</a-button
|
||||||
|
>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<!-- 未登录-绑定三方账号 -->
|
<!-- 未登录-绑定三方账号 -->
|
||||||
|
@ -74,23 +81,25 @@
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
<a-form-item
|
<a-form-item
|
||||||
label="验证码"
|
label="验证码"
|
||||||
v-bind="validateInfos.captcha"
|
v-bind="validateInfos.verifyCode"
|
||||||
>
|
>
|
||||||
<a-input
|
<a-input
|
||||||
v-model:value="formData.captcha"
|
v-model:value="formData.verifyCode"
|
||||||
placeholder="请输入验证码"
|
placeholder="请输入验证码"
|
||||||
>
|
>
|
||||||
<template #addonAfter>
|
<template #addonAfter>
|
||||||
<span style="cursor: pointer">
|
<img
|
||||||
图形验证码
|
:src="captcha.base64"
|
||||||
</span>
|
@click="getCode"
|
||||||
|
style="cursor: pointer"
|
||||||
|
/>
|
||||||
</template>
|
</template>
|
||||||
</a-input>
|
</a-input>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
<a-form-item>
|
<a-form-item>
|
||||||
<a-button
|
<a-button
|
||||||
type="primary"
|
type="primary"
|
||||||
@click="handleSubmit"
|
@click="handleLoginBind"
|
||||||
style="width: 100%"
|
style="width: 100%"
|
||||||
>
|
>
|
||||||
登录并绑定账户
|
登录并绑定账户
|
||||||
|
@ -105,32 +114,58 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { getImage } from '@/utils/comm';
|
import { getImage, LocalStore } from '@/utils/comm';
|
||||||
|
import { TOKEN_KEY } from '@/utils/variable';
|
||||||
import { Form } from 'ant-design-vue';
|
import { Form } from 'ant-design-vue';
|
||||||
|
import { message } from 'ant-design-vue';
|
||||||
|
|
||||||
import { applicationInfo } from '@/api/bind';
|
import { applicationInfo, bindAccount } from '@/api/bind';
|
||||||
|
import { code, authLogin } from '@/api/login';
|
||||||
|
|
||||||
const useForm = Form.useForm;
|
const useForm = Form.useForm;
|
||||||
|
|
||||||
interface formData {
|
interface formData {
|
||||||
username: string;
|
username: string;
|
||||||
password: string;
|
password: string;
|
||||||
captcha: string;
|
verifyCode: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const token = computed(() => LocalStore.get(TOKEN_KEY));
|
||||||
|
|
||||||
|
// 已登录直接绑定
|
||||||
|
const getUrlCode = () => {
|
||||||
|
const url = new URLSearchParams(window.location.href);
|
||||||
|
return url.get('code') as string;
|
||||||
|
};
|
||||||
// 三方应用信息
|
// 三方应用信息
|
||||||
|
const accountInfo = ref({
|
||||||
|
avatar: '',
|
||||||
|
name: '',
|
||||||
|
});
|
||||||
const getAppInfo = async () => {
|
const getAppInfo = async () => {
|
||||||
const code: string = '73ab60c88979a1475963a5dde31e374b';
|
const code = getUrlCode();
|
||||||
const res = await applicationInfo(code);
|
const res = await applicationInfo(code);
|
||||||
console.log('getAppInfo: ', res);
|
accountInfo.value = res?.result?.result;
|
||||||
};
|
};
|
||||||
getAppInfo();
|
getAppInfo();
|
||||||
|
|
||||||
// 登录表单
|
/**
|
||||||
|
* 立即绑定
|
||||||
|
*/
|
||||||
|
const handleBind = async () => {
|
||||||
|
const code = getUrlCode();
|
||||||
|
const res = await bindAccount(code);
|
||||||
|
console.log('bindAccount: ', res);
|
||||||
|
message.success('绑定成功');
|
||||||
|
goRedirect();
|
||||||
|
setTimeout(() => window.close(), 1000);
|
||||||
|
};
|
||||||
|
|
||||||
|
// 未登录-先登录再绑定
|
||||||
const formData = ref<formData>({
|
const formData = ref<formData>({
|
||||||
username: '',
|
username: '',
|
||||||
password: '',
|
password: '',
|
||||||
captcha: '',
|
verifyCode: '',
|
||||||
});
|
});
|
||||||
const formRules = ref({
|
const formRules = ref({
|
||||||
username: [
|
username: [
|
||||||
|
@ -145,7 +180,7 @@ const formRules = ref({
|
||||||
message: '请输入密码',
|
message: '请输入密码',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
captcha: [
|
verifyCode: [
|
||||||
{
|
{
|
||||||
required: true,
|
required: true,
|
||||||
message: '请输入验证码',
|
message: '请输入验证码',
|
||||||
|
@ -158,17 +193,40 @@ const { resetFields, validate, validateInfos } = useForm(
|
||||||
formRules.value,
|
formRules.value,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取图形验证码
|
||||||
|
*/
|
||||||
|
const captcha = ref({
|
||||||
|
base64: '',
|
||||||
|
key: '',
|
||||||
|
});
|
||||||
|
const getCode = async () => {
|
||||||
|
const res: any = await code();
|
||||||
|
captcha.value = res.result;
|
||||||
|
};
|
||||||
|
getCode();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 登录并绑定账户
|
* 登录并绑定账户
|
||||||
*/
|
*/
|
||||||
const handleSubmit = () => {
|
const handleLoginBind = () => {
|
||||||
validate()
|
validate()
|
||||||
.then(() => {
|
.then(async () => {
|
||||||
console.log('toRaw:', toRaw(formData.value));
|
const code = getUrlCode();
|
||||||
console.log('formData.value:', formData.value);
|
const params = {
|
||||||
|
...formData.value,
|
||||||
|
verifyKey: captcha.value.key,
|
||||||
|
bindCode: code,
|
||||||
|
expires: 3600000,
|
||||||
|
};
|
||||||
|
const res = await authLogin(params);
|
||||||
|
console.log('res: ', res);
|
||||||
|
message.success('登录成功');
|
||||||
|
goRedirect();
|
||||||
|
setTimeout(() => window.close(), 1000);
|
||||||
})
|
})
|
||||||
.catch((err) => {
|
.catch((err) => {
|
||||||
console.log('error', err);
|
getCode();
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,9 +1,59 @@
|
||||||
<template>
|
<template>
|
||||||
<Form />
|
<Form
|
||||||
|
ref='form'
|
||||||
|
:options='options'
|
||||||
|
:initValue='initValue'
|
||||||
|
/>
|
||||||
|
<a-button @click='submit'>提交</a-button>
|
||||||
|
<a-button @click='reset'>重置</a-button>
|
||||||
|
<a-button @click='setValue'>修改name</a-button>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup name='FormDemo'>
|
<script setup name='FormDemo'>
|
||||||
const data = reactive({})
|
import { componentType } from 'components/Form'
|
||||||
|
const form = ref()
|
||||||
|
const initValue = reactive({})
|
||||||
|
|
||||||
|
const submit = () => {
|
||||||
|
form.value.formValidate().then(res => {
|
||||||
|
console.log(res)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const reset = () => {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
const setValue =() => {
|
||||||
|
initValue.name = '111111'
|
||||||
|
}
|
||||||
|
|
||||||
|
const options = reactive({
|
||||||
|
name: {
|
||||||
|
component: componentType.input,
|
||||||
|
componentProps: {
|
||||||
|
style: {
|
||||||
|
width: '200px'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
title: '测试',
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
sex: {
|
||||||
|
component: componentType.select,
|
||||||
|
title: '性别',
|
||||||
|
options: [
|
||||||
|
{ label: '111', value: 1 },
|
||||||
|
{ label: '222', value: 2 },
|
||||||
|
],
|
||||||
|
required: true,
|
||||||
|
rules: [
|
||||||
|
{ required: true, message: '请选择性别'}
|
||||||
|
],
|
||||||
|
tooltip: '性别',
|
||||||
|
default: 1
|
||||||
|
}
|
||||||
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
|
|
Loading…
Reference in New Issue