邓洁: 用户管理接口

This commit is contained in:
邓洁
2023-12-22 23:11:01 +08:00
parent 1cb5c6c258
commit 56f954e354
7 changed files with 372 additions and 144 deletions

8
src/api/tunnel.js Normal file
View File

@@ -0,0 +1,8 @@
import request from '@/utils/request.js'
export const getTunnelOption = (siteId) => {
return request({
url: `/tunnel/tunnel/option/${siteId}`,
method: 'get'
})
}

42
src/api/user.js Normal file
View File

@@ -0,0 +1,42 @@
import request from '@/utils/request.js'
export const getUser = (params) => {
return request({
url: '/admin/user/tunnel',
method: 'get',
params
})
}
export const getUserDetail = (userId) => {
return request({
url: `/admin/user/info/${userId}`,
method: 'get'
})
}
export const editUser = (data) => {
return request({
url: '/admin/user',
method: 'put',
data
})
}
export const addUser = (data) => {
return request({
url: '/admin/user',
method: 'post',
data
})
}
export const deleteUser = (userId) => {
return request({
url: `/admin/user/${userId}`,
method: 'delete'
})
}
export const getRoleOption = () => {
return request({
url: '/admin/role/option',
method: 'get'
})
}

View File

@@ -12,7 +12,7 @@
-khtml-user-select: none; /*早期浏览器*/ -khtml-user-select: none; /*早期浏览器*/
user-select: none; user-select: none;
font-family: "MicrosoftYaHei", "微软雅黑", "Helvetica Neue", Helvetica, Arial, font-family: "MicrosoftYaHei", "微软雅黑", "Helvetica Neue", Helvetica, Arial,
sans-serif; sans-serif;
} }
body { body {
@@ -97,6 +97,7 @@ body,
.current-site { .current-site {
display: flex; display: flex;
align-items: center; align-items: center;
> span:first-child { > span:first-child {
color: #f7b500; color: #f7b500;
margin-right: 20px; margin-right: 20px;
@@ -486,43 +487,72 @@ body,
background: #072247 !important; background: #072247 !important;
border: 1px solid #0F82AF !important; border: 1px solid #0F82AF !important;
} }
.el-popper { .el-popper {
max-width: 202px !important; max-width: 200px !important;
box-sizing: border-box; box-sizing: border-box;
} }
.el-popper__arrow::before { .el-popper__arrow::before {
display: none; display: none;
} }
.el-select-dropdown{
.el-select-dropdown { width: 200px!important;
width: 200px !important;
} }
.el-select-dropdown__item{
.el-select-dropdown__item { >span{
color: #fff !important;
}
.el-select-dropdown__item.hover {
background-color: #072247 !important;
}
.el-select-dropdown__item:hover {
background-color: #072247 !important;
color: #08B7B8 !important;
}
.el-select-dropdown__item.selected {
color: #08B7B8 !important;
}
.el-select-dropdown__list {
.el-select-dropdown__item:first-child {
color: #FFFFFF; color: #FFFFFF;
}
}
.el-select .el-input .el-select__caret {
font-size: 35px!important;
}
.el-select-dropdown__item.hover,.el-select-dropdown__item:hover{
background-color: #064B66!important;
width:198px!important;
}
.el-select-dropdown.is-multiple .el-select-dropdown__item.selected{
background-color: #064B66!important;
width:200px!important;
}
.el-select-tags-wrapper{
.el-tag{
padding: 28px 20px!important;
font-size: 35px;
.el-icon{
width: 40px;
height: 40px;
font-size: 40px!important;
}
}
}
.current-site {
.el-select-dropdown {
width: 200px !important;
}
&:hover { .el-select-dropdown__item {
color: #08B7B8 !important; color: #fff !important;
}
.el-select-dropdown__item.hover {
background-color: #072247 !important;
}
.el-select-dropdown__item:hover {
background-color: #072247 !important;
color: #08B7B8 !important;
}
.el-select-dropdown__item.selected {
color: #08B7B8 !important;
}
.el-select-dropdown__list {
.el-select-dropdown__item:first-child {
color: #FFFFFF;
&:hover {
color: #08B7B8 !important;
}
} }
} }
} }
@@ -542,8 +572,8 @@ input[type="number"] {
width: 40px !important; width: 40px !important;
height: 40px !important; height: 40px !important;
border-radius: 25px !important; border-radius: 25px !important;
border: 4px solid #05FEFF!important; border: 4px solid #05FEFF !important;
background-color: transparent!important; background-color: transparent !important;
} }
.el-checkbox__input.is-checked .el-checkbox__inner { .el-checkbox__input.is-checked .el-checkbox__inner {
@@ -559,11 +589,11 @@ input[type="number"] {
//border-top: 0; //border-top: 0;
border-radius: 25px; border-radius: 25px;
top: 6px; top: 6px;
left:6px; left: 6px;
//left: 12px; //left: 12px;
font-size: 30px; font-size: 30px;
background: #05FEFF; background: #05FEFF;
border-color: transparent!important; border-color: transparent !important;
} }
//取消 确定按钮 //取消 确定按钮
@@ -599,11 +629,13 @@ input[type="number"] {
font-size: 38px; font-size: 38px;
} }
} }
.el-pagination.is-background .btn-prev:disabled{
background-color: transparent!important; .el-pagination.is-background .btn-prev:disabled {
color: #60DDDE!important; background-color: transparent !important;
color: #60DDDE !important;
} }
.el-pagination.is-background .btn-next:disabled{
background-color: transparent!important; .el-pagination.is-background .btn-next:disabled {
color: #60DDDE!important; background-color: transparent !important;
color: #60DDDE !important;
} }

View File

@@ -51,7 +51,7 @@ const routes = [
} }
}, },
{ {
path: '/user', path: '/user/:siteId(\\d+)',
name: 'user', name: 'user',
component: () => import('@/views/user/index.vue'), component: () => import('@/views/user/index.vue'),
meta: { meta: {

View File

@@ -85,6 +85,7 @@ const selectIndex = ref(-1);
const showFan = ref(false); const showFan = ref(false);
const drawerLeft = ref(true); const drawerLeft = ref(true);
const drawerRight = ref(true); const drawerRight = ref(true);
const currentSiteId = ref(0);
const currentSite = ref(""); const currentSite = ref("");
const siteList = ref([]) const siteList = ref([])
const currentUser = ref(""); const currentUser = ref("");
@@ -123,6 +124,7 @@ const getOtherInfo = () => {
getLargeScreenInfo().then((res) => { getLargeScreenInfo().then((res) => {
if (res?.code === 1000) { if (res?.code === 1000) {
routeList.value = res.data.routeList routeList.value = res.data.routeList
currentSiteId.value = res.data.siteOption[0].value
currentSite.value = res.data.siteOption[0].label currentSite.value = res.data.siteOption[0].label
siteList.value = res.data.siteOption siteList.value = res.data.siteOption
tunnelId.value = res.data.tunnelOption[0].value tunnelId.value = res.data.tunnelOption[0].value
@@ -165,13 +167,12 @@ const manageSelect = (index) => {
if (index === 0) { if (index === 0) {
router.push("/site"); router.push("/site");
} else if (index === 1) { } else if (index === 1) {
router.push("/tunnel/1"); router.push("/tunnel/"+tunnelId.value);
} else if (index === 2) { } else if (index === 2) {
router.push("/user"); router.push("/user/"+currentSiteId.value);
} }
}; };
const handleCommand = (item) => { const handleCommand = (item) => {
console.log('commads', item)
currentSite.value = item.label currentSite.value = item.label
getTunnel(item.value) getTunnel(item.value)
} }

View File

@@ -7,10 +7,10 @@
</div> </div>
<div class="tunnel-title"></div> <div class="tunnel-title"></div>
<div class="all-del-btn"> <div class="all-del-btn">
<div class="all-btn" @click="handleAll"> <!-- <div class="all-btn" @click="handleAll">-->
全选 <!-- 全选-->
</div> <!-- </div>-->
<div class="all-btn del-btn" @click="handleMoreDelete"> <div class="all-btn del-btn" @click="handleDelete">
删除 删除
</div> </div>
</div> </div>
@@ -22,26 +22,29 @@
<div> <div>
<el-input <el-input
v-model="username" v-model="username"
clearable
placeholder="输入搜索内容" placeholder="输入搜索内容"
/> />
</div> </div>
<el-button type="primary" :icon="Search" style="margin-left: 20px">搜索</el-button> <el-button type="primary" :icon="Search" style="margin-left: 20px" @click="getInfo">搜索</el-button>
</div> </div>
<div>用户管理</div> <div>用户管理</div>
<div class="add-btn" @click="addUser">添加用户</div> <div class="add-btn" @click="handleAddUser">添加用户</div>
</div> </div>
<div class="device-table"> <div class="device-table">
<el-table stripe ref="multipleTable" <el-table stripe ref="multipleTable" @select="handleSelect"
style="border-bottom: 1px #06e5e5 solid;background-color: #011c29;--el-table-border-color: none;margin-top: 80px;" style="border-bottom: 1px #06e5e5 solid;background-color: #011c29;--el-table-border-color: none;margin-top: 80px;"
:header-cell-style="{backgroundColor: '#064B66',color: '#fff',fontSize: '40px',borderBottom: 'none' }" :header-cell-style="{backgroundColor: '#064B66',color: '#fff',fontSize: '40px',borderBottom: 'none' }"
:cell-style="{textAlign: 'center',borderBottom: 'none'}" :data="userData"> :cell-style="{textAlign: 'center',borderBottom: 'none'}" :data="userData">
<el-table-column type="selection" width="80"/> <el-table-column type="selection" width="80"/>
<el-table-column prop="account" label="账户" align="center"/> <el-table-column prop="userName" label="账户" align="center"/>
<el-table-column prop="password" label="密码" align="center"/> <el-table-column prop="nickName" label="昵称" align="center"/>
<el-table-column prop="identity" label="身份" align="center"/> <el-table-column prop="roleName" label="身份" align="center"/>
<el-table-column prop="phoneNumber" label="电话号码" align="center"/>
<el-table-column label="操作" align="center"> <el-table-column label="操作" align="center">
<template #default> <template #default="scope">
<el-button link type="primary" size="large" style="font-size: 40px;color: #17E1E2;" @click="editUser"> <el-button link type="primary" size="large" style="font-size: 40px;color: #17E1E2;"
@click="handleEditUser(scope.row)">
修改 修改
</el-button> </el-button>
</template> </template>
@@ -51,23 +54,49 @@
</div> </div>
</div> </div>
<el-dialog :close-on-click-modal="false" v-model="isVisited" width="1658px"> <el-dialog :close-on-click-modal="false" v-model="isVisited" width="1658px">
<div class="siteId"> <div class="user-title">
<span>{{ title }}</span> <span>{{ title }}</span>
</div> </div>
<el-form :model="form" :label-position="right" :rules="formRules" ref="formInstance" label-width="168px"> <el-form :model="form" :label-position="right" :rules="formRules" ref="formInstance" label-width="240px">
<el-form-item label="输入账户"> <el-form-item label="输入用户名称">
<el-input v-model="form.account" placeholder="请输入账户"/> <el-input v-model="form.userName" placeholder="请输入用户名称"/>
</el-form-item> </el-form-item>
<el-form-item label="输入密码"> <el-form-item label="输入用户昵称">
<el-input v-model="form.nickName" placeholder="请输入用户昵称"/>
</el-form-item>
<el-form-item label="输入电话号码">
<el-input v-model="form.phoneNumber" placeholder="输入电话号码"/>
</el-form-item>
<el-form-item label="输入密码" v-if="title==='添加用户'">
<el-input v-model="form.password" placeholder="请输入密码"/> <el-input v-model="form.password" placeholder="请输入密码"/>
</el-form-item> </el-form-item>
<el-form-item label="选择身份"> <el-form-item label="选择身份">
<el-checkbox-group v-model="form.identity" @change="handleChangeCheckbox"> <el-radio-group v-model="form.roleId" @change="(val) => {
<el-checkbox v-for="item in checkList" :label="item.label" :key="item.value"/> console.log('vaaa',val)
</el-checkbox-group> if (val >3){
getTunnel()
}}">
<el-radio v-for="item in radioList" :label="item.value" :key="item.value">{{ item.label }}</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="选择隧道" v-if="checkList.length!==0&&form.roleId>3">
<el-select
v-model="tunnelIndex"
multiple
filterable
clearable
placeholder="请选择隧道"
:fit-input-width="true"
>
<el-option
v-for="item in checkList"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
</el-form-item> </el-form-item>
</el-form> </el-form>
<template #footer> <template #footer>
<div class="btns"> <div class="btns">
<div class="cancel-btn" @click="isVisited=false"> <div class="cancel-btn" @click="isVisited=false">
@@ -91,66 +120,19 @@
<script setup> <script setup>
import {Search} from '@element-plus/icons-vue' import {Search} from '@element-plus/icons-vue'
import {addUser, editUser, getUser, getRoleOption} from "@/api/user";
import {ElMessage, ElMessageBox} from "element-plus";
import {getTunnelOption} from "@/api/tunnel";
import {deleteUser, getUserDetail} from "../../api/user";
const router = useRouter() const router = useRouter()
const title = ref('添加用户')
const siteId = reactive(router.currentRoute.value.params.siteId)
const tunnelIndex = ref()
const username = ref() const username = ref()
const userData = ref([ const userIds = ref()
{ const formInstance = ref()
account: '123343546', const userData = ref([])
password: '243',
identity: '超级管理员'
},
{
account: '123343546',
password: '243',
identity: '超级管理员'
},
{
account: '123343546',
password: '243',
identity: '超级管理员'
},
{
account: '123343546',
password: '243',
identity: '超级管理员'
},
{
account: '123343546',
password: '243',
identity: '超级管理员'
},
{
account: '123343546',
password: '243',
identity: '超级管理员'
},
{
account: '123343546',
password: '243',
identity: '超级管理员'
},
{
account: '123343546',
password: '243',
identity: '超级管理员'
},
{
account: '123343546',
password: '243',
identity: '超级管理员'
},
{
account: '123343546',
password: '243',
identity: '超级管理员'
},
{
account: '123343546',
password: '243',
identity: '超级管理员'
}
])
const pageInfo = reactive({ const pageInfo = reactive({
pageNum: 1, pageNum: 1,
pageSize: 6 pageSize: 6
@@ -159,32 +141,190 @@ const total = ref(10);
const isVisited = ref(false); const isVisited = ref(false);
const form = ref({ const form = ref({
password: '', password: '',
account: '', userName: '',
identity: [] nickName: '',
phoneNumber: '',
roleId: [],
tunnelIds: []
}); });
const formRules = ref({ const formRules = ref({
account: [{required: true, message: '请输入站点名称', trigger: 'blur'}], userName: [{required: true, message: '请输入用户名称', trigger: 'blur'}],
password: [{required: true, message: '请输入密码', trigger: 'blur'}] password: [{required: true, message: '请输入密码', trigger: 'blur'}]
}) })
const checkList = ref([ const radioList = ref([])
{label: "系统管理员", value: 111}, const checkList = ref([])
{label: "站点管理员", value: 222},
{label: "隧道管理员", value: 333},
{label: "巡查员", value: 444}
])
const multipleTable = ref() const multipleTable = ref()
const addUser = () => { const getTunnel = () => {
getTunnelOption(siteId).then(res => {
if (res.code === 1000) {
checkList.value = res.data
}
})
}
const handleAddUser = () => {
reset()
title.value = '添加用户'
isVisited.value = true isVisited.value = true
} }
const editUser = () => { const handleEditUser = (row) => {
reset()
getUserDetail(row.userId).then(res => {
if (res.code === 1000) {
form.value = res.data.user
form.value.roleId = res.data.roleIds[0]
}
})
title.value = '修改用户'
isVisited.value = true isVisited.value = true
} }
const handleAll = () => { const handleAll = () => {
multipleTable.value.toggleAllSelection() multipleTable.value.toggleAllSelection()
} }
const handleDelete = () => {
ElMessageBox.confirm(`是否确认删除该用户吗?`, '系统提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
deleteUser(userIds.value).then(res => {
if (res.code === 1000) {
ElMessage.success(res.msg)
getInfo()
}
})
})
}
const reset = () => {
form.value = {
password: '',
userName: '',
nickName: '',
phoneNumber: '',
roleId: [],
tunnelIds: []
}
}
const getRoleOptionInfo = () => {
getRoleOption().then(res => {
if (res.code === 1000) {
radioList.value = res.data
}
})
}
getRoleOptionInfo()
const getInfo = () => {
getUser({
siteId: siteId,
userName: username.value
}).then(res => {
if (res.code === 1000) {
console.log('res', res)
userData.value = res.data.rows
total.value = res.data.total
}
})
}
getInfo()
const handleSubmit = async (formInstance) => {
if (!formInstance) return;
formInstance.validate(async (valid) => {
if (!valid) return;
const data = {
siteId: siteId,
roleIds: [form.value.roleId],
...form.value
}
if (title.value === '添加用户') {
await addUser(data).then(res => {
if (res.code === 1000) {
getInfo()
isVisited.value = false
} else {
ElMessage.warning(res.msg)
}
})
} else {
await editUser(data).then(res => {
if (res.code === 1000) {
getInfo()
isVisited.value = false
} else {
ElMessage.warning(res.msg)
}
})
}
})
}
const handleSelect = async (selection, row) => {
if (selection.length !== 0) {
// disabled.value = false
userIds.value = row.userId
if (selection.length > 1) {
const del_row = selection.shift();
multipleTable.value.toggleRowSelection(del_row, false);
}
} else {
// disabled.value = true
}
}
</script> </script>
<style scoped lang="scss"> <style scoped lang="scss">
:deep(.el-table__header-wrapper .el-checkbox) {
display: none
}
:deep(.el-select-dropdown__item:hover) {
background-color: #064B66 !important;
width: 137px !important;
}
:deep(.el-radio-group) {
margin-top: 10px;
}
:deep(.el-radio__label) {
color: #FFFFFF;
font-size: 38px;
}
:deep(.el-radio__inner) {
width: 40px;
height: 40px;
border-radius: 25px;
border: 4px solid #05FEFF;
background-color: transparent;
}
:deep(.el-radio__input.is-checked+.el-radio__label) {
color: #FFFFFF;
}
:deep(.el-radio__input.is-checked .el-radio__inner ) {
background: #064B66;
border-color: #05FEFF !important;
}
:deep(.el-radio__inner::after) {
width: 18px;
height: 18px;
background: #05FEFF;
}
.user-title {
display: flex;
justify-content: center;
margin: 0 0 60px 0;
font-size: 50px;
color: #FFFFFF;
}
:deep(.el-table__empty-block) {
background: #064B66;
font-size: 30px;
min-height: 200px;
}
.tunnel-bgc { .tunnel-bgc {
padding: 85px 0 0 0; padding: 85px 0 0 0;
width: 100%; width: 100%;
@@ -393,14 +533,6 @@ const handleAll = () => {
} }
} }
:deep(.el-checkbox-group) {
margin-top: 10px;
}
:deep(.el-checkbox__label) {
color: #FFFFFF;
font-size: 38px;
}
.pagination { .pagination {
position: absolute; position: absolute;

View File

@@ -1,18 +1,19 @@
import { fileURLToPath, URL } from 'node:url' import {fileURLToPath, URL} from 'node:url'
import { defineConfig } from 'vite' import {defineConfig} from 'vite'
import AutoImport from 'unplugin-auto-import/vite' import AutoImport from 'unplugin-auto-import/vite'
import Components from 'unplugin-vue-components/vite' import Components from 'unplugin-vue-components/vite'
import { ElementPlusResolver } from 'unplugin-vue-components/resolvers' import {ElementPlusResolver} from 'unplugin-vue-components/resolvers'
import Icons from 'unplugin-icons/vite' import Icons from 'unplugin-icons/vite'
import IconsResolver from 'unplugin-icons/resolver' import IconsResolver from 'unplugin-icons/resolver'
import vue from '@vitejs/plugin-vue' import vue from '@vitejs/plugin-vue'
import Inspect from 'vite-plugin-inspect' import Inspect from 'vite-plugin-inspect'
export default defineConfig({ export default defineConfig({
plugins: [ plugins: [
vue(), vue(),
AutoImport({ AutoImport({
//自动导入vue相关函数 //自动导入vue相关函数
imports: ['vue','vue-router'], imports: ['vue', 'vue-router'],
resolvers: [ resolvers: [
ElementPlusResolver(), ElementPlusResolver(),
@@ -57,6 +58,18 @@ export default defineConfig({
strictPort: false, strictPort: false,
open: true, open: true,
proxy: { proxy: {
// '/api/tunnel': {
// // target: 'http://gateway.feashow.cn',
// target: 'http://192.168.31.175:8000',
// changeOrigin: true,
// rewrite: (path) => path.replace(/^\/api/, ''),
// },
// '/api/admin': {
// // target: 'http://gateway.feashow.cn',
// target: 'http://192.168.31.175:8000',
// changeOrigin: true,
// rewrite: (path) => path.replace(/^\/api/, ''),
// },
'/api': { '/api': {
target: 'http://web-tunnel.feashow.com/api', target: 'http://web-tunnel.feashow.com/api',
// target: 'http://192.168.31.175:8000', // target: 'http://192.168.31.175:8000',