用户信息修改
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
|
// 刷新token
|
||||||
export function refreshToken(): Promise<any> {
|
export function refreshToken(): Promise<any> {
|
||||||
const adminInfo = useAdminInfo()
|
const adminInfo = useAdminInfo()
|
||||||
return login({
|
return login({
|
||||||
grant_type: 'refresh_token',
|
grant_type: 'refresh_token',
|
||||||
refresh_token: adminInfo.refresh_token,
|
refresh_token: adminInfo.refresh_token,
|
||||||
username: adminInfo.username
|
username: adminInfo.loginName
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -108,8 +117,7 @@ export async function updatePassword(params: any) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export function checkUser(data: any) {
|
||||||
export function checkUser(data:any) {
|
|
||||||
return request({
|
return request({
|
||||||
url: '/user-boot/user/check',
|
url: '/user-boot/user/check',
|
||||||
method: 'put',
|
method: 'put',
|
||||||
|
|||||||
@@ -24,40 +24,21 @@
|
|||||||
size="18"
|
size="18"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<el-popover
|
<el-dropdown style='height: 100%;' @command='handleCommand'>
|
||||||
@show="onCurrentNavMenu(true, 'adminInfo')"
|
<div class="admin-info" :class="state.currentNavMenu == 'adminInfo' ? 'hover' : ''">
|
||||||
@hide="onCurrentNavMenu(false, 'adminInfo')"
|
<el-avatar :size="25" fit="fill">
|
||||||
placement="bottom-end"
|
<img src="@/assets/avatar.png" alt="" />
|
||||||
:hide-after="0"
|
</el-avatar>
|
||||||
:width="260"
|
<div class="admin-name">{{ adminInfo.nickname }}</div>
|
||||||
trigger="click"
|
|
||||||
popper-class="admin-info-box"
|
|
||||||
v-model:visible="state.showAdminInfoPopover"
|
|
||||||
>
|
|
||||||
<template #reference>
|
|
||||||
<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>
|
|
||||||
<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>
|
</div>
|
||||||
</el-popover>
|
<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>
|
||||||
|
</el-dropdown>
|
||||||
<div @click="configStore.setLayout('showDrawer', true)" class="nav-menu-item">
|
<div @click="configStore.setLayout('showDrawer', true)" class="nav-menu-item">
|
||||||
<Icon
|
<Icon
|
||||||
:color="configStore.getColorVal('headerBarTabColor')"
|
:color="configStore.getColorVal('headerBarTabColor')"
|
||||||
@@ -67,27 +48,30 @@
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<Config />
|
<Config />
|
||||||
|
<PopupPwd ref='popupPwd' />
|
||||||
|
<AdminInfo ref='popupAdminInfo' />
|
||||||
<!-- <TerminalVue /> -->
|
<!-- <TerminalVue /> -->
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { reactive } from 'vue'
|
import { reactive, ref } from 'vue'
|
||||||
import screenfull from 'screenfull'
|
import screenfull from 'screenfull'
|
||||||
import { useConfig } from '@/stores/config'
|
import { useConfig } from '@/stores/config'
|
||||||
import { ElMessage } from 'element-plus'
|
import { ElMessage } from 'element-plus'
|
||||||
import Config from './config.vue'
|
import Config from './config.vue'
|
||||||
import { useAdminInfo } from '@/stores/adminInfo'
|
import { useAdminInfo } from '@/stores/adminInfo'
|
||||||
import { Local, Session } from '@/utils/storage'
|
|
||||||
import { ADMIN_INFO } from '@/stores/constant/cacheKey'
|
|
||||||
import router from '@/router'
|
import router from '@/router'
|
||||||
import { routePush } from '@/utils/router'
|
import { routePush } from '@/utils/router'
|
||||||
import { fullUrl } from '@/utils/common'
|
import { fullUrl } from '@/utils/common'
|
||||||
import html2canvas from 'html2canvas'
|
import html2canvas from 'html2canvas'
|
||||||
|
import PopupPwd from './popup/password.vue'
|
||||||
|
import AdminInfo from './popup/adminInfo.vue'
|
||||||
|
|
||||||
const adminInfo = useAdminInfo()
|
const adminInfo = useAdminInfo()
|
||||||
const configStore = useConfig()
|
const configStore = useConfig()
|
||||||
|
const popupPwd = ref()
|
||||||
|
const popupAdminInfo = ref()
|
||||||
const state = reactive({
|
const state = reactive({
|
||||||
isFullScreen: false,
|
isFullScreen: false,
|
||||||
currentNavMenu: '',
|
currentNavMenu: '',
|
||||||
@@ -99,10 +83,9 @@ const onCurrentNavMenu = (status: boolean, name: string) => {
|
|||||||
state.currentNavMenu = status ? name : ''
|
state.currentNavMenu = status ? name : ''
|
||||||
}
|
}
|
||||||
const savePng = () => {
|
const savePng = () => {
|
||||||
html2canvas(document.body,{
|
html2canvas(document.body, {
|
||||||
scale: 1,
|
scale: 1,
|
||||||
useCORS: true
|
useCORS: true
|
||||||
|
|
||||||
}).then(function (canvas) {
|
}).then(function (canvas) {
|
||||||
var link = document.createElement('a')
|
var link = document.createElement('a')
|
||||||
link.href = canvas.toDataURL('image/png')
|
link.href = canvas.toDataURL('image/png')
|
||||||
@@ -126,19 +109,23 @@ const onAdminInfo = () => {
|
|||||||
routePush({ name: 'routine/adminInfo' })
|
routePush({ name: 'routine/adminInfo' })
|
||||||
}
|
}
|
||||||
|
|
||||||
const onLogout = () => {
|
const handleCommand = (key: string) => {
|
||||||
router.push({ name: 'login' })
|
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>
|
</script>
|
||||||
|
|
||||||
<style scoped lang="scss">
|
<style scoped lang="scss">
|
||||||
@@ -146,12 +133,14 @@ const onLogout = () => {
|
|||||||
border-radius: var(--el-border-radius-base);
|
border-radius: var(--el-border-radius-base);
|
||||||
box-shadow: var(--el-box-shadow-light);
|
box-shadow: var(--el-box-shadow-light);
|
||||||
}
|
}
|
||||||
|
|
||||||
.nav-menus {
|
.nav-menus {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
margin-left: auto;
|
margin-left: auto;
|
||||||
background-color: v-bind('configStore.getColorVal("headerBarBackground")');
|
background-color: v-bind('configStore.getColorVal("headerBarBackground")');
|
||||||
|
|
||||||
.nav-menu-item {
|
.nav-menu-item {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
width: 40px;
|
width: 40px;
|
||||||
@@ -159,16 +148,19 @@ const onLogout = () => {
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
|
||||||
.nav-menu-icon {
|
.nav-menu-icon {
|
||||||
box-sizing: content-box;
|
box-sizing: content-box;
|
||||||
color: v-bind('configStore.getColorVal("headerBarTabColor")');
|
color: v-bind('configStore.getColorVal("headerBarTabColor")');
|
||||||
}
|
}
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
.icon {
|
.icon {
|
||||||
animation: twinkle 0.3s ease-in-out;
|
animation: twinkle 0.3s ease-in-out;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.admin-info {
|
.admin-info {
|
||||||
display: flex;
|
display: flex;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
@@ -177,48 +169,58 @@ const onLogout = () => {
|
|||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
user-select: none;
|
user-select: none;
|
||||||
color: v-bind('configStore.getColorVal("headerBarTabColor")');
|
color: v-bind('configStore.getColorVal("headerBarTabColor")');
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
color: v-bind('configStore.getColorVal("headerBarTabActiveColor")');
|
color: v-bind('configStore.getColorVal("headerBarTabActiveColor")');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.admin-name {
|
.admin-name {
|
||||||
padding-left: 6px;
|
padding-left: 6px;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
}
|
}
|
||||||
|
|
||||||
.nav-menu-item:hover,
|
.nav-menu-item:hover,
|
||||||
.admin-info:hover,
|
.admin-info:hover,
|
||||||
.nav-menu-item.hover,
|
.nav-menu-item.hover,
|
||||||
.admin-info.hover {
|
.admin-info.hover {
|
||||||
background: v-bind('configStore.getColorVal("headerBarHoverBackground")');
|
background: v-bind('configStore.getColorVal("headerBarHoverBackground")');
|
||||||
|
|
||||||
.nav-menu-icon {
|
.nav-menu-icon {
|
||||||
color: v-bind('configStore.getColorVal("headerBarTabActiveColor")') !important;
|
color: v-bind('configStore.getColorVal("headerBarTabActiveColor")') !important;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.dropdown-menu-box :deep(.el-dropdown-menu__item) {
|
.dropdown-menu-box :deep(.el-dropdown-menu__item) {
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.admin-info-base {
|
.admin-info-base {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
padding-top: 10px;
|
padding-top: 10px;
|
||||||
|
|
||||||
.admin-info-other {
|
.admin-info-other {
|
||||||
display: block;
|
display: block;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
padding: 10px 0;
|
padding: 10px 0;
|
||||||
|
|
||||||
.admin-info-name {
|
.admin-info-name {
|
||||||
font-size: var(--el-font-size-large);
|
font-size: var(--el-font-size-large);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.admin-info-footer {
|
.admin-info-footer {
|
||||||
padding: 10px 0;
|
padding: 10px 0;
|
||||||
margin: 0 -12px -12px -12px;
|
margin: 0 -12px -12px -12px;
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-around;
|
justify-content: space-around;
|
||||||
}
|
}
|
||||||
|
|
||||||
.pt2 {
|
.pt2 {
|
||||||
padding-top: 2px;
|
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 { getRouteMenu, dictDataCache } from '@/api/auth'
|
||||||
import { getAreaList } from '@/api/common'
|
import { getAreaList } from '@/api/common'
|
||||||
import { BasicDictData } from '@/stores/interface'
|
import { BasicDictData } from '@/stores/interface'
|
||||||
|
import { getUserById } from '@/api/user-boot/user'
|
||||||
|
|
||||||
defineOptions({
|
defineOptions({
|
||||||
components: { Default, Classic, Streamline, Double }
|
components: { Default, Classic, Streamline, Double }
|
||||||
@@ -50,9 +51,10 @@ onBeforeMount(() => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
const init = async () => {
|
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.area = res[0].data
|
||||||
dictData.state.basic = res[1].data
|
dictData.state.basic = res[1].data
|
||||||
|
adminInfo.dataFill(res[2].data)
|
||||||
})
|
})
|
||||||
/**
|
/**
|
||||||
* 后台初始化请求,获取站点配置,动态路由等信息
|
* 后台初始化请求,获取站点配置,动态路由等信息
|
||||||
|
|||||||
@@ -11,13 +11,36 @@ export const useAdminInfo = defineStore('adminInfo', {
|
|||||||
expires_in: 0,
|
expires_in: 0,
|
||||||
scope: '',
|
scope: '',
|
||||||
nickname: '',
|
nickname: '',
|
||||||
userType: 1,
|
userType: 0,
|
||||||
deptIndex: '',
|
deptIndex: '',
|
||||||
userIndex: '',
|
userIndex: '',
|
||||||
client_id: '',
|
client_id: '',
|
||||||
headSculpture: '',
|
headSculpture: '',
|
||||||
jti: '',
|
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: {
|
actions: {
|
||||||
|
|||||||
@@ -45,8 +45,32 @@ export interface AdminInfo {
|
|||||||
deptIndex: string
|
deptIndex: string
|
||||||
userIndex: string
|
userIndex: string
|
||||||
client_id: string
|
client_id: string
|
||||||
headSculpture: string
|
headSculpture: any
|
||||||
jti: string
|
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 {
|
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 个字符',
|
message: '长度在 6 到 16 个字符',
|
||||||
trigger: 'blur'
|
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: [
|
newPwd: [
|
||||||
{ required: true, message: '请输入密码', trigger: 'blur' },
|
{ required: true, message: '请输入密码', trigger: 'blur' },
|
||||||
@@ -109,12 +93,14 @@ const open = (id: string) => {
|
|||||||
const submit = async () => {
|
const submit = async () => {
|
||||||
formRef.value.validate((valid:boolean) => {
|
formRef.value.validate((valid:boolean) => {
|
||||||
if (valid) {
|
if (valid) {
|
||||||
updatePassword({
|
passwordConfirm(form.password).then((res: any) => {
|
||||||
id: form.id,
|
updatePassword({
|
||||||
newPassword: form.newPwd
|
id: form.id,
|
||||||
}).then((res: any) => {
|
newPassword: form.newPwd
|
||||||
ElMessage.success('密码修改成功')
|
}).then((res: any) => {
|
||||||
dialogVisible.value = false
|
ElMessage.success('密码修改成功')
|
||||||
|
dialogVisible.value = false
|
||||||
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="default-main device-manage" :style="{ height: pageHeight.height }" v-loading="loading">
|
<div class="default-main device-manage" :style="{ height: pageHeight.height }" v-loading="loading">
|
||||||
<DeviceTree @node-click="nodeClick" @init="nodeClick"></DeviceTree>
|
<DeviceTree @node-click="nodeClick" @init="nodeClick"></DeviceTree>
|
||||||
<div class="device-manage-right" v-if="deviceData" >
|
<div class="device-manage-right" v-if="deviceData">
|
||||||
<el-descriptions title="设备基本信息" class="mb10" :column="3" border>
|
<el-descriptions title="设备基本信息" class="mb10" :column="3" border>
|
||||||
<template #extra>
|
<template #extra>
|
||||||
<el-button
|
<el-button
|
||||||
@@ -39,7 +39,7 @@
|
|||||||
lazy
|
lazy
|
||||||
:label="item.name"
|
:label="item.name"
|
||||||
:name="item.id"
|
:name="item.id"
|
||||||
v-for="(item,index) in deviceData.dataSetList"
|
v-for="(item, index) in deviceData.dataSetList"
|
||||||
:key="index"
|
:key="index"
|
||||||
></el-tab-pane>
|
></el-tab-pane>
|
||||||
<div :style="{ height: tableHeight }" v-loading="tableLoading">
|
<div :style="{ height: tableHeight }" v-loading="tableLoading">
|
||||||
@@ -131,7 +131,7 @@ queryByCode('Device_Type').then(res => {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
const echoName = (value: any, arr: any[]) => {
|
const echoName = (value: any, arr: any[]) => {
|
||||||
return arr.find(item => item.value == value).label
|
return arr.find(item => item.value == value)?.label
|
||||||
}
|
}
|
||||||
const openGroup = () => {
|
const openGroup = () => {
|
||||||
if (!dataSet.value) {
|
if (!dataSet.value) {
|
||||||
|
|||||||
@@ -1,136 +1,136 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="default-main">
|
<div class='default-main'>
|
||||||
<TableHeader>
|
<TableHeader>
|
||||||
<template v-slot:select>
|
<template v-slot:select>
|
||||||
<el-form-item label="设备类型">
|
<el-form-item label='设备类型'>
|
||||||
<!-- <el-input v-model="tableStore.table.params.searchValue" placeholder="请输入设备类型" /> -->
|
<!-- <el-input v-model="tableStore.table.params.searchValue" placeholder="请输入设备类型" /> -->
|
||||||
<el-select
|
<el-select
|
||||||
v-model="tableStore.table.params.devType"
|
v-model='tableStore.table.params.devType'
|
||||||
clearable
|
clearable
|
||||||
@change="devTypeChange"
|
@change='devTypeChange'
|
||||||
placeholder="请选择设备类型"
|
placeholder='请选择设备类型'
|
||||||
>
|
>
|
||||||
<el-option
|
<el-option
|
||||||
v-for="item in devTypeOptions"
|
v-for='item in devTypeOptions'
|
||||||
:key="item.value"
|
:key='item.value'
|
||||||
:label="item.label"
|
:label='item.label'
|
||||||
:value="item.value"
|
:value='item.value'
|
||||||
/>
|
/>
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="设备型号">
|
<el-form-item label='设备型号'>
|
||||||
<el-select v-model="tableStore.table.params.devModel" clearable placeholder="请选择设备型号">
|
<el-select v-model='tableStore.table.params.devModel' clearable placeholder='请选择设备型号'>
|
||||||
<el-option
|
<el-option
|
||||||
v-for="item in devModelOptionsFilter"
|
v-for='item in devModelOptionsFilter'
|
||||||
:key="item.value"
|
:key='item.value'
|
||||||
:label="item.label"
|
:label='item.label'
|
||||||
:value="item.value"
|
:value='item.value'
|
||||||
/>
|
/>
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="通讯协议">
|
<el-form-item label='通讯协议'>
|
||||||
<el-select v-model="tableStore.table.params.devAccessMethod" clearable placeholder="请选择通讯协议">
|
<el-select v-model='tableStore.table.params.devAccessMethod' clearable placeholder='请选择通讯协议'>
|
||||||
<el-option label="MQTT" value="mqtt"></el-option>
|
<el-option label='MQTT' value='mqtt'></el-option>
|
||||||
<el-option label="CLD" value="cloud"></el-option>
|
<el-option label='CLD' value='cloud'></el-option>
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="状态">
|
<el-form-item label='状态'>
|
||||||
<el-select v-model="tableStore.table.params.status" clearable placeholder="请选择状态">
|
<el-select v-model='tableStore.table.params.status' clearable placeholder='请选择状态'>
|
||||||
<el-option label="未注册" :value="1"></el-option>
|
<el-option label='未注册' :value='1'></el-option>
|
||||||
<el-option label="注册" :value="2"></el-option>
|
<el-option label='注册' :value='2'></el-option>
|
||||||
<el-option label="接入" :value="3"></el-option>
|
<el-option label='接入' :value='3'></el-option>
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</template>
|
</template>
|
||||||
<template v-slot:operation>
|
<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-button>
|
||||||
<el-upload
|
<el-upload
|
||||||
style="display: inline-block"
|
style='display: inline-block'
|
||||||
action=""
|
action=''
|
||||||
accept=".xlsx"
|
accept='.xlsx'
|
||||||
class="upload-demo"
|
class='upload-demo'
|
||||||
:show-file-list="false"
|
:show-file-list='false'
|
||||||
:auto-upload="false"
|
:auto-upload='false'
|
||||||
:on-change="bulkImport"
|
: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-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>
|
</template>
|
||||||
</TableHeader>
|
</TableHeader>
|
||||||
<Table ref="tableRef"></Table>
|
<Table ref='tableRef'></Table>
|
||||||
|
|
||||||
<el-dialog
|
<el-dialog
|
||||||
:title="dialogTitle"
|
:title='dialogTitle'
|
||||||
v-model="dialogFormVisible"
|
v-model='dialogFormVisible'
|
||||||
:close-on-click-modal="false"
|
:close-on-click-modal='false'
|
||||||
width="600px"
|
width='600px'
|
||||||
:before-close="resetForm"
|
:before-close='resetForm'
|
||||||
>
|
>
|
||||||
<el-form :model="form" label-width="120px" :rules="rules" ref="ruleFormRef">
|
<el-form :model='form' label-width='120px' :rules='rules' ref='ruleFormRef'>
|
||||||
<el-form-item label="设备名称:" prop="name">
|
<el-form-item label='设备名称:' prop='name'>
|
||||||
<el-input
|
<el-input
|
||||||
v-model="form.name"
|
v-model='form.name'
|
||||||
autocomplete="off"
|
autocomplete='off'
|
||||||
clearable
|
clearable
|
||||||
placeholder="请输入(项目名称+设备名称)"
|
placeholder='请输入(项目名称+设备名称)'
|
||||||
></el-input>
|
></el-input>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="网络设备ID:" prop="ndid" class="top">
|
<el-form-item label='网络设备ID:' prop='ndid' class='top'>
|
||||||
<el-input v-model="form.ndid" autocomplete="off" placeholder="请输入"></el-input>
|
<el-input v-model='form.ndid' autocomplete='off' placeholder='请输入'></el-input>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="设备类型:" prop="devType" class="top">
|
<el-form-item label='设备类型:' prop='devType' class='top'>
|
||||||
<el-select
|
<el-select
|
||||||
v-model="form.devType"
|
v-model='form.devType'
|
||||||
placeholder="请选择"
|
placeholder='请选择'
|
||||||
style="width: 100%"
|
style='width: 100%'
|
||||||
@change="formDevTypeChange"
|
@change='formDevTypeChange'
|
||||||
clearable
|
clearable
|
||||||
>
|
>
|
||||||
<el-option
|
<el-option
|
||||||
v-for="item in devTypeOptions"
|
v-for='item in devTypeOptions'
|
||||||
:key="item.value"
|
:key='item.value'
|
||||||
:label="item.label"
|
:label='item.label'
|
||||||
:value="item.value"
|
:value='item.value'
|
||||||
></el-option>
|
></el-option>
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="设备型号:" prop="devModel" class="top">
|
<el-form-item label='设备型号:' prop='devModel' class='top'>
|
||||||
<el-select v-model="form.devModel" placeholder="请选择" style="width: 100%" clearable>
|
<el-select v-model='form.devModel' placeholder='请选择' style='width: 100%' clearable>
|
||||||
<el-option
|
<el-option
|
||||||
v-for="item in formDevModelOptionsFilter"
|
v-for='item in formDevModelOptionsFilter'
|
||||||
:key="item.value"
|
:key='item.value'
|
||||||
:label="item.label"
|
:label='item.label'
|
||||||
:value="item.value"
|
:value='item.value'
|
||||||
></el-option>
|
></el-option>
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="通讯协议:" prop="devAccessMethod" class="top">
|
<el-form-item label='通讯协议:' prop='devAccessMethod' class='top'>
|
||||||
<el-select v-model="form.devAccessMethod" placeholder="请选择" style="width: 100%" clearable>
|
<el-select v-model='form.devAccessMethod' placeholder='请选择' style='width: 100%' clearable>
|
||||||
<el-option label="MQTT" value="MQTT"></el-option>
|
<el-option label='MQTT' value='MQTT'></el-option>
|
||||||
<el-option label="CLD" value="cloud"></el-option>
|
<el-option label='CLD' value='cloud'></el-option>
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
<el-form-item label="合同号:" prop="cntractNo" class="top">
|
<el-form-item label='合同号:' prop='cntractNo' class='top'>
|
||||||
<el-input v-model="form.cntractNo" autocomplete="off" placeholder="请输入"></el-input>
|
<el-input v-model='form.cntractNo' autocomplete='off' placeholder='请输入'></el-input>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-form>
|
</el-form>
|
||||||
<template #footer>
|
<template #footer>
|
||||||
<el-button @click="resetForm">取 消</el-button>
|
<el-button @click='resetForm'>取 消</el-button>
|
||||||
<el-button type="primary" @click="onSubmit">确 定</el-button>
|
<el-button type='primary' @click='onSubmit'>确 定</el-button>
|
||||||
</template>
|
</template>
|
||||||
</el-dialog>
|
</el-dialog>
|
||||||
|
|
||||||
<div class="qrcode-label">
|
<div class='qrcode-label'>
|
||||||
<div class="qrcode-label-title">{{ deivce.mac }}</div>
|
<div class='qrcode-label-title'>{{ deivce.mac }}</div>
|
||||||
<img class="qrcode-label-img" alt="二维码加载失败" :src="deivce.qrPath" />
|
<img class='qrcode-label-img' alt='二维码加载失败' :src='deivce.qrPath' />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script setup lang="ts">
|
<script setup lang='ts'>
|
||||||
import { ref, onMounted, provide, computed, reactive, nextTick } from 'vue'
|
import { ref, onMounted, provide, computed, reactive, nextTick } from 'vue'
|
||||||
import TableStore from '@/utils/tableStore'
|
import TableStore from '@/utils/tableStore'
|
||||||
import Table from '@/components/table/index.vue'
|
import Table from '@/components/table/index.vue'
|
||||||
@@ -146,6 +146,7 @@ import {
|
|||||||
} from '@/api/cs-system-boot/device'
|
} from '@/api/cs-system-boot/device'
|
||||||
import html2canvas from 'html2canvas'
|
import html2canvas from 'html2canvas'
|
||||||
import { fullUrl } from '@/utils/common'
|
import { fullUrl } from '@/utils/common'
|
||||||
|
|
||||||
defineOptions({
|
defineOptions({
|
||||||
name: 'govern/log/debug'
|
name: 'govern/log/debug'
|
||||||
})
|
})
|
||||||
@@ -261,7 +262,7 @@ const tableStore = new TableStore({
|
|||||||
buttons: [
|
buttons: [
|
||||||
{
|
{
|
||||||
name: 'edit',
|
name: 'edit',
|
||||||
title:'编辑',
|
title: '编辑',
|
||||||
type: 'primary',
|
type: 'primary',
|
||||||
icon: 'el-icon-Edit',
|
icon: 'el-icon-Edit',
|
||||||
render: 'tipButton',
|
render: 'tipButton',
|
||||||
@@ -430,9 +431,10 @@ onMounted(() => {
|
|||||||
}, 100)
|
}, 100)
|
||||||
})
|
})
|
||||||
|
|
||||||
const addMenu = () => {}
|
const addMenu = () => {
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
<style lang="scss" scoped>
|
<style lang='scss' scoped>
|
||||||
.qrcode-label {
|
.qrcode-label {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 0;
|
top: 0;
|
||||||
|
|||||||
Reference in New Issue
Block a user