Commit 7c14ee4b by 李俊

Merge branch 'develop' of gitlab.seetatech.com:seeta-device/deviceManage into develop

2 parents 7cbcf27f 0eab7795
Pipeline #5454 passed
in 6 minutes 59 seconds
......@@ -5,7 +5,7 @@
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
<title>SeetaAIoT</title>
<title>AIoT Base</title>
</head>
<body>
<script type="text/javascript" src="./config.js"></script>
......
......@@ -4,25 +4,6 @@
</div>
</template>
<script>
export default {
data() {
return {
formatData: [
{
label: 'test',
key: 'name',
type: 'input',
required: true,
validator: ['notEmpty', 'min2', 'max64', 'normName'],
placeholder: 'test',
},
],
}
},
}
</script>
<style>
#app {
font-family: PingFangSC-Regular, 微软雅黑;
......
......@@ -33,6 +33,9 @@ export const deleteApp = data => axios(GET, FRONT + APPID + '/delete', data)
export const setApp = data => axios(GET, FRONT + APPID + '/set', data)
export const addApp = data => axios(POST, FRONT + APPID + '/add', data)
const ACCOUNt = '/account'
export const getAccount = data => axios(GET, FRONT + ACCOUNt + '/query', data)
const DEVICE = '/device'
export const getDevice = data => axios(POST, FRONT + DEVICE + '/query_list', data)
export const getDeviceService = data => axios(GET, FRONT + DEVICE + '/service/query')
......
......@@ -62,6 +62,9 @@ Axios.interceptors.response.use(res => {
if (res && res.data && res.data.code !== 0) {
notificationError('提示', res.data.msg)
}
if (res && res.data && res.data.code === 22 && res.data.msg === 'user do not login') {
Router.push('/login')
}
return res
}, error => {
error.response && error.response.data && notificationError('提示', error.response.data.message)
......
......@@ -16,7 +16,7 @@
</ul>
<template v-slot:reference>
<span class="user-info flex right">
<span v-if="userData.info">{{ userData.info.creater }}</span>
<span>{{ name }}</span>
<i class="iconfont icon-mianxingxiala"
:class="{
'expand': showInfo,
......@@ -32,6 +32,7 @@ import { getUser, removeUser } from '@/utils/user'
import { logoutApi } from '@/axios'
import Dialog from '@/helpers/dialog'
import seetaPopover from '@/components/seeta-ui/seeta-popover.vue'
import browserStorage from '@/services/local-storage'
@Component({
components: {
......@@ -40,7 +41,9 @@ import seetaPopover from '@/components/seeta-ui/seeta-popover.vue'
})
export default class userInfo extends Vue {
showInfo: boolean = false
get name() {
return browserStorage.getItem('nickname') || browserStorage.getItem('username')
}
get userData() { return getUser() }
get shouldConfirmBeforeLeave(): boolean {
......
......@@ -14,6 +14,18 @@ export default [
component: () => import('@views/register')
},
{
path: '/overview',
name: 'overview',
meta: { title: '总览页面', icon: 'icon-wendanggongju', hidden: true },
component: () => import('@layouts/basicLayout'),
children: [{
path: '/overview',
name: 'overview',
meta: { title: '总览页面' },
component: () => import('@views/overview')
}]
},
{
path: '/device',
name: 'device',
meta: { title: '设备列表', icon: 'icon-shebei' },
......
......@@ -6,11 +6,11 @@
<div class="page-nav">
<div class="search-fields">
<span class="fields">用户名:</span>
<st-input width="240px" class="align contents" id="align-input" v-model="userName"></st-input>
<st-input width="240px" class="align contents" id="align-input" v-model="nickname" @input="getData"></st-input>
<!-- <input type="text" id="raw-input" autocomplete="off" class="align contents" :style="{borderColor: borderColor}" placeholder="请输入" @blur="getData" v-model.trim="deviceName" @keyup.enter="getData" @input="checkSearchContent"> -->
<span class="fields">用户角色:</span>
<st-select
v-model="userRole"
v-model="role"
:options="userRoleOptions"
size="small"
style="width: 240px"
......@@ -63,37 +63,47 @@
<div slot="body" class="popup-body">
<st-form
label-width="90px"
style="height: 440px"
ref="form"
:model="form"
:rules="rules">
<st-form-item
:label="'账号:'">
<st-form-item :label="'账号:'" prop="username">
<st-input v-model="form.username" :disabled="submitType === 'edit'"></st-input>
</st-form-item>
<st-form-item
:label="'角色:'">
<st-input v-model="form.role"></st-input>
:label="'昵称:'" prop="nickname">
<st-input v-model="form.nickname"></st-input>
</st-form-item>
<st-form-item
:label="'邮箱:'">
<st-form-item :label="'角色:'" prop="role">
<st-select v-model="form.role" :options="userRoleOptions" clearable>
</st-select>
</st-form-item>
<st-form-item :label="'邮箱:'" prop="email">
<st-input v-model="form.email"></st-input>
</st-form-item>
<st-form-item v-if="submitType === 'create'"
:label="'初始密码:'">
<st-form-item v-if="submitType === 'create'" :label="'初始密码:'" prop="passwd">
<st-input v-model="form.passwd" type="password"></st-input>
</st-form-item>
<st-form-item v-if="submitType === 'create'"
:label="'重复密码:'">
<st-form-item v-if="submitType === 'create'" :label="'重复密码:'" prop="confirmPwd">
<st-input v-model="form.confirmPwd" type="password"></st-input>
</st-form-item>
<st-form-item v-if="submitType === 'edit'"
:label="'原密码:'">
<st-form-item v-if="submitType === 'edit'" :label="'原密码:'" prop="passwordd">
<st-input v-model="form.passwordd" type="password"></st-input>
</st-form-item>
<st-form-item v-if="submitType === 'edit'"
:label="'新密码:'">
<st-form-item v-if="submitType === 'edit'" :label="'新密码:'" prop="new_passwordd">
<st-input v-model="form.new_passwordd" type="password"></st-input>
</st-form-item>
<st-form-item
:label="'备注:'">
<st-input
type="textarea"
placeholder="请输入"
v-model="form.description"
maxlength="100"
show-word-limit
>
</st-input>
</st-form-item>
</st-form>
</div>
<div slot="footer" class="popup-footer flex right">
......@@ -122,13 +132,17 @@ export default {
}
return {
// 查询字段
userName: '',
userRole: '',
nickname: '',
role: '',
created_at: [],
showDialog: false,
submitType: 'create',
form: {},
userRoleOptions: [],
userRoleOptions: [
{ value: 'admin', label: '管理员' },
{ value: 'operator', label: '操作员' },
{ value: 'watcher', label: '观察员' },
],
currentPage: 1,
currentSize: 10,
loadingStatus: false,
......@@ -139,7 +153,14 @@ export default {
},
{
label: '角色',
render: 'role'
render: row => {
switch (row.role) {
case 'operator': return '操作员'
case 'admin': return '管理员'
case 'watcher': return '观察员'
default: return ''
}
}
},
{
label: '邮箱',
......@@ -155,7 +176,7 @@ export default {
},
{
label: '备注',
render: 'desc'
render: 'description'
},
{
label: '操作',
......@@ -167,7 +188,11 @@ export default {
tokenList: [],
total: 0,
rules: { // 表单校验
passwordConfirmation: [
username: [{ required: true, message: '请输入账号', trigger: 'blur' }],
nickname: [{ required: true, message: '请输入昵称', trigger: 'blur' }],
role: [{ required: true, message: '请选择角色', trigger: 'change' }],
passwd: [{ required: true, message: '请输入密码', trigger: 'blur' }],
confirmPwd: [
{ required: true, message: '请确认密码', trigger: 'blur' },
{ validator: validatePasswordConfirmation, trigger: 'blur' }
]
......@@ -198,9 +223,8 @@ export default {
switch (this.submitType) {
case 'create':
submitForm = JSON.parse(JSON.stringify(this.form))
delete submitForm.email
delete submitForm.confirmPwd
submitForm.creater = 'admin'
submitForm.creater = browserStorage.getItem('username')
res = await createUser(submitForm)
if (res && res.data && res.data.code === 0) {
this.getData()
......@@ -209,9 +233,8 @@ export default {
break
case 'edit':
submitForm = JSON.parse(JSON.stringify(this.form))
delete submitForm.email
delete submitForm.confirmPwd
submitForm.creater = 'admin'
submitForm.creater = browserStorage.getItem('username')
res = await editUser(submitForm)
if (res && res.data && res.data.code === 0) {
this.getData()
......@@ -250,7 +273,7 @@ export default {
},
async getData() {
this.loadingStatus = true
const res = await getUsers({ pages: this.currentPage - 1, pagesize: this.currentSize })
const res = await getUsers({ pages: this.currentPage - 1, pagesize: this.currentSize, nickname: this.nickname, role: this.role, begin_date: this.created_at ? this.created_at[0] : '', end_date: this.created_at ? this.created_at[1] : '' })
if (res && res.data && res.data.code === 0) {
this.tokenList = res.data.data.users
this.total = res.data.data.total
......@@ -262,6 +285,23 @@ export default {
</script>
<style lang="sass" scoped>
.update-dialog
::v-deep input
&::placeholder
font-size: 14px
font-family: PingFangSC-Regular, PingFang SC
font-weight: 400
color:#999999
::v-deep.el-input__inner, ::v-deep.el-textarea, ::v-deep.el-textarea__inner
font-size: 14px
font-family: PingFangSC-Regular, PingFang SC
font-weight: 400
color: #333
&::placeholder
font-size: 14px
font-family: PingFangSC-Regular, PingFang SC
font-weight: 400
color:#999999
.popup-body
::v-deep.el-form-item
height: 32px
......@@ -272,6 +312,12 @@ export default {
::v-deep.el-form-item__content
height: 32px!important
line-height: 32px!important
::v-deep input
&::placeholder
font-size: 14px
font-family: PingFangSC-Regular, PingFang SC
font-weight: 400
color:#999999
.search-fields
::v-deep input
&::placeholder
......
......@@ -25,8 +25,8 @@
</div>
<div slot="operate" slot-scope="row">
<span class="operate" v-if="row.ismainapp === 0" @click="setHostApp(row)">设置为主应用</span>
<span class="operate" v-else @click="cancelHostApp(row)">取消设置为主应用</span>
<span class="operate operate-delete" @click="handleDelete(row)">删除</span>
<!-- <span class="operate" v-else @click="cancelHostApp(row)">取消设置为主应用</span> -->
<span class="operate operate-delete" v-if="row.ismainapp === 0" @click="handleDelete(row)">删除</span>
</div>
</st-table>
</div>
......@@ -162,14 +162,14 @@ export default {
}
},
async setHostApp(row) {
const res = await setApp({ appid: row.appid, mainapp: 1, username: 'test' })
const res = await setApp({ appid: row.appid, mainapp: 1, username: browserStorage.getItem('nickname') })
if (res && res.data && res.data.code === 0) {
Toast.success('操作成功')
this.getData()
}
},
async cancelHostApp(row) {
const res = await setApp({ appid: row.appid, mainapp: 0, username: 'test' })
const res = await setApp({ appid: row.appid, mainapp: 0, username: browserStorage.getItem('nickname') })
if (res && res.data && res.data.code === 0) {
Toast.success('操作成功')
this.getData()
......
<template>
<div class="data-list-common flex column main-content flex-1">
<div class="header">
<span class="title">{{'数据列表 / 编辑'}}</span>
<span class="title">{{'数据列表 / 编辑 / ' + $route.query.name}}</span>
</div>
<div class="page-content" @click="handleClick">
<div class="content-header">
<st-button type="primary" @click="addTableData">
<i class="iconfont icon-tianjia"></i><span class="text">{{'插入数据'}}</span></st-button>
<div class="search-box">
<el-checkbox v-model="isBase64">Base64</el-checkbox>
<st-select
<!-- <el-checkbox v-model="isBase64">Base64</el-checkbox> -->
<!-- <st-select
v-model="inputVal"
:options="orderOptions"
size="small"
......@@ -17,9 +17,9 @@
clearable
placeholder="序号"
>
</st-select>
</st-select> -->
<div class="search">
<input type="text" class="search-input" placeholder="请输入搜索内容" v-model="inputVal">
<input type="text" class="search-input" placeholder="请输入搜索内容" v-model="content" @input="getData">
<i class="el-input__icon el-icon-search"></i>
</div>
</div>
......@@ -95,7 +95,7 @@ import { base64ToString, stringToBase64, isASCII } from '@/utils/typeConversion'
export default {
data() {
return {
inputVal: '',
content: '',
isBase64: false,
loadingStatus: false,
totalColumns: Number(this.$route.query.columns),
......@@ -134,7 +134,7 @@ export default {
methods: {
async getData() {
this.loadingStatus = true
const res = await getData({ name: this.$route.query.name, pages: this.currentPage - 1, pagesize: this.currentSize })
const res = await getData({ name: this.$route.query.name, pages: this.currentPage - 1, pagesize: this.currentSize, content: this.content })
if (res && res.data && res.data.code === 0) {
this.tableData = res.data.table.data.map(item => {
item.binary = item.binary.map(base64 => {
......@@ -189,7 +189,7 @@ export default {
binaryItem.push(ite.value)
}
})
if (binaryItem.length === Number(this.$route.query.columns)) {
if (binaryItem.length === this.totalColumns) {
binaryData.push(binaryItem)
}
})
......@@ -209,7 +209,7 @@ export default {
},
addTableData() {
const binary = []
for (let i = 0; i < Number(this.$route.query.columns); i++) {
for (let i = 0; i < this.totalColumns; i++) {
binary.push({ type: '', value: '' })
}
this.insertData.push({
......@@ -252,7 +252,8 @@ export default {
if (this.agoCell !== cell) {
this.clearCell(this.agoCell)
}
this.columnIndex = Number(column.label.substring(1))
// 编辑行时扩展列
if (!row.id) this.columnIndex = Number(column.label.substring(1))
cell.getElementsByClassName('el-select')[0] && cell.getElementsByClassName('el-select')[0].classList.remove('none-display')
if (cell.getElementsByTagName('input')[0] && cell.getElementsByTagName('input')[1]) {
cell.getElementsByTagName('input')[0].classList.add('write')
......@@ -386,6 +387,7 @@ export default {
width: 240px
height: 32px
position: relative
margin-left: 10px
.search-input
width: 100%
padding-right: 35px
......
......@@ -8,7 +8,7 @@
<st-button type="primary" id="btn" @click="showDialog = true">
<i class="iconfont icon-tianjia"></i><span class="text">{{'创建数据表'}}</span></st-button>
<div class="search">
<input type="text" class="search-input" placeholder="请输入搜索内容" v-model="inputVal">
<input type="text" class="search-input" placeholder="请输入搜索内容" v-model="inputVal" @input="getData">
<i class="el-input__icon el-icon-search"></i>
</div>
</div>
......@@ -87,7 +87,7 @@ export default {
render: 'rows'
},
{
label: '容量',
label: '容量(kb)',
render: 'storage'
},
{
......@@ -129,7 +129,7 @@ export default {
methods: {
async getData() {
this.loadingStatus = true
const res = await getTable({ pages: this.currentPage - 1, pagesize: this.currentSize })
const res = await getTable({ pages: this.currentPage - 1, pagesize: this.currentSize, name: this.inputVal })
if (res && res.data && res.data.code === 0) {
this.tokenList = res.data.data.tables.map((item, index) => {
item.order = index + 1 + (this.currentPage - 1) * this.currentSize
......
......@@ -17,7 +17,7 @@
<st-form-item
:label="'模板类型'+':'"
prop="type">
<st-input v-model="form.type"></st-input>
<st-input v-model="form.type" :disabled="$route.query.level === '2'"></st-input>
</st-form-item>
<st-form-item
:label="'基础模板'+':'"
......@@ -30,7 +30,7 @@
clearable
>
</st-select> -->
<el-select v-model="form.base" placeholder="请选择" style="width: 400px;height: 32px;line-height: 32px">
<el-select v-model="form.base" placeholder="请选择" style="width: 400px;height: 32px;line-height: 32px" @change="handleSelectBase">
<el-option
v-for="item in baseOptions"
:key="item.name"
......@@ -65,12 +65,12 @@
style="width: 100%">
<el-table-column label="字段">
<template slot-scope="scope">
<input type="text" v-model="scope.row.field" @blur="handleBlur" placeholder="请输入">
<input type="text" v-model="scope.row.field" @blur="handleBlur" placeholder="请输入" :disabled="Boolean(scope.row.level)">
</template>
</el-table-column>
<el-table-column label="类型">
<template slot-scope="scope">
<pack-select v-model="scope.row.type" placeholder="请选择" @blur="handleBlur" @visible-change="handleVisibleChange" @change="handleChange(scope.row)">
<pack-select v-model="scope.row.type" placeholder="请选择" @blur="handleBlur" @visible-change="handleVisibleChange" @change="handleChange(scope.row)" :disabled="Boolean(scope.row.level)">
<el-option
v-for="item in typeOptions"
:key="item.value"
......@@ -87,8 +87,8 @@
<span class="upload-btn" v-if="!scope.row.value">Select File</span>
<input type="file" @blur="handleBlur" @change="(event) => handleUpload(event, scope.row)" class="input-btn" v-if="!scope.row.value">
<span v-if="scope.row.value">
<span style="float: left;margin-right: 10px">{{calculateByte(scope.row.value)}}字节</span>
<el-image style="width: 42px; height: 28px;overflow: visible" :src="scope.row.value" fit="fit">
<span style="float: left;margin-right: 10px" @click="scope.row.value = ''">{{calculateByte(scope.row.value)}}字节</span>
<el-image style="width: 42px; height: 28px;overflow: visible" :src="scope.row.value" fit="fit" :preview-src-list="[scope.row.value]">
<div slot="error" style="width: 80px; height: 28px;overflow: visible">(不可预览)</div>
</el-image>
</span>
......@@ -107,7 +107,9 @@
</el-table-column>
<el-table-column label="操作">
<template slot-scope="scope">
<span @click="handleDelete(scope.$index)" class="delete-btn">删除</span>
<span @click="handleHidden(scope.row)" class="delete-btn" style="color: #E6A23C" v-if="scope.row.level">隐藏</span>
<span @click="handleReturnBack(scope.row, scope.$index)" style="color: #409EFF" class="delete-btn" v-if="scope.row.level && scope.row.value != originalData[scope.$index].value">撤回</span>
<span @click="handleDelete(scope.$index)" class="delete-btn" v-if="!scope.row.level">删除</span>
</template>
</el-table-column>
</el-table>
......@@ -126,7 +128,7 @@
</template>
<script>
import { createParameter, getTable, getParameter } from '@/axios'
import { createParameter, getTable, getParameter, detailParameter } from '@/axios'
import { fileToBase64 } from '@/utils/typeConversion'
import { calculateByte } from '@/utils/system'
import Dialog from '@/helpers/dialog'
......@@ -151,6 +153,7 @@ export default {
tableOptions: [],
baseOptions: [],
tableData: [],
originalData: [],
flexHeight: 0,
currentRow: ''
}
......@@ -183,8 +186,37 @@ export default {
this.baseOptions = res.data.parameters.datas
}
},
async handleSelectBase(value) {
const res = await detailParameter({ name: value })
if (res && res.data && res.data.code === 0) {
this.form.type = res.data.type
this.tableData = []
const binaryObj = res.data.parameters.binary
const scalarsObj = res.data.parameters.scalars
const tableObj = res.data.parameters.table
for (const key in binaryObj) {
this.tableData.push({ field: key, type: 'blob', value: binaryObj[key], level: 1 })
}
for (const key in scalarsObj) {
this.tableData.push({ field: key, type: typeof scalarsObj[key], value: scalarsObj[key], level: 1 })
}
for (const key in tableObj) {
this.tableData.push({ field: key, type: 'table', value: tableObj[key], level: 1 })
}
this.originalData = JSON.parse(JSON.stringify(this.tableData))
}
},
async save() {
const tableData = this.tableData.filter(item => item.field && item.value)
const tableDataTemp = this.tableData.filter(item => item.field !== '' && item.type !== '' && item.value !== '')
// 最终提交的数据字段名不重复
const temp = []
const tableData = []
for (let i = 0; i < tableDataTemp.length; i++) {
if (!temp.includes(tableDataTemp[i].field)) {
temp.push(tableDataTemp[i].field)
tableData.push(tableDataTemp[i])
}
}
const scalarsArr = tableData.filter(item => item.type === 'string' || item.type === 'number')
const binaryArr = tableData.filter(item => item.type === 'blob')
const tableArr = tableData.filter(item => item.type === 'table')
......@@ -192,9 +224,6 @@ export default {
const binaryObj = {}
const tableObj = {}
for (let i = 0; i < scalarsArr.length; i++) {
scalarsObj[scalarsArr[i].field] = scalarsArr[i].value
}
for (let j = 0; j < binaryArr.length; j++) {
binaryObj[binaryArr[j].field] = binaryArr[j].value
}
for (let k = 0; k < tableArr.length; k++) {
......@@ -210,11 +239,13 @@ export default {
})
if (res && res.data && res.data.code === 0) {
Toast.success('操作成功')
this.$router.push({ path: '/params' })
// this.$router.push({ path: '/params' })
}
},
cancel() {
this.$router.push({ path: '/params' })
// this.$router.push({ path: '/params' })
this.form = {}
this.tableData = []
},
async handleUpload(event, row) {
row.value = await fileToBase64(event.target.files[0])
......@@ -222,8 +253,17 @@ export default {
insertTableData() {
this.tableData.push({ field: '', type: '', value: '' })
},
handleReturnBack(row, index) {
row.value = JSON.parse(JSON.stringify(this.originalData[index])).value
this.$forceUpdate()
},
handleHidden(row) {
row.value = null
this.$forceUpdate()
},
handleDelete(index) {
this.tableData.splice(index, 1)
this.$forceUpdate()
},
setFlexHeight() {
const ele = document.getElementsByClassName('flex-item') && document.getElementsByClassName('flex-item')[0]
......@@ -242,6 +282,7 @@ export default {
event.target && event.target.classList && event.target.classList.remove('write')
},
cellClick(row, column, cell, event) {
if (row.level && (column.label === '字段' || column.label === '类型')) return
if (cell.getElementsByTagName('input')[0]) {
cell.getElementsByTagName('input')[0].classList.add('write')
cell.getElementsByTagName('input')[0].focus()
......
......@@ -26,20 +26,22 @@
:options="definitions"
:pagination="false"
:data="{
list: tokenList,
list: tableData,
total: total,
}"
:outerLoading="loadingStatus">
<div slot="value" slot-scope="row">
<span v-if="row.value === null" class="cell-null">null</span>
<span v-else>
<span v-if="row.type === 'number' || row.type === 'string'">{{row.value}}</span>
<span v-if="row.type === 'blob'" style="line-height: 28px">
<!-- TODO -->
<span style="float: left;margin-right: 10px">{{calculateByte(row.value)}}字节</span>
<el-image style="width: 42px; height: 28px;overflow: visible" :src="row.value" fit="fit">
<span style="float: left;margin-right: 10px">{{parseInt(calculateByte(row.value))}}&nbsp;字节</span>
<el-image style="width: 42px; height: 28px;overflow: visible" :src="row.value" fit="fit" :preview-src-list="[row.value]">
<div slot="error" style="width: 80px; height: 28px;overflow: visible">(不可预览)</div>
</el-image>
</span>
<span v-if="row.type === 'table'" style="color: #409EFF; cursor: pointer" @click="$router.push({ path: '/data' })">{{row.value}}</span>
<span v-if="row.type === 'table'" style="color: #409EFF; cursor: pointer" @click="handleToTableDetail(row.value)">{{row.value}}</span>
</span>
</div>
</st-table>
</st-form-item>
......@@ -49,7 +51,7 @@
</template>
<script>
import { detailParameter } from '@/axios'
import { detailParameter, getTable } from '@/axios'
import { calculateByte } from '@/utils/system'
export default {
data() {
......@@ -71,7 +73,8 @@ export default {
slotName: 'value'
}
],
tokenList: [],
baseData: [],
tableData: [],
total: 0
}
},
......@@ -79,24 +82,69 @@ export default {
this.loadingStatus = true
const res = await detailParameter({ name: this.$route.query.name })
if (res && res.data && res.data.code === 0) {
let binaryObj = {}
let scalarsObj = {}
let tableObj = {}
let binaryObj1 = {}
let scalarsObj1 = {}
let tableObj1 = {}
if (res.data.base) {
const base = await detailParameter({ name: res.data.base })
if (base && base.data && base.data.code === 0) {
binaryObj1 = base.data.parameters.binary
scalarsObj1 = base.data.parameters.scalars
tableObj1 = base.data.parameters.table
this.baseObj = Object.assign(JSON.parse(JSON.stringify(binaryObj1)), JSON.parse(JSON.stringify(scalarsObj1)), JSON.parse(JSON.stringify(tableObj1)))
for (const key in binaryObj1) {
this.baseData.push({ field: key, type: 'blob', value: binaryObj1[key], level: 1 })
}
for (const key in scalarsObj1) {
this.baseData.push({ field: key, type: typeof scalarsObj1[key], value: scalarsObj1[key], level: 1 })
}
for (const key in tableObj1) {
this.baseData.push({ field: key, type: 'table', value: tableObj1[key], level: 1 })
}
}
}
this.form = res.data
const binaryObj = res.data.parameters.binary
const scalarsObj = res.data.parameters.scalars
const tableObj = res.data.parameters.table
binaryObj = Object.assign(JSON.parse(JSON.stringify(binaryObj1)), res.data.parameters.binary)
scalarsObj = Object.assign(JSON.parse(JSON.stringify(scalarsObj1)), res.data.parameters.scalars)
tableObj = Object.assign(JSON.parse(JSON.stringify(tableObj1)), res.data.parameters.table)
const frontData = []
const endData = []
for (const key in binaryObj) {
this.tokenList.push({ field: key, type: 'blob', value: binaryObj[key] })
if (binaryObj1[key]) {
frontData.push({ field: key, type: 'blob', value: binaryObj[key], level: 1 })
} else {
endData.push({ field: key, type: 'blob', value: binaryObj[key] })
}
}
for (const key in scalarsObj) {
this.tokenList.push({ field: key, type: typeof scalarsObj[key], value: scalarsObj[key] })
if (scalarsObj1[key]) {
frontData.push({ field: key, type: typeof scalarsObj[key], value: scalarsObj[key], level: 1 })
} else {
endData.push({ field: key, type: typeof scalarsObj[key], value: scalarsObj[key] })
}
}
for (const key in tableObj) {
this.tokenList.push({ field: key, type: 'table', value: tableObj[key] })
if (tableObj1[key]) {
frontData.push({ field: key, type: 'table', value: tableObj[key], level: 1 })
} else {
endData.push({ field: key, type: 'table', value: tableObj[key] })
}
}
this.tableData = frontData.concat(endData)
}
this.loadingStatus = false
},
methods: {
calculateByte: base64 => calculateByte(base64),
async handleToTableDetail(name) {
const res = await getTable({ pages: 0, pagesize: 1, name: name })
if (res && res.data && res.data.code === 0) {
this.$router.push({ path: '/data/edit', query: { name: name, columns: res.data.data && res.data.data.tables.length && res.data.data.tables[0].columns } })
}
}
}
}
</script>
......@@ -121,4 +169,12 @@ export default {
::v-deep .cell
height: 28px
line-height: 28px!important
.cell-null
display: inline-block
height: 26px
line-height: 26px
padding: 0 10px
color: #fff
background: #ccc
border-radius: 4px
</style>
......@@ -9,7 +9,7 @@
<st-button type="primary" @click="$router.push({ path: '/params/add', query: { level: 1 } })">
<i class="iconfont icon-tianjia"></i><span class="text">{{'添加'}}</span></st-button>
<div class="search">
<input type="text" class="search-input" placeholder="请输入搜索内容" v-model="oneVal">
<input type="text" class="search-input" placeholder="请输入搜索内容" v-model="oneVal" @input="getOneData">
<i class="el-input__icon el-icon-search"></i>
</div>
</div>
......@@ -46,7 +46,7 @@
<st-button type="primary" @click="$router.push({ path: '/params/add', query: { level: 2 } })">
<i class="iconfont icon-tianjia"></i><span class="text">{{'添加'}}</span></st-button>
<div class="search">
<input type="text" class="search-input" placeholder="请输入搜索内容" v-model="twoVal">
<input type="text" class="search-input" placeholder="请输入搜索内容" v-model="twoVal" @input="getTwoData">
<i class="el-input__icon el-icon-search"></i>
</div>
</div>
......@@ -130,7 +130,7 @@ export default {
methods: {
async getOneData() {
this.loadingOne = true
const oneLevel = await getParameter({ base: 1, pages: this.oneCurrentPage - 1, pagesize: 10 })
const oneLevel = await getParameter({ base: 1, pages: this.oneCurrentPage - 1, pagesize: 10, name: this.oneVal })
if (oneLevel && oneLevel.data && oneLevel.data.code === 0) {
this.oneList = oneLevel.data.parameters.datas.map((item, index) => {
item.order = index + 1 + (this.oneCurrentPage - 1) * 10
......@@ -142,7 +142,7 @@ export default {
},
async getTwoData() {
this.loadingTwo = true
const twoLevel = await getParameter({ parent: this.parentLevel === '' ? 0 : this.parentLevel, pages: this.twoCurrentPage - 1, pagesize: 10 })
const twoLevel = await getParameter({ parent: this.parentLevel === '' ? 0 : this.parentLevel, pages: this.twoCurrentPage - 1, pagesize: 10, name: this.twoVal })
if (twoLevel && twoLevel.data && twoLevel.data.code === 0) {
this.twoList = twoLevel.data.parameters.datas.map((item, index) => {
item.order = index + 1 + (this.twoCurrentPage - 1) * 10
......@@ -194,6 +194,8 @@ export default {
height: calc(100% - 60px)
.list-content
height: 100%
::v-deep .current-row td:last-child
border-right: 4px solid #409EFF
.table-box
height: 100%
::v-deep.el-table
......
......@@ -11,17 +11,30 @@
<st-form-item
style="margin-bottom:10px"
:label="'头像'+':'">
<el-image style="width: 80px; height: 80px" :src="userData.image" fit="fit"></el-image>
<el-upload
ref="mask-images"
accept=".jpg,.jpeg,.png,.bmp"
:class="{disabled: imageList.length >= 1}"
action=""
:limit="1"
:file-list="imageList"
list-type="picture-card"
:on-change="handleChange"
:on-remove="handleRemove"
:auto-upload="false">
<i class="el-icon-plus" ></i>
<!-- <span v-if="!imageList.length" style="position: absolute;top: 30px;left: 46px">上传照片</span> -->
</el-upload>
</st-form-item>
<st-form-item
style="margin-bottom:10px"
:label="'账户'+':'">
<span>{{userData.role}}</span>
<span>{{userData.username}}</span>
</st-form-item>
<st-form-item
style="margin-bottom:10px"
:label="'姓名'+':'">
<span>{{userData.creater}}</span><span class="btn-text" @click="showDialog = true;type = 'name'">编辑</span>
<span>{{userData.nickname}}</span><span class="btn-text" @click="showDialog = true;type = 'name';form = JSON.parse(JSON.stringify(userData))">编辑</span>
</st-form-item>
<st-form-item
style="margin-bottom:10px"
......@@ -43,28 +56,25 @@
<div slot="header" class="popup-header">{{'编辑'}}</div>
<div slot="body" class="popup-body">
<st-form
:label-width="type === 'password' ? '90px' : ''"
ref="form">
<st-form-item v-if="type === 'email'"
:label="'邮箱:'">
<st-input v-model="email"></st-input>
:label-width="type === 'password' ? '100px' : ''"
ref="form"
:model="form"
:rules="rules">
<st-form-item v-if="type === 'email'" :label="'邮箱:'" prop="email">
<st-input v-model="form.email"></st-input>
</st-form-item>
<st-form-item v-if="type === 'name'"
:label="'姓名:'">
<st-input v-model="name"></st-input>
<st-form-item v-if="type === 'name'" :label="'姓名:'" prop="nickname">
<st-input v-model="form.nickname"></st-input>
</st-form-item>
<div v-if="type === 'password'">
<st-form-item
:label="'当前密码:'">
<st-input v-model="password"></st-input>
<st-form-item :label="'当前密码:'" prop="password">
<st-input v-model="form.password" type="password"></st-input>
</st-form-item>
<st-form-item
:label="'新密码:'">
<st-input v-model="newPwd"></st-input>
<st-form-item :label="'新密码:'" prop="newPwd">
<st-input v-model="form.newPwd" type="password"></st-input>
</st-form-item>
<st-form-item
:label="'新密码:'">
<st-input v-model="confirmPwd"></st-input>
<st-form-item :label="'确认新密码:'" prop="confirmPwd">
<st-input v-model="form.confirmPwd" type="password"></st-input>
</st-form-item>
</div>
</st-form>
......@@ -78,26 +88,139 @@
</template>
<script>
import { editUser } from '@/axios'
import { getUser } from '@/utils/user'
import browserStorage from '@/services/local-storage'
export default {
data() {
const validatePassword = (rule, value, callback) => {
if (value === '') {
callback(new Error('请输入密码'))
} else if (!(/^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)[a-zA-Z\d\-_]{8,64}$/.test(value))) {
callback(new Error('密码必须包含大小写字母和数字,大于8位且小于64位'))
} else {
callback()
}
}
const validatePasswordConfirmation = (rule, value, callback) => {
if (value === '') {
callback(new Error('请确认密码'))
} else if (value !== this.confirmPwd) {
callback(new Error('密码与确认密码不一致'))
} else {
callback()
}
}
return {
showDialog: false,
userData: {},
form: {},
imageList: [],
type: '',
email: '',
name: '',
password: '',
newPwd: '',
confirmPwd: ''
confirmPwd: '',
rules: {
nickname: [
{ required: true, message: '请输入姓名' }
],
email: [
{ required: true, message: '请输入邮箱' },
{ type: 'email', message: '邮箱格式不正确' },
],
password: [
{ required: true, message: '请输入密码' },
{ validator: validatePassword, message: '密码必须包含大小写字母和数字,大于8位且小于64位' },
],
newPwd: [
{ required: true, message: '请输入密码' },
{ validator: validatePassword, message: '密码必须包含大小写字母和数字,大于8位且小于64位' },
],
confirmPwd: [
{ required: true, message: '请确认密码' },
{ validator: validatePasswordConfirmation, trigger: 'blur', message: '密码与确认密码不一致' },
],
}
}
},
mounted() {
this.userData = getUser().info
this.userData.username = browserStorage.getItem('username')
this.userData.nickname = browserStorage.getItem('nickname')
this.imageList = [{ url: browserStorage.getItem('image') }]
this.userData.email = browserStorage.getItem('email')
},
methods: {
submit() {
this.$refs.form.validate(async valid => {
if (valid) {
let res = {}
switch (this.type) {
case 'name': res = await editUser({ username: browserStorage.getItem('username'), nickname: this.form.nickname })
if (res && res.data && res.data.code === 0) {
browserStorage.setItem('nickname', this.form.nickname)
this.userData.nickname = browserStorage.getItem('nickname')
Toast.success('操作成功')
}
break
case 'email': res = await editUser({ username: browserStorage.getItem('username'), email: this.form.email })
if (res && res.data && res.data.code === 0) {
browserStorage.setItem('email', this.form.email)
this.userData.email = browserStorage.getItem('email')
Toast.success('操作成功')
}
break
case 'password': res = await editUser({ username: browserStorage.getItem('username'), password: this.form.password, new_password: this.form.newPwd })
if (res && res.data && res.data.code === 0) {
Toast.success('操作成功')
}
break
default:
break
}
this.showDialog = false
}
})
},
fileToBase64(file) {
return new Promise((resolve, reject) => {
try {
const read = new FileReader()
read.onload = function(e) {
resolve(e.target.result)
}
read.readAsDataURL(file)
} catch (err) {
reject(err)
}
})
},
async handleChange(file, fileList) {
this.imageList = fileList
if (file.size > 64 * 1024) {
Toast.danger('图片大小不能超过64KB')
this.imageList = []
return
}
const base64 = await this.fileToBase64(file.raw)
const res = await editUser({ username: browserStorage.getItem('username'), image: base64 })
if (res && res.data && res.data.code === 0) {
browserStorage.setItem('image', base64)
this.imageList[0].url = base64
} else {
this.imageList = []
}
},
async handleRemove(file, fileList) {
this.imageList = []
const res = await editUser({ username: browserStorage.getItem('username'), image: '' })
if (res && res.data && res.data.code === 0) {
browserStorage.setItem('image', '')
} else {
this.imageList = [{ url: browserStorage.getItem('image') }]
}
},
cancelSubmit() {
this.showDialog = false
......@@ -107,6 +230,9 @@ export default {
</script>
<style lang="sass" scoped>
.disabled
::v-deep .el-upload--picture-card
display: none
.page-content
text-align: left
.btn-text
......
......@@ -3,8 +3,9 @@
<div class="header">
<span class="title">{{'设置中心'}}</span>
</div>
<div class="page-content">
</div>
<img src="@/assets/unresolved.png" alt="">
<!-- <div class="page-content">
</div> -->
</div>
</template>
......
......@@ -293,7 +293,11 @@ export default {
// TokenId
browserStorage.setItem('token', res.data.token)
browserStorage.setItem('user', JSON.stringify(res.data))
this.$router.push({ path: '/params' })
browserStorage.setItem('image', res.data.image)
browserStorage.setItem('email', res.data.email)
browserStorage.setItem('nickname', res.data.nickname)
browserStorage.setItem('username', this.userName)
this.$router.push({ path: '/overview' })
} else {
Toast.danger(res.data.msg)
}
......
<template>
<div class="data-list-common flex column main-content flex-1">
<div class="page-content">
<div class="apply">
<span style="margin-right: 30px">当前应用:<span v-if="applyInfo">{{applyInfo.appid}}</span></span>
<el-button type="primary" size="small" @click="$router.push({ name: 'apply' })">切换</el-button>
<div style="margin-left: 70px" v-if="applyInfo">{{applyInfo.description}}</div>
</div>
<div id="main"></div>
</div>
</div>
</template>
<script>
import { getApp, getAccount } from '@/axios'
import * as echarts from 'echarts'
export default {
data() {
return {
applyInfo: {},
devicesInfo: {},
myChart: null,
option: {}
}
},
mounted() {
const chartDom = document.getElementById('main')
this.myChart = echarts.init(chartDom)
this.getApply()
this.getAccount()
this.repint()
},
methods: {
async getApply() {
const res = await getApp({ pages: 0, pagesize: 100000000 })
if (res && res.data && res.data.code === 0) {
this.applyInfo = res.data.data.apps.filter(item => item.ismainapp === 1)[0]
}
},
repint() {
window.onresize = () => {
setTimeout(() => {
this.myChart.resize()
}, 10)
}
},
async getAccount() {
const res = await getAccount()
if (res && res.data && res.data.code === 0) {
this.devicesInfo = res.data
this.myChart.setOption({
tooltip: {
trigger: 'item'
},
series: [
{
name: '设备状态',
type: 'pie',
radius: ['40%', '70%'],
avoidLabelOverlap: true,
labelLine: {
show: true
},
data: [
{ value: res.data.onlines, name: '在线' },
{ value: res.data.offlines, name: '离线' },
{ value: res.data.exceptions, name: '异常' },
]
}
]
})
}
}
}
}
</script>
<style lang="sass" scoped>
.apply
text-align: left
.box
width: 100%
height: 100%
#main
width: 100%
height: 100%
display: flex
justify-content: center
</style>
Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!