用户信息修改

This commit is contained in:
仲么了
2024-01-26 16:15:40 +08:00
parent 04665478fc
commit 5267ae1903
13 changed files with 457 additions and 173 deletions

View File

@@ -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.

View File

@@ -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,8 +117,7 @@ export async function updatePassword(params: any) {
}
export function checkUser(data:any) {
export function checkUser(data: any) {
return request({
url: '/user-boot/user/check',
method: 'put',

View File

@@ -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: '',
@@ -99,10 +83,9 @@ const onCurrentNavMenu = (status: boolean, name: string) => {
state.currentNavMenu = status ? name : ''
}
const savePng = () => {
html2canvas(document.body,{
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;
}

View 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>

View 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>

View File

@@ -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)
})
/**
* 后台初始化请求,获取站点配置,动态路由等信息

View File

@@ -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: {

View File

@@ -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
View File

@@ -0,0 +1 @@
dialog 弹框标准模版

78
src/template/dialog.vue Normal file
View 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>

View File

@@ -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
})
})
}
})
}

View File

@@ -1,7 +1,7 @@
<template>
<div class="default-main device-manage" :style="{ height: pageHeight.height }" v-loading="loading">
<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>
<template #extra>
<el-button
@@ -39,7 +39,7 @@
lazy
:label="item.name"
:name="item.id"
v-for="(item,index) in deviceData.dataSetList"
v-for="(item, index) in deviceData.dataSetList"
:key="index"
></el-tab-pane>
<div :style="{ height: tableHeight }" v-loading="tableLoading">
@@ -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) {

View File

@@ -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'
})
@@ -261,7 +262,7 @@ const tableStore = new TableStore({
buttons: [
{
name: 'edit',
title:'编辑',
title: '编辑',
type: 'primary',
icon: 'el-icon-Edit',
render: 'tipButton',
@@ -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;