云查询管理、新登陆页面
parent
f2b0837ead
commit
445ecde28f
Binary file not shown.
|
After Width: | Height: | Size: 415 B |
Binary file not shown.
|
After Width: | Height: | Size: 888 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 311 B |
Binary file not shown.
|
After Width: | Height: | Size: 36 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 439 B |
Binary file not shown.
|
After Width: | Height: | Size: 695 B |
|
|
@ -0,0 +1,42 @@
|
|||
import { defHttp } from '@/utils/http/axios';
|
||||
enum Api{
|
||||
getLeftTree = '/api/SysDataItemDetail/Load',
|
||||
addLeftItem = '/api/SysDataItemDetail/Add',
|
||||
delLeftItem = '/api/SysDataItemDetail/Delete',
|
||||
editLeftItem = '/api/SysDataItemDetail/Update',
|
||||
LoadPage = '/api/DroneCloudQueryContent/LoadPage',
|
||||
Get = '/api/DroneCloudQueryContent/Get',
|
||||
Add = '/api/DroneCloudQueryContent/Add',
|
||||
Update = '/api/DroneCloudQueryContent/Update',
|
||||
Delete = '/api/DroneCloudQueryContent/Delete',
|
||||
}
|
||||
|
||||
// 分类
|
||||
export function getLeftTree(params) {
|
||||
return defHttp.get({ url: Api.getLeftTree, params });
|
||||
}
|
||||
|
||||
export function addLeftItem(params){
|
||||
return defHttp.post({ url: Api.addLeftItem + '?code=' + params.itemCode, params });
|
||||
}
|
||||
|
||||
export function delLeftItem(params){
|
||||
return defHttp.post({ url: Api.delLeftItem + '?id=' + params.id });
|
||||
}
|
||||
|
||||
// 云查询管理
|
||||
export function LoadPage(params) {
|
||||
return defHttp.get({ url: Api.LoadPage, params });
|
||||
}
|
||||
export function Get(params) {
|
||||
return defHttp.get({ url: Api.Get, params });
|
||||
}
|
||||
export function Add(params) {
|
||||
return defHttp.post({ url: Api.Add, params });
|
||||
}
|
||||
export function Update(params) {
|
||||
return defHttp.post({ url: Api.Update, params });
|
||||
}
|
||||
export function Delete(params) {
|
||||
return defHttp.post({ url: Api.Delete + '?id=' + params.id , params });
|
||||
}
|
||||
|
|
@ -36,7 +36,8 @@ export const RootRoute: AppRouteRecordRaw = {
|
|||
export const LoginRoute: AppRouteRecordRaw = {
|
||||
path: '/login',
|
||||
name: 'Login',
|
||||
component: () => import('@/views/sys/login/Login.vue'),
|
||||
// component: () => import('@/views/sys/login/Login.vue'),
|
||||
component: () => import('@/views/sys/login_lindidiaocha/Login.vue'),
|
||||
meta: {
|
||||
title: t('routes.basic.login'),
|
||||
},
|
||||
|
|
|
|||
|
|
@ -0,0 +1,137 @@
|
|||
<template>
|
||||
<div class="categories-modal-container">
|
||||
<a-form
|
||||
ref="formRef"
|
||||
:model="props.modalData.data"
|
||||
:rules="props.modalData.type.indexOf('tree') > -1 ? treeRules : rightRules"
|
||||
labelAlign="right"
|
||||
:label-col="{ span: 6 }"
|
||||
>
|
||||
<template v-if="props.modalData.type.indexOf('tree') > -1">
|
||||
<a-form-item label="名称" name="itemName">
|
||||
<a-input v-model:value="props.modalData.data.itemName" />
|
||||
</a-form-item>
|
||||
<a-form-item label="类型" name="itemValue">
|
||||
<a-select v-model:value="props.modalData.data.itemValue">
|
||||
<a-select-option value="vector_data">矢量数据</a-select-option>
|
||||
<a-select-option value="imgage_data">影像数据</a-select-option>
|
||||
</a-select>
|
||||
</a-form-item>
|
||||
</template>
|
||||
<template v-else>
|
||||
<a-form-item label="ID" name="id" v-if="false">
|
||||
<a-input v-model:value="props.modalData.data.id" disabled />
|
||||
</a-form-item>
|
||||
<a-form-item label="名称" name="name">
|
||||
<a-input v-model:value="props.modalData.data.name" />
|
||||
</a-form-item>
|
||||
<a-form-item label="图层" name="layer">
|
||||
<a-select v-model:value="props.modalData.data.layer">
|
||||
<a-select-option value="1">图层1</a-select-option>
|
||||
<a-select-option value="2">图层2</a-select-option>
|
||||
</a-select>
|
||||
</a-form-item>
|
||||
<a-form-item label="数据表" name="tableName">
|
||||
<a-select v-model:value="props.modalData.data.tableName">
|
||||
<a-select-option value="1">数据表1</a-select-option>
|
||||
<a-select-option value="2">数据表2</a-select-option>
|
||||
</a-select>
|
||||
</a-form-item>
|
||||
<a-form-item label="叠加图层" name="overlayList">
|
||||
<a-select v-model:value="props.modalData.data.overlayList" mode="multiple">
|
||||
<a-select-option value="1" checked>天地图</a-select-option>
|
||||
<a-select-option value="2">图层2</a-select-option>
|
||||
<a-select-option value="3">图层3</a-select-option>
|
||||
<a-select-option value="4">图层4</a-select-option>
|
||||
</a-select>
|
||||
</a-form-item>
|
||||
<a-form-item label="是否分类" name="isClass">
|
||||
<a-switch
|
||||
v-model:checked="props.modalData.data.isClass"
|
||||
checked-children="是"
|
||||
un-checked-children="否"
|
||||
checked-value="1"
|
||||
un-checked-value="0"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="分类字段" name="classField" v-if="props.modalData.data.isClass">
|
||||
<a-select v-model:value="props.modalData.data.classField">
|
||||
<a-select-option value="1">字段1</a-select-option>
|
||||
<a-select-option value="2">字段2</a-select-option>
|
||||
<a-select-option value="3">字段3</a-select-option>
|
||||
<a-select-option value="4">字段4</a-select-option>
|
||||
</a-select>
|
||||
</a-form-item>
|
||||
<a-form-item label="分类名称" name="className" v-if="props.modalData.data.isClass">
|
||||
<a-input v-model:value="props.modalData.data.className" />
|
||||
</a-form-item>
|
||||
<a-form-item label="选择面积计算字段" name="areaField">
|
||||
<a-select v-model:value="props.modalData.data.areaField">
|
||||
<a-select-option value="1">面积1</a-select-option>
|
||||
<a-select-option value="2">面积2</a-select-option>
|
||||
<a-select-option value="3">面积3</a-select-option>
|
||||
<a-select-option value="4">面积4</a-select-option>
|
||||
</a-select>
|
||||
</a-form-item>
|
||||
<a-form-item label="是否合计" name="isSum">
|
||||
<a-switch
|
||||
v-model:checked="props.modalData.data.isSum"
|
||||
checked-children="是"
|
||||
un-checked-children="否"
|
||||
checked-value="1"
|
||||
un-checked-value="0"
|
||||
/>
|
||||
</a-form-item>
|
||||
</template>
|
||||
</a-form>
|
||||
<div class="modal-footer">
|
||||
<a-button style="margin-right: 10px" @click="closeModal">取消</a-button>
|
||||
<a-button type="primary" @click="submit">确定</a-button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { defineProps, defineEmits, ref } from 'vue';
|
||||
const props = defineProps(['modalData', 'modalForm']);
|
||||
const emit = defineEmits(['closeModal', 'submit']);
|
||||
const formRef = ref();
|
||||
const treeRules = {
|
||||
itemName: [{ required: true, message: '名称不能为空', trigger: 'blur' }],
|
||||
itemValue: [{ required: true, message: '类型不能为空', trigger: 'blur' }],
|
||||
};
|
||||
const rightRules = {
|
||||
itemName: [{ required: true, message: '分类名称不能为空', trigger: 'blur' }],
|
||||
itemCode: [{ required: true, message: '所属分类不能为空', trigger: 'blur' }],
|
||||
};
|
||||
const submit = () => {
|
||||
formRef.value
|
||||
.validate()
|
||||
.then(() => {
|
||||
emit('submit');
|
||||
})
|
||||
.catch((error) => {
|
||||
console.log('error', error);
|
||||
});
|
||||
};
|
||||
const closeModal = () => {
|
||||
emit('closeModal');
|
||||
formRef.value.resetFields();
|
||||
};
|
||||
const clearModalData = () => {
|
||||
formRef.value.resetFields();
|
||||
};
|
||||
defineExpose({
|
||||
clearModalData,
|
||||
});
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.categories-modal-container {
|
||||
padding: 10px 25px;
|
||||
.modal-footer {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
margin-top: 20px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,360 @@
|
|||
<template>
|
||||
<div class="page-div categories-page">
|
||||
<div class="tree-div w-1/5 xl:w-1/6 m-4 mr-0">
|
||||
<div class="header">
|
||||
<div class="buttons-div">
|
||||
<a-button
|
||||
type="primary"
|
||||
color="info"
|
||||
style="margin-right: 10px"
|
||||
@click="buttonClick('treeAdd')"
|
||||
>
|
||||
添加分类
|
||||
</a-button>
|
||||
<a-button type="primary" color="error" @click="buttonClick('treeDel')">
|
||||
删除分类
|
||||
</a-button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="content">
|
||||
<div class="showTree">
|
||||
<BasicTree
|
||||
ref="treeRef"
|
||||
:treeData="showLTree"
|
||||
:loading="lLoading"
|
||||
:fieldNames="{ key: 'itemValue', title: 'itemName' }"
|
||||
@select="
|
||||
(selectedKeys, { node }) => {
|
||||
getLeftSelectId(node.itemDetailId);
|
||||
changeTypeId(node.key);
|
||||
}
|
||||
"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="right-div w-4/5 xl:w-5/6">
|
||||
<BasicTable @register="registerTable">
|
||||
<template #toolbar>
|
||||
<PermissionBtn @btnEvent="buttonClick"></PermissionBtn>
|
||||
</template>
|
||||
<template #bodyCell="{ column, record }">
|
||||
<template v-if="column.key === 'enabledMark'">
|
||||
<a-tag v-if="record.enabledMark" color="success">正常</a-tag>
|
||||
<a-tag v-else color="error">停用</a-tag>
|
||||
</template>
|
||||
</template>
|
||||
</BasicTable>
|
||||
</div>
|
||||
<a-modal
|
||||
class="categories-modal"
|
||||
v-model:open="openModal"
|
||||
:title="modalData.title"
|
||||
:afterClose="clearModal"
|
||||
>
|
||||
<UseModal ref="modalForm" :modalData="modalData" @closeModal="closeModal" @submit="submit" />
|
||||
</a-modal>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ExclamationCircleOutlined } from '@ant-design/icons-vue';
|
||||
import UseModal from './Modal/index.vue';
|
||||
import { BasicTree } from '@/components/Tree';
|
||||
import { BasicTable, useTable } from '@/components/Table';
|
||||
import { PermissionBtn } from '@/components/PermissionBtn/index';
|
||||
import { ref, onMounted, reactive, watch, createVNode, unref } from 'vue';
|
||||
import {
|
||||
getLeftTree,
|
||||
addLeftItem,
|
||||
delLeftItem,
|
||||
LoadPage,
|
||||
Add,
|
||||
Update,
|
||||
Delete,
|
||||
} from '@/api/sys/cloud';
|
||||
import { columns, emptyRightItem, emptyLeftItem, searchFormSchema } from './util';
|
||||
import { Modal, message } from 'ant-design-vue';
|
||||
import dayjs from 'dayjs';
|
||||
|
||||
const modalForm = ref();
|
||||
let lLoading = ref(false);
|
||||
let typeId = ref('');
|
||||
let selectTreeId = ref('');
|
||||
let showLTree = ref([]);
|
||||
let openModal = ref(false);
|
||||
const modalData = reactive({
|
||||
title: '',
|
||||
data: {},
|
||||
type: '',
|
||||
});
|
||||
const treeRef = ref();
|
||||
const firstRequestCode = ref('');
|
||||
|
||||
const [registerTable, { reload, getSelectRows }] = useTable({
|
||||
// beforeFetch: (params) => {
|
||||
// console.log(firstRequestCode.value, 'before');
|
||||
// if (firstRequestCode.value !== '') {
|
||||
// params = { ...params, code: firstRequestCode.value };
|
||||
// } else {
|
||||
// params = { ...params, code: typeId.value };
|
||||
// }
|
||||
// return params;
|
||||
// },
|
||||
api: LoadPage,
|
||||
columns,
|
||||
formConfig: {
|
||||
labelWidth: 120,
|
||||
schemas: searchFormSchema,
|
||||
},
|
||||
showIndexColumn: false,
|
||||
rowSelection: {
|
||||
type: 'radio',
|
||||
},
|
||||
useSearchForm: true,
|
||||
bordered: true,
|
||||
showTableSetting: true,
|
||||
handleSearchInfoFn(info) {
|
||||
return info;
|
||||
},
|
||||
immediate: false,
|
||||
afterFetch(res) {
|
||||
firstRequestCode.value = '';
|
||||
return res;
|
||||
},
|
||||
});
|
||||
const getLeftTreeData = (isMounted) => {
|
||||
lLoading.value = true;
|
||||
getLeftTree({ code: 'cloudQueryManagement' })
|
||||
.then((res) => {
|
||||
showLTree.value = res;
|
||||
lLoading.value = false;
|
||||
if (isMounted && res.length > 0) {
|
||||
firstRequestCode.value = res[0].key;
|
||||
typeId.value = res[0].key;
|
||||
unref(treeRef).setSelectedKeys([res[0].key]);
|
||||
}
|
||||
reload();
|
||||
})
|
||||
.catch((err) => {
|
||||
lLoading.value = false;
|
||||
});
|
||||
};
|
||||
onMounted(() => {
|
||||
getLeftTreeData(true);
|
||||
});
|
||||
const changeTypeId = (value) => {
|
||||
typeId.value = value;
|
||||
reload();
|
||||
};
|
||||
const getLeftSelectId = (value) => {
|
||||
selectTreeId.value = value;
|
||||
};
|
||||
const submit = () => {
|
||||
let userName = localStorage.getItem('fireUserLoginName');
|
||||
switch (modalData.type) {
|
||||
case 'treeAdd':
|
||||
addLeftItem({
|
||||
...modalData.data,
|
||||
createUserName: userName,
|
||||
modifyUserName: userName,
|
||||
createDate: dayjs().format('YYYY-MM-DD HH:mm:ss'),
|
||||
modifyDate: dayjs().format('YYYY-MM-DD HH:mm:ss'),
|
||||
enabledMark: 1,
|
||||
sortCode: showLTree.value.length,
|
||||
})
|
||||
.then((res) => {
|
||||
getLeftTreeData(false);
|
||||
openModal.value = false;
|
||||
})
|
||||
.catch((err) => {
|
||||
console.log(err);
|
||||
});
|
||||
break;
|
||||
case 'btnAdd':
|
||||
Add({
|
||||
...modalData.data,
|
||||
createUserName: userName,
|
||||
modifyUserName: userName,
|
||||
createDate: dayjs().format('YYYY-MM-DD HH:mm:ss'),
|
||||
modifyDate: dayjs().format('YYYY-MM-DD HH:mm:ss'),
|
||||
})
|
||||
.then((res) => {
|
||||
reload();
|
||||
openModal.value = false;
|
||||
})
|
||||
.catch((err) => {
|
||||
console.log(err);
|
||||
});
|
||||
break;
|
||||
case 'btnEdit':
|
||||
Update({
|
||||
...modalData.data,
|
||||
modifyUserName: userName,
|
||||
modifyDate: dayjs().format('YYYY-MM-DD HH:mm:ss'),
|
||||
})
|
||||
.then((res) => {
|
||||
reload();
|
||||
openModal.value = false;
|
||||
})
|
||||
.catch((err) => {
|
||||
console.log(err);
|
||||
});
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
};
|
||||
const buttonClick = (diffType) => {
|
||||
let check = false;
|
||||
switch (diffType) {
|
||||
case 'treeAdd':
|
||||
openModal.value = true;
|
||||
modalData.title = '添加分组';
|
||||
modalData.data = emptyLeftItem;
|
||||
modalData.type = diffType;
|
||||
break;
|
||||
case 'treeDel':
|
||||
check = selectTreeId.value === '' ? true : false;
|
||||
if (check) {
|
||||
message.warning('请选择一条分组数据');
|
||||
return;
|
||||
}
|
||||
Modal.confirm({
|
||||
title: '是否确认删除?',
|
||||
icon: createVNode(ExclamationCircleOutlined),
|
||||
onCancel() {},
|
||||
onOk() {
|
||||
return delLeftItem({ id: selectTreeId.value })
|
||||
.then((res) => {
|
||||
getLeftTreeData(false);
|
||||
typeId.value = '';
|
||||
reload();
|
||||
})
|
||||
.catch((err) => {
|
||||
console.log(err);
|
||||
});
|
||||
},
|
||||
});
|
||||
break;
|
||||
case 'btnAdd':
|
||||
openModal.value = true;
|
||||
modalData.title = '添加';
|
||||
modalData.data = emptyRightItem;
|
||||
modalData.type = diffType;
|
||||
break;
|
||||
case 'btnDelete':
|
||||
check = getSelectRows().length !== 1 ? true : false;
|
||||
if (check) {
|
||||
message.warning('请选择一条数据');
|
||||
return;
|
||||
}
|
||||
Modal.confirm({
|
||||
title: '是否确认删除?',
|
||||
icon: createVNode(ExclamationCircleOutlined),
|
||||
onCancel() {},
|
||||
onOk() {
|
||||
console.log(getSelectRows()[0]);
|
||||
|
||||
let id = getSelectRows()[0].id;
|
||||
return Delete({ id: id })
|
||||
.then((res) => {
|
||||
reload();
|
||||
})
|
||||
.catch((err) => {
|
||||
console.log(err);
|
||||
});
|
||||
},
|
||||
});
|
||||
break;
|
||||
case 'btnEdit':
|
||||
if (getSelectRows().length !== 1) {
|
||||
message.warning('请选择一条数据');
|
||||
return;
|
||||
}
|
||||
let editData = getSelectRows()[0];
|
||||
console.log(editData);
|
||||
modalData.title = '编辑';
|
||||
modalData.data = { ...editData };
|
||||
modalData.type = diffType;
|
||||
openModal.value = true;
|
||||
break;
|
||||
}
|
||||
};
|
||||
const closeModal = () => {
|
||||
openModal.value = false;
|
||||
};
|
||||
const clearModal = () => {
|
||||
modalForm.value.clearModalData();
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.page-div {
|
||||
position: relative;
|
||||
display: flex;
|
||||
height: calc(100% - 20px);
|
||||
display: flex;
|
||||
|
||||
.tree-div {
|
||||
background-color: #fff;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
.header {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
padding: 10px;
|
||||
border-bottom: 1px solid #eee;
|
||||
.buttons-div {
|
||||
display: flex;
|
||||
justify-content: left;
|
||||
}
|
||||
.search-div {
|
||||
margin-top: 10px;
|
||||
display: flex;
|
||||
}
|
||||
}
|
||||
.content {
|
||||
border-radius: 5px;
|
||||
height: 100%;
|
||||
overflow: auto;
|
||||
.showTree {
|
||||
height: 100%;
|
||||
overflow: auto;
|
||||
}
|
||||
}
|
||||
}
|
||||
.right-div {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
<style lang="scss">
|
||||
.categories-page {
|
||||
.tree-div {
|
||||
.h-full {
|
||||
height: auto;
|
||||
}
|
||||
.search-div {
|
||||
.ant-btn-primary {
|
||||
background-color: #2a7dc9;
|
||||
}
|
||||
.ant-input-search-button {
|
||||
width: 42px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.categories-modal {
|
||||
.ant-modal-footer > button {
|
||||
display: none;
|
||||
}
|
||||
.ant-modal-footer {
|
||||
margin-top: 0px;
|
||||
border-top: 0px;
|
||||
}
|
||||
}
|
||||
// ant-table-header
|
||||
</style>
|
||||
|
|
@ -0,0 +1,86 @@
|
|||
export const columns = [
|
||||
{
|
||||
title: 'ID',
|
||||
dataIndex: 'id',
|
||||
resizable: true,
|
||||
ifShow: false,
|
||||
},
|
||||
{
|
||||
title: '名称',
|
||||
dataIndex: 'name',
|
||||
resizable: true,
|
||||
width: 100,
|
||||
},
|
||||
{
|
||||
title: '图层',
|
||||
dataIndex: 'layer',
|
||||
resizable: true,
|
||||
width: 100,
|
||||
},
|
||||
{
|
||||
title: '数据表',
|
||||
dataIndex: 'tableName',
|
||||
resizable: true,
|
||||
width: 100,
|
||||
},
|
||||
{
|
||||
title: '叠加图层',
|
||||
dataIndex: 'overlayList',
|
||||
resizable: true,
|
||||
width: 100,
|
||||
},
|
||||
{
|
||||
title: '是否分类',
|
||||
dataIndex: 'isClass',
|
||||
resizable: true,
|
||||
width: 100,
|
||||
},
|
||||
{
|
||||
title: '分类字段',
|
||||
dataIndex: 'classField',
|
||||
resizable: true,
|
||||
width: 100,
|
||||
},
|
||||
{
|
||||
title: '分类名称',
|
||||
dataIndex: 'className',
|
||||
resizable: true,
|
||||
width: 100,
|
||||
},
|
||||
{
|
||||
title: '选择面积计算字段',
|
||||
dataIndex: 'areaField',
|
||||
resizable: true,
|
||||
width: 100,
|
||||
},
|
||||
{
|
||||
title: '是否合计',
|
||||
dataIndex: 'isSum',
|
||||
resizable: true,
|
||||
width: 100,
|
||||
}
|
||||
];
|
||||
export const emptyLeftItem = {
|
||||
itemName: '',
|
||||
itemValue: '',
|
||||
};
|
||||
export const emptyRightItem = {
|
||||
id: '',
|
||||
name: '',
|
||||
layer: '',
|
||||
tableName: '',
|
||||
overlayList: ['1'],
|
||||
isClass: 0,
|
||||
classField: '',
|
||||
className: '',
|
||||
areaField:'',
|
||||
isSum: 0,
|
||||
};
|
||||
export const searchFormSchema = [
|
||||
{
|
||||
field: 'key',
|
||||
label: '关键字',
|
||||
component: 'Input',
|
||||
colProps: { span: 8 },
|
||||
},
|
||||
];
|
||||
|
|
@ -0,0 +1,405 @@
|
|||
<template>
|
||||
<div style="padding: 24px; overflow-y: hidden">
|
||||
<a-tabs v-model:activeKey="activeKey">
|
||||
<a-tab-pane key="imageBoundary" tab="影像边界shp">
|
||||
<div class="flex-column">
|
||||
<a-row style="overflow-y: hidden">
|
||||
<a-col :span="12" style="padding: 20px; border: 1px silver solid; margin-left: 10px">
|
||||
<a-form
|
||||
ref="form"
|
||||
v-modal:model="currentAppForm"
|
||||
labelAlign="right"
|
||||
label-width="80px"
|
||||
:label-col="labelCol"
|
||||
:wrapper-col="wrapperCol"
|
||||
size="mini"
|
||||
>
|
||||
<a-form-item label="当前版本">
|
||||
<span style="font-size: 15px; font-weight: bold; color: #000">
|
||||
<a-input v-model:value="currentAppInfo.edition" :bordered="false" />
|
||||
</span>
|
||||
</a-form-item>
|
||||
<a-form-item label="版本号">
|
||||
<a-input-number v-model:value="currentAppForm.edition" />
|
||||
</a-form-item>
|
||||
<a-form-item label="项目名称">
|
||||
<a-input
|
||||
v-model:value="currentAppForm.project_name"
|
||||
defaultValue="drone_enforcement"
|
||||
disabled="true"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="上传">
|
||||
<a-upload
|
||||
v-model:file-list="fileList"
|
||||
:name="imageBoundary_name"
|
||||
:multiple="true"
|
||||
:customRequest="handleCustomRequest"
|
||||
:headers="headers"
|
||||
:progress="progress"
|
||||
:beforeUpload="beforeUpload"
|
||||
>
|
||||
<a-button :loading="imageBoundary_loading"> 点击上传 </a-button>
|
||||
</a-upload>
|
||||
{{ fileName }}
|
||||
<DeleteOutlined v-if="fileName != ''" @click="deleteFileName" />
|
||||
</a-form-item>
|
||||
<a-form-item label="描述信息">
|
||||
<a-textarea
|
||||
type="textarea"
|
||||
v-model:value="currentAppForm.description"
|
||||
:rows="4"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="是否必须更新" label-width="120px">
|
||||
<a-radio-group v-model:value="currentAppForm.must_update" size="medium">
|
||||
<a-radio :bordered="false" :value="1">是</a-radio>
|
||||
<a-radio :bordered="false" :value="0">否</a-radio>
|
||||
</a-radio-group>
|
||||
</a-form-item>
|
||||
<a-form-item :wrapper-col="{ offset: 10, span: 14 }">
|
||||
<a-button type="primary" @click="onSubmit">立即创建</a-button>
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
</a-col>
|
||||
</a-row>
|
||||
</div>
|
||||
</a-tab-pane>
|
||||
<a-tab-pane key="imageRelease" tab="影像发布事件">
|
||||
<div class="flex-column">
|
||||
<a-row style="overflow-y: hidden">
|
||||
<a-col :span="12" style="padding: 20px; border: 1px silver solid; margin-left: 10px">
|
||||
<a-form
|
||||
ref="fly_form"
|
||||
v-model:model="fly_currentAppForm"
|
||||
labelAlign="right"
|
||||
label-width="80px"
|
||||
:label-col="labelCol"
|
||||
:wrapper-col="wrapperCol"
|
||||
size="mini"
|
||||
>
|
||||
<a-form-item label="当前版本">
|
||||
<span style="font-size: 15px; font-weight: bold; color: #000">
|
||||
<a-input :bordered="false" />
|
||||
</span>
|
||||
</a-form-item>
|
||||
<a-form-item label="版本号">
|
||||
<a-input-number v-model:value="fly_currentAppForm.edition" />
|
||||
</a-form-item>
|
||||
<a-form-item label="项目名称">
|
||||
<a-input v-model:value="fly_currentAppForm.project_name" />
|
||||
</a-form-item>
|
||||
<a-form-item label="上传">
|
||||
<a-upload
|
||||
v-model:file-list="fly_fileList"
|
||||
:name="imageRelease_name"
|
||||
:multiple="true"
|
||||
:customRequest="handleCustomRequest"
|
||||
:headers="headers"
|
||||
:progress="progress"
|
||||
:beforeUpload="beforeUpload"
|
||||
>
|
||||
<a-button :loading="imageRelease_loading"> 点击上传 </a-button>
|
||||
</a-upload>
|
||||
{{ fly_fileName }}
|
||||
<DeleteOutlined v-if="fileName != ''" @click="deleteFileName" />
|
||||
</a-form-item>
|
||||
<a-form-item label="描述信息">
|
||||
<a-textarea
|
||||
type="textarea"
|
||||
v-model:value="fly_currentAppForm.description"
|
||||
:rows="4"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="是否必须更新" label-width="120px">
|
||||
<a-radio-group v-model:value="fly_currentAppForm.must_update" size="medium">
|
||||
<a-radio :bordered="false" :value="1">是</a-radio>
|
||||
<a-radio :bordered="false" :value="0">否</a-radio>
|
||||
</a-radio-group>
|
||||
</a-form-item>
|
||||
<a-form-item :wrapper-col="{ offset: 10, span: 14 }">
|
||||
<a-button type="primary" @click="onFlyControlSubmit">立即创建</a-button>
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
</a-col>
|
||||
</a-row>
|
||||
</div>
|
||||
</a-tab-pane>
|
||||
<a-tab-pane key="history" tab="历史记录">
|
||||
<div>
|
||||
<BasicTable @register="registerTable">
|
||||
<template #toolbar>
|
||||
<a-button type="primary" @click="updateimage">更新最新影像</a-button>
|
||||
</template>
|
||||
<template #bodyCell="{ column, record }">
|
||||
<template v-if="column.key === 'enabledMark'">
|
||||
<a-tag v-if="record.enabledMark" color="success">正常</a-tag>
|
||||
<a-tag v-else color="error">停用</a-tag>
|
||||
</template>
|
||||
</template>
|
||||
</BasicTable>
|
||||
</div>
|
||||
</a-tab-pane>
|
||||
</a-tabs>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
// vue
|
||||
import { ref, onMounted } from 'vue';
|
||||
// vben
|
||||
import { useMessage } from '@/hooks/web/useMessage';
|
||||
import { DeleteOutlined, UploadOutlined } from '@ant-design/icons-vue';
|
||||
import { message, Upload } from 'ant-design-vue';
|
||||
import type { UploadProps } from 'ant-design-vue';
|
||||
import { BasicTable, useTable } from '@/components/Table';
|
||||
import { useGlobSetting } from '@/hooks/setting';
|
||||
import { columns, searchFormSchema } from './util';
|
||||
// api
|
||||
import { fun_GetUpdateFiles, fun_AddAppFiles } from '@/api/demo/version';
|
||||
import { fun_Load, fun_Upload } from '@/api/demo/files';
|
||||
|
||||
const { createMessage } = useMessage();
|
||||
const { apiUrl } = useGlobSetting();
|
||||
|
||||
// 表单栅格
|
||||
const labelCol = { span: 6 };
|
||||
const wrapperCol = { span: 18 };
|
||||
// 影像边界shp-当前版本信息
|
||||
let currentAppInfo = ref({});
|
||||
// 标签页
|
||||
let activeKey = ref('imageBoundary');
|
||||
// 上传文件列表
|
||||
let fileList: any = ref([]);
|
||||
let fly_fileList: any = ref([]);
|
||||
const imageBoundary_loading = ref<boolean>(false);
|
||||
const imageRelease_loading = ref<boolean>(false);
|
||||
|
||||
const imageBoundary_name = ref<string>('');
|
||||
const imageRelease_name = ref<string>('');
|
||||
// 上传的文件
|
||||
const fileName = ref('');
|
||||
const fly_fileName = ref('');
|
||||
let filePath = '';
|
||||
let fly_filePath = '';
|
||||
|
||||
// 影像边界shp
|
||||
const currentAppForm = ref({
|
||||
edition: '',
|
||||
description: '',
|
||||
filepath: '',
|
||||
must_update: '',
|
||||
project_name: '',
|
||||
createuser: '',
|
||||
createtime: '',
|
||||
});
|
||||
// 影像发布事件
|
||||
const fly_currentAppForm = ref({
|
||||
edition: '',
|
||||
description: '',
|
||||
filepath: '',
|
||||
must_update: '',
|
||||
project_name: '',
|
||||
createuser: '',
|
||||
createtime: '',
|
||||
});
|
||||
|
||||
// 版本
|
||||
async function getAppInfo() {
|
||||
fun_GetUpdateFiles({ project: 'drone_enforcement' }).then(async (res) => {
|
||||
if (res) {
|
||||
currentAppForm.value.project_name = res.project_name;
|
||||
currentAppForm.value.description = res.description;
|
||||
currentAppInfo.value = res;
|
||||
}
|
||||
});
|
||||
deleteFileName();
|
||||
}
|
||||
|
||||
// 上传文件接口
|
||||
const handleCustomRequest = (file, progress) => {
|
||||
if (activeKey.value === 'imageBoundary') {
|
||||
fileList.value = [];
|
||||
fun_Upload(file, progress)
|
||||
.then((res: any) => {
|
||||
if (res.data.result.length > 0) {
|
||||
fileName.value = res.data.result[0].fileName;
|
||||
filePath = res.data.result[0].filePath;
|
||||
imageBoundary_loading.value = false;
|
||||
}
|
||||
})
|
||||
.catch((err) => {
|
||||
imageBoundary_loading.value = false;
|
||||
file.onError(err);
|
||||
createMessage.error(err.message);
|
||||
});
|
||||
} else if (activeKey.value === 'imageRelease') {
|
||||
fly_fileList.value = [];
|
||||
fun_Upload(file, progress)
|
||||
.then((res: any) => {
|
||||
if (res.data.result.length > 0) {
|
||||
fly_fileName.value = res.data.result[0].fileName;
|
||||
fly_filePath = res.data.result[0].filePath;
|
||||
imageRelease_loading.value = false;
|
||||
}
|
||||
})
|
||||
.catch((err) => {
|
||||
imageRelease_loading.value = false;
|
||||
file.onError(err);
|
||||
createMessage.error(err.message);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
// 上传之前
|
||||
const beforeUpload: UploadProps['beforeUpload'] = (file) => {
|
||||
let extension = file.name.substring(file.name.lastIndexOf('.') + 1);
|
||||
let size = file.size / 1024 / 1024;
|
||||
const isApk = extension === 'apk';
|
||||
const suitableSize = size < 100;
|
||||
|
||||
if (activeKey.value === 'imageBoundary') {
|
||||
imageBoundary_name.value = file.name;
|
||||
} else {
|
||||
imageRelease_name.value = file.name;
|
||||
}
|
||||
if (!isApk) {
|
||||
createMessage.error('只能上传后缀是.apk的文件');
|
||||
}
|
||||
if (!suitableSize) {
|
||||
createMessage.error('文件大小不得超过100M');
|
||||
}
|
||||
if (isApk && suitableSize) {
|
||||
if (activeKey.value === 'imageBoundary') {
|
||||
imageBoundary_loading.value = true;
|
||||
} else {
|
||||
imageRelease_loading.value = true;
|
||||
}
|
||||
}
|
||||
return (isApk && suitableSize) || Upload.LIST_IGNORE;
|
||||
};
|
||||
|
||||
// 删除文件
|
||||
function deleteFileName() {
|
||||
// 影像边界shp-删除文件
|
||||
if (activeKey.value === 'imageBoundary') {
|
||||
fileName.value = '';
|
||||
filePath = '';
|
||||
fileList.value = [];
|
||||
} else {
|
||||
// 影像发布事件-删除文件
|
||||
fly_fileName.value = '';
|
||||
fly_filePath = '';
|
||||
fly_fileList.value = [];
|
||||
}
|
||||
}
|
||||
|
||||
// 影像边界shp-立即创建
|
||||
function onSubmit() {
|
||||
if (fileName.value == '' || filePath == '') {
|
||||
createMessage.warn(`请选择上传文件!`);
|
||||
return;
|
||||
}
|
||||
if (currentAppForm.value.edition == '') {
|
||||
createMessage.warn(`请先填写版本号!`);
|
||||
return;
|
||||
}
|
||||
if (currentAppForm.value.project_name != 'drone_enforcement') {
|
||||
createMessage.warn(`请不要修改项目名称!`);
|
||||
currentAppForm.value.project_name = 'drone_enforcement';
|
||||
return;
|
||||
}
|
||||
fun_Load({ key: fileName.value }).then((res) => {
|
||||
if (res.items.length > 0) {
|
||||
currentAppForm.value.filepath = res.items[0].filePath;
|
||||
fun_AddAppFiles(currentAppForm.value).then((res2) => {
|
||||
if (res2) {
|
||||
createMessage.success(`上传成功!`);
|
||||
currentAppForm.value = {
|
||||
createtime: '',
|
||||
createuser: '',
|
||||
edition: '',
|
||||
description: '',
|
||||
filepath: '',
|
||||
must_update: '',
|
||||
project_name: '',
|
||||
};
|
||||
fileList.value = [];
|
||||
getAppInfo();
|
||||
} else {
|
||||
createMessage.warn(`接口错误!`);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
createMessage.warn(`上传文件出现错误!`);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// 影像发布事件-立即创建
|
||||
function onFlyControlSubmit() {
|
||||
if (fly_fileName.value == '' || fly_filePath == '') {
|
||||
createMessage.warn(`请选择上传文件!`);
|
||||
return;
|
||||
}
|
||||
if (fly_currentAppForm.value.edition == '') {
|
||||
createMessage.warn(`请先填写版本号!`);
|
||||
return;
|
||||
}
|
||||
if (fly_currentAppForm.value.project_name == '') {
|
||||
createMessage.warn(`请先填写项目名称!`);
|
||||
return;
|
||||
}
|
||||
fun_Load({ key: fly_fileName.value }).then((res) => {
|
||||
if (res.items.length > 0) {
|
||||
fly_currentAppForm.value.filepath = res.items[0].filePath;
|
||||
fun_AddAppFiles(fly_currentAppForm.value).then((res2) => {
|
||||
if (res2) {
|
||||
createMessage.success(`上传成功!`);
|
||||
fly_currentAppForm.value = {
|
||||
createtime: '',
|
||||
createuser: '',
|
||||
edition: '',
|
||||
description: '',
|
||||
filepath: '',
|
||||
must_update: '',
|
||||
project_name: '',
|
||||
};
|
||||
fly_fileList.value = [];
|
||||
getAppInfo();
|
||||
} else {
|
||||
createMessage.warn(`接口错误!`);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
createMessage.warn(`上传文件出现错误!`);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// 历史记录
|
||||
const [registerTable, { reload, getSelectRows }] = useTable({
|
||||
// api: getRightTable,
|
||||
columns,
|
||||
formConfig: {
|
||||
labelWidth: 120,
|
||||
schemas: searchFormSchema,
|
||||
},
|
||||
showIndexColumn: false,
|
||||
rowSelection: {
|
||||
type: 'radio',
|
||||
},
|
||||
useSearchForm: true,
|
||||
bordered: true,
|
||||
showTableSetting: true,
|
||||
handleSearchInfoFn(info) {
|
||||
return info;
|
||||
},
|
||||
immediate: false,
|
||||
});
|
||||
|
||||
onMounted(() => {
|
||||
// 版本
|
||||
getAppInfo();
|
||||
});
|
||||
</script>
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
import dayjs from 'dayjs';
|
||||
|
||||
export const columns = [
|
||||
{
|
||||
title: 'ID',
|
||||
dataIndex: 'id',
|
||||
resizable: true,
|
||||
ifShow: false,
|
||||
},
|
||||
{
|
||||
title: '时间',
|
||||
dataIndex: 'time',
|
||||
resizable: true,
|
||||
width: 100,
|
||||
},
|
||||
{
|
||||
title: '名称',
|
||||
dataIndex: 'name',
|
||||
resizable: true,
|
||||
width: 100,
|
||||
},
|
||||
{
|
||||
title: '地址',
|
||||
dataIndex: 'geoserver',
|
||||
resizable: true,
|
||||
width: 100,
|
||||
},
|
||||
];
|
||||
|
||||
export const searchFormSchema = [
|
||||
{
|
||||
field: '[startTime, endTime]',
|
||||
label: '日期范围',
|
||||
component: 'RangePicker',
|
||||
colProps: { span: 8 },
|
||||
componentProps: {
|
||||
format: 'YYYY-MM',
|
||||
picker: 'month',
|
||||
placeholder: ['开始日期', '结束日期'],
|
||||
defaultValue: [dayjs(dayjs(), 'YYYY-MM-DD'), dayjs(dayjs(), 'YYYY-MM-DD')]
|
||||
},
|
||||
},
|
||||
];
|
||||
|
|
@ -0,0 +1,79 @@
|
|||
<template>
|
||||
<template v-if="getShow">
|
||||
<Form class="p-4 enter-x" :model="formData" :rules="getFormRules" ref="formRef">
|
||||
<FormItem name="account" class="enter-x">
|
||||
<Input
|
||||
size="large"
|
||||
v-model:value="formData.account"
|
||||
:placeholder="t('sys.login.userName')"
|
||||
/>
|
||||
</FormItem>
|
||||
|
||||
<FormItem name="mobile" class="enter-x">
|
||||
<Input size="large" v-model:value="formData.mobile" :placeholder="t('sys.login.mobile')" />
|
||||
</FormItem>
|
||||
<FormItem name="sms" class="enter-x">
|
||||
<CountdownInput
|
||||
size="large"
|
||||
v-model:value="formData.sms"
|
||||
:placeholder="t('sys.login.smsCode')"
|
||||
/>
|
||||
</FormItem>
|
||||
|
||||
<FormItem>
|
||||
<Button class="logon" size="large" block @click="handleReset" :loading="loading">
|
||||
{{ t('common.resetText') }}
|
||||
</Button>
|
||||
<Button size="large" block class="mt-4" @click="handleBackLogin">
|
||||
{{ t('sys.login.backSignIn') }}
|
||||
</Button>
|
||||
</FormItem>
|
||||
</Form>
|
||||
</template>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { reactive, ref, computed, unref } from 'vue';
|
||||
import LoginFormTitle from './LoginFormTitle.vue';
|
||||
import { Form, Input, Button } from 'ant-design-vue';
|
||||
import { CountdownInput } from '@/components/CountDown';
|
||||
import { useI18n } from '@/hooks/web/useI18n';
|
||||
import { useLoginState, useFormRules, LoginStateEnum } from './useLogin';
|
||||
|
||||
const FormItem = Form.Item;
|
||||
const { t } = useI18n();
|
||||
const { handleBackLogin, getLoginState } = useLoginState();
|
||||
const { getFormRules } = useFormRules();
|
||||
|
||||
const formRef = ref();
|
||||
const loading = ref(false);
|
||||
|
||||
const formData = reactive({
|
||||
account: '',
|
||||
mobile: '',
|
||||
sms: '',
|
||||
});
|
||||
|
||||
const getShow = computed(() => unref(getLoginState) === LoginStateEnum.RESET_PASSWORD);
|
||||
|
||||
async function handleReset() {
|
||||
const form = unref(formRef);
|
||||
if (!form) return;
|
||||
await form.resetFields();
|
||||
}
|
||||
</script>
|
||||
<style lang="less" scoped>
|
||||
.logon {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
text-align: center;
|
||||
justify-content: center;
|
||||
|
||||
background: #0f915f;
|
||||
border-radius: 6px;
|
||||
|
||||
font-family: Alibaba PuHuiTi;
|
||||
font-weight: 500;
|
||||
font-size: 21px;
|
||||
color: #ffffff;
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,155 @@
|
|||
<template>
|
||||
<div class="login" style="background-color: #f0f0f0; width: 100%; height: 100%">
|
||||
<div class="title">
|
||||
<img src="/login_lindidiaocha/logo.png" />
|
||||
<div class="title_span">
|
||||
<a-col>
|
||||
<a-row><span class="title_CN">临沂市自然资源综合监管平台</span></a-row>
|
||||
<a-row>
|
||||
<span class="title_EN">
|
||||
Linyi City Natural Resources Comprehensive Supervision Platform
|
||||
</span>
|
||||
</a-row>
|
||||
</a-col>
|
||||
</div>
|
||||
</div>
|
||||
<div class="bg">
|
||||
<div
|
||||
class="bg_login"
|
||||
:style="{
|
||||
height: `${isRegister ? 600 : 400}px`,
|
||||
}"
|
||||
>
|
||||
<LoginForm />
|
||||
<ForgetPasswordForm />
|
||||
<RegisterForm />
|
||||
<MobileForm />
|
||||
<QrCodeForm />
|
||||
</div>
|
||||
</div>
|
||||
<div class="bottom">
|
||||
版权所有:临沂市自然资源和规划局 技术支持:山东慧创信息科技有限公司
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { unref } from 'vue';
|
||||
import { AppDarkModeToggle, AppLocalePicker, AppLogo } from '@/components/Application';
|
||||
import { useGlobSetting } from '@/hooks/setting';
|
||||
import { useDesign } from '@/hooks/web/useDesign';
|
||||
import { useI18n } from '@/hooks/web/useI18n';
|
||||
import { useLocaleStore } from '@/store/modules/locale';
|
||||
import { computed } from 'vue';
|
||||
import ForgetPasswordForm from './ForgetPasswordForm.vue';
|
||||
import LoginForm from './LoginForm.vue';
|
||||
import MobileForm from './MobileForm.vue';
|
||||
import QrCodeForm from './QrCodeForm.vue';
|
||||
import RegisterForm from './RegisterForm.vue';
|
||||
import { LoginStateEnum, useLoginState } from './useLogin';
|
||||
const { getLoginState } = useLoginState();
|
||||
|
||||
const isRegister = computed(() => unref(getLoginState) === LoginStateEnum.REGISTER);
|
||||
|
||||
defineProps({
|
||||
sessionTimeout: {
|
||||
type: Boolean,
|
||||
},
|
||||
});
|
||||
|
||||
const globSetting = useGlobSetting();
|
||||
const { prefixCls } = useDesign('login');
|
||||
const { t } = useI18n();
|
||||
const localeStore = useLocaleStore();
|
||||
const showLocale = localeStore.getShowPicker;
|
||||
const title = computed(() => globSetting?.title ?? '');
|
||||
</script>
|
||||
<style lang="less">
|
||||
.login {
|
||||
// 页面不能被选中
|
||||
-webkit-user-select: none; /* Safari */
|
||||
-moz-user-select: none; /* Firefox */
|
||||
-ms-user-select: none; /* IE/Edge */
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.title {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
top: calc((25% - 230px));
|
||||
left: 143px;
|
||||
height: 99px;
|
||||
|
||||
img {
|
||||
width: 99px;
|
||||
margin-right: 28px;
|
||||
}
|
||||
|
||||
&_span {
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
top: 22px;
|
||||
}
|
||||
|
||||
&_CN {
|
||||
width: 100%;
|
||||
height: 50px;
|
||||
font-family: Alibaba PuHuiTi;
|
||||
font-weight: bold;
|
||||
font-size: 50px;
|
||||
color: #131313;
|
||||
letter-spacing: 3px;
|
||||
}
|
||||
&_EN {
|
||||
position: relative;
|
||||
top: 10px;
|
||||
width: 100%;
|
||||
height: 22px;
|
||||
font-family: Alibaba PuHuiTi;
|
||||
font-weight: 300;
|
||||
font-size: 22px;
|
||||
color: #131313;
|
||||
text-shadow: 0px 3px 7px rgba(0, 0, 0, 0.35);
|
||||
opacity: 0.3;
|
||||
}
|
||||
}
|
||||
|
||||
.bg {
|
||||
position: relative;
|
||||
top: 50px;
|
||||
width: 100%;
|
||||
height: calc(100% - 280px);
|
||||
background-image: url('/login_lindidiaocha/bg.png');
|
||||
background-position: center center;
|
||||
background-repeat: no-repeat;
|
||||
background-size: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
text-align: center;
|
||||
|
||||
&_login {
|
||||
position: relative;
|
||||
left: 1170px;
|
||||
width: 294.1px;
|
||||
background-color: #ffffff;
|
||||
border-radius: 5px;
|
||||
}
|
||||
}
|
||||
|
||||
.bottom {
|
||||
width: 628px;
|
||||
height: 18px;
|
||||
font-family: Alibaba PuHuiTi;
|
||||
font-weight: 400;
|
||||
font-size: 18px;
|
||||
border-radius: 5px;
|
||||
|
||||
position: absolute;
|
||||
bottom: 26px;
|
||||
|
||||
display: flex;
|
||||
align-items: center;
|
||||
text-align: center;
|
||||
justify-content: center;
|
||||
left: calc(50% - 628px / 2);
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,203 @@
|
|||
<template>
|
||||
<LoginFormTitle class="login_title" />
|
||||
<Form
|
||||
class="p-4 enter-x"
|
||||
:model="formData"
|
||||
:rules="getFormRules"
|
||||
ref="formRef"
|
||||
v-show="getShow"
|
||||
@keypress.enter="handleLogin"
|
||||
>
|
||||
<FormItem name="account">
|
||||
<Input
|
||||
size="large"
|
||||
v-model:value="formData.account"
|
||||
placeholder="请输入账户名"
|
||||
class="fix-auto-fill"
|
||||
>
|
||||
<template #prefix>
|
||||
<img src="/public/login_lindidiaocha/account.png" />
|
||||
</template>
|
||||
</Input>
|
||||
</FormItem>
|
||||
<FormItem name="password">
|
||||
<InputPassword
|
||||
size="large"
|
||||
visibilityToggle
|
||||
v-model:value="formData.password"
|
||||
placeholder="密码"
|
||||
>
|
||||
<template #prefix>
|
||||
<img src="/public/login_lindidiaocha/password.png" />
|
||||
</template>
|
||||
</InputPassword>
|
||||
</FormItem>
|
||||
|
||||
<ARow>
|
||||
<ACol :span="12">
|
||||
<FormItem>
|
||||
<Checkbox v-model:checked="rememberMe" size="small">
|
||||
{{ t('sys.login.rememberMe') }}
|
||||
</Checkbox>
|
||||
</FormItem>
|
||||
</ACol>
|
||||
<ACol :span="12">
|
||||
<FormItem
|
||||
:style="{
|
||||
'text-align': 'right',
|
||||
}"
|
||||
>
|
||||
<Button type="link" size="small" @click="setLoginState(LoginStateEnum.RESET_PASSWORD)">
|
||||
{{ t('sys.login.forgetPassword') }}
|
||||
</Button>
|
||||
</FormItem>
|
||||
</ACol>
|
||||
</ARow>
|
||||
|
||||
<FormItem>
|
||||
<Button size="large" block @click="handleLogin" :loading="loading" class="logon">
|
||||
立即登录
|
||||
</Button>
|
||||
</FormItem>
|
||||
</Form>
|
||||
<div class="bottom" v-if="getShow">
|
||||
<Button type="link" block size="small" @click="setLoginState(LoginStateEnum.REGISTER)">
|
||||
<template #icon>
|
||||
<img src="/public/login_lindidiaocha/register.png" />
|
||||
</template>
|
||||
<span> 用户注册</span>
|
||||
</Button>
|
||||
|
|
||||
<Button type="link" block size="small">
|
||||
<template #icon>
|
||||
<img src="/public/login_lindidiaocha/download.png" />
|
||||
</template>
|
||||
<span> 下载APP</span>
|
||||
</Button>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { reactive, ref, unref, computed } from 'vue';
|
||||
|
||||
import { Checkbox, Form, Input, Row, Col, Button, Divider } from 'ant-design-vue';
|
||||
// import {
|
||||
// GithubFilled,
|
||||
// WechatFilled,
|
||||
// AlipayCircleFilled,
|
||||
// GoogleCircleFilled,
|
||||
// TwitterCircleFilled,
|
||||
// } from '@ant-design/icons-vue';
|
||||
import LoginFormTitle from './LoginFormTitle.vue';
|
||||
|
||||
import { useI18n } from '@/hooks/web/useI18n';
|
||||
import { useMessage } from '@/hooks/web/useMessage';
|
||||
|
||||
import { useUserStore } from '@/store/modules/user';
|
||||
import { LoginStateEnum, useLoginState, useFormRules, useFormValid } from './useLogin';
|
||||
import { useDesign } from '@/hooks/web/useDesign';
|
||||
//import { onKeyStroke } from '@vueuse/core';
|
||||
|
||||
const ACol = Col;
|
||||
const ARow = Row;
|
||||
const FormItem = Form.Item;
|
||||
const InputPassword = Input.Password;
|
||||
const { t } = useI18n();
|
||||
const { notification, createErrorModal } = useMessage();
|
||||
const { prefixCls } = useDesign('login');
|
||||
const userStore = useUserStore();
|
||||
|
||||
const { setLoginState, getLoginState } = useLoginState();
|
||||
const { getFormRules } = useFormRules();
|
||||
|
||||
const formRef = ref();
|
||||
const loading = ref(false);
|
||||
const rememberMe = ref(false);
|
||||
|
||||
const formData = reactive({
|
||||
// account: 'vben',
|
||||
// password: '123456',
|
||||
account: '',
|
||||
password: '',
|
||||
});
|
||||
|
||||
const { validForm } = useFormValid(formRef);
|
||||
|
||||
//onKeyStroke('Enter', handleLogin);
|
||||
|
||||
const getShow = computed(() => unref(getLoginState) === LoginStateEnum.LOGIN);
|
||||
|
||||
async function handleLogin() {
|
||||
const data = await validForm();
|
||||
if (!data) return;
|
||||
try {
|
||||
loading.value = true;
|
||||
const userInfo = await userStore.login({
|
||||
password: data.password,
|
||||
account: data.account,
|
||||
mode: 'none', //不要默认的错误提示
|
||||
});
|
||||
console.log(userInfo);
|
||||
localStorage.setItem('fireUserLoginName', userInfo.name);
|
||||
if (userInfo) {
|
||||
notification.success({
|
||||
message: t('sys.login.loginSuccessTitle'),
|
||||
description: `${t('sys.login.loginSuccessDesc')}: ${userInfo.name}`,
|
||||
duration: 3,
|
||||
});
|
||||
}
|
||||
} catch (error) {
|
||||
createErrorModal({
|
||||
title: t('sys.api.errorTip'),
|
||||
content: (error as unknown as Error).message || t('sys.api.networkExceptionMsg'),
|
||||
getContainer: () => document.body.querySelector(`.${prefixCls}`) || document.body,
|
||||
});
|
||||
} finally {
|
||||
loading.value = false;
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style lang="less" scoped>
|
||||
.login_title {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
text-align: center;
|
||||
justify-content: center;
|
||||
|
||||
height: 68px;
|
||||
font-family: Alibaba PuHuiTi;
|
||||
font-weight: 900;
|
||||
font-size: 22px;
|
||||
color: #131313;
|
||||
}
|
||||
|
||||
.logon {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
text-align: center;
|
||||
justify-content: center;
|
||||
|
||||
background: #0f915f;
|
||||
border-radius: 6px;
|
||||
|
||||
font-family: Alibaba PuHuiTi;
|
||||
font-weight: 500;
|
||||
font-size: 21px;
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
.bottom {
|
||||
position: absolute;
|
||||
bottom: 0px;
|
||||
left: 0px;
|
||||
height: 50px;
|
||||
width: 100%;
|
||||
background: #ebf3f1;
|
||||
|
||||
Button {
|
||||
font-family: Microsoft YaHei;
|
||||
font-weight: 400;
|
||||
font-size: 14px;
|
||||
color: #999999;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
<template>
|
||||
<div class="login_title">
|
||||
{{ getFormTitle }}
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { computed, unref } from 'vue';
|
||||
import { useI18n } from '@/hooks/web/useI18n';
|
||||
import { LoginStateEnum, useLoginState } from './useLogin';
|
||||
|
||||
const { t } = useI18n();
|
||||
|
||||
const { getLoginState } = useLoginState();
|
||||
|
||||
const getFormTitle = computed(() => {
|
||||
const titleObj = {
|
||||
[LoginStateEnum.RESET_PASSWORD]: '重置密码',
|
||||
[LoginStateEnum.LOGIN]: '用户登录',
|
||||
[LoginStateEnum.REGISTER]: t('sys.login.signUpFormTitle'),
|
||||
[LoginStateEnum.MOBILE]: t('sys.login.mobileSignInFormTitle'),
|
||||
[LoginStateEnum.QR_CODE]: t('sys.login.qrSignInFormTitle'),
|
||||
};
|
||||
return titleObj[unref(getLoginState)];
|
||||
});
|
||||
</script>
|
||||
<style lang="less" scoped>
|
||||
.login_title {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
text-align: center;
|
||||
justify-content: center;
|
||||
|
||||
height: 68px;
|
||||
font-family: Alibaba PuHuiTi;
|
||||
font-weight: 900;
|
||||
font-size: 22px;
|
||||
color: #131313;
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,63 @@
|
|||
<template>
|
||||
<div v-if="getShow">
|
||||
<LoginFormTitle class="enter-x" />
|
||||
<Form class="p-4 enter-x" :model="formData" :rules="getFormRules" ref="formRef">
|
||||
<FormItem name="mobile" class="enter-x">
|
||||
<Input
|
||||
size="large"
|
||||
v-model:value="formData.mobile"
|
||||
:placeholder="t('sys.login.mobile')"
|
||||
class="fix-auto-fill"
|
||||
/>
|
||||
</FormItem>
|
||||
<FormItem name="sms" class="enter-x">
|
||||
<CountdownInput
|
||||
size="large"
|
||||
class="fix-auto-fill"
|
||||
v-model:value="formData.sms"
|
||||
:placeholder="t('sys.login.smsCode')"
|
||||
/>
|
||||
</FormItem>
|
||||
|
||||
<FormItem class="enter-x">
|
||||
<Button type="primary" size="large" block @click="handleLogin" :loading="loading">
|
||||
{{ t('sys.login.loginButton') }}
|
||||
</Button>
|
||||
<Button size="large" block class="mt-4" @click="handleBackLogin">
|
||||
{{ t('sys.login.backSignIn') }}
|
||||
</Button>
|
||||
</FormItem>
|
||||
</Form>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { reactive, ref, computed, unref } from 'vue';
|
||||
import { Form, Input, Button } from 'ant-design-vue';
|
||||
import { CountdownInput } from '@/components/CountDown';
|
||||
import LoginFormTitle from './LoginFormTitle.vue';
|
||||
import { useI18n } from '@/hooks/web/useI18n';
|
||||
import { useLoginState, useFormRules, useFormValid, LoginStateEnum } from './useLogin';
|
||||
|
||||
const FormItem = Form.Item;
|
||||
const { t } = useI18n();
|
||||
const { handleBackLogin, getLoginState } = useLoginState();
|
||||
const { getFormRules } = useFormRules();
|
||||
|
||||
const formRef = ref();
|
||||
const loading = ref(false);
|
||||
|
||||
const formData = reactive({
|
||||
mobile: '',
|
||||
sms: '',
|
||||
});
|
||||
|
||||
const { validForm } = useFormValid(formRef);
|
||||
|
||||
const getShow = computed(() => unref(getLoginState) === LoginStateEnum.MOBILE);
|
||||
|
||||
async function handleLogin() {
|
||||
const data = await validForm();
|
||||
if (!data) return;
|
||||
console.log(data);
|
||||
}
|
||||
</script>
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
<template>
|
||||
<div v-if="getShow">
|
||||
<LoginFormTitle class="enter-x" />
|
||||
<div class="enter-x min-w-64 min-h-64">
|
||||
<QrCode
|
||||
:value="qrCodeUrl"
|
||||
class="enter-x flex justify-center xl:justify-start"
|
||||
:width="280"
|
||||
/>
|
||||
<Divider class="enter-x">{{ t('sys.login.scanSign') }}</Divider>
|
||||
<Button size="large" block class="mt-4 enter-x" @click="handleBackLogin">
|
||||
{{ t('sys.login.backSignIn') }}
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { computed, unref } from 'vue';
|
||||
import LoginFormTitle from './LoginFormTitle.vue';
|
||||
import { Button, Divider } from 'ant-design-vue';
|
||||
import { QrCode } from '@/components/Qrcode';
|
||||
import { useI18n } from '@/hooks/web/useI18n';
|
||||
import { useLoginState, LoginStateEnum } from './useLogin';
|
||||
|
||||
const qrCodeUrl = 'https://vben.vvbin.cn/login';
|
||||
|
||||
const { t } = useI18n();
|
||||
const { handleBackLogin, getLoginState } = useLoginState();
|
||||
|
||||
const getShow = computed(() => unref(getLoginState) === LoginStateEnum.QR_CODE);
|
||||
</script>
|
||||
|
|
@ -0,0 +1,112 @@
|
|||
<template>
|
||||
<div v-if="getShow">
|
||||
<Form class="p-4 enter-x" :model="formData" :rules="getFormRules" ref="formRef">
|
||||
<FormItem name="account" class="enter-x">
|
||||
<Input
|
||||
class="fix-auto-fill"
|
||||
size="large"
|
||||
v-model:value="formData.account"
|
||||
:placeholder="t('sys.login.userName')"
|
||||
/>
|
||||
</FormItem>
|
||||
<FormItem name="mobile" class="enter-x">
|
||||
<Input
|
||||
size="large"
|
||||
v-model:value="formData.mobile"
|
||||
:placeholder="t('sys.login.mobile')"
|
||||
class="fix-auto-fill"
|
||||
/>
|
||||
</FormItem>
|
||||
<FormItem name="sms" class="enter-x">
|
||||
<CountdownInput
|
||||
size="large"
|
||||
class="fix-auto-fill"
|
||||
v-model:value="formData.sms"
|
||||
:placeholder="t('sys.login.smsCode')"
|
||||
/>
|
||||
</FormItem>
|
||||
<FormItem name="password" class="enter-x">
|
||||
<StrengthMeter
|
||||
size="large"
|
||||
v-model:value="formData.password"
|
||||
:placeholder="t('sys.login.password')"
|
||||
/>
|
||||
</FormItem>
|
||||
<FormItem name="confirmPassword" class="enter-x">
|
||||
<InputPassword
|
||||
size="large"
|
||||
visibilityToggle
|
||||
v-model:value="formData.confirmPassword"
|
||||
:placeholder="t('sys.login.confirmPassword')"
|
||||
/>
|
||||
</FormItem>
|
||||
|
||||
<FormItem class="enter-x" name="policy">
|
||||
<!-- No logic, you need to deal with it yourself -->
|
||||
<Checkbox v-model:checked="formData.policy" size="small">
|
||||
{{ t('sys.login.policy') }}
|
||||
</Checkbox>
|
||||
</FormItem>
|
||||
|
||||
<Button class="logon" size="large" block @click="handleRegister" :loading="loading">
|
||||
{{ t('sys.login.registerButton') }}
|
||||
</Button>
|
||||
<Button size="large" block class="mt-4 enter-x" @click="handleBackLogin">
|
||||
{{ t('sys.login.backSignIn') }}
|
||||
</Button>
|
||||
</Form>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { reactive, ref, unref, computed } from 'vue';
|
||||
import LoginFormTitle from './LoginFormTitle.vue';
|
||||
import { Form, Input, Button, Checkbox } from 'ant-design-vue';
|
||||
import { StrengthMeter } from '@/components/StrengthMeter';
|
||||
import { CountdownInput } from '@/components/CountDown';
|
||||
import { useI18n } from '@/hooks/web/useI18n';
|
||||
import { useLoginState, useFormRules, useFormValid, LoginStateEnum } from './useLogin';
|
||||
|
||||
const FormItem = Form.Item;
|
||||
const InputPassword = Input.Password;
|
||||
const { t } = useI18n();
|
||||
const { handleBackLogin, getLoginState } = useLoginState();
|
||||
|
||||
const formRef = ref();
|
||||
const loading = ref(false);
|
||||
|
||||
const formData = reactive({
|
||||
account: '',
|
||||
password: '',
|
||||
confirmPassword: '',
|
||||
mobile: '',
|
||||
sms: '',
|
||||
policy: false,
|
||||
});
|
||||
|
||||
const { getFormRules } = useFormRules(formData);
|
||||
const { validForm } = useFormValid(formRef);
|
||||
|
||||
const getShow = computed(() => unref(getLoginState) === LoginStateEnum.REGISTER);
|
||||
|
||||
async function handleRegister() {
|
||||
const data = await validForm();
|
||||
if (!data) return;
|
||||
console.log(data);
|
||||
}
|
||||
</script>
|
||||
<style lang="less" scoped>
|
||||
.logon {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
text-align: center;
|
||||
justify-content: center;
|
||||
|
||||
background: #0f915f;
|
||||
border-radius: 6px;
|
||||
|
||||
font-family: Alibaba PuHuiTi;
|
||||
font-weight: 500;
|
||||
font-size: 21px;
|
||||
color: #ffffff;
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,54 @@
|
|||
<template>
|
||||
<transition>
|
||||
<div :class="prefixCls" v-if="true">
|
||||
<Login sessionTimeout />
|
||||
</div>
|
||||
</transition>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { onBeforeUnmount, onMounted, ref } from 'vue';
|
||||
import Login from './Login.vue';
|
||||
import { useDesign } from '@/hooks/web/useDesign';
|
||||
import { useUserStore } from '@/store/modules/user';
|
||||
import { usePermissionStore } from '@/store/modules/permission';
|
||||
import { useAppStore } from '@/store/modules/app';
|
||||
import { PermissionModeEnum } from '@/enums/appEnum';
|
||||
import { type Nullable } from '@vben/types';
|
||||
|
||||
const { prefixCls } = useDesign('st-login');
|
||||
const userStore = useUserStore();
|
||||
const permissionStore = usePermissionStore();
|
||||
const appStore = useAppStore();
|
||||
const userId = ref<Nullable<number | string>>(0);
|
||||
|
||||
const isBackMode = () => {
|
||||
return appStore.getProjectConfig.permissionMode === PermissionModeEnum.BACK;
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
// 记录当前的UserId
|
||||
userId.value = userStore.getUserInfo?.userId;
|
||||
console.log('Mounted', userStore.getUserInfo);
|
||||
});
|
||||
|
||||
onBeforeUnmount(() => {
|
||||
if (userId.value && userId.value !== userStore.getUserInfo.userId) {
|
||||
// 登录的不是同一个用户,刷新整个页面以便丢弃之前用户的页面状态
|
||||
document.location.reload();
|
||||
} else if (isBackMode() && permissionStore.getLastBuildMenuTime === 0) {
|
||||
// 后台权限模式下,没有成功加载过菜单,就重新加载整个页面。这通常发生在会话过期后按F5刷新整个页面后载入了本模块这种场景
|
||||
document.location.reload();
|
||||
}
|
||||
});
|
||||
</script>
|
||||
<style lang="less" scoped>
|
||||
@prefix-cls: ~'@{namespace}-st-login';
|
||||
|
||||
.@{prefix-cls} {
|
||||
position: fixed;
|
||||
z-index: 9999999;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: @component-background;
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,130 @@
|
|||
import type { FormInstance } from 'ant-design-vue/lib/form/Form';
|
||||
import type {
|
||||
RuleObject,
|
||||
NamePath,
|
||||
Rule as ValidationRule,
|
||||
} from 'ant-design-vue/lib/form/interface';
|
||||
import { ref, computed, unref, Ref } from 'vue';
|
||||
import { useI18n } from '@/hooks/web/useI18n';
|
||||
|
||||
export enum LoginStateEnum {
|
||||
LOGIN,
|
||||
REGISTER,
|
||||
RESET_PASSWORD,
|
||||
MOBILE,
|
||||
QR_CODE,
|
||||
}
|
||||
|
||||
const currentState = ref(LoginStateEnum.LOGIN);
|
||||
|
||||
// 这里也可以优化
|
||||
// import { createGlobalState } from '@vueuse/core'
|
||||
|
||||
export function useLoginState() {
|
||||
function setLoginState(state: LoginStateEnum) {
|
||||
currentState.value = state;
|
||||
}
|
||||
|
||||
const getLoginState = computed(() => currentState.value);
|
||||
|
||||
function handleBackLogin() {
|
||||
setLoginState(LoginStateEnum.LOGIN);
|
||||
}
|
||||
|
||||
return { setLoginState, getLoginState, handleBackLogin };
|
||||
}
|
||||
|
||||
export function useFormValid<T extends Object = any>(formRef: Ref<FormInstance>) {
|
||||
const validate = computed(() => {
|
||||
const form = unref(formRef);
|
||||
return form?.validate ?? ((_nameList?: NamePath) => Promise.resolve());
|
||||
});
|
||||
|
||||
async function validForm() {
|
||||
const form = unref(formRef);
|
||||
if (!form) return;
|
||||
const data = await form.validate();
|
||||
return data as T;
|
||||
}
|
||||
|
||||
return { validate, validForm };
|
||||
}
|
||||
|
||||
export function useFormRules(formData?: Recordable) {
|
||||
const { t } = useI18n();
|
||||
|
||||
const getAccountFormRule = computed(() => createRule(t('sys.login.accountPlaceholder')));
|
||||
const getPasswordFormRule = computed(() => createRule(t('sys.login.passwordPlaceholder')));
|
||||
const getSmsFormRule = computed(() => createRule(t('sys.login.smsPlaceholder')));
|
||||
const getMobileFormRule = computed(() => createRule(t('sys.login.mobilePlaceholder')));
|
||||
|
||||
const validatePolicy = async (_: RuleObject, value: boolean) => {
|
||||
return !value ? Promise.reject(t('sys.login.policyPlaceholder')) : Promise.resolve();
|
||||
};
|
||||
|
||||
const validateConfirmPassword = (password: string) => {
|
||||
return async (_: RuleObject, value: string) => {
|
||||
if (!value) {
|
||||
return Promise.reject(t('sys.login.passwordPlaceholder'));
|
||||
}
|
||||
if (value !== password) {
|
||||
return Promise.reject(t('sys.login.diffPwd'));
|
||||
}
|
||||
return Promise.resolve();
|
||||
};
|
||||
};
|
||||
|
||||
const getFormRules = computed((): { [k: string]: ValidationRule | ValidationRule[] } => {
|
||||
const accountFormRule = unref(getAccountFormRule);
|
||||
const passwordFormRule = unref(getPasswordFormRule);
|
||||
const smsFormRule = unref(getSmsFormRule);
|
||||
const mobileFormRule = unref(getMobileFormRule);
|
||||
|
||||
const mobileRule = {
|
||||
sms: smsFormRule,
|
||||
mobile: mobileFormRule,
|
||||
};
|
||||
switch (unref(currentState)) {
|
||||
// register form rules
|
||||
case LoginStateEnum.REGISTER:
|
||||
return {
|
||||
account: accountFormRule,
|
||||
password: passwordFormRule,
|
||||
confirmPassword: [
|
||||
{ validator: validateConfirmPassword(formData?.password), trigger: 'change' },
|
||||
],
|
||||
policy: [{ validator: validatePolicy, trigger: 'change' }],
|
||||
...mobileRule,
|
||||
};
|
||||
|
||||
// reset password form rules
|
||||
case LoginStateEnum.RESET_PASSWORD:
|
||||
return {
|
||||
account: accountFormRule,
|
||||
...mobileRule,
|
||||
};
|
||||
|
||||
// mobile form rules
|
||||
case LoginStateEnum.MOBILE:
|
||||
return mobileRule;
|
||||
|
||||
// login form rules
|
||||
default:
|
||||
return {
|
||||
account: accountFormRule,
|
||||
password: passwordFormRule,
|
||||
};
|
||||
}
|
||||
});
|
||||
return { getFormRules };
|
||||
}
|
||||
|
||||
function createRule(message: string): ValidationRule[] {
|
||||
return [
|
||||
{
|
||||
required: true,
|
||||
message,
|
||||
trigger: 'change',
|
||||
},
|
||||
];
|
||||
}
|
||||
Loading…
Reference in New Issue