用户信息修改
This commit is contained in:
25
README.md
25
README.md
@@ -1,18 +1,15 @@
|
||||
# Vue 3 + TypeScript + Vite
|
||||
Vue 3 + TypeScript + Vite
|
||||
这个模板可以帮助您开始使用Vue 3和TypeScript在Vite中进行开发。该模板使用了Vue 3的<script setup>单文件组件,请查看script setup文档了解更多信息。
|
||||
|
||||
This template should help get you started developing with Vue 3 and TypeScript in Vite. The template uses Vue 3 `<script setup>` SFCs, check out the [script setup docs](https://v3.vuejs.org/api/sfc-script-setup.html#sfc-script-setup) to learn more.
|
||||
推荐的IDE设置
|
||||
VS Code + Volar(并禁用Vetur)+ TypeScript Vue Plugin (Volar)。
|
||||
在TS中对.vue导入提供类型支持
|
||||
TypeScript 默认情况下无法处理.vue导入的类型信息,因此我们用vue-tsc替换了tsc CLI进行类型检查。在编辑器中,我们需要TypeScript Vue Plugin (Volar)来让TypeScript语言服务了解.vue类型。
|
||||
|
||||
## Recommended IDE Setup
|
||||
如果独立的TypeScript插件对您来说不够快,Volar还实现了一种Take Over Mode,它的性能更好。您可以按照以下步骤启用它:
|
||||
|
||||
- [VS Code](https://code.visualstudio.com/) + [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) (and disable Vetur) + [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin).
|
||||
禁用内置的TypeScript扩展
|
||||
从VSCode的命令面板中运行Extensions: Show Built-in Extensions
|
||||
找到TypeScript and JavaScript Language Features,右键单击并选择Disable (Workspace)
|
||||
通过运行Developer: Reload Window命令重新加载VSCode窗口。
|
||||
|
||||
## Type Support For `.vue` Imports in TS
|
||||
|
||||
TypeScript cannot handle type information for `.vue` imports by default, so we replace the `tsc` CLI with `vue-tsc` for type checking. In editors, we need [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin) to make the TypeScript language service aware of `.vue` types.
|
||||
|
||||
If the standalone TypeScript plugin doesn't feel fast enough to you, Volar has also implemented a [Take Over Mode](https://github.com/johnsoncodehk/volar/discussions/471#discussioncomment-1361669) that is more performant. You can enable it by the following steps:
|
||||
|
||||
1. Disable the built-in TypeScript Extension
|
||||
1. Run `Extensions: Show Built-in Extensions` from VSCode's command palette
|
||||
2. Find `TypeScript and JavaScript Language Features`, right click and select `Disable (Workspace)`
|
||||
2. Reload the VSCode window by running `Developer: Reload Window` from the command palette.
|
||||
|
||||
@@ -34,13 +34,22 @@ export function login(params: LoginData) {
|
||||
})
|
||||
}
|
||||
|
||||
//获取用户信息
|
||||
export function getUserById() {
|
||||
const adminInfo = useAdminInfo()
|
||||
return request({
|
||||
url: '/user-boot/user/getUserById?id=' + adminInfo.userIndex,
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
|
||||
// 刷新token
|
||||
export function refreshToken(): Promise<any> {
|
||||
const adminInfo = useAdminInfo()
|
||||
return login({
|
||||
grant_type: 'refresh_token',
|
||||
refresh_token: adminInfo.refresh_token,
|
||||
username: adminInfo.username
|
||||
username: adminInfo.loginName
|
||||
})
|
||||
}
|
||||
|
||||
@@ -108,7 +117,6 @@ export async function updatePassword(params: any) {
|
||||
}
|
||||
|
||||
|
||||
|
||||
export function checkUser(data: any) {
|
||||
return request({
|
||||
url: '/user-boot/user/check',
|
||||
|
||||
@@ -24,40 +24,21 @@
|
||||
size="18"
|
||||
/>
|
||||
</div>
|
||||
<el-popover
|
||||
@show="onCurrentNavMenu(true, 'adminInfo')"
|
||||
@hide="onCurrentNavMenu(false, 'adminInfo')"
|
||||
placement="bottom-end"
|
||||
:hide-after="0"
|
||||
:width="260"
|
||||
trigger="click"
|
||||
popper-class="admin-info-box"
|
||||
v-model:visible="state.showAdminInfoPopover"
|
||||
>
|
||||
<template #reference>
|
||||
<el-dropdown style='height: 100%;' @command='handleCommand'>
|
||||
<div class="admin-info" :class="state.currentNavMenu == 'adminInfo' ? 'hover' : ''">
|
||||
<el-avatar :size="25" fit="fill">
|
||||
<img src="@/assets/avatar.png" alt="" />
|
||||
</el-avatar>
|
||||
<div class="admin-name">{{ adminInfo.nickname }}</div>
|
||||
</div>
|
||||
<template #dropdown>
|
||||
<el-dropdown-menu>
|
||||
<el-dropdown-item command="adminInfo">个人资料</el-dropdown-item>
|
||||
<el-dropdown-item command="changePwd">修改密码</el-dropdown-item>
|
||||
<el-dropdown-item command="layout">退出登录</el-dropdown-item>
|
||||
</el-dropdown-menu>
|
||||
</template>
|
||||
<div>
|
||||
<div class="admin-info-base">
|
||||
<el-avatar :size="70" fit="fill">
|
||||
<img src="@/assets/avatar.png" alt="" />
|
||||
</el-avatar>
|
||||
<div class="admin-info-other">
|
||||
<div class="admin-info-name">{{ adminInfo.nickname }}</div>
|
||||
<div class="admin-info-lasttime">{{ adminInfo.last_login_time }}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="admin-info-footer">
|
||||
<el-button @click="onAdminInfo" type="primary" plain>个人资料</el-button>
|
||||
<el-button @click="onLogout" type="danger" plain>退出登录</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</el-popover>
|
||||
</el-dropdown>
|
||||
<div @click="configStore.setLayout('showDrawer', true)" class="nav-menu-item">
|
||||
<Icon
|
||||
:color="configStore.getColorVal('headerBarTabColor')"
|
||||
@@ -67,27 +48,30 @@
|
||||
/>
|
||||
</div>
|
||||
<Config />
|
||||
<PopupPwd ref='popupPwd' />
|
||||
<AdminInfo ref='popupAdminInfo' />
|
||||
<!-- <TerminalVue /> -->
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { reactive } from 'vue'
|
||||
import { reactive, ref } from 'vue'
|
||||
import screenfull from 'screenfull'
|
||||
import { useConfig } from '@/stores/config'
|
||||
import { ElMessage } from 'element-plus'
|
||||
import Config from './config.vue'
|
||||
import { useAdminInfo } from '@/stores/adminInfo'
|
||||
import { Local, Session } from '@/utils/storage'
|
||||
import { ADMIN_INFO } from '@/stores/constant/cacheKey'
|
||||
import router from '@/router'
|
||||
import { routePush } from '@/utils/router'
|
||||
import { fullUrl } from '@/utils/common'
|
||||
import html2canvas from 'html2canvas'
|
||||
import PopupPwd from './popup/password.vue'
|
||||
import AdminInfo from './popup/adminInfo.vue'
|
||||
|
||||
const adminInfo = useAdminInfo()
|
||||
const configStore = useConfig()
|
||||
|
||||
const popupPwd = ref()
|
||||
const popupAdminInfo = ref()
|
||||
const state = reactive({
|
||||
isFullScreen: false,
|
||||
currentNavMenu: '',
|
||||
@@ -102,7 +86,6 @@ const savePng = () => {
|
||||
html2canvas(document.body, {
|
||||
scale: 1,
|
||||
useCORS: true
|
||||
|
||||
}).then(function (canvas) {
|
||||
var link = document.createElement('a')
|
||||
link.href = canvas.toDataURL('image/png')
|
||||
@@ -126,19 +109,23 @@ const onAdminInfo = () => {
|
||||
routePush({ name: 'routine/adminInfo' })
|
||||
}
|
||||
|
||||
const onLogout = () => {
|
||||
const handleCommand = (key: string) => {
|
||||
console.log(key)
|
||||
switch (key) {
|
||||
case 'adminInfo':
|
||||
popupAdminInfo.value.open()
|
||||
break
|
||||
case 'changePwd':
|
||||
popupPwd.value.open()
|
||||
break
|
||||
case 'layout':
|
||||
router.push({ name: 'login' })
|
||||
break
|
||||
default:
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
// const onClearCache = (type: string) => {
|
||||
// if (type == 'storage' || type == 'all') {
|
||||
// const adminInfo = Local.get(ADMIN_INFO)
|
||||
// Session.clear()
|
||||
// Local.clear()
|
||||
// Local.set(ADMIN_INFO, adminInfo)
|
||||
// if (type == 'storage') return
|
||||
// }
|
||||
// }
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@@ -146,12 +133,14 @@ const onLogout = () => {
|
||||
border-radius: var(--el-border-radius-base);
|
||||
box-shadow: var(--el-box-shadow-light);
|
||||
}
|
||||
|
||||
.nav-menus {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
height: 100%;
|
||||
margin-left: auto;
|
||||
background-color: v-bind('configStore.getColorVal("headerBarBackground")');
|
||||
|
||||
.nav-menu-item {
|
||||
height: 100%;
|
||||
width: 40px;
|
||||
@@ -159,16 +148,19 @@ const onLogout = () => {
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
cursor: pointer;
|
||||
|
||||
.nav-menu-icon {
|
||||
box-sizing: content-box;
|
||||
color: v-bind('configStore.getColorVal("headerBarTabColor")');
|
||||
}
|
||||
|
||||
&:hover {
|
||||
.icon {
|
||||
animation: twinkle 0.3s ease-in-out;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.admin-info {
|
||||
display: flex;
|
||||
height: 100%;
|
||||
@@ -177,48 +169,58 @@ const onLogout = () => {
|
||||
cursor: pointer;
|
||||
user-select: none;
|
||||
color: v-bind('configStore.getColorVal("headerBarTabColor")');
|
||||
|
||||
&:hover {
|
||||
color: v-bind('configStore.getColorVal("headerBarTabActiveColor")');
|
||||
}
|
||||
}
|
||||
|
||||
.admin-name {
|
||||
padding-left: 6px;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.nav-menu-item:hover,
|
||||
.admin-info:hover,
|
||||
.nav-menu-item.hover,
|
||||
.admin-info.hover {
|
||||
background: v-bind('configStore.getColorVal("headerBarHoverBackground")');
|
||||
|
||||
.nav-menu-icon {
|
||||
color: v-bind('configStore.getColorVal("headerBarTabActiveColor")') !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.dropdown-menu-box :deep(.el-dropdown-menu__item) {
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.admin-info-base {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
flex-wrap: wrap;
|
||||
padding-top: 10px;
|
||||
|
||||
.admin-info-other {
|
||||
display: block;
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
padding: 10px 0;
|
||||
|
||||
.admin-info-name {
|
||||
font-size: var(--el-font-size-large);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.admin-info-footer {
|
||||
padding: 10px 0;
|
||||
margin: 0 -12px -12px -12px;
|
||||
display: flex;
|
||||
justify-content: space-around;
|
||||
}
|
||||
|
||||
.pt2 {
|
||||
padding-top: 2px;
|
||||
}
|
||||
|
||||
54
src/layouts/admin/components/popup/adminInfo.vue
Normal file
54
src/layouts/admin/components/popup/adminInfo.vue
Normal file
@@ -0,0 +1,54 @@
|
||||
<template>
|
||||
<el-dialog class='cn-operate-dialog' v-model='dialogVisible' :title='title'>
|
||||
<el-scrollbar>
|
||||
<el-form :inline='false' :model='form' label-width='120px'>
|
||||
<el-form-item label='用户名称:'>
|
||||
<el-input v-model='form.name' :disabled='true'></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label='登录名称:' class='top'>
|
||||
<el-input v-model='form.loginName' :disabled='true'></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label='归属部门名称:' class='top'>
|
||||
<el-input v-model='form.deptName' :disabled='true'></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label='拥有的角色:' class='top'>
|
||||
<el-input v-model='form.role' :disabled='true'></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label='电话号码:' class='top'>
|
||||
<el-input v-model='form.phone' :disabled='true'></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label='电子邮箱:' class='top'>
|
||||
<el-input v-model='form.email' :disabled='true'></el-input>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</el-scrollbar>
|
||||
</el-dialog>
|
||||
</template>
|
||||
<script lang='ts' setup>
|
||||
import { ref, inject } from 'vue'
|
||||
import { reactive } from 'vue'
|
||||
import { useAdminInfo } from '@/stores/adminInfo'
|
||||
|
||||
|
||||
const dialogVisible = ref(false)
|
||||
const title = ref('用户信息')
|
||||
const adminInfo = useAdminInfo()
|
||||
const formRef = ref()
|
||||
const form = reactive({
|
||||
name: '',
|
||||
deptName: '',
|
||||
phone: '',
|
||||
email: '',
|
||||
role: '',
|
||||
loginName: ''
|
||||
})
|
||||
|
||||
|
||||
const open = () => {
|
||||
dialogVisible.value = true
|
||||
for (const key in form) {
|
||||
form[key] = Array.isArray(adminInfo.$state[key]) ? adminInfo.$state[key].join(',') : adminInfo.$state[key]
|
||||
}
|
||||
}
|
||||
defineExpose({ open })
|
||||
</script>
|
||||
107
src/layouts/admin/components/popup/password.vue
Normal file
107
src/layouts/admin/components/popup/password.vue
Normal file
@@ -0,0 +1,107 @@
|
||||
<template>
|
||||
<el-dialog class='cn-operate-dialog' v-model='dialogVisible' :title='title'>
|
||||
<el-scrollbar>
|
||||
<el-form :inline='false' :model='form' label-width='120px' :rules='rules' ref='formRef'>
|
||||
<el-form-item label='校验密码:' prop='password'>
|
||||
<el-input v-model='form.password' type='password' placeholder='请输入校验密码' show-password />
|
||||
</el-form-item>
|
||||
<el-form-item label='新密码:' prop='newPwd' style='margin-top: 20px'>
|
||||
<el-input v-model='form.newPwd' type='password' placeholder='请输入新密码' show-password />
|
||||
</el-form-item>
|
||||
<el-form-item label='确认密码:' prop='confirmPwd' style='margin-top: 20px'>
|
||||
<el-input v-model='form.confirmPwd' type='password' placeholder='请输入确认密码' show-password />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</el-scrollbar>
|
||||
<template #footer>
|
||||
<span class='dialog-footer'>
|
||||
<el-button @click='dialogVisible = false'>取消</el-button>
|
||||
<el-button type='primary' @click='submit'>确认</el-button>
|
||||
</span>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</template>
|
||||
<script lang='ts' setup>
|
||||
import { ref, inject } from 'vue'
|
||||
import { reactive } from 'vue'
|
||||
import { ElMessage } from 'element-plus'
|
||||
import { passwordConfirm, updatePassword } from '@/api/user-boot/user'
|
||||
import { validatePwd } from '@/utils/common'
|
||||
import { useAdminInfo } from '@/stores/adminInfo'
|
||||
|
||||
const adminInfo = useAdminInfo()
|
||||
const dialogVisible = ref(false)
|
||||
const title = ref('修改密码')
|
||||
const formRef = ref()
|
||||
// 注意不要和表单ref的命名冲突
|
||||
const form = reactive({
|
||||
password: '',
|
||||
newPwd: '',
|
||||
confirmPwd: ''
|
||||
})
|
||||
const rules = {
|
||||
password: [
|
||||
{ required: true, message: '请输入校验密码', trigger: 'blur' },
|
||||
{
|
||||
min: 6,
|
||||
max: 16,
|
||||
message: '长度在 6 到 16 个字符',
|
||||
trigger: 'blur'
|
||||
}
|
||||
],
|
||||
newPwd: [
|
||||
{ required: true, message: '请输入密码', trigger: 'blur' },
|
||||
{
|
||||
min: 6,
|
||||
max: 16,
|
||||
message: '长度在 6 到 16 个字符',
|
||||
trigger: 'blur'
|
||||
},
|
||||
{ validator: validatePwd, trigger: 'blur' }
|
||||
],
|
||||
confirmPwd: [
|
||||
{ required: true, message: '请确认密码', trigger: 'blur' },
|
||||
{
|
||||
min: 6,
|
||||
max: 16,
|
||||
message: '长度在 6 到 16 个字符',
|
||||
trigger: 'blur'
|
||||
},
|
||||
{
|
||||
validator: (rule: any, value: string, callback: any) => {
|
||||
if (value === '') {
|
||||
callback(new Error('请再次输入密码'))
|
||||
} else if (value !== form.newPwd) {
|
||||
callback(new Error('两次输入密码不一致!'))
|
||||
} else {
|
||||
callback()
|
||||
}
|
||||
},
|
||||
trigger: 'blur',
|
||||
required: true
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
const open = () => {
|
||||
dialogVisible.value = true
|
||||
}
|
||||
const submit = () => {
|
||||
formRef.value.validate(async valid => {
|
||||
if (valid) {
|
||||
passwordConfirm(form.password)
|
||||
.then(res => {
|
||||
updatePassword({
|
||||
id: adminInfo.$state.userIndex,
|
||||
newPassword: form.newPwd
|
||||
}).then((res: any) => {
|
||||
ElMessage.success('密码修改成功')
|
||||
dialogVisible.value = false
|
||||
})
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
defineExpose({ open })
|
||||
</script>
|
||||
@@ -23,6 +23,7 @@ import { adminBaseRoutePath } from '@/router/static'
|
||||
import { getRouteMenu, dictDataCache } from '@/api/auth'
|
||||
import { getAreaList } from '@/api/common'
|
||||
import { BasicDictData } from '@/stores/interface'
|
||||
import { getUserById } from '@/api/user-boot/user'
|
||||
|
||||
defineOptions({
|
||||
components: { Default, Classic, Streamline, Double }
|
||||
@@ -50,9 +51,10 @@ onBeforeMount(() => {
|
||||
})
|
||||
|
||||
const init = async () => {
|
||||
await Promise.all([getAreaList(), dictDataCache()]).then(res => {
|
||||
await Promise.all([getAreaList(), dictDataCache(),getUserById()]).then(res => {
|
||||
dictData.state.area = res[0].data
|
||||
dictData.state.basic = res[1].data
|
||||
adminInfo.dataFill(res[2].data)
|
||||
})
|
||||
/**
|
||||
* 后台初始化请求,获取站点配置,动态路由等信息
|
||||
|
||||
@@ -11,13 +11,36 @@ export const useAdminInfo = defineStore('adminInfo', {
|
||||
expires_in: 0,
|
||||
scope: '',
|
||||
nickname: '',
|
||||
userType: 1,
|
||||
userType: 0,
|
||||
deptIndex: '',
|
||||
userIndex: '',
|
||||
client_id: '',
|
||||
headSculpture: '',
|
||||
jti: '',
|
||||
loginName: ''
|
||||
name: '',
|
||||
deptId: '',
|
||||
phone: '',
|
||||
email: '',
|
||||
limitIpStart: '',
|
||||
limitIpEnd: '',
|
||||
limitTime: '',
|
||||
casualUser: 0,
|
||||
type: 0,
|
||||
smsNotice: 0,
|
||||
emailNotice: 0,
|
||||
role: [],
|
||||
devCode: '',
|
||||
id: '',
|
||||
loginName: '',
|
||||
state: 0,
|
||||
registerTime: '',
|
||||
loginTime: '',
|
||||
deptName: '',
|
||||
areaId: '',
|
||||
areaName: '',
|
||||
deptLevel: 0,
|
||||
roleList: [],
|
||||
roleCode: []
|
||||
}
|
||||
},
|
||||
actions: {
|
||||
|
||||
@@ -45,8 +45,32 @@ export interface AdminInfo {
|
||||
deptIndex: string
|
||||
userIndex: string
|
||||
client_id: string
|
||||
headSculpture: string
|
||||
headSculpture: any
|
||||
jti: string
|
||||
name: string
|
||||
deptId: string
|
||||
phone: string
|
||||
email: string
|
||||
limitIpStart: string
|
||||
limitIpEnd: string
|
||||
limitTime: string
|
||||
casualUser: number
|
||||
type: number
|
||||
smsNotice: number
|
||||
emailNotice: number
|
||||
role: string[]
|
||||
devCode: any
|
||||
id: string
|
||||
loginName: string
|
||||
state: number
|
||||
registerTime: string
|
||||
loginTime: string
|
||||
deptName: string
|
||||
areaId: string
|
||||
areaName: string
|
||||
deptLevel: number
|
||||
roleList: string[]
|
||||
roleCode: string[]
|
||||
}
|
||||
|
||||
export interface DictData {
|
||||
|
||||
1
src/template/README.md
Normal file
1
src/template/README.md
Normal file
@@ -0,0 +1 @@
|
||||
dialog 弹框标准模版
|
||||
78
src/template/dialog.vue
Normal file
78
src/template/dialog.vue
Normal file
@@ -0,0 +1,78 @@
|
||||
<template>
|
||||
<el-dialog class='cn-operate-dialog' v-model='dialogVisible' :title='title'>
|
||||
<el-scrollbar>
|
||||
<el-form :inline='false' :model='form' label-width='120px' :rules='rules' ref='formRef'>
|
||||
<el-form-item label='角色名称'>
|
||||
<el-input v-model='form.name' placeholder='请输入菜单名称' />
|
||||
</el-form-item>
|
||||
<el-form-item label='角色编码'>
|
||||
<el-input v-model='form.code' placeholder='请输入菜单名称' />
|
||||
</el-form-item>
|
||||
<el-form-item label='角色描述'>
|
||||
<el-input v-model='form.remark' :rows='2' type='textarea' placeholder='请输入描述' />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</el-scrollbar>
|
||||
<template #footer>
|
||||
<span class='dialog-footer'>
|
||||
<el-button @click='dialogVisible = false'>取消</el-button>
|
||||
<el-button type='primary' @click='submit'>确认</el-button>
|
||||
</span>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</template>
|
||||
<script lang='ts' setup>
|
||||
import { ref, inject } from 'vue'
|
||||
import { reactive } from 'vue'
|
||||
import { ElMessage } from 'element-plus'
|
||||
import TableStore from '@/utils/tableStore' // 若不是列表页面弹框可删除
|
||||
|
||||
|
||||
const dialogVisible = ref(false)
|
||||
const title = ref('')
|
||||
const tableStore = inject('tableStore') as TableStore
|
||||
const formRef = ref()
|
||||
// 注意不要和表单ref的命名冲突
|
||||
const form = reactive({
|
||||
code: '',
|
||||
name: '',
|
||||
remark: '',
|
||||
id: ''
|
||||
})
|
||||
const rules = {
|
||||
name: [{ required: true, message: '角色名称不能为空', trigger: 'blur' }],
|
||||
code: [{ required: true, message: '角色编码不能为空', trigger: 'blur' }]
|
||||
}
|
||||
|
||||
const open = (text: string, data?: anyObj) => {
|
||||
title.value = text
|
||||
dialogVisible.value = true
|
||||
if (data) {
|
||||
// 表单赋值
|
||||
for (let key in form) {
|
||||
form[key] = data[key]
|
||||
}
|
||||
} else {
|
||||
// 在此处恢复默认表单
|
||||
for (let key in form) {
|
||||
form[key] = ''
|
||||
}
|
||||
}
|
||||
}
|
||||
const submit = () => {
|
||||
formRef.value.validate(async (valid) => {
|
||||
if (valid) {
|
||||
if (form.id) {
|
||||
// await update(form)
|
||||
} else {
|
||||
// await create(form)
|
||||
}
|
||||
ElMessage.success('保存成功')
|
||||
tableStore.index()
|
||||
dialogVisible.value = false
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
defineExpose({ open })
|
||||
</script>
|
||||
@@ -47,22 +47,6 @@ const rules = {
|
||||
message: '长度在 6 到 16 个字符',
|
||||
trigger: 'blur'
|
||||
},
|
||||
{
|
||||
validator: (rule: any, value: string, callback: any) => {
|
||||
if (value === '') {
|
||||
callback(new Error('请输入旧密码'))
|
||||
} else {
|
||||
passwordConfirm(value)
|
||||
.then(res => {
|
||||
callback()
|
||||
})
|
||||
.catch(() => {
|
||||
callback(new Error('旧密码不正确'))
|
||||
})
|
||||
}
|
||||
},
|
||||
trigger: 'blur'
|
||||
}
|
||||
],
|
||||
newPwd: [
|
||||
{ required: true, message: '请输入密码', trigger: 'blur' },
|
||||
@@ -109,6 +93,7 @@ const open = (id: string) => {
|
||||
const submit = async () => {
|
||||
formRef.value.validate((valid:boolean) => {
|
||||
if (valid) {
|
||||
passwordConfirm(form.password).then((res: any) => {
|
||||
updatePassword({
|
||||
id: form.id,
|
||||
newPassword: form.newPwd
|
||||
@@ -116,6 +101,7 @@ const submit = async () => {
|
||||
ElMessage.success('密码修改成功')
|
||||
dialogVisible.value = false
|
||||
})
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -131,7 +131,7 @@ queryByCode('Device_Type').then(res => {
|
||||
})
|
||||
})
|
||||
const echoName = (value: any, arr: any[]) => {
|
||||
return arr.find(item => item.value == value).label
|
||||
return arr.find(item => item.value == value)?.label
|
||||
}
|
||||
const openGroup = () => {
|
||||
if (!dataSet.value) {
|
||||
|
||||
@@ -1,136 +1,136 @@
|
||||
<template>
|
||||
<div class="default-main">
|
||||
<div class='default-main'>
|
||||
<TableHeader>
|
||||
<template v-slot:select>
|
||||
<el-form-item label="设备类型">
|
||||
<el-form-item label='设备类型'>
|
||||
<!-- <el-input v-model="tableStore.table.params.searchValue" placeholder="请输入设备类型" /> -->
|
||||
<el-select
|
||||
v-model="tableStore.table.params.devType"
|
||||
v-model='tableStore.table.params.devType'
|
||||
clearable
|
||||
@change="devTypeChange"
|
||||
placeholder="请选择设备类型"
|
||||
@change='devTypeChange'
|
||||
placeholder='请选择设备类型'
|
||||
>
|
||||
<el-option
|
||||
v-for="item in devTypeOptions"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value"
|
||||
v-for='item in devTypeOptions'
|
||||
:key='item.value'
|
||||
:label='item.label'
|
||||
:value='item.value'
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="设备型号">
|
||||
<el-select v-model="tableStore.table.params.devModel" clearable placeholder="请选择设备型号">
|
||||
<el-form-item label='设备型号'>
|
||||
<el-select v-model='tableStore.table.params.devModel' clearable placeholder='请选择设备型号'>
|
||||
<el-option
|
||||
v-for="item in devModelOptionsFilter"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value"
|
||||
v-for='item in devModelOptionsFilter'
|
||||
:key='item.value'
|
||||
:label='item.label'
|
||||
:value='item.value'
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="通讯协议">
|
||||
<el-select v-model="tableStore.table.params.devAccessMethod" clearable placeholder="请选择通讯协议">
|
||||
<el-option label="MQTT" value="mqtt"></el-option>
|
||||
<el-option label="CLD" value="cloud"></el-option>
|
||||
<el-form-item label='通讯协议'>
|
||||
<el-select v-model='tableStore.table.params.devAccessMethod' clearable placeholder='请选择通讯协议'>
|
||||
<el-option label='MQTT' value='mqtt'></el-option>
|
||||
<el-option label='CLD' value='cloud'></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="状态">
|
||||
<el-select v-model="tableStore.table.params.status" clearable placeholder="请选择状态">
|
||||
<el-option label="未注册" :value="1"></el-option>
|
||||
<el-option label="注册" :value="2"></el-option>
|
||||
<el-option label="接入" :value="3"></el-option>
|
||||
<el-form-item label='状态'>
|
||||
<el-select v-model='tableStore.table.params.status' clearable placeholder='请选择状态'>
|
||||
<el-option label='未注册' :value='1'></el-option>
|
||||
<el-option label='注册' :value='2'></el-option>
|
||||
<el-option label='接入' :value='3'></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</template>
|
||||
<template v-slot:operation>
|
||||
<el-button type="primary" @click="downLoadFile" class="ml10" icon="el-icon-Download">
|
||||
<el-button type='primary' @click='downLoadFile' class='ml10' icon='el-icon-Download'>
|
||||
模版下载
|
||||
</el-button>
|
||||
<el-upload
|
||||
style="display: inline-block"
|
||||
action=""
|
||||
accept=".xlsx"
|
||||
class="upload-demo"
|
||||
:show-file-list="false"
|
||||
:auto-upload="false"
|
||||
:on-change="bulkImport"
|
||||
style='display: inline-block'
|
||||
action=''
|
||||
accept='.xlsx'
|
||||
class='upload-demo'
|
||||
:show-file-list='false'
|
||||
:auto-upload='false'
|
||||
:on-change='bulkImport'
|
||||
>
|
||||
<el-button type="primary" class="ml10" icon="el-icon-Tickets">批量导入</el-button>
|
||||
<el-button type='primary' class='ml10' icon='el-icon-Tickets'>批量导入</el-button>
|
||||
</el-upload>
|
||||
<el-button type="primary" class="ml10" @click="add" icon="el-icon-Plus">新增设备</el-button>
|
||||
<el-button type='primary' class='ml10' @click='add' icon='el-icon-Plus'>新增设备</el-button>
|
||||
</template>
|
||||
</TableHeader>
|
||||
<Table ref="tableRef"></Table>
|
||||
<Table ref='tableRef'></Table>
|
||||
|
||||
<el-dialog
|
||||
:title="dialogTitle"
|
||||
v-model="dialogFormVisible"
|
||||
:close-on-click-modal="false"
|
||||
width="600px"
|
||||
:before-close="resetForm"
|
||||
:title='dialogTitle'
|
||||
v-model='dialogFormVisible'
|
||||
:close-on-click-modal='false'
|
||||
width='600px'
|
||||
:before-close='resetForm'
|
||||
>
|
||||
<el-form :model="form" label-width="120px" :rules="rules" ref="ruleFormRef">
|
||||
<el-form-item label="设备名称:" prop="name">
|
||||
<el-form :model='form' label-width='120px' :rules='rules' ref='ruleFormRef'>
|
||||
<el-form-item label='设备名称:' prop='name'>
|
||||
<el-input
|
||||
v-model="form.name"
|
||||
autocomplete="off"
|
||||
v-model='form.name'
|
||||
autocomplete='off'
|
||||
clearable
|
||||
placeholder="请输入(项目名称+设备名称)"
|
||||
placeholder='请输入(项目名称+设备名称)'
|
||||
></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="网络设备ID:" prop="ndid" class="top">
|
||||
<el-input v-model="form.ndid" autocomplete="off" placeholder="请输入"></el-input>
|
||||
<el-form-item label='网络设备ID:' prop='ndid' class='top'>
|
||||
<el-input v-model='form.ndid' autocomplete='off' placeholder='请输入'></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="设备类型:" prop="devType" class="top">
|
||||
<el-form-item label='设备类型:' prop='devType' class='top'>
|
||||
<el-select
|
||||
v-model="form.devType"
|
||||
placeholder="请选择"
|
||||
style="width: 100%"
|
||||
@change="formDevTypeChange"
|
||||
v-model='form.devType'
|
||||
placeholder='请选择'
|
||||
style='width: 100%'
|
||||
@change='formDevTypeChange'
|
||||
clearable
|
||||
>
|
||||
<el-option
|
||||
v-for="item in devTypeOptions"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value"
|
||||
v-for='item in devTypeOptions'
|
||||
:key='item.value'
|
||||
:label='item.label'
|
||||
:value='item.value'
|
||||
></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="设备型号:" prop="devModel" class="top">
|
||||
<el-select v-model="form.devModel" placeholder="请选择" style="width: 100%" clearable>
|
||||
<el-form-item label='设备型号:' prop='devModel' class='top'>
|
||||
<el-select v-model='form.devModel' placeholder='请选择' style='width: 100%' clearable>
|
||||
<el-option
|
||||
v-for="item in formDevModelOptionsFilter"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value"
|
||||
v-for='item in formDevModelOptionsFilter'
|
||||
:key='item.value'
|
||||
:label='item.label'
|
||||
:value='item.value'
|
||||
></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="通讯协议:" prop="devAccessMethod" class="top">
|
||||
<el-select v-model="form.devAccessMethod" placeholder="请选择" style="width: 100%" clearable>
|
||||
<el-option label="MQTT" value="MQTT"></el-option>
|
||||
<el-option label="CLD" value="cloud"></el-option>
|
||||
<el-form-item label='通讯协议:' prop='devAccessMethod' class='top'>
|
||||
<el-select v-model='form.devAccessMethod' placeholder='请选择' style='width: 100%' clearable>
|
||||
<el-option label='MQTT' value='MQTT'></el-option>
|
||||
<el-option label='CLD' value='cloud'></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="合同号:" prop="cntractNo" class="top">
|
||||
<el-input v-model="form.cntractNo" autocomplete="off" placeholder="请输入"></el-input>
|
||||
<el-form-item label='合同号:' prop='cntractNo' class='top'>
|
||||
<el-input v-model='form.cntractNo' autocomplete='off' placeholder='请输入'></el-input>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<el-button @click="resetForm">取 消</el-button>
|
||||
<el-button type="primary" @click="onSubmit">确 定</el-button>
|
||||
<el-button @click='resetForm'>取 消</el-button>
|
||||
<el-button type='primary' @click='onSubmit'>确 定</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
|
||||
<div class="qrcode-label">
|
||||
<div class="qrcode-label-title">{{ deivce.mac }}</div>
|
||||
<img class="qrcode-label-img" alt="二维码加载失败" :src="deivce.qrPath" />
|
||||
<div class='qrcode-label'>
|
||||
<div class='qrcode-label-title'>{{ deivce.mac }}</div>
|
||||
<img class='qrcode-label-img' alt='二维码加载失败' :src='deivce.qrPath' />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
<script setup lang='ts'>
|
||||
import { ref, onMounted, provide, computed, reactive, nextTick } from 'vue'
|
||||
import TableStore from '@/utils/tableStore'
|
||||
import Table from '@/components/table/index.vue'
|
||||
@@ -146,6 +146,7 @@ import {
|
||||
} from '@/api/cs-system-boot/device'
|
||||
import html2canvas from 'html2canvas'
|
||||
import { fullUrl } from '@/utils/common'
|
||||
|
||||
defineOptions({
|
||||
name: 'govern/log/debug'
|
||||
})
|
||||
@@ -430,9 +431,10 @@ onMounted(() => {
|
||||
}, 100)
|
||||
})
|
||||
|
||||
const addMenu = () => {}
|
||||
const addMenu = () => {
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
<style lang='scss' scoped>
|
||||
.qrcode-label {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
|
||||
Reference in New Issue
Block a user