医生管理新建,列表

This commit is contained in:
zhaoyz 2024-04-10 19:07:22 +08:00
parent 03c27fd31b
commit 628244785b
14 changed files with 420 additions and 372 deletions

View File

@ -1,77 +0,0 @@
/*
//统一管理咱们项目用户相关的接口
import request from '@/utils/request'
import type {
loginFormData,
loginResponseData,
userInfoReponseData,
} from './type'
//项目用户相关的请求地址
enum API {
LOGIN_URL = '/admin/acl/index/login',
USERINFO_URL = '/admin/acl/index/info',
LOGOUT_URL = '/admin/acl/index/logout',
}
//登录接口
export const reqLogin = (data: loginFormData) =>
request.post<any, loginResponseData>(API.LOGIN_URL, data)
//获取用户信息
export const reqUserInfo = () =>
request.get<any, userInfoReponseData>(API.USERINFO_URL)
//退出登录
export const reqLogout = () => request.post<any, any>(API.LOGOUT_URL)
*/
import request, {getData} from "@/utils/request";
const userInfoUrl = '/admin/user/info'
const editUserUrl = '/admin/user/edit'
const editPasswordUrl = '/admin/user/password'
const userPageUrl = '/admin/user/page'
export function getUserInfo() {
return new Promise(resolve => {
getData(userInfoUrl).then((data: any) => {
resolve(data.data)
})
})
}
export function updateUserInfo(data: any) {
return new Promise(resolve => {
request.request({
url: editUserUrl,
method: 'put',
data
}).then((res: any) => {
resolve(res.data)
})
})
}
export function editPassword(data: any) {
return new Promise(resolve => {
request.request({
url: editPasswordUrl,
method: "PUT",
data
}).then((res: any) => {
resolve(res.data)
}).catch(err => {
resolve(err)
})
})
}
export function userPage(data: any) {
return new Promise(resolve => {
getData(userPageUrl, data).then((res: any) => {
resolve(res.data)
}).catch(err => {
console.log(err)
})
})
}

View File

@ -1,31 +0,0 @@
/*
//定义用户相关数据的ts类型
//用户登录接口携带参数的ts类型
export interface loginFormData {
username: string
password: string
}
//定义全部接口返回数据都拥有ts类型
export interface ResponseData {
code: number
message: string
ok: boolean
}
//定义登录接口返回数据类型
export interface loginResponseData extends ResponseData {
data: string
}
//定义获取用户信息返回数据类型
export interface userInfoReponseData extends ResponseData {
data: {
routes: string[]
buttons: string[]
roles: string[]
name: string
avatar: string
}
}
*/

13
src/api/role.ts Normal file
View File

@ -0,0 +1,13 @@
import {getData} from "@/utils/request";
const getRoleListUrl = '/admin/role/list'
export function getRoleList() {
return new Promise((resolve, reject) => {
getData(getRoleListUrl).then((res: any) => {
resolve(res.data)
}).catch(error => {
reject(error)
})
})
}

65
src/api/user.ts Normal file
View File

@ -0,0 +1,65 @@
import request, {CommonHeaderEnum, getData, postData} from "@/utils/request";
const userInfoUrl = '/admin/user/info'
const editUserUrl = '/admin/user/edit'
const editPasswordUrl = '/admin/user/password'
const userPageUrl = '/admin/user/page'
const addUserUrl = '/admin/user'
export function getUserInfo() {
return new Promise(resolve => {
getData(userInfoUrl).then((data: any) => {
resolve(data.data)
})
})
}
export function updateUserInfo(data: any) {
return new Promise(resolve => {
request.request({
url: editUserUrl,
method: 'put',
data
}).then((res: any) => {
resolve(res.data)
})
})
}
export function editPassword(data: any) {
return new Promise(resolve => {
request.request({
url: editPasswordUrl,
method: "PUT",
data
}).then((res: any) => {
resolve(res.data)
}).catch(err => {
resolve(err)
})
})
}
export function userPage(data: any) {
return new Promise(resolve => {
getData(userPageUrl, data).then((res: any) => {
resolve(res.data)
}).catch(err => {
console.log(err)
})
})
}
export function addUser(data: any) {
return new Promise((resolve, reject) => {
postData(addUserUrl, data).then((res: any) => {
resolve(res.data)
}).catch(error => {
reject(error)
})
})
}

View File

@ -7,10 +7,7 @@
<script lang='ts' setup>
import { onMounted, reactive, ref, toRefs, watch } from 'vue'
interface Props {
total: number
}
const props = withDefaults(defineProps<Props>(), {
const props = withDefaults(defineProps(), {
total: () => 0
})

View File

@ -55,7 +55,7 @@ import {onMounted, reactive, ref, toRefs, watch} from 'vue'
import {ElMessage} from 'element-plus'
import type {UploadProps} from 'element-plus'
import {useLoginStore} from '@/stores/user-info-store'
import {editPassword, getUserInfo, updateUserInfo} from "@/api/acl/user";
import {editPassword, getUserInfo, updateUserInfo} from "@/api/user";
import {handleHttpUpload} from "@/api/file-upload";
const emit = defineEmits(['close'])

View File

@ -7,7 +7,7 @@ import * as CryptoJS from 'crypto-js';
export function encryption(src: string, keyWord: string) {
const key = CryptoJS.enc.Utf8.parse(keyWord);
// 加密
var encrypted = CryptoJS.AES.encrypt(src, key, {
let encrypted = CryptoJS.AES.encrypt(src, key, {
iv: key,
mode: CryptoJS.mode.CFB,
padding: CryptoJS.pad.NoPadding,
@ -23,7 +23,7 @@ export function encryption(src: string, keyWord: string) {
export function decryption(src: string, keyWord: string) {
const key = CryptoJS.enc.Utf8.parse(keyWord);
// 解密逻辑
var decryptd = CryptoJS.AES.decrypt(src, key, {
let decryptd = CryptoJS.AES.decrypt(src, key, {
iv: key,
mode: CryptoJS.mode.CFB,
padding: CryptoJS.pad.NoPadding,

View File

@ -22,6 +22,9 @@ const axiosInstance = axios.create({
baseURL: BASE_URL
});
/**
* @deprecated
*/
export const get = (url: any, params: any, success: any) => {
axiosInstance.get(url, params)
.then(res => {
@ -31,6 +34,10 @@ export const get = (url: any, params: any, success: any) => {
success(err);
});
};
/**
* @deprecated
*/
export const post = (url: any, params: any, success: any) => {
axiosInstance.post(url, params)
.then(res => {
@ -40,6 +47,7 @@ export const post = (url: any, params: any, success: any) => {
success(err);
});
};
export const getMapJson = (name: string) => {
return axiosInstance.post(BASE_URL+'/static/json/' + name)
}

View File

@ -69,7 +69,7 @@ import {getHospitalsData} from '@/static-data/core'
import userInfoForm from '@/components/user-info.vue'
import {wsApi} from "@/api/ws";
import {Session} from "@/utils/storage";
import {logout} from "@/api/acl/login";
import {logout} from "@/api/login";
const router = useRouter()
const route = useRoute()

View File

@ -134,7 +134,7 @@ import {useLoginStore} from '@/stores/user-info-store'
import {getPhoneAreasData} from '@/static-data/core'
import {v4} from "uuid";
import SliderVerify from "@/components/SliderVerify/index.vue";
import * as loginApi from "@/api/acl/login";
import * as loginApi from "@/api/login";
import {Session} from "@/utils/storage";
import * as hospitalApi from "@/api/hospital";
@ -356,8 +356,8 @@ function sliderSuccess() {
randomStr: v4()
}).then((data: any) => {
sliderVConf.value.isShowSelf = false
if (data.code == 1) {
ElMessage.error(data.msg)
if (data.code == 1 || data.error) {
ElMessage.error(data.msg ? data.msg : data.error)
loading.value = false
} else {
// token

View File

@ -19,40 +19,49 @@
</div>
<div class="table-part">
<el-table ref="tableRef" v-loading="loading" :data="tableData" height="100%" border show-overflow-tooltip
:row-class-name="({ row }: any) => !row.enable && 'disable'" @row-click="tableRowClick">
:row-class-name="({ row }: any) => row.lockFlag == 1 && 'disable'" @row-click="tableRowClick">
<el-table-column type="selection" width="55"/>
<el-table-column type="index" label="#" width="55" align="center"/>
<el-table-column property="name" label="姓名" width="120" align="center"/>
<el-table-column label="手机号" width="220" align="center">
<template #default="scope">{{ scope.row.phone.slice(0, 3) + '****' + scope.row.phone.slice(7)
}}</template>
<template #default="scope">{{
scope.row.phone.slice(0, 3) + '****' + scope.row.phone.slice(7)
}}
</template>
</el-table-column>
<el-table-column property="role" label="角色" width="220" align="center" />
<el-table-column label="启用" width="120" align="center">
<el-table-column label="角色" width="220" align="center">
<template #default="scope">
<span @click.stop><el-switch v-model="scope.row.enable" @change="enableChange(scope.row)" /></span>
<span v-for="(item, index) in scope.row.roleList" :key="index">
{{ item.roleName }} {{ (scope.row.roleList.length - 1) == index ? '' : '' }}
</span>
</template>
</el-table-column>
<el-table-column label="锁定" width="120" align="center">
<template #default="scope">
<span @click.stop><el-switch v-model="scope.row.lockFlag" @change="enableChange(scope.row)"/></span>
</template>
</el-table-column>
<el-table-column label="操作" align="center">
<template #default="scope">
<span @click.stop>
<el-button link icon="RefreshLeft" @click="resetPassword(scope.row)"
:disabled="!scope.row.enable">密码</el-button>
:disabled="!scope.row.lockFlag">密码</el-button>
<el-button link icon="EditPen" @click="editData(scope.row)"
:disabled="!scope.row.enable">修改</el-button>
:disabled="!scope.row.lockFlag">修改</el-button>
<el-button link icon="Delete" @click="removeData(scope.row)"
:disabled="!scope.row.enable">删除</el-button>
:disabled="!scope.row.lockFlag">删除</el-button>
</span>
</template>
</el-table-column>
</el-table>
</div>
<div class="pagination-part">
<CommonPagination :total="100" @paginationChange="paginationChange" />
<CommonPagination :total="total" @paginationChange="paginationChange"/>
</div>
</div>
<el-dialog v-model="isFormDialog" :title="formDialogTitle" width="750px">
<DoctorForm ref="doctorFormRef" :type="formDialogTitle === '添加' ? 'add' : 'edit'" @close="isFormDialog = false" @save="doctorFormSave" />
<DoctorForm ref="doctorFormRef" :type="formDialogTitle === '添加' ? 'add' : 'edit'" @close="isFormDialog = false"
@save="doctorFormSave"/>
</el-dialog>
<ImportDialog ref="importDialogRef" title="用户导入" templateUrl="#" importUrl="#"/>
</template>
@ -64,7 +73,7 @@ import { tableRemoveRow, exportData } from '@/utils/table-util'
import CommonPagination from '@/components/common-pagination.vue'
import DoctorForm from './form/doctor-form.vue'
import ImportDialog from '@/components/import-dialog.vue'
import {userPage} from "@/api/acl/user";
import {userPage} from "@/api/user";
const tableRef = ref()
const doctorFormRef = ref()
@ -77,40 +86,31 @@ const queryParams = ref({
userName: ''
} as any)
const tableData = ref([] as any)
let current = 0;
const size = 10;
let current = 0
let size = 10
const total = ref(0)
queryData()
function queryData(e?: any) {
loading.value = true
if(e?.userName) {
tableData.value = tableData.value.filter((item: any) => item.name.indexOf(e.userName) !== -1)
loading.value = false
return
}else{
queryParams.value = {}
tableData.value = []
setTimeout(() => {
while (tableData.value.length < 10) {
tableData.value.push({
id: tableData.value.length + 1,
userName: 'cscs',
name: '测试' + tableData.value.length,
phone: '12312345678',
role: '高级管理员',
enable: true,
})
}
loading.value = false
}, 200);
}
userPage({
current,
size,
name: queryParams.value.userName
}).then((res: any) => {
loading.value = false
total.value = res.data.total
tableData.value = res.data.records
if (current < total.value) {
current += size
}
console.log(res)
}).catch(error => {
loading.value = false
})
}
const addData = () => {
isFormDialog.value = true
formDialogTitle.value = '添加'
@ -134,12 +134,16 @@ const removeData = (e?: any) => {
})
}
const enableChange = (e: any) => {
ElMessage.success(e.enable ? '启用成功' : '禁用成功')
if (e.lockFlag == 0) {
} else {}
ElMessage.success(e.lockFlag ? '启用成功' : '禁用成功')
}
const resetPassword = (e: any) => {
ElMessageBox.confirm('是否确定要重置密码?', '系统提醒', {type: 'warning', draggable: true}).then(() => {
ElMessage.success('重置成功!')
}).catch(() => { })
}).catch(() => {
})
}
const editData = (e: any) => {
isFormDialog.value = true
@ -162,10 +166,9 @@ const doctorFormSave = (data: any, type: string) => {
}
})
}
// console.log(data, type)
}
const paginationChange = (page: number, size: number) => {
console.log(page, size)
}
</script>

View File

@ -2,8 +2,9 @@
<el-form ref="formRef" :model="formData" :rules="rules" label-width="80">
<el-row>
<el-col :span="12">
<el-form-item label="用户名" prop="userName">
<el-input v-model="formData.userName" placeholder="请输入用户名" :disabled="type === 'edit'"></el-input>
<el-form-item label="用户名" prop="username">
<el-input v-model="formData.username" placeholder="请输入用户名"
:disabled="type === 'edit'"></el-input>
</el-form-item>
</el-col>
<el-col :span="12">
@ -15,14 +16,15 @@
<el-row>
<el-col :span="12">
<el-form-item label="角色" prop="role">
<el-select v-model="formData.role" placeholder="请选择角色">
<el-option v-for="item in roleOption" :key="item.value" :label="item.label" :value="item.value" />
<el-select v-model="formData.role" placeholder="请选择角色" multiple>
<el-option v-for="item in roleOption" :key="item.roleId" :label="item.roleName"
:value="item.roleId"/>
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="邮箱" prop="mailbox">
<el-input v-model="formData.mailbox" placeholder="请输入邮箱"></el-input>
<el-form-item label="邮箱" prop="email">
<el-input v-model="formData.email" placeholder="请输入邮箱"></el-input>
</el-form-item>
</el-col>
</el-row>
@ -33,14 +35,22 @@
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="启用" prop="enable">
<el-radio-group v-model="formData.enable">
<el-radio :label="true" border>有效</el-radio>
<el-radio :label="false" border>禁用</el-radio>
<el-form-item label="启用" prop="lockFlag">
<el-radio-group v-model="formData.lockFlag">
<el-radio :label="'0'" border>有效</el-radio>
<el-radio :label="'1'" border>禁用</el-radio>
</el-radio-group>
</el-form-item>
</el-col>
</el-row>
<el-row v-if="type === 'edit'">
<el-col :span="12">
<el-form-item label="密码" prop="password">
<el-input v-model="formData.password" placeholder="请输入密码"
:disabled="type === 'edit'"></el-input>
</el-form-item>
</el-col>
</el-row>
<div style="text-align: right;padding-top: 80px;">
<el-button class="f18" @click="close">取消</el-button>
@ -52,6 +62,8 @@
<script lang='ts' setup>
import {onMounted, reactive, ref, toRefs, watch} from 'vue'
import {ElMessage, ElMessageBox} from 'element-plus'
import {getRoleList} from "@/api/role";
import {addUser} from "@/api/user";
const emit = defineEmits(['close', 'save'])
@ -59,11 +71,7 @@ const props = defineProps({
type: String
})
const roleOption = [
{ label: '普通用户', value: '普通用户' },
{ label: '中级管理员', value: '中级管理员' },
{ label: '高级管理员', value: '高级管理员' },
]
const roleOption = ref<any>([])
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}$/;
@ -81,7 +89,7 @@ const validatorPhone = (rule: any, value: any, callback: any) => {
}
const rules = reactive({
userName: [
username: [
{required: true, message: '请输入用户名', trigger: ['blur', 'change']},
],
name: [
@ -93,48 +101,69 @@ const rules = reactive({
phone: [
{required: true, validator: validatorPhone, trigger: ['blur', 'change']},
],
password: [
{required: true, message: '请输入密码', trigger: ['blur', 'change']},
]
})
const formRef = ref()
const formData = ref({
id: '',
userName: '',
username: '',
name: '',
role: '',
mailbox: '',
email: '',
phone: '',
enable: true,
password: '',
lockFlag: '0',
} as any)
onMounted(() => {
resetData()
})
getRoleList().then((res: any) => {
if (res && res.code == 0) {
roleOption.value = res.data
} else {
ElMessage.error('角色列表获取失败')
}
console.log(res)
})
defineExpose({
formData,
resetData,
})
function close() {
emit('close')
}
function resetData() {
getRoleList()
formRef.value.resetFields()
formData.value = {
id: '',
userName: '',
username: '',
name: '',
role: '',
mailbox: '',
email: '',
phone: '',
enable: true,
password: '',
lockFlag: '0',
}
}
const saveData = async () => {
await formRef.value.validate((valid: any, fields: any) => {
if (valid) {
addUser(formData.value).then((data: any) => {
console.log(data)
})
ElMessage.success('保存成功!')
emit('save', formData.value, props.type)
console.log(formData.value)
close()
} else {
// console.log('error submit!', fields)
@ -150,6 +179,7 @@ const saveData = async () => {
text-align: justify;
text-align-last: justify;
padding: 0 10px 0 20px;
&:before {
display: none;
}

View File

@ -57,6 +57,7 @@ function resetRemoteTaskItem(e: RemoteItem) {
index: e.index,
})
}
function initRemoteTask() {
remoteTask.value = remoteStore.remoteTasks
if (remoteTask.value.length < 1) {
@ -189,6 +190,45 @@ function disconnectSurgeryData(username: string, db: string) {
const account = "admin";
surgeryClient.unsubscribe("/topic/user/" + account + ":" + db + "/surgeryData");
}
const chatClient = new Client({
brokerURL: 'ws://localhost:5173/socket.io/admin/rax/chat',
connectHeaders: {
token: Session.get('token')
},
reconnectDelay: 5000,
heartbeatIncoming: 60000,
heartbeatOutgoing: 60000
})
chatClient.activate()
const patientName = '111'
const idNum = '111'
const date = '20230505'
function sendChatMessage() {
const message = {
patientName: patientName,
idNum: idNum,
date: date,
msg: '测试消息'
}
chatClient.publish({
destination: '/front/sendMessage',
headers: {
token: Session.get('token')
},
body: JSON.stringify(message)
})
}
chatClient.onConnect = () => {
chatClient.subscribe('/topic/user/' + patientName + idNum + date + '/chatroomMessage', (data: any) => {
console.log(data)
})
}
</script>
<style lang='scss' scoped>