Files
kh-device-client/src/views/systemOverview/systemSettings/SystemSettings.vue
T
2024-04-16 11:30:45 +08:00

570 lines
20 KiB
Vue

<template>
<a-spin :spinning="loading">
<a-row :gutter="20" type="flex" class="mb-20">
<a-col flex="556px">
<common-card title="系统设置">
<a-form :form="sysSettingForm" class="custom-vertical-form">
<div class="mb-20">
<a-form-item label="服务器IP">
<a-input placeholder="请输入服务器IP" :max-length="50"
@change="event => event.target.value = event.target.value.trim()"
v-decorator.trim="['serverIp', validatorRules.serverIp]"/>
</a-form-item>
<a-form-item label="服务器端口号">
<a-input placeholder="请输入服务器端口号" :max-length="50"
@change="event => event.target.value = event.target.value.trim()"
v-decorator.trim="['serverPort', validatorRules.serverPort]"/>
</a-form-item>
<a-form-item label="数据采集协议">
<j-dict-select-tag :triggerChange="true"
dictCode="data_acquisition_protocol"
v-decorator="['dataAcquisitionProtocol', validatorRules.dataAcquisitionProtocol]"
placeholder="请选择数据采集协议">
</j-dict-select-tag>
</a-form-item>
<a-form-item label="数据采集周期">
<j-dict-select-tag :triggerChange="true"
dictCode="data_acquisition_cycle"
v-decorator="['dataAcquisitionCycle', validatorRules.dataAcquisitionCycle]"
placeholder="请选择数据采集周期">
</j-dict-select-tag>
</a-form-item>
</div>
<div class="flex-center custom-btns-box">
<a-button type="primary" ghost @click="handleResetSysSettingForm" style="margin-right: 16px;">
<img :src="require('@assets/images/icon/refresh.png')" alt="恢复默认设置" class="btn-icon">
<span class="btn-text">恢复默认设置</span>
</a-button>
<a-button type="primary" @click="handleSaveSysSetting">
<img :src="require('@assets/images/icon/save.png')" alt="保存设置" class="btn-icon">
<span class="btn-text">保存设置</span>
</a-button>
</div>
</a-form>
</common-card>
</a-col>
<a-col flex="auto">
<common-card title="用户信息">
<a-table
ref="table"
size="middle"
bordered
rowKey="id"
:scroll="{x: true,y:286}"
:columns="userInfo.columns"
:dataSource="userInfo.dataSource"
:pagination="userInfo.ipagination"
@change="handleUserInfoTableChange($event, 'userInfo')">
<template slot="text" slot-scope="text">
<a-tooltip>
<template slot="title">{{ text || text === 0 ? text : global.emptyLine }}</template>
<div class="table-text">{{ text || text === 0 ? text : global.emptyLine }}</div>
</a-tooltip>
</template>
<template slot="userType" slot-scope="text, record">
<a-tooltip>
<template slot="title">{{ text || text === 0 ? text : global.emptyLine }}</template>
<div class="table-text"
:class="{
'tag-blue width-76': record.userType === userType.admin.value,
'tag-green width-76': record.userType === userType.common.value
}">{{ text || text === 0 ? text : global.emptyLine }}</div>
</a-tooltip>
</template>
<span slot="action" slot-scope="text, record, index" class="operation-btns">
<a class="primary" @click="handleEditUser(record, index)">编辑</a>
<a class="danger" @click="handleDeleteUser(record, index)">删除</a>
</span>
</a-table>
</common-card>
</a-col>
</a-row>
<a-row :gutter="20" type="flex">
<a-col flex="556px">
<common-card title="添加用户">
<a-form :form="addUserForm" class="custom-vertical-form">
<a-form-item style="margin-bottom: 0;">
<div class="upload-avatar-box">
<j-image-upload v-decorator="['avatar', validatorRules.avatar]"
class="upload-avatar"
:number="1"
uploadLimitHideBtn
accept='.png,.PNG,.jpg,.JPG'></j-image-upload>
</div>
</a-form-item>
<a-row type="flex" :gutter="20" class="mb-4">
<a-col :span="12">
<a-form-item label="用户名称">
<a-input placeholder="请输入用户名称" :max-length="50"
@change="event => event.target.value = event.target.value.trim()"
v-decorator="['username', validatorRules.username]"/>
</a-form-item>
</a-col>
<a-col :span="12">
<a-form-item label="用户类别">
<j-dict-select-tag :triggerChange="true"
dictCode="user_type"
v-decorator="['userType', validatorRules.userType]"
placeholder="请选择用户类别">
</j-dict-select-tag>
</a-form-item>
</a-col>
<a-col :span="12">
<a-form-model-item label="所属单位">
<j-select-depart
placeholder="请选择所属单位"
v-decorator="['selecteddeparts', validatorRules.selecteddeparts]"
:backDepart="true"
:treeOpera="true"></j-select-depart>
</a-form-model-item>
</a-col>
<a-col :span="12">
<a-form-model-item label="联系方式">
<a-input placeholder="请输入联系方式"
v-decorator="['phone', validatorRules.phone]" />
</a-form-model-item>
</a-col>
</a-row>
<div class="flex-center custom-btns-box">
<a-button type="primary" @click="handleAddUser">
<img :src="require('@assets/images/icon/add.png')" alt="添加" class="btn-icon">
<span class="btn-text">添加</span>
</a-button>
</div>
</a-form>
</common-card>
</a-col>
<a-col flex="auto">
<common-card title="通讯日志">
<a-table
ref="table"
size="middle"
bordered
rowKey="id"
:scroll="{x: true,y:286}"
:columns="communicationLog.columns"
:dataSource="communicationLog.dataSource"
:pagination="communicationLog.ipagination"
@change="handleCommunicationLogTableChange">
<template slot="text" slot-scope="text">
<a-tooltip>
<template slot="title">{{ text || text === 0 ? text : global.emptyLine }}</template>
<div class="table-text">{{ text || text === 0 ? text : global.emptyLine }}</div>
</a-tooltip>
</template>
<!-- 消息类型 -->
<template slot="msgType" slot-scope="text">
<a-tooltip>
<template slot="title">{{ text || text === 0 ? text : global.emptyLine }}</template>
<div class="table-text"
:class="{
'tag-blue width-118': text === msgType.hostToDevice.label,
'tag-green width-118': text === msgType.deviceToHost.label
}">{{ text || text === 0 ? text : global.emptyLine }}</div>
</a-tooltip>
</template>
</a-table>
</common-card>
</a-col>
</a-row>
<!-- 用户信息编辑 -->
<user-info-modal ref="userInfoModal" @ok="loadUserList"/>
</a-spin>
</template>
<script>
import CommonCard from '@comp/CommonCard'
import { addUserInfo, delUserInfo, getSysSetting, getUserPage, saveSysSetting } from '@api/systemOverview'
import { dataAcquisitionCycle, dataAcquisitionProtocol, msgType, userType } from '@/enums/commonEnums'
import { getRSAPublicKey } from '@/utils/encryption'
import { JSEncrypt } from 'jsencrypt'
import UserInfoModal from '@views/systemOverview/systemSettings/modules/UserInfoModal'
export default {
name: 'SystemSettings',
components: { UserInfoModal, CommonCard },
data () {
return {
userType,
msgType,
loading: false,
// 系统设置表单
sysSettingForm: this.$form.createForm(this),
// 添加用户表单
addUserForm: this.$form.createForm(this),
// 默认值
sysSettingFormDefault: {
id: 'default',
serverIp: '11.13.105.96',
serverPort: '1502',
dataAcquisitionProtocol: dataAcquisitionProtocol.modbusRtu.value,
dataAcquisitionCycle: dataAcquisitionCycle.tenSeconds.value
},
// 后端保存的值
sysSettingFormData: {},
// 表单校验
validatorRules: {
serverIp: { rules: [{ required: true, message: '请输入服务器IP' }], validateTrigger: 'blur' },
serverPort: { rules: [{ required: true, message: '请选择服务器端口号' }], validateTrigger: 'blur' },
dataAcquisitionProtocol: { rules: [{ required: true, message: '请选择数据采集协议' }], validateTrigger: 'change' },
dataAcquisitionCycle: { rules: [{ required: true, message: '请输入数据采集周期' }], validateTrigger: 'change' },
username: { rules: [{ required: true, message: '请输入用户名称' }], validateTrigger: 'blur' },
userType: { rules: [{ required: true, message: '请选择用户类别' }], validateTrigger: 'change' },
selecteddeparts: { rules: [{ required: true, message: '请选择所属单位' }], validateTrigger: 'change' },
phone: { rules: [{ required: true, message: '请输入联系方式' }, { validator: this.validateMobile }], validateTrigger: 'blur' }
},
// 用户信息相关
userInfo: {
columns: [
{
dataIndex: 'username',
title: '用户名',
align: 'center',
width: '20%',
scopedSlots: { customRender: 'text' }
},
{
dataIndex: 'phone',
title: '联系方式',
align: 'center',
width: '20%',
scopedSlots: { customRender: 'text' }
},
{
dataIndex: 'userType_dictText',
title: '用户类别',
align: 'center',
width: '20%',
scopedSlots: { customRender: 'userType' }
},
{
dataIndex: 'orgCodeTxt',
title: '所属单位',
align: 'center',
width: '20%',
scopedSlots: { customRender: 'text' }
},
{
title: '用户管理',
dataIndex: 'action',
scopedSlots: { customRender: 'action' },
align: 'center',
width: '20%'
}
],
dataSource: [],
/* 分页参数 */
ipagination: {
current: 1,
pageSize: 10,
pageSizeOptions: ['10', '20', '30'],
showTotal: (total, range) => {
return '共' + total + '条'
},
showQuickJumper: true,
showSizeChanger: true,
total: 0
},
/* 排序参数 */
isorter: {
column: 'createTime',
order: 'desc'
}
},
// 通讯日志相关
communicationLog: {
columns: [
{
dataIndex: 'time',
title: '时间',
align: 'center',
width: '30%',
scopedSlots: { customRender: 'text' }
},
{
dataIndex: 'msgType',
title: '消息类型',
align: 'center',
width: '30%',
scopedSlots: { customRender: 'msgType' }
},
{
dataIndex: 'msgContent',
title: '消息内容',
align: 'center',
width: '40%',
scopedSlots: { customRender: 'text' }
}
],
dataSource: [
{
id: '1',
time: '2024-3-15 13:55:26',
msgType: 'Host-》Device',
msgContent: '01 03 00 00 00 05 89 C5'
},
{
id: '2',
time: '2024-3-15 13:55:26',
msgType: 'Device-》Host',
msgContent: '01 03 00 00 00 05 89 C5'
},
{
id: '3',
time: '2024-3-15 13:55:26',
msgType: 'Host-》Device',
msgContent: '01 03 00 00 00 05 89 C5'
},
{
id: '4',
time: '2024-3-15 13:55:26',
msgType: 'Device-》Host',
msgContent: '01 03 00 00 00 05 89 C5'
},
{
id: '5',
time: '2024-3-15 13:55:26',
msgType: 'Host-》Device',
msgContent: '01 03 00 00 00 05 89 C5'
},
{
id: '6',
time: '2024-3-15 13:55:26',
msgType: 'Device-》Host',
msgContent: '01 03 00 00 00 05 89 C5'
},
{
id: '7',
time: '2024-3-15 13:55:26',
msgType: 'Host-》Device',
msgContent: '01 03 00 00 00 05 89 C5'
},
{
id: '8',
time: '2024-3-15 13:55:26',
msgType: 'Device-》Host',
msgContent: '01 03 00 00 00 05 89 C5'
}
],
/* 分页参数 */
ipagination: {
current: 1,
pageSize: 10,
pageSizeOptions: ['1', '10', '20', '30'],
showTotal: (total, range) => {
return '共' + total + '条'
},
showQuickJumper: true,
showSizeChanger: true,
total: 0
},
/* 排序参数 */
isorter: {
column: 'createTime',
order: 'desc'
}
},
// 公钥
rsaPublicKey: '',
// 默认用户信息(调用系统加用户接口,默认密码123456)
defaultUserInfo: {
password: '123456',
confirmpassword: '123456',
userIdentity: '1'
}
}
},
created () {
this.loadPage()
},
methods: {
// 恢复默认配置
handleResetSysSettingForm () {
this.sysSettingForm.resetFields()
this.sysSettingForm.setFieldsValue(this.sysSettingFormDefault)
// 回显表单上之后,保存到后端
this.$nextTick(() => {
this.handleSaveSysSetting()
})
},
loadPage () {
this.loadSysSetting()
this.loadUserList()
},
// 获取默认配置
loadSysSetting () {
getSysSetting({ id: this.sysSettingFormDefault.id }).then(res => {
if (res.success) {
const data = res.result || {}
this.sysSettingFormData = data
this.sysSettingForm.setFieldsValue(data)
}
})
},
// 保存设置
handleSaveSysSetting () {
this.sysSettingForm.validateFields((err, values) => {
if (!err) {
const formData = Object.assign({}, values)
// 后端只保存一条数据id固定
formData.id = this.sysSettingFormDefault.id
saveSysSetting(formData).then((res) => {
if (res.success) {
this.$message.success(res.message)
} else {
this.$message.warning(res.message)
}
}).finally(() => {
})
}
})
},
// 加载用户信息
loadUserList (arg) {
// 加载数据 若传入参数1则加载第一页的内容
if (arg === 1) {
this.userInfo.ipagination.current = 1
}
this.userInfo.loading = true
const params = {
pageNo: this.userInfo.ipagination.current,
pageSize: this.userInfo.ipagination.pageSize,
...this.userInfo.isorter
}
getUserPage(params).then((res) => {
if (res.success) {
// update-begin---author:zhangyafei Date:20201118 for:适配不分页的数据列表------------
this.userInfo.dataSource = res.result.records || res.result
if (res.result.total) {
this.userInfo.ipagination.total = res.result.total
} else {
this.userInfo.ipagination.total = 0
}
// update-end---author:zhangyafei Date:20201118 for:适配不分页的数据列表------------
} else {
this.$message.warning(res.message)
}
}).finally(() => {
this.userInfo.loading = false
})
},
handleUserInfoTableChange (pagination) {
this.userInfo.ipagination = pagination
this.loadUserList()
},
handleCommunicationLogTableChange (pagination) {
this.communicationLog.ipagination = pagination
},
// 添加用户
async handleAddUser () {
// 获取公钥
await getRSAPublicKey().then(res => {
this.rsaPublicKey = res.result
})
// 校验表单
this.addUserForm.validateFields((err, values) => {
if (!err) {
const formData = Object.assign({}, this.defaultUserInfo, values)
formData.rsaPublicKey = this.rsaPublicKey
// 对密码、手机号进行加密
const encrypt = new JSEncrypt()
encrypt.setPublicKey(this.rsaPublicKey)
if (formData.password) {
formData.password = encrypt.encrypt(formData.password)
}
if (formData.phone) {
formData.phone = encrypt.encrypt(formData.phone)
}
addUserInfo(formData).then((res) => {
if (res.success) {
this.$message.success(res.message)
} else {
this.$message.warning(res.message)
}
}).finally(() => {
this.loadUserList()
})
}
})
},
// 校验手机号
validateMobile (rule, value, callback) {
if (!value || new RegExp(/^1([38][0-9]|4[579]|5[0-3,5-9]|6[6]|7[0135678]|9[89])\d{8}$/).test(value)) {
callback()
} else {
callback(new Error('您的手机号码格式不正确'))
}
},
// 编辑用户
handleEditUser (record) {
// this.$refs.userInfoModal.edit(record)
},
// 删除用户
handleDeleteUser (record) {
const { id } = record
this.$confirm({
title: '确认删除',
content: '确定要删除此条数据吗?',
onOk: () => {
delUserInfo({ id }).then((res) => {
if (res.success) {
this.$message.success(res.message)
// 判断当前删除的数据是否是最后一页的最后一条数据,如果是的话页码减一
if (this.userInfo.ipagination.current > 1 && ((this.userInfo.ipagination.current - 1) * this.userInfo.ipagination.pageSize) + 1 === this.userInfo.ipagination.total) {
this.userInfo.ipagination.current -= 1
}
this.loadData()
} else {
this.$message.warning(res.message)
}
}).finally(() => {
this.loadUserList()
})
}
})
}
}
}
</script>
<style lang="less" scoped>
.upload-avatar-box {
position: relative;
width: calc(100% + 40px);
height: 168px;
background: url("~@/assets/images/systemOverview/systemSettings/upload-avatar.png") no-repeat center center;
background-size: 124px 124px;
.upload-avatar {
width: 120px;
height: 120px;
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
// 隐藏上传组件
/deep/.ant-upload-select {
opacity: 0;
}
/deep/.ant-upload-list-picture-card .ant-upload-list-item {
border: none;
width: 120px;
height: 120px;
padding: 1px;
}
/deep/.ant-upload-list-picture .ant-upload-list-item-thumbnail,
/deep/.ant-upload-list-picture-card .ant-upload-list-item-thumbnail {
opacity: 1;
}
}
}
.width-118 {
width: 118px;
}
.width-76 {
width: 76px;
}
</style>