mirror of
https://gitee.com/xiongmao1988/rax-medical.git
synced 2025-08-23 20:44:58 +08:00
This commit is contained in:
parent
ac4a4fc26b
commit
5d3741e95a
|
@ -1,3 +1,10 @@
|
||||||
/// <reference types="vite/client" />
|
/// <reference types="vite/client" />
|
||||||
|
//解决ts文件引入vue文件出现红色警告问题
|
||||||
|
declare module '*.vue' {
|
||||||
|
import { defineComponent } from 'vue'
|
||||||
|
const Component: ReturnType<typeof defineComponent>
|
||||||
|
export default Component
|
||||||
|
}
|
||||||
|
/// <reference types="vite/client" />
|
||||||
declare module 'element-plus/dist/locale/zh-cn.mjs'
|
declare module 'element-plus/dist/locale/zh-cn.mjs'
|
||||||
declare module 'mockjs'
|
declare module 'mockjs'
|
|
@ -13,6 +13,7 @@
|
||||||
"axios": "^1.3.3",
|
"axios": "^1.3.3",
|
||||||
"echarts": "^5.4.1",
|
"echarts": "^5.4.1",
|
||||||
"element-plus": "2.3.1",
|
"element-plus": "2.3.1",
|
||||||
|
"js-cookie": "^3.0.5",
|
||||||
"pinia": "^2.1.7",
|
"pinia": "^2.1.7",
|
||||||
"sass": "^1.58.3",
|
"sass": "^1.58.3",
|
||||||
"uuid": "^9.0.1",
|
"uuid": "^9.0.1",
|
||||||
|
@ -22,7 +23,8 @@
|
||||||
"xlsx": "^0.18.5"
|
"xlsx": "^0.18.5"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/node": "^18.11.12",
|
"@types/js-cookie": "^3.0.6",
|
||||||
|
"@types/node": "^18.19.17",
|
||||||
"@types/uuid": "^9.0.8",
|
"@types/uuid": "^9.0.8",
|
||||||
"@vitejs/plugin-vue": "^4.0.0",
|
"@vitejs/plugin-vue": "^4.0.0",
|
||||||
"@vue/tsconfig": "^0.1.3",
|
"@vue/tsconfig": "^0.1.3",
|
||||||
|
|
|
@ -0,0 +1,53 @@
|
||||||
|
/*
|
||||||
|
//用户管理模块的接口
|
||||||
|
import request from '@/utils/request'
|
||||||
|
import type {
|
||||||
|
UserResponseData,
|
||||||
|
User,
|
||||||
|
AllRoleResponseData,
|
||||||
|
SetRoleData,
|
||||||
|
} from './type'
|
||||||
|
//枚举地址
|
||||||
|
enum API {
|
||||||
|
//获取全部已有用户账号信息
|
||||||
|
ALLUSER_URL = '/admin/acl/user/',
|
||||||
|
//添加一个新的用户账号
|
||||||
|
ADDUSER_URL = '/admin/acl/user/save',
|
||||||
|
//更新已有的用户账号
|
||||||
|
UPDATEUSER_URL = '/admin/acl/user/update',
|
||||||
|
//获取全部职位,当前账号拥有的职位接口
|
||||||
|
ALLROLEURL = '/admin/acl/user/toAssign/',
|
||||||
|
//给已有的用户分配角色接口
|
||||||
|
SETROLE_URL = '/admin/acl/user/doAssignRole',
|
||||||
|
//删除某一个账号
|
||||||
|
DELETEUSER_URL = '/admin/acl/user/remove/',
|
||||||
|
//批量删除的接口
|
||||||
|
DELETEALLUSER_URL = '/admin/acl/user/batchRemove',
|
||||||
|
}
|
||||||
|
//获取用户账号信息的接口
|
||||||
|
export const reqUserInfo = (page: number, limit: number, username: string) =>
|
||||||
|
request.get<any, UserResponseData>(
|
||||||
|
API.ALLUSER_URL + `${page}/${limit}/?username=${username}`,
|
||||||
|
)
|
||||||
|
//添加用户与更新已有用户的接口
|
||||||
|
export const reqAddOrUpdateUser = (data: User) => {
|
||||||
|
//携带参数有ID更新
|
||||||
|
if (data.id) {
|
||||||
|
return request.put<any, any>(API.UPDATEUSER_URL, data)
|
||||||
|
} else {
|
||||||
|
return request.post<any, any>(API.ADDUSER_URL, data)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//获取全部职位以及包含当前用户的已有的职位
|
||||||
|
export const reqAllRole = (userId: number) =>
|
||||||
|
request.get<any, AllRoleResponseData>(API.ALLROLEURL + userId)
|
||||||
|
//分配职位
|
||||||
|
export const reqSetUserRole = (data: SetRoleData) =>
|
||||||
|
request.post<any, any>(API.SETROLE_URL, data)
|
||||||
|
//删除某一个账号的信息
|
||||||
|
export const reqRemoveUser = (userId: number) =>
|
||||||
|
request.delete<any, any>(API.DELETEUSER_URL + userId)
|
||||||
|
//批量删除的接口
|
||||||
|
export const reqSelectUser = (idList: number[]) =>
|
||||||
|
request.delete(API.DELETEALLUSER_URL, { data: idList })
|
||||||
|
*/
|
|
@ -0,0 +1,55 @@
|
||||||
|
/*
|
||||||
|
//账号信息的ts类型
|
||||||
|
export interface ResponseData {
|
||||||
|
code: number
|
||||||
|
message: string
|
||||||
|
ok: boolean
|
||||||
|
}
|
||||||
|
//代表一个账号信息的ts类型
|
||||||
|
export interface User {
|
||||||
|
id?: number
|
||||||
|
createTime?: string
|
||||||
|
updateTime?: string
|
||||||
|
username?: string
|
||||||
|
password?: string
|
||||||
|
name?: string
|
||||||
|
phone?: null
|
||||||
|
roleName?: string
|
||||||
|
}
|
||||||
|
//数组包含全部的用户信息
|
||||||
|
export type Records = User[]
|
||||||
|
//获取全部用户信息接口返回的数据ts类型
|
||||||
|
export interface UserResponseData extends ResponseData {
|
||||||
|
data: {
|
||||||
|
records: Records
|
||||||
|
total: number
|
||||||
|
size: number
|
||||||
|
current: number
|
||||||
|
pages: number
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//代表一个职位的ts类型
|
||||||
|
export interface RoleData {
|
||||||
|
id?: number
|
||||||
|
createTime?: string
|
||||||
|
updateTime?: string
|
||||||
|
roleName: string
|
||||||
|
remark: null
|
||||||
|
}
|
||||||
|
//全部职位的列表
|
||||||
|
export type AllRole = RoleData[]
|
||||||
|
//获取全部职位的接口返回的数据ts类型
|
||||||
|
export interface AllRoleResponseData extends ResponseData {
|
||||||
|
data: {
|
||||||
|
assignRoles: AllRole
|
||||||
|
allRolesList: AllRole
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//给用户分配职位接口携带参数的ts类型
|
||||||
|
export interface SetRoleData {
|
||||||
|
roleIdList: number[]
|
||||||
|
userId: number
|
||||||
|
}
|
||||||
|
*/
|
|
@ -1,9 +1,9 @@
|
||||||
:root {
|
:root {
|
||||||
--main-color: #006080;
|
--main-color: #085a75;
|
||||||
--el-color-primary: var(--main-color);
|
--el-color-primary: var(--main-color);
|
||||||
--el-font-size-base: 16px;
|
--el-font-size-base: 16px;
|
||||||
}
|
}
|
||||||
$main-color: #006080;
|
$main-color: #085a75;
|
||||||
$red: #ea3323;
|
$red: #ea3323;
|
||||||
$border-color: #EBEEF5;
|
$border-color: #EBEEF5;
|
||||||
$border1-color: #E4E7ED;
|
$border1-color: #E4E7ED;
|
||||||
|
|
|
@ -0,0 +1,159 @@
|
||||||
|
<template>
|
||||||
|
<div></div>
|
||||||
|
</template>
|
||||||
|
<script setup lang="ts" name="global-websocket">
|
||||||
|
import { ElNotification } from 'element-plus';
|
||||||
|
import { Session } from '/@/utils/storage';
|
||||||
|
|
||||||
|
const emit = defineEmits(['rollback']);
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
uri: {
|
||||||
|
type: String,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const state = reactive({
|
||||||
|
webSocket: ref(), // webSocket实例
|
||||||
|
lockReconnect: false, // 重连锁,避免多次重连
|
||||||
|
maxReconnect: 6, // 最大重连次数, -1 标识无限重连
|
||||||
|
reconnectTime: 0, // 重连尝试次数
|
||||||
|
heartbeat: {
|
||||||
|
interval: 30 * 1000, // 心跳间隔时间
|
||||||
|
timeout: 10 * 1000, // 响应超时时间
|
||||||
|
pingTimeoutObj: ref(), // 延时发送心跳的定时器
|
||||||
|
pongTimeoutObj: ref(), // 接收心跳响应的定时器
|
||||||
|
pingMessage: JSON.stringify({ type: 'ping' }), // 心跳请求信息
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const token = computed(() => {
|
||||||
|
return Session.getToken();
|
||||||
|
});
|
||||||
|
|
||||||
|
const tenant = computed(() => {
|
||||||
|
return Session.getTenant();
|
||||||
|
});
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
initWebSocket();
|
||||||
|
});
|
||||||
|
|
||||||
|
onUnmounted(() => {
|
||||||
|
state.webSocket.close();
|
||||||
|
clearTimeoutObj(state.heartbeat);
|
||||||
|
});
|
||||||
|
|
||||||
|
const initWebSocket = () => {
|
||||||
|
// ws地址
|
||||||
|
let host = window.location.host;
|
||||||
|
// baseURL
|
||||||
|
let baseURL = import.meta.env.VITE_API_URL;
|
||||||
|
let wsUri = `ws://${host}${baseURL}${props.uri}?access_token=${token.value}&TENANT-ID=${tenant.value}`;
|
||||||
|
// 建立连接
|
||||||
|
state.webSocket = new WebSocket(wsUri);
|
||||||
|
// 连接成功
|
||||||
|
state.webSocket.onopen = onOpen;
|
||||||
|
// 连接错误
|
||||||
|
state.webSocket.onerror = onError;
|
||||||
|
// 接收信息
|
||||||
|
state.webSocket.onmessage = onMessage;
|
||||||
|
// 连接关闭
|
||||||
|
state.webSocket.onclose = onClose;
|
||||||
|
};
|
||||||
|
|
||||||
|
const reconnect = () => {
|
||||||
|
if (!token) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (state.lockReconnect || (state.maxReconnect !== -1 && state.reconnectTime > state.maxReconnect)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
state.lockReconnect = true;
|
||||||
|
setTimeout(() => {
|
||||||
|
state.reconnectTime++;
|
||||||
|
// 建立新连接
|
||||||
|
initWebSocket();
|
||||||
|
state.lockReconnect = false;
|
||||||
|
}, 5000);
|
||||||
|
};
|
||||||
|
/**
|
||||||
|
* 清空定时器
|
||||||
|
*/
|
||||||
|
const clearTimeoutObj = (heartbeat: any) => {
|
||||||
|
heartbeat.pingTimeoutObj && clearTimeout(heartbeat.pingTimeoutObj);
|
||||||
|
heartbeat.pongTimeoutObj && clearTimeout(heartbeat.pongTimeoutObj);
|
||||||
|
};
|
||||||
|
/**
|
||||||
|
* 开启心跳
|
||||||
|
*/
|
||||||
|
const startHeartbeat = () => {
|
||||||
|
const webSocket = state.webSocket;
|
||||||
|
const heartbeat = state.heartbeat;
|
||||||
|
// 清空定时器
|
||||||
|
clearTimeoutObj(heartbeat);
|
||||||
|
// 延时发送下一次心跳
|
||||||
|
heartbeat.pingTimeoutObj = setTimeout(() => {
|
||||||
|
// 如果连接正常
|
||||||
|
if (webSocket.readyState === 1) {
|
||||||
|
//这里发送一个心跳,后端收到后,返回一个心跳消息,
|
||||||
|
webSocket.send(heartbeat.pingMessage);
|
||||||
|
// 心跳发送后,如果服务器超时未响应则断开,如果响应了会被重置心跳定时器
|
||||||
|
heartbeat.pongTimeoutObj = setTimeout(() => {
|
||||||
|
webSocket.close();
|
||||||
|
}, heartbeat.timeout);
|
||||||
|
} else {
|
||||||
|
// 否则重连
|
||||||
|
reconnect();
|
||||||
|
}
|
||||||
|
}, heartbeat.interval);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 连接成功事件
|
||||||
|
*/
|
||||||
|
const onOpen = () => {
|
||||||
|
//开启心跳
|
||||||
|
startHeartbeat();
|
||||||
|
state.reconnectTime = 0;
|
||||||
|
};
|
||||||
|
/**
|
||||||
|
* 连接失败事件
|
||||||
|
* @param e
|
||||||
|
*/
|
||||||
|
const onError = () => {
|
||||||
|
//重连
|
||||||
|
reconnect();
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 连接关闭事件
|
||||||
|
* @param e
|
||||||
|
*/
|
||||||
|
const onClose = () => {
|
||||||
|
//重连
|
||||||
|
reconnect();
|
||||||
|
};
|
||||||
|
/**
|
||||||
|
* 接收服务器推送的信息
|
||||||
|
* @param msgEvent
|
||||||
|
*/
|
||||||
|
const onMessage = (msgEvent: any) => {
|
||||||
|
//收到服务器信息,心跳重置并发送
|
||||||
|
startHeartbeat();
|
||||||
|
const text = msgEvent.data;
|
||||||
|
|
||||||
|
if (text.indexOf('pong') > 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ElNotification.warning({
|
||||||
|
title: '消息提醒',
|
||||||
|
dangerouslyUseHTMLString: true,
|
||||||
|
message: text + '请及时处理',
|
||||||
|
offset: 60,
|
||||||
|
});
|
||||||
|
|
||||||
|
emit('rollback', text);
|
||||||
|
};
|
||||||
|
</script>
|
|
@ -78,16 +78,23 @@ const validatorPassword = (rule: any, value: any, callback: any) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
const validatorPhone = (rule: any, value: any, callback: any) => {
|
const validatorPhone = (rule: any, value: any, callback: any) => {
|
||||||
if (value.length == 11) {
|
var isPhone = /^1(3\d|4[5-9]|5[0-35-9]|6[2567]|7[0-8]|8\d|9[0-35-9])\d{8}$/;
|
||||||
callback();
|
|
||||||
|
|
||||||
|
if (value.indexOf('****') >= 0) {
|
||||||
|
return callback().trim();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isPhone.test(value)) {
|
||||||
|
callback(new Error('请输入合法手机号'));
|
||||||
} else {
|
} else {
|
||||||
callback(new Error('手机号码长度为11位'));
|
callback();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const rules = reactive({
|
const rules = reactive({
|
||||||
phone: [
|
phone: [
|
||||||
{ required: true, validator:validatorPhone, trigger: 'change' },
|
{ required: true, validator:validatorPhone, trigger: 'blur' },
|
||||||
],
|
],
|
||||||
name: [
|
name: [
|
||||||
{ required: true, message: '请输入姓名', trigger: 'blur' },
|
{ required: true, message: '请输入姓名', trigger: 'blur' },
|
||||||
|
|
|
@ -8,6 +8,7 @@ import * as ElementPlusIconsVue from '@element-plus/icons-vue'
|
||||||
import { ElDialog } from 'element-plus'
|
import { ElDialog } from 'element-plus'
|
||||||
import TableAbility from '@/components/table-ability.vue'
|
import TableAbility from '@/components/table-ability.vue'
|
||||||
|
|
||||||
|
|
||||||
import 'element-plus/dist/index.css';
|
import 'element-plus/dist/index.css';
|
||||||
import './assets/css/global.scss';
|
import './assets/css/global.scss';
|
||||||
import './assets/font/iconfont.css';
|
import './assets/font/iconfont.css';
|
||||||
|
|
|
@ -0,0 +1,22 @@
|
||||||
|
/*
|
||||||
|
import type { RouteRecordRaw } from 'vue-router'
|
||||||
|
import type { CategoryObj } from '@/api/product/attr/type'
|
||||||
|
//定义小仓库数据state类型
|
||||||
|
export interface UserState {
|
||||||
|
token: string | null
|
||||||
|
menuRoutes: RouteRecordRaw[]
|
||||||
|
username: string
|
||||||
|
avatar: string
|
||||||
|
buttons: string[]
|
||||||
|
}
|
||||||
|
|
||||||
|
//定义分类仓库state对象的ts类型
|
||||||
|
export interface CategoryState {
|
||||||
|
c1Id: string | number
|
||||||
|
c1Arr: CategoryObj[]
|
||||||
|
c2Arr: CategoryObj[]
|
||||||
|
c2Id: string | number
|
||||||
|
c3Arr: CategoryObj[]
|
||||||
|
c3Id: string | number
|
||||||
|
}
|
||||||
|
*/
|
|
@ -0,0 +1,112 @@
|
||||||
|
/*
|
||||||
|
//创建用户相关的小仓库
|
||||||
|
import { defineStore } from 'pinia'
|
||||||
|
//引入接口
|
||||||
|
import { reqLogin, reqUserInfo, reqLogout } from '@/api/user'
|
||||||
|
import type {
|
||||||
|
loginFormData,
|
||||||
|
loginResponseData,
|
||||||
|
userInfoReponseData,
|
||||||
|
} from '@/api/user/type'
|
||||||
|
import type { UserState } from './types/type'
|
||||||
|
//引入操作本地存储的工具方法
|
||||||
|
import { SET_TOKEN, GET_TOKEN, REMOVE_TOKEN } from '@/utils/token'
|
||||||
|
//引入路由(常量路由)
|
||||||
|
import { constantRoute, asnycRoute, anyRoute } from '@/router/routes'
|
||||||
|
|
||||||
|
//引入深拷贝方法
|
||||||
|
//@ts-expect-error
|
||||||
|
import cloneDeep from 'lodash/cloneDeep'
|
||||||
|
import router from '@/router'
|
||||||
|
//用于过滤当前用户需要展示的异步路由
|
||||||
|
function filterAsyncRoute(asnycRoute: any, routes: any) {
|
||||||
|
return asnycRoute.filter((item: any) => {
|
||||||
|
if (routes.includes(item.name)) {
|
||||||
|
if (item.children && item.children.length > 0) {
|
||||||
|
//硅谷333账号:product\trademark\attr\sku
|
||||||
|
item.children = filterAsyncRoute(item.children, routes)
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
//创建用户小仓库
|
||||||
|
const useUserStore = defineStore('User', {
|
||||||
|
//小仓库存储数据地方
|
||||||
|
state: (): UserState => {
|
||||||
|
return {
|
||||||
|
token: GET_TOKEN(), //用户唯一标识token
|
||||||
|
menuRoutes: constantRoute, //仓库存储生成菜单需要数组(路由)
|
||||||
|
username: '',
|
||||||
|
avatar: '',
|
||||||
|
//存储当前用户是否包含某一个按钮
|
||||||
|
buttons: [],
|
||||||
|
}
|
||||||
|
},
|
||||||
|
//异步|逻辑的地方
|
||||||
|
actions: {
|
||||||
|
//用户登录的方法
|
||||||
|
async userLogin(data: loginFormData) {
|
||||||
|
//登录请求
|
||||||
|
const result: loginResponseData = await reqLogin(data)
|
||||||
|
//登录请求:成功200->token
|
||||||
|
//登录请求:失败201->登录失败错误的信息
|
||||||
|
if (result.code == 200) {
|
||||||
|
//pinia仓库存储一下token
|
||||||
|
//由于pinia|vuex存储数据其实利用js对象
|
||||||
|
this.token = result.data as string
|
||||||
|
//本地存储持久化存储一份
|
||||||
|
SET_TOKEN(result.data as string)
|
||||||
|
//能保证当前async函数返回一个成功的promise
|
||||||
|
return 'ok'
|
||||||
|
} else {
|
||||||
|
return Promise.reject(new Error(result.data))
|
||||||
|
}
|
||||||
|
},
|
||||||
|
//获取用户信息方法
|
||||||
|
async userInfo() {
|
||||||
|
//获取用户信息进行存储仓库当中[用户头像、名字]
|
||||||
|
const result: userInfoReponseData = await reqUserInfo()
|
||||||
|
//如果获取用户信息成功,存储一下用户信息
|
||||||
|
if (result.code == 200) {
|
||||||
|
this.username = result.data.name
|
||||||
|
this.avatar = result.data.avatar
|
||||||
|
this.buttons = result.data.buttons
|
||||||
|
//计算当前用户需要展示的异步路由
|
||||||
|
const userAsyncRoute = filterAsyncRoute(
|
||||||
|
cloneDeep(asnycRoute),
|
||||||
|
result.data.routes,
|
||||||
|
)
|
||||||
|
//菜单需要的数据整理完毕
|
||||||
|
this.menuRoutes = [...constantRoute, ...userAsyncRoute, anyRoute]
|
||||||
|
//目前路由器管理的只有常量路由:用户计算完毕异步路由、任意路由动态追加
|
||||||
|
;[...userAsyncRoute, anyRoute].forEach((route: any) => {
|
||||||
|
router.addRoute(route)
|
||||||
|
})
|
||||||
|
return 'ok'
|
||||||
|
} else {
|
||||||
|
return Promise.reject(new Error(result.message))
|
||||||
|
}
|
||||||
|
},
|
||||||
|
//退出登录
|
||||||
|
async userLogout() {
|
||||||
|
//退出登录请求
|
||||||
|
const result: any = await reqLogout()
|
||||||
|
if (result.code == 200) {
|
||||||
|
//目前没有mock接口:退出登录接口(通知服务器本地用户唯一标识失效)
|
||||||
|
this.token = ''
|
||||||
|
this.username = ''
|
||||||
|
this.avatar = ''
|
||||||
|
REMOVE_TOKEN()
|
||||||
|
return 'ok'
|
||||||
|
} else {
|
||||||
|
return Promise.reject(new Error(result.message))
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
getters: {},
|
||||||
|
})
|
||||||
|
//对外暴露获取小仓库方法
|
||||||
|
export default useUserStore
|
||||||
|
*/
|
|
@ -1,4 +1,10 @@
|
||||||
|
//进行axios二次封装:使用请求与响应拦截器
|
||||||
import axios from "axios";
|
import axios from "axios";
|
||||||
|
/*
|
||||||
|
import { ElMessage } from 'element-plus'
|
||||||
|
//引入用户相关的仓库
|
||||||
|
import useUserStore from '@/stores/modules/user'
|
||||||
|
*/
|
||||||
|
|
||||||
export const HOST = 'http://localhost:9999';
|
export const HOST = 'http://localhost:9999';
|
||||||
const BASE_URL = import.meta.env.BASE_URL
|
const BASE_URL = import.meta.env.BASE_URL
|
||||||
|
@ -29,4 +35,65 @@ export const getData = (url: string, params?: any) => {
|
||||||
}
|
}
|
||||||
export const postData = (url: string, params?: any) => {
|
export const postData = (url: string, params?: any) => {
|
||||||
return axios.post(url, params)
|
return axios.post(url, params)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
//第一步:利用axios对象的create方法,去创建axios实例(其他的配置:基础路径、超时的时间)
|
||||||
|
const request = axios.create({
|
||||||
|
//基础路径
|
||||||
|
baseURL: import.meta.env.VITE_APP_BASE_API, //基础路径上会携带/api
|
||||||
|
timeout: 5000, //超时的时间的设置
|
||||||
|
})
|
||||||
|
//第二步:request实例添加请求与响应拦截器
|
||||||
|
request.interceptors.request.use((config) => {
|
||||||
|
//获取用户相关的小仓库:获取仓库内部token,登录成功以后携带给服务器
|
||||||
|
const userStore = useUserStore()
|
||||||
|
if (userStore.token) {
|
||||||
|
config.headers.token = userStore.token
|
||||||
|
}
|
||||||
|
//config配置对象,headers属性请求头,经常给服务器端携带公共参数
|
||||||
|
//返回配置对象
|
||||||
|
return config
|
||||||
|
})
|
||||||
|
|
||||||
|
//第三步:响应拦截器
|
||||||
|
request.interceptors.response.use(
|
||||||
|
(response) => {
|
||||||
|
//成功回调
|
||||||
|
//简化数据
|
||||||
|
return response.data
|
||||||
|
},
|
||||||
|
(error) => {
|
||||||
|
//失败回调:处理http网络错误的
|
||||||
|
//定义一个变量:存储网络错误信息
|
||||||
|
let message = ''
|
||||||
|
//http状态码
|
||||||
|
const status = error.response.status
|
||||||
|
switch (status) {
|
||||||
|
case 401:
|
||||||
|
message = 'TOKEN过期'
|
||||||
|
break
|
||||||
|
case 403:
|
||||||
|
message = '无权访问'
|
||||||
|
break
|
||||||
|
case 404:
|
||||||
|
message = '请求地址错误'
|
||||||
|
break
|
||||||
|
case 500:
|
||||||
|
message = '服务器出现问题'
|
||||||
|
break
|
||||||
|
default:
|
||||||
|
message = '网络出现问题'
|
||||||
|
break
|
||||||
|
}
|
||||||
|
//提示错误信息
|
||||||
|
ElMessage({
|
||||||
|
type: 'error',
|
||||||
|
message,
|
||||||
|
})
|
||||||
|
return Promise.reject(error)
|
||||||
|
},
|
||||||
|
)
|
||||||
|
//对外暴露
|
||||||
|
export default request*/
|
||||||
|
|
|
@ -0,0 +1,78 @@
|
||||||
|
/*
|
||||||
|
import Cookies from 'js-cookie';
|
||||||
|
|
||||||
|
/!**
|
||||||
|
* window.localStorage 浏览器永久缓存
|
||||||
|
* @method set 设置永久缓存
|
||||||
|
* @method get 获取永久缓存
|
||||||
|
* @method remove 移除永久缓存
|
||||||
|
* @method clear 移除全部永久缓存
|
||||||
|
*!/
|
||||||
|
export const Local = {
|
||||||
|
// 查看 v2.4.3版本更新日志
|
||||||
|
setKey(key: string) {
|
||||||
|
// @ts-ignore
|
||||||
|
return `${__NEXT_NAME__}:${key}`;
|
||||||
|
},
|
||||||
|
// 设置永久缓存
|
||||||
|
set<T>(key: string, val: T) {
|
||||||
|
window.localStorage.setItem(Local.setKey(key), JSON.stringify(val));
|
||||||
|
},
|
||||||
|
// 获取永久缓存
|
||||||
|
get(key: string) {
|
||||||
|
let json = <string>window.localStorage.getItem(Local.setKey(key));
|
||||||
|
return JSON.parse(json);
|
||||||
|
},
|
||||||
|
// 移除永久缓存
|
||||||
|
remove(key: string) {
|
||||||
|
window.localStorage.removeItem(Local.setKey(key));
|
||||||
|
},
|
||||||
|
// 移除全部永久缓存
|
||||||
|
clear() {
|
||||||
|
window.localStorage.clear();
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
/!**
|
||||||
|
* window.sessionStorage 浏览器临时缓存
|
||||||
|
* @method set 设置临时缓存
|
||||||
|
* @method get 获取临时缓存
|
||||||
|
* @method remove 移除临时缓存
|
||||||
|
* @method clear 移除全部临时缓存
|
||||||
|
*!/
|
||||||
|
export const Session = {
|
||||||
|
// 设置临时缓存
|
||||||
|
set(key: string, val: any) {
|
||||||
|
if (key === 'token' || key === 'refresh_token') {
|
||||||
|
Cookies.set(key, val);
|
||||||
|
}
|
||||||
|
window.sessionStorage.setItem(key, JSON.stringify(val));
|
||||||
|
},
|
||||||
|
// 获取临时缓存
|
||||||
|
get(key: string) {
|
||||||
|
if (key === 'token' || key === 'refresh_token') return Cookies.get(key);
|
||||||
|
let json = <string>window.sessionStorage.getItem(key);
|
||||||
|
return JSON.parse(json);
|
||||||
|
},
|
||||||
|
// 移除临时缓存
|
||||||
|
remove(key: string) {
|
||||||
|
if (key === 'token' || key === 'refresh_token') return Cookies.remove(key);
|
||||||
|
window.sessionStorage.removeItem(key);
|
||||||
|
},
|
||||||
|
// 移除全部临时缓存
|
||||||
|
clear() {
|
||||||
|
Cookies.remove('token');
|
||||||
|
Cookies.remove('refresh_token');
|
||||||
|
Cookies.remove('tenantId');
|
||||||
|
window.sessionStorage.clear();
|
||||||
|
},
|
||||||
|
// 获取当前存储的 token
|
||||||
|
getToken() {
|
||||||
|
return this.get('token');
|
||||||
|
},
|
||||||
|
// 获取当前的租户
|
||||||
|
getTenant() {
|
||||||
|
return Local.get('tenantId') ? Local.get('tenantId') : 1;
|
||||||
|
},
|
||||||
|
};
|
||||||
|
*/
|
|
@ -4,14 +4,20 @@ export const getTime = () => {
|
||||||
//通过内置构造函数Date
|
//通过内置构造函数Date
|
||||||
const hours = new Date().getHours()
|
const hours = new Date().getHours()
|
||||||
//情况的判断
|
//情况的判断
|
||||||
if (hours <= 9) {
|
if (hours < 9) {
|
||||||
message = '早上'
|
message = '早上'
|
||||||
} else if (hours <= 12) {
|
} else if (hours < 12) {
|
||||||
message = '上午'
|
message = '上午'
|
||||||
} else if (hours <= 18) {
|
} else if (hours < 14) {
|
||||||
|
message = '中午'
|
||||||
|
} else if (hours < 17) {
|
||||||
message = '下午'
|
message = '下午'
|
||||||
} else {
|
} else if (hours < 19) {
|
||||||
|
message = '傍晚'
|
||||||
|
} else if (hours < 22) {
|
||||||
message = '晚上'
|
message = '晚上'
|
||||||
|
} else {
|
||||||
|
message = '夜里'
|
||||||
}
|
}
|
||||||
return message
|
return message
|
||||||
}
|
}
|
||||||
|
|
|
@ -68,6 +68,7 @@ import TimeBarChart from "./time-bar-chart.vue";
|
||||||
import WeekCalendar from "./week-calendar.vue";
|
import WeekCalendar from "./week-calendar.vue";
|
||||||
import SystemLogs from "@/components/system-logs.vue";
|
import SystemLogs from "@/components/system-logs.vue";
|
||||||
|
|
||||||
|
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
const userInfo = useLoginStore().getlogin()
|
const userInfo = useLoginStore().getlogin()
|
||||||
|
|
||||||
|
|
|
@ -207,15 +207,16 @@ function fn1(res:any) {
|
||||||
align-items: center;
|
align-items: center;
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
|
|
||||||
|
|
||||||
.menu-item {
|
.menu-item {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
font-size: 17px;
|
font-size: 20px;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
color: $main-color;
|
color: $main-color;
|
||||||
height: 70px;
|
height: 70px;
|
||||||
padding: 0 10px;
|
padding: 0 15px;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
transition: all .5s;
|
transition: all .5s;
|
||||||
-webkit-transition: all .5s;
|
-webkit-transition: all .5s;
|
||||||
|
|
|
@ -8,114 +8,114 @@
|
||||||
</el-select>
|
</el-select>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<img v-show="!isShowRegister" class="logo move_2" src="@/assets/imgs/logo.png">
|
<img v-show="!isShowRegister" class="logo move_2" src="@/assets/imgs/logo.png">
|
||||||
<div v-if="!isShowRegister" class="login-block move_2">
|
<div v-if="!isShowRegister" class="login-block move_2">
|
||||||
<div class="login-way">
|
<div class="login-way">
|
||||||
<span :class="passwordLogin && 'active'" @click="passwordLogin = true">密码登录</span>
|
<span :class="passwordLogin && 'active'" @click="passwordLogin = true">密码登录</span>
|
||||||
<span :class="!passwordLogin && 'active'" @click="passwordLogin = false">验证码登录</span>
|
<span :class="!passwordLogin && 'active'" @click="passwordLogin = false">验证码登录</span>
|
||||||
</div>
|
</div>
|
||||||
<el-form ref="loginFormRef" :model="loginParams" :rules="loginRules" label-width="0" size="small">
|
<el-form ref="loginFormRef" :model="loginParams" :rules="loginRules" label-width="0" size="small">
|
||||||
<div class="login-form password-login" v-if="passwordLogin">
|
<div class="login-form password-login" v-if="passwordLogin">
|
||||||
<el-form-item prop="account">
|
<el-form-item prop="account">
|
||||||
<el-input v-model="loginParams.account" placeholder="请输入用户名">
|
<el-input v-model="loginParams.account" placeholder="请输入用户名">
|
||||||
<template #prepend>
|
<template #prepend>
|
||||||
<el-icon>
|
<el-icon>
|
||||||
<User/>
|
<User/>
|
||||||
</el-icon>
|
</el-icon>
|
||||||
</template>
|
</template>
|
||||||
</el-input>
|
</el-input>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item prop="password">
|
<el-form-item prop="password">
|
||||||
<el-input v-model="loginParams.password" type="password" show-password placeholder="请输入密码">
|
<el-input v-model="loginParams.password" type="password" show-password placeholder="请输入密码">
|
||||||
<template #prepend>
|
<template #prepend>
|
||||||
<el-icon>
|
<el-icon>
|
||||||
<Lock/>
|
<Lock/>
|
||||||
</el-icon>
|
</el-icon>
|
||||||
</template>
|
</template>
|
||||||
</el-input>
|
</el-input>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-button :loading="loading" class="login-btn" type="primary" @click="login('password')">登录</el-button>
|
<el-button :loading="loading" class="login-btn" type="primary" @click="login('password')">登录</el-button>
|
||||||
<span class="register-btn" @click="getCaptchaCode()">注册账号</span>
|
<span class="register-btn" @click="getCaptchaCode()">注册账号</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="login-form code-login" v-else>
|
<div class="login-form code-login" v-else>
|
||||||
<el-form-item prop="phone">
|
<el-form-item prop="phone">
|
||||||
<el-input v-model="loginParams.phone" placeholder="请输入手机号">
|
<el-input v-model="loginParams.phone" placeholder="请输入手机号">
|
||||||
<template #prepend>
|
<template #prepend>
|
||||||
<div @click.stop style="display: flex;align-items: center;">
|
<div @click.stop style="display: flex;align-items: center;">
|
||||||
<el-dropdown @command="selectPhoneArea">
|
<el-dropdown @command="selectPhoneArea">
|
||||||
<span style="color: #909399;">{{ loginParams.phoneArea }}<el-icon>
|
<span style="color: #909399;">{{ loginParams.phoneArea }}<el-icon>
|
||||||
<DCaret />
|
<DCaret />
|
||||||
</el-icon></span>
|
</el-icon></span>
|
||||||
<template #dropdown>
|
<template #dropdown>
|
||||||
<el-dropdown-menu>
|
<el-dropdown-menu>
|
||||||
<el-dropdown-item v-for="item in phoneAreas" :command="item">{{ item
|
<el-dropdown-item v-for="item in phoneAreas" :command="item">{{ item
|
||||||
}}</el-dropdown-item>
|
}}</el-dropdown-item>
|
||||||
</el-dropdown-menu>
|
</el-dropdown-menu>
|
||||||
</template>
|
</template>
|
||||||
</el-dropdown>
|
</el-dropdown>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</el-input>
|
</el-input>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item prop="code">
|
<el-form-item prop="code">
|
||||||
<el-input v-model="loginParams.code" placeholder="请输入6位短信验证码">
|
<el-input v-model="loginParams.code" placeholder="请输入6位短信验证码">
|
||||||
<template #append>
|
<template #append>
|
||||||
<span class="send-btn" @click="sendCode">{{ loginParams.sendText }}</span>
|
<span class="send-btn" @click="sendCode">{{ loginParams.sendText }}</span>
|
||||||
</template>
|
</template>
|
||||||
</el-input>
|
</el-input>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-button class="login-btn" type="primary" @click="login('code')">登录</el-button>
|
<el-button class="login-btn" type="primary" @click="login('code')">登录</el-button>
|
||||||
|
</div>
|
||||||
|
</el-form>
|
||||||
|
</div>
|
||||||
|
<div v-else class="register-block move_2">
|
||||||
|
<div class="header-box">
|
||||||
|
<span class="title">新用户申请</span>
|
||||||
|
<el-icon @click="isShowRegister = false">
|
||||||
|
<Close />
|
||||||
|
</el-icon>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<el-form ref="registerFormRef" :model="registerParams" :rules="registerRules" label-width="100">
|
||||||
|
<el-form-item label="用户名" prop="account">
|
||||||
|
<el-input v-model="registerParams.account" placeholder="请输入用户名"></el-input>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="密码" prop="password">
|
||||||
|
<el-input v-model="registerParams.password" type="password" show-password
|
||||||
|
placeholder="请输入密码"></el-input>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="姓名" prop="name">
|
||||||
|
<el-input v-model="registerParams.name" placeholder="请输入姓名"></el-input>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="手机号" prop="phone">
|
||||||
|
<el-input v-model="registerParams.phone" placeholder="请输入手机号"></el-input>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="医院" prop="hospital">
|
||||||
|
<el-select v-model="registerParams.hospital" style="width: 100%;">
|
||||||
|
<el-option v-for="item in hospitals" :key="item.value" :label="item.label"
|
||||||
|
:value="item.value" />
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="性别" prop="sex">
|
||||||
|
<el-radio-group v-model="registerParams.sex">
|
||||||
|
<el-radio label="男" />
|
||||||
|
<el-radio label="女" />
|
||||||
|
</el-radio-group>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="验证码" prop="code">
|
||||||
|
<el-input v-model="registerParams.code" placeholder="请输入验证码"
|
||||||
|
style="width: calc(100% - 110px);"></el-input>
|
||||||
|
<img width="100" height="32" style="margin-left: 10px;" :src="captchaImgUrl" />
|
||||||
|
<a class="change_img" @click="refreshImg" href="#">看不清?</a>
|
||||||
|
</el-form-item>
|
||||||
|
|
||||||
|
</el-form>
|
||||||
|
<div class="footer-box">
|
||||||
|
<el-button type="primary" @click="register">注 册</el-button>
|
||||||
|
<span @click="isShowRegister = false">已有账号?</span>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</el-form>
|
|
||||||
</div>
|
|
||||||
<div v-else class="register-block move_2">
|
|
||||||
<div class="header-box">
|
|
||||||
<span class="title">新用户申请</span>
|
|
||||||
<el-icon @click="isShowRegister = false">
|
|
||||||
<Close />
|
|
||||||
</el-icon>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<el-form ref="registerFormRef" :model="registerParams" :rules="registerRules" label-width="100">
|
|
||||||
<el-form-item label="用户名" prop="account">
|
|
||||||
<el-input v-model="registerParams.account" placeholder="请输入用户名"></el-input>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="密码" prop="password">
|
|
||||||
<el-input v-model="registerParams.password" type="password" show-password
|
|
||||||
placeholder="请输入密码"></el-input>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="姓名" prop="name">
|
|
||||||
<el-input v-model="registerParams.name" placeholder="请输入姓名"></el-input>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="手机号" prop="phone">
|
|
||||||
<el-input v-model="registerParams.phone" placeholder="请输入手机号"></el-input>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="医院" prop="hospital">
|
|
||||||
<el-select v-model="registerParams.hospital" style="width: 100%;">
|
|
||||||
<el-option v-for="item in hospitals" :key="item.value" :label="item.label"
|
|
||||||
:value="item.value" />
|
|
||||||
</el-select>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="性别" prop="sex">
|
|
||||||
<el-radio-group v-model="registerParams.sex">
|
|
||||||
<el-radio label="男" />
|
|
||||||
<el-radio label="女" />
|
|
||||||
</el-radio-group>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="验证码" prop="code">
|
|
||||||
<el-input v-model="registerParams.code" placeholder="请输入验证码"
|
|
||||||
style="width: calc(100% - 110px);"></el-input>
|
|
||||||
<img width="100" height="32" style="margin-left: 10px;" :src="captchaImgUrl" />
|
|
||||||
<a class="change_img" @click="refreshImg" href="#">看不清?</a>
|
|
||||||
</el-form-item>
|
|
||||||
|
|
||||||
</el-form>
|
|
||||||
<div class="footer-box">
|
|
||||||
<el-button type="primary" @click="register">注 册</el-button>
|
|
||||||
<span @click="isShowRegister = false">已有账号?</span>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<SliderVerify v-model:isShowSelf="sliderVConf.isShowSelf" :width="sliderVConf.width" :imgUrl="sliderImgUrl"
|
<SliderVerify v-model:isShowSelf="sliderVConf.isShowSelf" :width="sliderVConf.width" :imgUrl="sliderImgUrl"
|
||||||
|
@ -123,6 +123,9 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang='ts' setup>
|
<script lang='ts' setup>
|
||||||
|
import { ElNotification } from 'element-plus';
|
||||||
|
//引入获取当前时间的函数
|
||||||
|
import { getTime } from '@/utils/time';
|
||||||
import {onMounted, reactive, ref, toRefs, watch} from 'vue'
|
import {onMounted, reactive, ref, toRefs, watch} from 'vue'
|
||||||
import {useRouter,useRoute} from 'vue-router'
|
import {useRouter,useRoute} from 'vue-router'
|
||||||
import {ElMessage, ElMessageBox} from 'element-plus'
|
import {ElMessage, ElMessageBox} from 'element-plus'
|
||||||
|
@ -131,9 +134,8 @@ import {getHospitalsData, getPhoneAreasData} from '@/static-data/core'
|
||||||
import {v4} from "uuid";
|
import {v4} from "uuid";
|
||||||
import {HOST} from "@/utils/request";
|
import {HOST} from "@/utils/request";
|
||||||
import SliderVerify from "@/components/SliderVerify/index.vue";
|
import SliderVerify from "@/components/SliderVerify/index.vue";
|
||||||
import { ElNotification } from 'element-plus';
|
|
||||||
//引入获取当前时间的函数
|
|
||||||
import { getTime } from '@/utils/time';
|
|
||||||
//引入用户相关的小仓库
|
//引入用户相关的小仓库
|
||||||
//import useUserStore from "@/stores/user-info-store";
|
//import useUserStore from "@/stores/user-info-store";
|
||||||
//let useStore = useUserStore();
|
//let useStore = useUserStore();
|
||||||
|
@ -171,11 +173,19 @@ const validatorPassword = (rule: any, value: any, callback: any) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
const validatorPhone = (rule: any, value: any, callback: any) => {
|
const validatorPhone = (rule: any, value: any, callback: any) => {
|
||||||
if (value.length == 11) {
|
var isPhone = /^1(3\d|4[5-9]|5[0-35-9]|6[2567]|7[0-8]|8\d|9[0-35-9])\d{8}$/;
|
||||||
callback();
|
|
||||||
} else {
|
|
||||||
callback(new Error('手机号码长度为11位'));
|
if (value.indexOf('****') >= 0) {
|
||||||
|
return callback().trim();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!isPhone.test(value)) {
|
||||||
|
callback(new Error('请输入合法手机号'));
|
||||||
|
} else {
|
||||||
|
callback();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const loginRules = reactive({
|
const loginRules = reactive({
|
||||||
|
@ -186,7 +196,7 @@ const loginRules = reactive({
|
||||||
{ required: true, validator: validatorPassword, trigger: 'change' },
|
{ required: true, validator: validatorPassword, trigger: 'change' },
|
||||||
],
|
],
|
||||||
phone: [
|
phone: [
|
||||||
{ required: true, validator:validatorPhone, trigger: 'change' },
|
{ required: true, validator:validatorPhone, trigger: 'blur' },
|
||||||
],
|
],
|
||||||
code: [
|
code: [
|
||||||
{ required: true, message: '请输入验证码', trigger: 'blur' },
|
{ required: true, message: '请输入验证码', trigger: 'blur' },
|
||||||
|
@ -308,30 +318,33 @@ const login = async (type: string) => {
|
||||||
if (valid) {
|
if (valid) {
|
||||||
// console.log('submit!')
|
// console.log('submit!')
|
||||||
sliderVConf.value.isShowSelf = true
|
sliderVConf.value.isShowSelf = true
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
// console.log('error submit!', fields)
|
// console.log('error submit!', fields)
|
||||||
}
|
}
|
||||||
|
|
||||||
//加载效果:开始加载
|
//加载效果:开始加载
|
||||||
loading.value = true;
|
loading.value = true;
|
||||||
|
|
||||||
/*try {
|
|
||||||
//保证登录成功
|
|
||||||
await useStore.userLogin(loginFormRef);
|
|
||||||
|
|
||||||
}*/
|
|
||||||
|
|
||||||
//编程式导航跳转到展示数据首页
|
|
||||||
//判断登录的时候,路由路径当中是否有query参数,如果有就往query参数挑战,没有跳转到首页
|
|
||||||
let redirect: any = $route.query.redirect;
|
|
||||||
$router.push({ path: redirect || '/' });
|
|
||||||
//登录成功提示信息
|
|
||||||
ElNotification({
|
ElNotification({
|
||||||
type: 'success',
|
type: 'success',
|
||||||
message: '欢迎回来',
|
message: '欢迎回来',
|
||||||
title: `HI,${getTime()}好`
|
title: `HI,${getTime()}好`
|
||||||
});
|
});
|
||||||
|
|
||||||
|
/*try {
|
||||||
|
//保证登录成功
|
||||||
|
await useStore.userLogin(loginFormRef);
|
||||||
|
//编程式导航跳转到展示数据首页
|
||||||
|
//判断登录的时候,路由路径当中是否有query参数,如果有就往query参数挑战,没有跳转到首页
|
||||||
|
let redirect: any = $route.query.redirect;
|
||||||
|
$router.push({ path: redirect || '/' });
|
||||||
|
|
||||||
//登录成功加载效果也消失
|
//登录成功加载效果也消失
|
||||||
loading.value = false;
|
loading.value = false;
|
||||||
|
}*/
|
||||||
|
|
||||||
|
|
||||||
/*} catch (error) {
|
/*} catch (error) {
|
||||||
//登录失败加载效果消息
|
//登录失败加载效果消息
|
||||||
loading.value = false;
|
loading.value = false;
|
||||||
|
@ -342,6 +355,8 @@ const login = async (type: string) => {
|
||||||
})*/
|
})*/
|
||||||
|
|
||||||
})
|
})
|
||||||
|
//登录成功加载效果也消失
|
||||||
|
loading.value = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
function getCaptchaCode() {
|
function getCaptchaCode() {
|
||||||
|
@ -395,8 +410,7 @@ const toHome = () => {
|
||||||
background: url(@/assets/imgs/login/login_bck.png) no-repeat;
|
background: url(@/assets/imgs/login/login_bck.png) no-repeat;
|
||||||
background-size: cover;
|
background-size: cover;
|
||||||
}
|
}
|
||||||
|
.right-content {
|
||||||
.right-content {
|
|
||||||
position: relative;
|
position: relative;
|
||||||
width: 50%;
|
width: 50%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
@ -407,8 +421,8 @@ const toHome = () => {
|
||||||
|
|
||||||
.select-hospital-box {
|
.select-hospital-box {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 50px;
|
top: 25px;
|
||||||
right: 50px;
|
right: 25px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.logo {
|
.logo {
|
||||||
|
@ -535,5 +549,6 @@ const toHome = () => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -31,10 +31,10 @@ function initChart(chartData: any) {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
grid: {
|
grid: {
|
||||||
left: 20,
|
left: 30,
|
||||||
right: 50,
|
right: 50,
|
||||||
bottom: 5,
|
bottom: 5,
|
||||||
top: 20,
|
top: 50,
|
||||||
containLabel: true,
|
containLabel: true,
|
||||||
},
|
},
|
||||||
xAxis: {
|
xAxis: {
|
||||||
|
@ -50,6 +50,7 @@ function initChart(chartData: any) {
|
||||||
data: chartData.xData,
|
data: chartData.xData,
|
||||||
},
|
},
|
||||||
yAxis: {
|
yAxis: {
|
||||||
|
name: '数量',
|
||||||
show: true,
|
show: true,
|
||||||
type: 'value',
|
type: 'value',
|
||||||
min: 0,
|
min: 0,
|
||||||
|
@ -62,6 +63,7 @@ function initChart(chartData: any) {
|
||||||
type: 'line',
|
type: 'line',
|
||||||
symbol: 'none',
|
symbol: 'none',
|
||||||
smooth: true,
|
smooth: true,
|
||||||
|
color: 'rgb(0, 96, 128)',
|
||||||
showSymbol: false,
|
showSymbol: false,
|
||||||
lineStyle: {
|
lineStyle: {
|
||||||
color: 'rgb(0, 96, 128)',
|
color: 'rgb(0, 96, 128)',
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="table-page custom-table-table">
|
<div class="table-page custom-table-table">
|
||||||
<h3 class="main-color" style="font-size: 30px;line-height: 1;padding: 10px 0;">近30天登陆汇总</h3>
|
<h3 class="main-color" style="font-size: 25px;line-height: 1;padding: 8px 0;">近30天登陆汇总</h3>
|
||||||
<div style="width: 100%;height: 35%;">
|
<div style="width: 100%;height: 35%;">
|
||||||
<LoginChart />
|
<LoginChart />
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -64,6 +64,22 @@ const roleOption = [
|
||||||
{ label: '中级管理员', value: '中级管理员' },
|
{ label: '中级管理员', value: '中级管理员' },
|
||||||
{ label: '高级管理员', value: '高级管理员' },
|
{ label: '高级管理员', value: '高级管理员' },
|
||||||
]
|
]
|
||||||
|
|
||||||
|
const validatorPhone = (rule: any, value: any, callback: any) => {
|
||||||
|
var isPhone = /^1(3\d|4[5-9]|5[0-35-9]|6[2567]|7[0-8]|8\d|9[0-35-9])\d{8}$/;
|
||||||
|
|
||||||
|
|
||||||
|
if (value.indexOf('****') >= 0) {
|
||||||
|
return callback().trim();
|
||||||
|
}
|
||||||
|
if (!isPhone.test(value)) {
|
||||||
|
callback(new Error('请输入合法手机号'));
|
||||||
|
} else {
|
||||||
|
callback();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
const rules = reactive({
|
const rules = reactive({
|
||||||
userName: [
|
userName: [
|
||||||
{ required: true, message: '请输入用户名', trigger: ['blur', 'change'] },
|
{ required: true, message: '请输入用户名', trigger: ['blur', 'change'] },
|
||||||
|
@ -75,7 +91,7 @@ const rules = reactive({
|
||||||
{ required: true, message: '请选择角色', trigger: ['blur', 'change'] },
|
{ required: true, message: '请选择角色', trigger: ['blur', 'change'] },
|
||||||
],
|
],
|
||||||
phone: [
|
phone: [
|
||||||
{ required: true, message: '请输入电话', trigger: ['blur', 'change'] },
|
{ required: true, validator:validatorPhone, trigger: ['blur', 'change'] },
|
||||||
],
|
],
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
|
@ -96,6 +96,7 @@ const breakRemote = () => {
|
||||||
.input-box {
|
.input-box {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
|
||||||
&>span {
|
&>span {
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -254,8 +254,8 @@ $size: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.right-box .value {
|
.right-box .value {
|
||||||
color: #f8b300;
|
color: $main-color;
|
||||||
border-color: #f8b300;
|
border-color: $main-color;
|
||||||
}
|
}
|
||||||
|
|
||||||
.row-item.alarm {
|
.row-item.alarm {
|
||||||
|
@ -341,12 +341,12 @@ $size: 20px;
|
||||||
|
|
||||||
.row-item.yellow {
|
.row-item.yellow {
|
||||||
.label {
|
.label {
|
||||||
background: #f8b300;
|
background: $main-color;
|
||||||
}
|
}
|
||||||
|
|
||||||
.value {
|
.value {
|
||||||
color: #f8b300;
|
color: $main-color;
|
||||||
border-color: #f8b300;
|
border-color: $main-color;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -242,7 +242,7 @@ const breakRemote = () => {
|
||||||
.right-box {
|
.right-box {
|
||||||
@extend .common-box;
|
@extend .common-box;
|
||||||
.label {
|
.label {
|
||||||
background: #f8b300;
|
background: $main-color;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.row-item {
|
.row-item {
|
||||||
|
@ -288,8 +288,8 @@ const breakRemote = () => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.right-box .value {
|
.right-box .value {
|
||||||
color: #f8b300;
|
color: $main-color;
|
||||||
border-color: #f8b300;
|
border-color: $main-color;
|
||||||
}
|
}
|
||||||
.row-item.alarm {
|
.row-item.alarm {
|
||||||
.label {
|
.label {
|
||||||
|
@ -361,11 +361,11 @@ const breakRemote = () => {
|
||||||
}
|
}
|
||||||
.row-item.yellow {
|
.row-item.yellow {
|
||||||
.label {
|
.label {
|
||||||
background: #f8b300;
|
background: $main-color;
|
||||||
}
|
}
|
||||||
.value {
|
.value {
|
||||||
color: #f8b300;
|
color:$main-color;
|
||||||
border-color: #f8b300;
|
border-color: $main-color;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -63,7 +63,6 @@ onMounted(() => {
|
||||||
.main-box {
|
.main-box {
|
||||||
flex-grow: 1;
|
flex-grow: 1;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: calc(100% - 60px);
|
|
||||||
background: white;
|
background: white;
|
||||||
padding: 20px;
|
padding: 20px;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user