| New file |
| | |
| | | <template> |
| | | <div class="s-authority-management"> |
| | | <div class="authority-table s-table" v-if="display"> |
| | | <el-table |
| | | highlight-current-row |
| | | :data="userList" |
| | | style="width: 100%" |
| | | :header-cell-style="{background:'#f8f8f8',color:'#222222'}" |
| | | > |
| | | <el-table-column align="center" type="index" label="序号" width="100"></el-table-column> |
| | | <el-table-column :align="'center'" prop="username" label="用户名"></el-table-column> |
| | | <el-table-column :align="'center'" prop="role" label="角色"> |
| | | <template slot-scope="scope">{{scope.row.sysRoles | roles}}</template> |
| | | </el-table-column> |
| | | <el-table-column label="操作" :align="'center'"> |
| | | <template slot-scope="scope"> |
| | | <el-tooltip content="编辑" placement="top" popper-class="atooltip"> |
| | | <i |
| | | class="el-icon-edit" |
| | | style="font-size: 18px;" |
| | | @click="handleEdit(scope.$index, scope.row)" |
| | | ></i> |
| | | </el-tooltip> |
| | | <el-tooltip content="删除" placement="top" popper-class="atooltip" v-show="false"> |
| | | <!-- :disabled="scope.row.sysRoles | roles | isSuper" --> |
| | | <i |
| | | class="el-icon-delete" |
| | | style="font-size: 18px; color:red;" |
| | | @click="handleDelete(scope.$index, scope.row)" |
| | | ></i> |
| | | </el-tooltip> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | | </div> |
| | | <div class="authority-details" v-if="!display"> |
| | | <el-form label-width="80px" :rules="rules" ref="editForm" :model="editForm"> |
| | | <el-form-item label="用户名" style="width:580px" prop="username"> |
| | | <!-- <el-input v-model="editForm.username" placeholder="请输入" size="small"></el-input> --> |
| | | <span class="m10" v-if="editForm.username == 'admin' || editForm.username == 'basic'">{{editForm.username}}</span> |
| | | <el-input v-model="editForm.username" size="small" v-else></el-input> |
| | | </el-form-item> |
| | | |
| | | <el-form-item label="新密码" style="width:580px" v-show="loginUser != editForm.username"> |
| | | <el-input show-password v-model="editForm.newPwd" placeholder="请输入密码" size="small"></el-input> |
| | | </el-form-item> |
| | | |
| | | <el-form-item |
| | | label="确认密码" |
| | | style="width:580px" |
| | | prop="checkPass" |
| | | v-show="loginUser != editForm.username" |
| | | > |
| | | <el-input show-password v-model="editForm.checkPass" placeholder="请输入再次输入密码" size="small"></el-input> |
| | | </el-form-item> |
| | | |
| | | <el-form-item label="权限配置" style="width:580px;"> |
| | | <!-- <el-transfer |
| | | id="e-transfer" |
| | | :titles="['全部角色', '当前角色']" |
| | | v-model="editForm.roleIds" |
| | | :props="{key: 'id', label: 'name'}" |
| | | :data="roledata" |
| | | ></el-transfer>--> |
| | | |
| | | <el-tree |
| | | ref="treeMenus" |
| | | :data="sysMenus" |
| | | :props="props" |
| | | node-key="id" |
| | | :default-checked-keys="userMenus" |
| | | show-checkbox |
| | | check-on-click-node |
| | | default-expand-all |
| | | style="margin-top: 10px;" |
| | | ></el-tree> |
| | | </el-form-item> |
| | | |
| | | <el-form-item style="width:580px;"> |
| | | <el-button type="primary" style="float: right" @click="save" size="small">保存</el-button> |
| | | <el-button type="info" style="margin-right: 10px;float: right" @click="goback" size="small">返回</el-button> |
| | | </el-form-item> |
| | | </el-form> |
| | | </div> |
| | | </div> |
| | | </template> |
| | | |
| | | <script> |
| | | |
| | | import { getUsers, getSysMenus, updataUser, getUserMenus } from "@/api/user" |
| | | |
| | | export default { |
| | | name: "AuthorityManage", |
| | | filters: { |
| | | roles(roles) { |
| | | return roles.map(r => { |
| | | return r.name |
| | | }).join(' ') |
| | | }, |
| | | isSuper(roles) { |
| | | return roles.indexOf("超级管理员") >= 0 |
| | | } |
| | | }, |
| | | data() { |
| | | const generateData = _ => { |
| | | const data = []; |
| | | for (let i = 1; i <= 15; i++) { |
| | | data.push({ |
| | | key: i, |
| | | label: `备选项 ${i}`, |
| | | disabled: i % 4 === 0 |
| | | }); |
| | | } |
| | | return data; |
| | | }; |
| | | const validateCheckPass = (rule, value, callback) => { |
| | | if (value !== this.editForm.newPwd) { |
| | | callback(new Error('两次输入密码不一致!')); |
| | | } else { |
| | | callback() |
| | | } |
| | | }; |
| | | var checkUserName = (rule, value, callback) => { |
| | | if (value && value !== ''){ |
| | | let regEn = /^[A-Za-z_@.]{2,10}$/ |
| | | console.log("用户名校验!",value) |
| | | if (!regEn.test(value)) { |
| | | callback(new Error('请输入2位到10位字母的用户名,不能以数字开头,且不能包含汉字')) |
| | | } else { |
| | | callback() |
| | | } |
| | | } else { |
| | | callback() |
| | | } |
| | | } |
| | | return { |
| | | display: true, |
| | | loginUser: JSON.parse(sessionStorage.getItem('userInfo')).username, |
| | | acknewpwd: "", |
| | | sysMenus: [], |
| | | userMenus: [], |
| | | rolevalue: [], |
| | | userList: [], |
| | | editForm: {}, |
| | | props: { |
| | | label: 'name' |
| | | }, |
| | | rules: { |
| | | username: [ |
| | | { validator: checkUserName, trigger: 'blur' } |
| | | ], |
| | | checkPass: [ |
| | | { validator: validateCheckPass, trigger: 'change' } |
| | | ] |
| | | } |
| | | }; |
| | | }, |
| | | mounted() { |
| | | this.fetchUserList(); |
| | | this.fetchSysMenus(); |
| | | this.initEditForm(); |
| | | }, |
| | | methods: { |
| | | initEditForm() { |
| | | this.editForm = { |
| | | id: "", |
| | | username: "", |
| | | newPwd: "", |
| | | checkPass: "", |
| | | menuIds: [] |
| | | } |
| | | }, |
| | | handleEdit(index, row) { |
| | | this.initEditForm() |
| | | this.display = !this.display; |
| | | this.editForm.id = row.id; |
| | | this.editForm.username = row.username; |
| | | this.userMenus = [] |
| | | getUserMenus({ userId: row.id }).then(rsp => { |
| | | if (rsp && rsp.success) { |
| | | this.userMenus = rsp.data.menus.map(menu => { |
| | | return menu.id |
| | | }) |
| | | } |
| | | }) |
| | | |
| | | }, |
| | | handleDelete(index, row) { |
| | | this.$notify({ |
| | | type: "warning", |
| | | message: "无法删除该用户" |
| | | }) |
| | | }, |
| | | goback() { |
| | | this.display = !this.display; |
| | | }, |
| | | save() { |
| | | this.$refs.editForm.validate((valid) => { |
| | | if (valid) { |
| | | this.editForm.menuIds = this.$refs.treeMenus.getCheckedKeys() |
| | | updataUser(this.editForm).then(rsp => { |
| | | if (rsp && rsp.success) { |
| | | this.$notify({ |
| | | type: "success", |
| | | message: "修改成功" |
| | | }) |
| | | } |
| | | }) |
| | | } |
| | | }); |
| | | }, |
| | | fetchUserList() { |
| | | getUsers().then(rsp => { |
| | | if (rsp && rsp.success) { |
| | | this.userList = rsp.data; |
| | | } |
| | | }) |
| | | }, |
| | | fetchSysMenus() { |
| | | getSysMenus().then(rsp => { |
| | | if (rsp && rsp.success) { |
| | | this.sysMenus = rsp.data; |
| | | } |
| | | }) |
| | | } |
| | | } |
| | | }; |
| | | </script> |
| | | <style lang="scss"> |
| | | .s-authority-management { |
| | | height: 100%; |
| | | width: 100%; |
| | | .authority-table, |
| | | .authority-details { |
| | | height: 100%; |
| | | width: 100%; |
| | | margin-top: 40px; |
| | | } |
| | | #e-transfer { |
| | | .el-button--primary { |
| | | color: #fff; |
| | | background-color: #bfbfbf; |
| | | border-color: #bfbfbf; |
| | | } |
| | | .el-button--primary:focus, |
| | | .el-button--primary:hover { |
| | | background: #4c4c4c; |
| | | border-color: #4c4c4c; |
| | | color: #fff; |
| | | } |
| | | .el-transfer-panel |
| | | .el-transfer-panel__header |
| | | .el-checkbox |
| | | .el-checkbox__label { |
| | | font-size: 14px; |
| | | } |
| | | } |
| | | .el-form-item__content { |
| | | text-align: left; |
| | | input { |
| | | max-width: 498px; |
| | | } |
| | | } |
| | | } |
| | | </style> |
| New file |
| | |
| | | <template> |
| | | <div class="s-basic-setting"> |
| | | <el-tabs |
| | | id="e-basic-setting" |
| | | v-model="activeName" |
| | | v-loading="loading" |
| | | :element-loading-text="loadingText" |
| | | type="border-card" |
| | | > |
| | | <!-- 本机信息 --> |
| | | <el-tab-pane |
| | | label="本机信息" |
| | | name="sysInfo" |
| | | v-if="isShow('settings:sysInfo')" |
| | | > |
| | | <el-menu |
| | | :default-openeds="openeds" |
| | | background-color="#fff" |
| | | text-color="#303133" |
| | | active-text-color="#409EFF" |
| | | style="height: 100%" |
| | | class="menu-css" |
| | | @open="menuOpen" |
| | | @close="menuClose" |
| | | > |
| | | <!-- 本机信息 --> |
| | | <el-submenu index="0"> |
| | | <template slot="title"> |
| | | <b class="tree-font">本机信息</b> |
| | | </template> |
| | | <el-menu-item-group class="item-group"> |
| | | <el-form |
| | | :model="sysinfo" |
| | | :rules="rules" |
| | | ref="sysinfo" |
| | | label-width="100px" |
| | | > |
| | | <el-row> |
| | | <el-col :span="12"> |
| | | <el-form-item label="名称" prop="server_name"> |
| | | <el-input |
| | | v-model="sysinfo.server_name" |
| | | placeholder="服务器名称" |
| | | size="small" |
| | | ></el-input> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="端口" prop="server_port"> |
| | | <el-input |
| | | v-model="sysinfo.server_port" |
| | | placeholder="WEB服务端口" |
| | | size="small" |
| | | ></el-input> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | |
| | | <el-row> |
| | | <el-col :span="12"> |
| | | <el-form-item label="IP" prop="ip"> |
| | | <ip-input |
| | | :ip="sysinfo.ip" |
| | | @on-blur="sysinfo.ip = arguments[0]" |
| | | ></ip-input> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="子网掩码" prop="subMask"> |
| | | <ip-input |
| | | :ip="sysinfo.subMask" |
| | | @on-blur="sysinfo.subMask = arguments[0]" |
| | | ></ip-input> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | |
| | | <el-row> |
| | | <el-col :span="12"> |
| | | <el-form-item label="网关" prop="gateway"> |
| | | <ip-input |
| | | :ip="sysinfo.gateway" |
| | | @on-blur="sysinfo.gateway = arguments[0]" |
| | | ></ip-input> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="DNS" prop="dns"> |
| | | <ip-input |
| | | :ip="sysinfo.dns" |
| | | @on-blur="sysinfo.dns = arguments[0]" |
| | | ></ip-input> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <div class="mt15 mb10 save-btn"> |
| | | <el-button type="primary" @click="submitSysinfo" size="small" |
| | | >保存</el-button |
| | | > |
| | | </div> |
| | | </el-form> |
| | | </el-menu-item-group> |
| | | </el-submenu> |
| | | |
| | | <el-submenu index="1"> |
| | | <template slot="title"> |
| | | <b class="tree-font">详细信息</b> |
| | | </template> |
| | | <el-menu-item-group class="item-group desc-info"> |
| | | <el-row :gutter="gutter"> |
| | | <el-col :span="12" class="flex-box"> |
| | | <div class="xiangqin-label">设备ID</div> |
| | | <div class="xiangqing-info">{{ sysinfo.server_id }}</div> |
| | | </el-col> |
| | | <!-- <el-col :span="12" class="flex-box"> |
| | | <div class="xiangqin-label">设备编号</div> |
| | | <div class="xiangqing-info">{{sysinfo.deviceNum}}</div> |
| | | </el-col>--> |
| | | <el-col :span="12" class="flex-box"> |
| | | <div class="xiangqin-label">设备型号</div> |
| | | <div class="xiangqing-info">{{ sysinfo.deviceModel }}</div> |
| | | </el-col> |
| | | <el-col :span="12" class="flex-box"> |
| | | <div class="xiangqin-label">设备类型</div> |
| | | <div class="xiangqing-info">{{ sysinfo.deviceDesc }}</div> |
| | | </el-col> |
| | | <el-col :span="12" class="flex-box"> |
| | | <div class="xiangqin-label">通道个数</div> |
| | | <div class="xiangqing-info">{{ sysinfo.channelCount }}</div> |
| | | </el-col> |
| | | <el-col :span="12" class="flex-box"> |
| | | <div class="xiangqin-label">主控版本</div> |
| | | <div class="xiangqing-info">{{ sysinfo.masterVersion }}</div> |
| | | </el-col> |
| | | <el-col :span="12" class="flex-box"> |
| | | <div class="xiangqin-label">web版本</div> |
| | | <div class="xiangqing-info">{{ sysinfo.webVersion }}</div> |
| | | </el-col> |
| | | <el-col :span="12" class="flex-box"> |
| | | <div class="xiangqin-label">硬盘信息</div> |
| | | <div class="xiangqing-info">{{ sysinfo.disks }}</div> |
| | | </el-col> |
| | | <el-col :span="12" class="flex-box"> |
| | | <div class="xiangqin-label">CPU</div> |
| | | <div class="xiangqing-info">{{ sysinfo.cpuInfo }}</div> |
| | | </el-col> |
| | | <el-col :span="12" class="flex-box"> |
| | | <div class="xiangqin-label">内存</div> |
| | | <div class="xiangqing-info">{{ sysinfo.mem }}</div> |
| | | </el-col> |
| | | <el-col :span="12" class="flex-box"> |
| | | <div class="xiangqin-label">运行时间</div> |
| | | <div class="xiangqing-info">{{ sysinfo.uptime }}</div> |
| | | </el-col> |
| | | </el-row> |
| | | </el-menu-item-group> |
| | | </el-submenu> |
| | | <!-- 事件录像时长 --> |
| | | <el-submenu index="2"> |
| | | <template slot="title"> |
| | | <b class="tree-font">事件录像时长</b> |
| | | </template> |
| | | <el-menu-item-group class="item-group"> |
| | | <el-form |
| | | label-width="150px" |
| | | class="alarmSetting" |
| | | style="padding-left: 5px; padding-right: 5px" |
| | | > |
| | | <el-form-item label="视频截取最短时长" style="width: 724px"> |
| | | <el-slider |
| | | id="cut_min_duration" |
| | | @input="min_len = min_video_len" |
| | | v-model="fakeObj.min" |
| | | :min="5 / 1.2" |
| | | :max="100" |
| | | :step="5 / 1.2" |
| | | show-stops |
| | | :show-tooltip="true" |
| | | :format-tooltip="formatTooltip" |
| | | ></el-slider> |
| | | <el-input-number |
| | | v-model="min_len" |
| | | @change="fakeObj.min = +(min_len / 1.2)" |
| | | controls-position="right" |
| | | :min="5" |
| | | :max="120" |
| | | size="small" |
| | | ></el-input-number |
| | | > s |
| | | </el-form-item> |
| | | <el-form-item label="视频截取最长时长" style="width: 724px"> |
| | | <el-slider |
| | | id="cut_max_duration" |
| | | v-model="fakeObj.max" |
| | | :min="5 / 1.2" |
| | | @input="max_len = max_video_len" |
| | | :max="100" |
| | | :step="5 / 1.2" |
| | | show-stops |
| | | :format-tooltip="formatTooltip" |
| | | :show-tooltip="true" |
| | | ></el-slider> |
| | | <el-input-number |
| | | v-model="max_len" |
| | | @change="fakeObj.max = +(max_len / 1.2)" |
| | | controls-position="right" |
| | | :min="5" |
| | | :max="120" |
| | | size="small" |
| | | ></el-input-number |
| | | > s |
| | | </el-form-item> |
| | | <div class="mt15 mb10 save-btn"> |
| | | <el-button type="primary" @click="submitAlarm" size="small" |
| | | >保存</el-button |
| | | > |
| | | </div> |
| | | </el-form> |
| | | </el-menu-item-group> |
| | | </el-submenu> |
| | | <!-- 对外服务IP 改名为外部网络(新tab)--> |
| | | </el-menu> |
| | | </el-tab-pane> |
| | | |
| | | <!-- 时间配置 --> |
| | | <el-tab-pane |
| | | label="时间配置" |
| | | name="timeSet" |
| | | v-if="isShow('settings:timeSet')" |
| | | > |
| | | <el-form label-width="100px"> |
| | | <el-form-item label="设备时间"> |
| | | {{ equipmentTime }} |
| | | </el-form-item> |
| | | <div style="text-align: left; padding: 10px 0px"> |
| | | <div class="time-type">NTP校时</div> |
| | | <div style="padding: 10px 0px"> |
| | | <el-radio v-model="syncType" label="1">NTP校时</el-radio> |
| | | </div> |
| | | </div> |
| | | |
| | | <el-form-item label="服务器地址"> |
| | | <ip-input |
| | | :ip="ntpServer" |
| | | @on-blur="ntpServer = arguments[0]" |
| | | :disabled="syncType === '2'" |
| | | ></ip-input> |
| | | </el-form-item> |
| | | |
| | | <el-form-item label="校时时间间隔" style="width: 41.3%"> |
| | | <el-input-number |
| | | v-model.number="timeInterval" |
| | | :min="1" |
| | | :max="60" |
| | | placeholder="请输入" |
| | | size="small" |
| | | :controls="false" |
| | | :disabled="syncType === '2'" |
| | | ></el-input-number |
| | | > 分钟 |
| | | <el-button |
| | | type="text" |
| | | style="position: absolute; left: 330px" |
| | | :disabled="syncType === '2'" |
| | | @click="testNTP" |
| | | :loading="ntpTestLoading" |
| | | >测试</el-button |
| | | > |
| | | </el-form-item> |
| | | |
| | | <div style="text-align: left; padding: 10px 0px"> |
| | | <div class="time-type">手动校时</div> |
| | | <div style="padding: 10px 0px"> |
| | | <el-radio v-model="syncType" label="2">手动校时</el-radio> |
| | | </div> |
| | | </div> |
| | | |
| | | <el-form-item label="设置时间"> |
| | | <el-date-picker |
| | | v-model="settime" |
| | | type="datetime" |
| | | placeholder="选择日期时间" |
| | | size="small" |
| | | value-format="yyyy-MM-dd HH:mm:ss" |
| | | :disabled="syncType === '1'" |
| | | ></el-date-picker> |
| | | <el-checkbox |
| | | v-model="settimeRadio" |
| | | style="margin-left: 12px" |
| | | @change="syncBrowser" |
| | | :disabled="syncType === '1'" |
| | | >同步本计算机时间</el-checkbox |
| | | > |
| | | </el-form-item> |
| | | |
| | | <el-col :span="12" style="padding-right: 40px"> |
| | | <el-form-item> |
| | | <el-button type="primary" @click="submitClock" size="small" |
| | | >保存</el-button |
| | | > |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-form> |
| | | </el-tab-pane> |
| | | |
| | | <!-- 集群管理 --> |
| | | <el-tab-pane |
| | | label="集群管理" |
| | | name="cluster" |
| | | v-if="isShow('settings:cluster')" |
| | | > |
| | | <cluster-management></cluster-management> |
| | | </el-tab-pane> |
| | | <!-- <el-tab-pane label="外部访问" name="fourth"> |
| | | <el-menu |
| | | :default-openeds="openeds" |
| | | background-color="#fff" |
| | | text-color="#303133" |
| | | active-text-color="#409EFF" |
| | | style="height: 100%;" |
| | | class="menu-css" |
| | | @open="menuOpen" |
| | | @close="menuClose" |
| | | > |
| | | <el-submenu index="0"> |
| | | <template slot="title"> |
| | | <b class="tree-font">外部访问设置</b> |
| | | </template> |
| | | <el-menu-item-group class="item-group"> |
| | | <el-form :model="sysinfo" :rules="rules" ref="sysinfo" label-width="100px"> |
| | | <div class="flex-box"> |
| | | <label>设置外部IP</label> |
| | | <div style="width:300px;"> |
| | | <ip-input :ip="ipServer.ip" @on-blur="ipServer.ip = arguments[0]"></ip-input> |
| | | </div> |
| | | <el-checkbox label="选用本机IP" size="small" style="margin-left: 20px"></el-checkbox> |
| | | </div> |
| | | <div class="flex-box"> |
| | | <label>域名</label> |
| | | <el-input size="small" v-model="ipServer.localhost"></el-input> |
| | | </div> |
| | | <div class="flex-box"> |
| | | <label>本地文件端口</label> |
| | | <el-input size="small" v-model="ipServer.localFilePort"></el-input> |
| | | </div> |
| | | <div class="mt15 mb10 save-btn"> |
| | | <el-button type="primary" @click="submitSysinfo" size="small">保存</el-button> |
| | | </div> |
| | | </el-form> |
| | | </el-menu-item-group> |
| | | </el-submenu> |
| | | </el-menu> |
| | | </el-tab-pane>--> |
| | | <el-tab-pane |
| | | label="权限管理" |
| | | name="permission" |
| | | v-if="isShow('settings:permission')" |
| | | > |
| | | <authority-management |
| | | v-if="activeName === 'permission'" |
| | | ></authority-management> |
| | | </el-tab-pane> |
| | | <el-tab-pane |
| | | label="广播设置" |
| | | name="broadcast" |
| | | v-if="isShow('settings:broadcast')" |
| | | > |
| | | <radio-set v-if="activeName === 'broadcast'"></radio-set> |
| | | </el-tab-pane> |
| | | </el-tabs> |
| | | </div> |
| | | </template> |
| | | |
| | | <script> |
| | | import { |
| | | getDevInfo, |
| | | getAlarmConfig, |
| | | saveDevInfo, |
| | | saveAlarmConfig, |
| | | getClockInfo, |
| | | saveClockInfo, |
| | | testNTPserver, |
| | | getResourceConfig, |
| | | saveResourceConfig, |
| | | } from "@/api/system"; |
| | | |
| | | import { isPort, isIPv4 } from "@/scripts/validate"; |
| | | import ipInput from "@/components/subComponents/IPInput"; |
| | | import TimeZones from "@/Pool/TimeZones"; |
| | | |
| | | import ClusterManagement from "./ClusterManagement"; |
| | | import AuthorityManagement from "./AuthorityManagement"; |
| | | import RadioSet from "./RadioSet"; |
| | | import config from "../../../../package.json"; |
| | | |
| | | export default { |
| | | name: "BasicSettings", |
| | | components: { |
| | | ipInput, |
| | | ClusterManagement, |
| | | AuthorityManagement, |
| | | RadioSet, |
| | | }, |
| | | computed: { |
| | | min_video_len() { |
| | | // return +(this.fakeObj.min * 1.2).toFixed(0); |
| | | return Math.round(this.fakeObj.min * 1.2); |
| | | }, |
| | | max_video_len() { |
| | | return Math.round(this.fakeObj.max * 1.2); |
| | | // return +(this.fakeObj.max * 1.2).toFixed(0); |
| | | }, |
| | | isAdmin() { |
| | | if ( |
| | | sessionStorage.getItem("userInfo") && |
| | | sessionStorage.getItem("userInfo") !== "" |
| | | ) { |
| | | let loginName = JSON.parse(sessionStorage.getItem("userInfo")).username; |
| | | return loginName === "superadmin" || loginName === "basic"; |
| | | } |
| | | return false; |
| | | }, |
| | | }, |
| | | directives: { |
| | | focus: { |
| | | inserted: function (el) { |
| | | el.querySelector("input").focus(); |
| | | }, |
| | | }, |
| | | }, |
| | | data() { |
| | | return { |
| | | loading: true, |
| | | loadingText: "", |
| | | gutter: 10, |
| | | activeName: "sysInfo", |
| | | timezone: "", |
| | | syncType: "1", |
| | | ntpServer: "", |
| | | equipmentTime: "", |
| | | NYPport: "", |
| | | settime: "", |
| | | timeInterval: 10, |
| | | settimeRadio: false, |
| | | clockTimer: null, |
| | | browserTimer: null, |
| | | timestamp: 0, |
| | | sysinfo: {}, |
| | | alarmConf: {}, |
| | | min_len: 0, |
| | | max_len: 0, |
| | | fakeObj: { |
| | | min: 0, |
| | | max: 0, |
| | | }, |
| | | originNetConfig: { |
| | | ip: "", |
| | | gw: "", |
| | | mask: "", |
| | | dns: "", |
| | | }, |
| | | rules: { |
| | | ip: [ |
| | | { |
| | | required: true, |
| | | message: "请输入IP地址", |
| | | trigger: "change", |
| | | }, |
| | | { validator: isIPv4, trigger: "change" }, |
| | | ], |
| | | ServerIp: [ |
| | | { |
| | | required: true, |
| | | message: "请输入IP地址", |
| | | trigger: "change", |
| | | }, |
| | | { validator: isIPv4, trigger: "change" }, |
| | | ], |
| | | ServerPort: [ |
| | | { |
| | | required: true, |
| | | message: "请输入端口", |
| | | trigger: "change", |
| | | }, |
| | | { validator: isPort, trigger: "change" }, |
| | | ], |
| | | GbServerPort: [ |
| | | { |
| | | required: true, |
| | | message: "请输入端口", |
| | | trigger: "change", |
| | | }, |
| | | { validator: isPort, trigger: "change" }, |
| | | ], |
| | | gateway: [ |
| | | { |
| | | required: true, |
| | | message: "请输入网关", |
| | | trigger: "change", |
| | | }, |
| | | { validator: isIPv4, trigger: "change" }, |
| | | ], |
| | | dns: [ |
| | | { |
| | | required: true, |
| | | message: "请输入dns地址", |
| | | trigger: "change", |
| | | }, |
| | | { validator: isIPv4, trigger: "change" }, |
| | | ], |
| | | server_name: [ |
| | | { required: true, message: "请输入名称", trigger: "change" }, |
| | | ], |
| | | subMask: [ |
| | | { |
| | | required: true, |
| | | message: "请输入子网掩码", |
| | | trigger: "change", |
| | | }, |
| | | { validator: isIPv4, trigger: "change" }, |
| | | ], |
| | | }, |
| | | openeds: ["0"], |
| | | ipServer: { |
| | | diyOrLocalIP: "1", |
| | | ip: "", |
| | | localhost: "", |
| | | localFilePort: "", |
| | | }, |
| | | locationCity: { |
| | | province: "", |
| | | city: "", |
| | | county: "", |
| | | provinceOptions: [], |
| | | cityOptions: [], |
| | | countyOptions: [], |
| | | }, |
| | | webPort: 0, |
| | | ntpTestLoading: false, |
| | | buttonAuthority: sessionStorage.getItem("buttonAuthoritys") || [], |
| | | }; |
| | | }, |
| | | created() { |
| | | if (this.isShow("settings:sysInfo")) { |
| | | this.activeName = "sysInfo"; |
| | | } else if (this.isShow("settings:timeSet")) { |
| | | this.activeName = "timeSet"; |
| | | } else if (this.isShow("settings:cluster")) { |
| | | this.activeName = "cluster"; |
| | | } else if (this.isShow("settings:permission")) { |
| | | this.activeName = "permission"; |
| | | } else if (this.isShow("settings:broadcast")) { |
| | | this.activeName = "broadcast"; |
| | | } |
| | | }, |
| | | mounted() { |
| | | this.$nextTick(() => { |
| | | this.initSysinfo(); |
| | | // this.initAlarmConf(); |
| | | this.initResourceConfig(); |
| | | this.initClockConf(); |
| | | //this.markStartTime(); |
| | | }); |
| | | }, |
| | | beforeDestroy() { |
| | | clearTimeout(this.clockTimer); |
| | | clearInterval(this.browserTimer); |
| | | }, |
| | | methods: { |
| | | formatTooltip(v){ |
| | | return Math.round(v*1.2) |
| | | }, |
| | | isShow(authority) { |
| | | return ( |
| | | this.isAdmin || this.buttonAuthority.indexOf("," + authority + ",") > -1 |
| | | ); |
| | | }, |
| | | initSysinfo() { |
| | | this.loadingText = "正在获取设备信息..."; |
| | | getDevInfo() |
| | | .then((rsp) => { |
| | | if (rsp && rsp.success) { |
| | | this.sysinfo = rsp.data; |
| | | this.sysinfo.gateway = this.sysinfo.gateway.trim(); |
| | | this.originNetConfig.ip = this.sysinfo.ip; |
| | | this.originNetConfig.mask = this.sysinfo.subMask; |
| | | this.originNetConfig.gw = this.sysinfo.gateway.trim(); |
| | | this.originNetConfig.dns = this.sysinfo.dns ? this.sysinfo.dns : ""; |
| | | // this.alarmConf.min_video_len = rsp.data.min_video_len; |
| | | // this.alarmConf.max_video_len = rsp.data.max_video_len; |
| | | this.fakeObj.min = rsp.data.min_video_len / 1.2 |
| | | this.fakeObj.max = rsp.data.max_video_len / 1.2 |
| | | if (this.sysinfo.deviceInfo) { |
| | | let devInfo = this.sysinfo.deviceInfo; |
| | | |
| | | this.sysinfo.cpuInfo = devInfo.cpu[0].modelName; |
| | | this.sysinfo.disks = "( " + devInfo.disk + ") "; |
| | | this.sysinfo.mem = |
| | | (devInfo.mem.total / 1024 / 1024 / 1024).toFixed(2) + "GB"; |
| | | // this.sysinfo.arch = devInfo.host.kernelArch; |
| | | this.sysinfo.uptime = this.secondsFormat(devInfo.host.uptime); |
| | | } |
| | | |
| | | if (!this.sysinfo.server_port) { |
| | | this.sysinfo.server_port = 7003; |
| | | } |
| | | |
| | | this.webPort = this.sysinfo.server_port; |
| | | |
| | | this.sysinfo.webVersion = "V" + config.version; |
| | | } |
| | | |
| | | this.loading = false; |
| | | }) |
| | | .catch((err) => { |
| | | this.loading = false; |
| | | }); |
| | | }, |
| | | secondsFormat(s) { |
| | | var day = Math.floor(s / (24 * 3600)); // Math.floor()向下取整 |
| | | var hour = Math.floor((s - day * 24 * 3600) / 3600); |
| | | var minute = Math.floor((s - day * 24 * 3600 - hour * 3600) / 60); |
| | | var second = s - day * 24 * 3600 - hour * 3600 - minute * 60; |
| | | return day + "天" + hour + "时" + minute + "分" + second + "秒"; |
| | | }, |
| | | initClockConf(ntpTest = false) { |
| | | getClockInfo().then((rsp) => { |
| | | if (rsp && rsp.success) { |
| | | this.timezone = rsp.data.time_zone; |
| | | if (!ntpTest) { |
| | | this.syncType = rsp.data.ntp ? "1" : "2"; |
| | | } |
| | | if (rsp.data.ntp) { |
| | | this.ntpServer = rsp.data.ntp_server; |
| | | this.timeInterval = rsp.data.interval; |
| | | } |
| | | this.timestamp = rsp.data.local_time; |
| | | if (this.clockTimer === null) { |
| | | this.runClock(); |
| | | } |
| | | } |
| | | }); |
| | | }, |
| | | runClock() { |
| | | this.equipmentTime = this.formatTime(++this.timestamp, "Y-M-D h:m:s"); |
| | | this.clockTimer = setTimeout(() => { |
| | | this.runClock(); |
| | | }, 1000); |
| | | }, |
| | | initAlarmConf() { |
| | | // getAlarmConfig().then(rsp => { |
| | | // if (rsp && rsp.success) { |
| | | // this.alarmConf = rsp.data; |
| | | // } |
| | | // }); |
| | | }, |
| | | initResourceConfig() { |
| | | getResourceConfig().then((rsp) => { |
| | | if (rsp && rsp.success) { |
| | | this.ipServer.diyOrLocalIP = rsp.data.ipType; |
| | | this.ipServer.ip = rsp.data.serviceIp; |
| | | this.ipServer.localhost = rsp.data.domain; |
| | | this.ipServer.localFilePort = rsp.data.filePort; |
| | | } |
| | | }); |
| | | }, |
| | | syncBrowser(enable) { |
| | | if (!enable) { |
| | | clearInterval(this.browserTimer); |
| | | } else { |
| | | this.browserTimer = setInterval(() => { |
| | | let timestamp = new Date().getTime() / 1000; |
| | | this.settime = this.formatTime(timestamp, "Y-M-D h:m:s"); |
| | | }, 1000); |
| | | } |
| | | }, |
| | | markStartTime() { |
| | | let timestamp = new Date().getTime() / 1000; |
| | | this.settime = this.formatTime(timestamp, "Y-M-D h:m:s"); |
| | | }, |
| | | submitSysinfo() { |
| | | this.$refs["sysinfo"].validate((valid) => { |
| | | if (valid) { |
| | | if ( |
| | | this.sysinfo.ip !== this.originNetConfig.ip || |
| | | this.sysinfo.subMask !== this.originNetConfig.mask || |
| | | this.sysinfo.dns !== this.originNetConfig.dns || |
| | | this.sysinfo.gateway !== this.originNetConfig.gw |
| | | ) { |
| | | if (this.sysinfo.ip !== this.originNetConfig.ip) { |
| | | let newUri = |
| | | location.protocol + |
| | | "//" + |
| | | this.sysinfo.ip + |
| | | ":" + |
| | | this.sysinfo.server_port; |
| | | var changeIPTimer = setTimeout(() => { |
| | | this.$alert( |
| | | '<strong>您已修改了服务器ip, 请重新登录</strong><a target="_parent" href="' + |
| | | newUri + |
| | | '"> ' + |
| | | newUri + |
| | | "<a/>", |
| | | "提示", |
| | | { |
| | | dangerouslyUseHTMLString: true, |
| | | } |
| | | ); |
| | | }, 10000); |
| | | } |
| | | |
| | | this.$confirm("确认需要修改服务器网络配置吗?", { |
| | | center: true, |
| | | cancelButtonClass: "comfirm-class-cancle", |
| | | confirmButtonClass: "comfirm-class-sure", |
| | | }) |
| | | .then(() => { |
| | | this.loading = true; |
| | | this.loadingText = "正在处理..."; |
| | | saveDevInfo(this.sysinfo) |
| | | .then((rsp) => { |
| | | if (rsp && rsp.success) { |
| | | this.$notify({ |
| | | type: "success", |
| | | message: "本机信息保存成功", |
| | | }); |
| | | } |
| | | this.initSysinfo(); |
| | | this.loading = false; |
| | | }) |
| | | .catch((err) => { |
| | | this.loading = false; |
| | | clearTimeout(changeIPTimer); |
| | | this.$notify({ |
| | | type: "error", |
| | | message: "保存失败", |
| | | }); |
| | | }); |
| | | }) |
| | | .catch((err) => {}); |
| | | } else { |
| | | saveDevInfo(this.sysinfo).then((rsp) => { |
| | | if (rsp && rsp.success) { |
| | | this.$notify({ |
| | | type: "success", |
| | | message: "本机信息保存成功", |
| | | }); |
| | | this.initSysinfo(); |
| | | } |
| | | }); |
| | | |
| | | if (this.sysinfo.server_port !== this.webPort) { |
| | | let newUri = |
| | | location.protocol + |
| | | "//" + |
| | | this.sysinfo.ip + |
| | | ":" + |
| | | this.sysinfo.server_port; |
| | | var changeIPTimer = setTimeout(() => { |
| | | this.$alert( |
| | | '<strong>您已修改了服务器端口, 请重新登录</strong><a target="_parent" href="' + |
| | | newUri + |
| | | '"> ' + |
| | | newUri + |
| | | "<a/>", |
| | | "提示", |
| | | { |
| | | dangerouslyUseHTMLString: true, |
| | | } |
| | | ); |
| | | }, 5000); |
| | | } |
| | | } |
| | | } else { |
| | | console.log("error submit!!"); |
| | | return false; |
| | | } |
| | | }); |
| | | }, |
| | | checkTimeZone(val) {}, |
| | | submitClock() { |
| | | if (this.syncType === "1") { |
| | | if (this.ntpServer === "") { |
| | | this.$notify({ |
| | | type: "error", |
| | | message: "NTP 服务器地址不能为空", |
| | | }); |
| | | return false; |
| | | } else if (this.timeInterval === "") { |
| | | this.timeInterval = 1; |
| | | } |
| | | } else { |
| | | if (this.settime === "") { |
| | | this.$notify({ |
| | | type: "error", |
| | | message: "设置时间不能为空", |
| | | }); |
| | | return false; |
| | | } |
| | | } |
| | | let requestBody = { |
| | | timeZone: this.timezone, |
| | | ntp: this.syncType === "1", |
| | | ntpServer: this.ntpServer, |
| | | interval: this.timeInterval, |
| | | newTime: this.settime, |
| | | }; |
| | | saveClockInfo(requestBody).then((rsp) => { |
| | | if (rsp && rsp.success) { |
| | | this.$notify({ |
| | | type: "success", |
| | | message: "设置成功", |
| | | }); |
| | | } |
| | | this.initClockConf(); |
| | | }); |
| | | }, |
| | | testNTP() { |
| | | this.ntpTestLoading = true; |
| | | testNTPserver({ server: this.ntpServer }) |
| | | .then((rsp) => { |
| | | if (rsp && rsp.success) { |
| | | this.$notify({ |
| | | type: "success", |
| | | message: "时间同步成功", |
| | | }); |
| | | } else { |
| | | this.$notify({ |
| | | type: "error", |
| | | message: "时间同步失败", |
| | | }); |
| | | } |
| | | this.ntpTestLoading = false; |
| | | this.initClockConf(true); |
| | | }) |
| | | .catch((err) => { |
| | | this.$notify({ |
| | | type: "error", |
| | | message: "时间同步失败,请检查服务器ip", |
| | | }); |
| | | this.ntpTestLoading = false; |
| | | }); |
| | | }, |
| | | submitAlarm() { |
| | | saveAlarmConfig({ |
| | | min_video_len: this.min_video_len, |
| | | max_video_len: this.max_video_len, |
| | | }).then((rsp) => { |
| | | if (rsp && rsp.success) { |
| | | this.$notify({ |
| | | type: "success", |
| | | message: "保存成功", |
| | | }); |
| | | } |
| | | }); |
| | | }, |
| | | // submitResource() { |
| | | // let regNum = /^[0-9]*$/; |
| | | // if (!this.vaildHost(this.ipServer.localhost)) { |
| | | // this.$notify({ |
| | | // type: "warning", |
| | | // message: "请输入正确格式得域名!", |
| | | // }); |
| | | // return false; |
| | | // } |
| | | // if (!regNum.test(this.ipServer.localFilePort)) { |
| | | // this.$notify({ |
| | | // type: "warning", |
| | | // message: "请输入正确的端口号!", |
| | | // }); |
| | | // return false; |
| | | // } |
| | | // saveResourceConfig({ |
| | | // domain: this.ipServer.localhost, |
| | | // ipType: this.ipServer.diyOrLocalIP, |
| | | // serviceIp: this.ipServer.ip, |
| | | // filePort: Number(this.ipServer.localFilePort), |
| | | // }).then((res) => { |
| | | // if (res && res.success) { |
| | | // this.$notify({ |
| | | // type: "success", |
| | | // message: "保存成功", |
| | | // }); |
| | | // } else { |
| | | // this.$notify({ |
| | | // type: "error", |
| | | // message: "保存失败", |
| | | // }); |
| | | // } |
| | | // }); |
| | | // }, |
| | | // onIpBlur(e, ip) { |
| | | // console.log(e, ip); |
| | | // }, |
| | | formatTime(number, format) { |
| | | var formateArr = ["Y", "M", "D", "h", "m", "s"]; |
| | | var returnArr = []; |
| | | |
| | | var date = new Date(number * 1000); |
| | | returnArr.push(date.getFullYear()); |
| | | returnArr.push(this.formatNumber(date.getMonth() + 1)); |
| | | returnArr.push(this.formatNumber(date.getDate())); |
| | | |
| | | returnArr.push(this.formatNumber(date.getHours())); |
| | | returnArr.push(this.formatNumber(date.getMinutes())); |
| | | returnArr.push(this.formatNumber(date.getSeconds())); |
| | | |
| | | for (var i in returnArr) { |
| | | format = format.replace(formateArr[i], returnArr[i]); |
| | | } |
| | | return format; |
| | | }, |
| | | |
| | | //数据转化 |
| | | formatNumber(n) { |
| | | n = n.toString(); |
| | | return n[1] ? n : "0" + n; |
| | | }, |
| | | menuOpen(event) {}, |
| | | menuClose(event) {}, |
| | | // handleEdit(row) { |
| | | // console.log(row); |
| | | // row.edit = true; |
| | | // }, |
| | | // handleCancel(row) { |
| | | // row.edit = false; |
| | | // console.log(row); |
| | | // }, |
| | | // handleSave(row) { |
| | | // console.log(row); |
| | | // row.edit = false; |
| | | // this.$notify({ |
| | | // message: "保存成功", |
| | | // type: "success", |
| | | // }); |
| | | // }, |
| | | //校验域名 |
| | | vaildHost(str) { |
| | | let re = /^(?=^.{3,255}$)(http(s)?:\/\/)?(www\.)?[a-zA-Z0-9][-a-zA-Z0-9]{0,62}(\.[a-zA-Z0-9][-a-zA-Z0-9]{0,62})+(:\d+)*(\/\w+\.\w+)*$/; |
| | | return re.test(str); |
| | | }, |
| | | }, |
| | | }; |
| | | </script> |
| | | <style lang="scss"> |
| | | .s-basic-setting { |
| | | width: 100%; |
| | | height: 100%; |
| | | .el-form { |
| | | width: 1000px; |
| | | |
| | | // margin-left: -80px; |
| | | .el-form-item { |
| | | text-align: left; |
| | | &.is-required:not(.is-no-asterisk) > .el-form-item__label:before { |
| | | margin-left: -8px; |
| | | } |
| | | .el-button { |
| | | float: right; |
| | | } |
| | | |
| | | .el-form-item__content { |
| | | text-align: left; |
| | | input { |
| | | max-width: 360px; |
| | | } |
| | | .el-date-editor.el-input, |
| | | .el-date-editor.el-input__inner { |
| | | width: 216px; |
| | | } |
| | | .el-checkbox__label { |
| | | padding-left: 5px; |
| | | } |
| | | } |
| | | |
| | | .el-form-item__label { |
| | | text-align: left; |
| | | } |
| | | } |
| | | } |
| | | .alarmSetting { |
| | | .el-input { |
| | | width: 100%; |
| | | // padding-right: 10px; |
| | | } |
| | | .el-select { |
| | | max-width: 113px; |
| | | } |
| | | .el-slider { |
| | | width: calc(100% - 120px); |
| | | display: inline-block; |
| | | padding-right: 30px; |
| | | box-sizing: border-box; |
| | | vertical-align: middle; |
| | | } |
| | | .el-input-number { |
| | | width: 100px; |
| | | display: inline-block; |
| | | .el-input { |
| | | width: 100%; |
| | | } |
| | | } |
| | | } |
| | | |
| | | .time-type { |
| | | height: 25px; |
| | | width: 413px; |
| | | line-height: 28px; |
| | | padding: 3px 23px; |
| | | font-size: 14px; |
| | | font-weight: 600; |
| | | background-color: #e4e6ed; |
| | | } |
| | | |
| | | #cut_min_duration { |
| | | .el-slider__bar { |
| | | background-color: #3d68e1; |
| | | } |
| | | .el-slider__button { |
| | | width: 10px; |
| | | height: 10px; |
| | | border: 4px solid #3d68e1; |
| | | } |
| | | } |
| | | |
| | | #cut_max_duration { |
| | | .el-slider__bar { |
| | | background-color: #ff9e6e; |
| | | } |
| | | .el-slider__button { |
| | | width: 10px; |
| | | height: 10px; |
| | | border: 4px solid #ff9e6e; |
| | | } |
| | | } |
| | | .menu-css, |
| | | .el-menu { |
| | | border-right: none; |
| | | list-style: none; |
| | | position: relative; |
| | | margin: 0; |
| | | padding-left: 10px; |
| | | background-color: #ffffff; |
| | | .el-submenu__title { |
| | | height: 35px; |
| | | line-height: 35px; |
| | | font-size: 14px; |
| | | color: #303133; |
| | | padding: 0 20px; |
| | | list-style: none; |
| | | cursor: pointer; |
| | | position: relative; |
| | | -webkit-transition: border-color 0.3s, background-color 0.3s, color 0.3s; |
| | | transition: border-color 0.3s, background-color 0.3s, color 0.3s; |
| | | -webkit-box-sizing: border-box; |
| | | box-sizing: border-box; |
| | | white-space: nowrap; |
| | | } |
| | | .tree-font { |
| | | font-family: PingFangSC-Medium; |
| | | font-size: 14px; |
| | | color: #222222; |
| | | text-align: left; |
| | | } |
| | | li { |
| | | text-align: left; |
| | | .el-submenu__title { |
| | | // border-bottom: solid 1px #e6e6e6; |
| | | padding-left: 10px !important; |
| | | background-color: #e4e6ed !important; |
| | | border-radius: 2px; |
| | | .el-submenu__icon-arrow { |
| | | position: absolute; |
| | | top: 50%; |
| | | right: auto; |
| | | left: 135px; |
| | | margin-top: -7px; |
| | | -webkit-transition: -webkit-transform 0.3s; |
| | | transition: -webkit-transform 0.3s; |
| | | transition: transform 0.3s; |
| | | transition: transform 0.3s, -webkit-transform 0.3s; |
| | | font-size: 12px; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | .save-btn { |
| | | text-align: right; |
| | | position: relative; |
| | | right: 40px; |
| | | } |
| | | } |
| | | </style> |
| | | <style lang="scss" scoped> |
| | | .flex-box { |
| | | display: flex; |
| | | height: 50px; |
| | | label { |
| | | width: 120px; |
| | | } |
| | | .el-input { |
| | | width: 300px; |
| | | } |
| | | } |
| | | .desc-info { |
| | | margin-bottom: 14px; |
| | | .flex-box { |
| | | height: 40px; |
| | | line-height: 40px; |
| | | .xiangqin-label { |
| | | width: 80px; |
| | | } |
| | | } |
| | | } |
| | | .menu-css, |
| | | .el-menu { |
| | | border-right: none; |
| | | list-style: none; |
| | | position: relative; |
| | | margin: 0; |
| | | padding-left: 0; |
| | | background-color: #ffffff; |
| | | |
| | | .tree-font { |
| | | font-family: PingFangSC-Medium; |
| | | font-size: 14px; |
| | | color: #222222; |
| | | text-align: left; |
| | | } |
| | | li { |
| | | text-align: left; |
| | | .el-submenu__title { |
| | | .el-submenu__icon-arrow { |
| | | position: absolute; |
| | | top: 50%; |
| | | right: 0; |
| | | margin-top: -7px; |
| | | -webkit-transition: -webkit-transform 0.3s; |
| | | transition: -webkit-transform 0.3s; |
| | | transition: transform 0.3s; |
| | | transition: transform 0.3s, -webkit-transform 0.3s; |
| | | font-size: 12px; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | </style> |
| | |
| | | <template> |
| | | <div class="cloud"> |
| | | <div class="inner"> |
| | | <!-- <div |
| | | class="rect" |
| | | :style="{width:`${minWidth+BaseWidth}px`,height:`${minHeight+BaseHeight}px`}" |
| | | >--> |
| | | <div class="rect"> |
| | | <!-- <div |
| | | class="node" |
| | | v-for="item in insideNodes" |
| | | :key="item.id" |
| | | :style="{top:item.t+'px',left:item.l+'px'}" |
| | | > |
| | | <span class="node-icon"> |
| | | </span> |
| | | <span class="node-name">{{item.nodeName}}</span> |
| | | </div>--> |
| | | <serfDiagram |
| | | ref="inside-nodes" |
| | | :members="insideNodes" |
| | |
| | | :startX="60" |
| | | class="outer-nodes" |
| | | ></serfDiagram> |
| | | <!-- <div |
| | | class="node" |
| | | v-for="(item,index) in outsideNodes" |
| | | :key="item.id" |
| | | :style="{top:36*(index+1)+'px',left:60*(index+1)+'px'}" |
| | | > |
| | | <span class="node-icon"></span> |
| | | <span class="node-name">{{item.nodeName}}</span> |
| | | </div>--> |
| | | </div> |
| | | </div> |
| | | </template> |
| | | <script> |
| | | import SerfDiagram from "@/components/serfDiagram"; |
| | | export default { |
| | | name: "cloudNode", |
| | | name: 'cloudNode', |
| | | props: { |
| | | nodes: Array, |
| | | nodes: Array |
| | | }, |
| | | components: { |
| | | SerfDiagram, |
| | | SerfDiagram |
| | | }, |
| | | data() { |
| | | data () { |
| | | return { |
| | | agentName: "", |
| | | agentName: '', |
| | | nodeIcons: [], |
| | | //insideNodes: [], |
| | | BaseWidth: 150, |
| | | BaseHeight: 70, |
| | | minWidth: 0, |
| | | minHeight: 0, |
| | | }; |
| | | mockData: [ |
| | | { |
| | | cluster_id: "b6132bfe-d3af-4710-ba89-436f614c2f46", |
| | | hardwareType: "01", |
| | | id: "DSVAD010120190622", |
| | | node_id: "DSVAD010120190622", |
| | | node_ip: "192.168.20.10:30190", |
| | | nodeName: "开发20.10-1", |
| | | role: 'pc' |
| | | }, |
| | | { |
| | | cluster_id: "b6132bfe-d3af-4710-ba89-436f614c2f", |
| | | hardwareType: "02", |
| | | id: "DSVAD010120190623", |
| | | node_id: "DSVAD010120190623", |
| | | node_ip: "192.168.20.10:30190", |
| | | nodeName: "开发测试20.11-1", |
| | | role: 'master' |
| | | }, |
| | | { |
| | | cluster_id: "b6132bfe-d3af-4710-ba89-436f614c2g", |
| | | hardwareType: "03", |
| | | id: "DSVAD010120190624", |
| | | node_id: "DSVAD010120190624", |
| | | node_ip: "192.168.20.10:30190", |
| | | nodeName: "测试20.13-1", |
| | | role: 'pc' |
| | | }, |
| | | { |
| | | cluster_id: "b6132bfe-d3af-4710-ba89-436f614c2h", |
| | | hardwareType: "03", |
| | | id: "DSVAD010120190625", |
| | | node_id: "DSVAD010120190625", |
| | | node_ip: "192.168.20.10:30190", |
| | | nodeName: "测试20.101-1", |
| | | role: 'server' |
| | | }, |
| | | { |
| | | cluster_id: "b6132bfe-d3af-4710-ba89-436f614cf", |
| | | hardwareType: "02", |
| | | id: "DSVAD01012019063", |
| | | node_id: "DSVAD01012019063", |
| | | node_ip: "192.168.20.10:30190", |
| | | nodeName: "开发测试20.15-1", |
| | | role: 'master' |
| | | }, |
| | | { |
| | | cluster_id: "b6132bfe-d3af-710-ba89-436f614cf", |
| | | hardwareType: "02", |
| | | id: "DSVAD0101201906", |
| | | node_id: "DSVAD0101209063", |
| | | node_ip: "192.168.20.10:30190", |
| | | nodeName: "k20.15-128437586", |
| | | role: 'master' |
| | | }, |
| | | { |
| | | cluster_id: "b612bfe-d3af-710-ba89-436f614cf", |
| | | hardwareType: "02", |
| | | id: "DSVAD010120906", |
| | | node_id: "DSVAD010120963", |
| | | node_ip: "192.168.20.107:30190", |
| | | nodeName: "kfl20.15-127586", |
| | | role: 'master' |
| | | }, |
| | | { |
| | | cluster_id: "b6132bfe-d3af-710-ba89-436f614cf", |
| | | hardwareType: "02", |
| | | id: "DSVAD0101201906", |
| | | node_id: "DSVAD001209063", |
| | | node_ip: "192.168.20.10:30190", |
| | | nodeName: "k20.15-128437586", |
| | | role: 'master' |
| | | }, |
| | | { |
| | | cluster_id: "b612bfe-d3af-710-ba89-436f614cf", |
| | | hardwareType: "02", |
| | | id: "DSVAD01010906", |
| | | node_id: "DSVAD012063", |
| | | node_ip: "192.168.20.107:30190", |
| | | nodeName: "kfl20.15-127586", |
| | | role: 'master' |
| | | }, |
| | | { |
| | | cluster_id: "b6132bfe-d3af-710-ba89-436f614cf", |
| | | hardwareType: "02", |
| | | id: "DSVAD0101201906", |
| | | node_id: "DSVAD0012063", |
| | | node_ip: "192.168.20.10:30190", |
| | | nodeName: "k20.15-128437586", |
| | | role: 'master' |
| | | }, |
| | | { |
| | | cluster_id: "b612bfe-d3af-710-ba89-436f614cf", |
| | | hardwareType: "02", |
| | | id: "DSVAD01010906", |
| | | node_id: "DSVAD01012063", |
| | | node_ip: "192.168.20.107:30190", |
| | | nodeName: "kfl20.15-127586", |
| | | role: 'master' |
| | | }, |
| | | ] |
| | | } |
| | | }, |
| | | mounted() { |
| | | console.log(this.nodes); |
| | | mounted () { |
| | | console.log(this.nodes) |
| | | //this.getInsideNodes(); |
| | | }, |
| | | methods: { |
| | | getRandom(index) { |
| | | getRandom (index) { |
| | | if (index % 2 == 0) { |
| | | return Math.random() * 20; |
| | | return Math.random() * 20 |
| | | } else { |
| | | return Math.random() * 50; |
| | | return Math.random() * 50 |
| | | } |
| | | }, |
| | | getInsideNodes() { |
| | | let arr = this.nodes.filter( |
| | | (item) => item.hardwareType == "01" || item.hardwareType == "02" |
| | | ); |
| | | getInsideNodes () { |
| | | //return this.nodes.filter(item=>item.hardwareType=='01'||item.hardwareType=='02'); |
| | | //return this.mockData.filter(item => item.hardwareType == '01' || item.hardwareType == '02'); |
| | | let arr = this.nodes.filter(item => item.hardwareType == '01' || item.hardwareType == '02'); |
| | | let len = arr.length; |
| | | let lefts = []; |
| | | let tops = []; |
| | |
| | | t: 30 * (index + 1), |
| | | nodeName: item.nodeName, |
| | | id: item.id, |
| | | workType: item.workType, |
| | | }; |
| | | workType: item.workType |
| | | } |
| | | }); |
| | | this.minWidth = Math.max(...lefts) - Math.min(...lefts); |
| | | this.minHeight = Math.max(...tops) - Math.min(...tops); |
| | | console.log("w,h", this.minWidth, this.minHeight); |
| | | console.log('w,h', this.minWidth, this.minHeight); |
| | | }, |
| | | }, |
| | | computed: { |
| | | cloudPic() { |
| | | return "/images/settings/cloud.png"; |
| | | cloudPic () { |
| | | return '/images/settings/cloud.png' |
| | | }, |
| | | insideNodes() { |
| | | return this.nodes.filter( |
| | | (item) => item.hardwareType == "01" || item.hardwareType == "02" |
| | | ); |
| | | insideNodes () { |
| | | return this.nodes.filter(item => item.hardwareType == '01' || item.hardwareType == '02'); |
| | | }, |
| | | insideSizeX() { |
| | | return 160 + 200 * 0.2 * this.insideNodes.length <= 400 |
| | | ? 160 + 200 * 0.2 * this.insideNodes.length |
| | | : 400; |
| | | insideSizeX () { |
| | | return 160 + 200 * 0.2 * (this.insideNodes.length) <= 400 ? 160 + 200 * 0.2 * (this.insideNodes.length) : 400; |
| | | }, |
| | | insideSizeY() { |
| | | return 140 + 200 * 0.2 * this.insideNodes.length <= 380 |
| | | ? 140 + 200 * 0.2 * this.insideNodes.length |
| | | : 380; |
| | | insideSizeY () { |
| | | return 140 + 200 * 0.2 * (this.insideNodes.length) <= 380 ? 140 + 200 * 0.2 * (this.insideNodes.length) : 380; |
| | | }, |
| | | insideStartX() { |
| | | return this.insideSizeX / 3; |
| | | insideStartX () { |
| | | return this.insideSizeX / 3 |
| | | }, |
| | | outsideNodes() { |
| | | return this.nodes.filter((item) => item.hardwareType == "03"); |
| | | }, |
| | | }, |
| | | }; |
| | | // insideNodes () { |
| | | // //return this.nodes.filter(item=>item.hardwareType=='01'||item.hardwareType=='02'); |
| | | // //return this.mockData.filter(item => item.hardwareType == '01' || item.hardwareType == '02'); |
| | | // let arr = this.mockData.filter(item => item.hardwareType == '01' || item.hardwareType == '02'); |
| | | // let len = arr.length; |
| | | // let lefts = []; |
| | | // let tops = []; |
| | | // let temp = arr.map((item,index)=>{ |
| | | // lefts.push((20-len)*(index+1)); |
| | | // tops.push(30*(index+1)); |
| | | // return { |
| | | // l: (20-len)*(index+1), |
| | | // t: 30*(index+1), |
| | | // nodeName: item.nodeName, |
| | | // id: item.id, |
| | | // workType: item.workType |
| | | // } |
| | | // }); |
| | | // return temp; |
| | | // }, |
| | | outsideNodes () { |
| | | return this.nodes.filter(item=>item.hardwareType=='03'); |
| | | //return this.mockData.filter(item => item.hardwareType == '03'); |
| | | } |
| | | } |
| | | } |
| | | </script> |
| | | <style lang="scss"> |
| | | .cloud { |
| | | width: 100%; |
| | | display: flex; |
| | | .inner { |
| | | background: url("/images/settings/easy-cloud.png") no-repeat; |
| | | background: url('/images/settings/easy-cloud.png') no-repeat; |
| | | background-size: 100%; |
| | | margin-top: -55px; |
| | | margin-left: 55px; |
| | | |
| | | margin-top: -80px; |
| | | .rect { |
| | | //background: rgba(176, 203, 253, 0.3); |
| | | position: relative; |
| | | margin: 130px 100px 70px; |
| | | margin: 130px 100px 100px; |
| | | .node { |
| | | position: absolute; |
| | | .node-icon { |
| New file |
| | |
| | | <template> |
| | | <div class="s-cluster-management"> |
| | | <div class="ui-top-view"> |
| | | <div class="ui-top-title">视频分析集群管理</div> |
| | | </div> |
| | | <el-row> |
| | | <el-col :span="12"> |
| | | <el-tabs v-model="activeName" id="e-alaycluster" v-if="!isHasColony"> |
| | | <el-tab-pane label="创建集群" name="1" :disabled="isHasColony"> |
| | | <el-form :model="ruleForm" :rules="rules" ref="ruleForm" label-width="100px"> |
| | | <el-form-item label="集群名称" prop="clustername"> |
| | | <el-input v-model="ruleForm.clustername" placeholder="手动输入, 如“集群A”" size="small"></el-input> |
| | | </el-form-item> |
| | | <el-form-item label="集群ID"> |
| | | <el-input v-model="clusterid" placeholder="不允许输入,保存后回显" disabled size="small"></el-input> |
| | | </el-form-item> |
| | | <el-form-item label="集群密码" prop="clusterpwd"> |
| | | <el-input v-model="ruleForm.clusterpwd" placeholder="请输入6位密码,或点击生成" size="small"> |
| | | <el-button type="text" slot="suffix" @click="generatePassword">生成密码</el-button> |
| | | </el-input> |
| | | </el-form-item> |
| | | <el-form-item label="集群IP" prop="virtualIp"> |
| | | <ip-input :ip="ruleForm.virtualIp" :on-blur="onIpBlur" class="ip-input-comp"></ip-input> |
| | | </el-form-item> |
| | | <el-form-item> |
| | | <el-button type="primary" size="small" @click="submitForm('ruleForm')">保存</el-button> |
| | | </el-form-item> |
| | | </el-form> |
| | | </el-tab-pane> |
| | | |
| | | <!-- 加入已有集群 --> |
| | | <el-tab-pane label="加入已有集群" name="2" :disabled="isHasColony"> |
| | | <el-form |
| | | label-width="80px" |
| | | :model="joinForm" |
| | | :rules="joinRules" |
| | | ref="joinForm" |
| | | class="join-form" |
| | | v-loading="joinLoading" |
| | | > |
| | | <el-form-item label="集群ID" style="width:440px" prop="clusterid"> |
| | | <el-input v-model="joinForm.clusterid" placeholder size="small"></el-input> |
| | | </el-form-item> |
| | | <el-form-item label="IP地址" style="width:440px" prop="clusterip"> |
| | | <el-input |
| | | v-model="joinForm.clusterip" |
| | | placeholder="请输入集群内任意IP地址" |
| | | size="small" |
| | | autocomplete="new-password" |
| | | ></el-input> |
| | | |
| | | <!-- <el-button size="mini" :disabled="searchDis" @click="searchColony">搜索集群</el-button> |
| | | <el-button size="mini" @click="stopSearch">停止搜索</el-button>--> |
| | | </el-form-item> |
| | | <el-form-item label="集群密码" prop="clusterpwd" style="width:440px"> |
| | | <el-input |
| | | v-model="joinForm.clusterpwd" |
| | | placeholder="请输入集群密码" |
| | | show-password |
| | | size="small" |
| | | autocomplete="new-password" |
| | | > |
| | | <el-button |
| | | type="text" |
| | | slot="suffix" |
| | | v-show="!searchDis" |
| | | @click="searchColony" |
| | | >搜索集群</el-button> |
| | | <el-button type="text" slot="suffix" v-show="searchDis" @click="stopSearch"> |
| | | <i class="el-icon-loading"></i>停止搜索 |
| | | </el-button> |
| | | </el-input> |
| | | </el-form-item> |
| | | <el-form-item style="width:440px"> |
| | | <el-button type="primary" @click="join('joinForm')" size="small">加入集群</el-button> |
| | | </el-form-item> |
| | | <div class="form-tip">请输入以上信息加入集群,或者通过集群密码搜索后进行加入</div> |
| | | </el-form> |
| | | </el-tab-pane> |
| | | </el-tabs> |
| | | <!-- 有集群的情况 --> |
| | | <div v-if="isHasColony" id="h-alaycluster"> |
| | | <el-form :model="ruleForm" ref="ruleForm" label-width="100px"> |
| | | <el-form-item label="集群名称" prop="clustername"> |
| | | <el-input v-model="ruleForm.clustername" placeholder="手动输入, 如“集群A”" size="small"></el-input> |
| | | </el-form-item> |
| | | <el-form-item label="集群ID"> |
| | | <el-input v-model="clusterid" placeholder="不允许输入,保存后回显" disabled size="small"></el-input> |
| | | </el-form-item> |
| | | <el-form-item label="集群密码" prop="clusterpwd"> |
| | | <el-input |
| | | v-model="ruleForm.clusterpwd" |
| | | disabled |
| | | placeholder="请输入6位密码,或点击生成" |
| | | size="small" |
| | | ></el-input> |
| | | </el-form-item> |
| | | |
| | | <el-form-item label="集群IP" prop="virtualIp"> |
| | | <ip-input :ip="ruleForm.virtualIp" :on-blur="onIpBlur" class="ip-input-comp"></ip-input> |
| | | </el-form-item> |
| | | <el-form-item style="text-align: right;"> |
| | | <el-button size="small" type="danger" @click="leave">退出集群</el-button> |
| | | <el-button |
| | | style="margin-right:10px;" |
| | | type="primary" |
| | | size="small" |
| | | @click="updateCluster('manageForm')" |
| | | >保存</el-button> |
| | | </el-form-item> |
| | | </el-form> |
| | | </div> |
| | | </el-col> |
| | | <el-col |
| | | :span="12" |
| | | style="height: 100%;" |
| | | v-if="members.length !== 0 && isSearch" |
| | | class="node-container" |
| | | > |
| | | <serfDiagram |
| | | ref="diagram" |
| | | :members="members" |
| | | :agent="agentName" |
| | | v-loading="loading" |
| | | :isShowHover="false" |
| | | @selected-node="joinNode" |
| | | class="nodes-svg" |
| | | ></serfDiagram> |
| | | </el-col> |
| | | <el-col |
| | | :span="12" |
| | | style="height: 100%;" |
| | | v-if="innerNodes.length !== 0 && !isSearch" |
| | | class="node-container" |
| | | > |
| | | <cloud-node :nodes="innerNodes"></cloud-node> |
| | | </el-col> |
| | | </el-row> |
| | | |
| | | <!-- <div class="ui-top-view"> |
| | | <div class="ui-top-title">存储集群管理</div> |
| | | </div> |
| | | <el-row> |
| | | <el-col :span="12"> |
| | | <el-tabs id="e-dbcluster" v-model="sActiveName"> |
| | | <el-tab-pane label="创建集群" name="s-first" v-if="sActiveName != 's-third1'"> |
| | | <el-button |
| | | type="primary" |
| | | style="float: left;margin: 20px 0px;" |
| | | size="small" |
| | | @click="createEsCluster()" |
| | | >创建存储集群</el-button> |
| | | |
| | | </el-tab-pane> |
| | | <el-tab-pane label="加入已有集群" name="s-second" v-if="sActiveName != 's-third1'"> |
| | | <el-form label-width="80px"> |
| | | <el-form-item label="IP地址" style="text-align: left;width: 300px;"> |
| | | <el-input |
| | | v-model="esNodeIp" |
| | | placeholder="请输入集群内任意IP地址" |
| | | size="small" |
| | | autocomplete="off" |
| | | ></el-input> |
| | | <el-checkbox |
| | | label="主节点" |
| | | v-model="esNodeType" |
| | | style="margin-left: 20px;position: absolute;" |
| | | ></el-checkbox> |
| | | </el-form-item> |
| | | <el-form-item> |
| | | <el-button |
| | | type="primary" |
| | | @click="joinESCluster()" |
| | | size="small" |
| | | style="float: left;" |
| | | >加入集群</el-button> |
| | | </el-form-item> |
| | | </el-form> |
| | | </el-tab-pane> |
| | | <el-tab-pane label="集群信息" name="s-third"> |
| | | <el-table :data="esNodes" style="width: 100%"> |
| | | <el-table-column prop="nodeType" label="节点类型"></el-table-column> |
| | | <el-table-column prop="name" label="节点名称"></el-table-column> |
| | | <el-table-column prop="ip" label="节点IP地址" min-width="90px"></el-table-column> |
| | | <el-table-column prop="buildDate" label="注册时间" min-width="120px"></el-table-column> |
| | | </el-table> |
| | | </el-tab-pane> |
| | | </el-tabs> |
| | | </el-col> |
| | | </el-row>--> |
| | | </div> |
| | | </template> |
| | | |
| | | <script> |
| | | import { |
| | | createSerfCluster, |
| | | randomPwd, |
| | | search, |
| | | getSearchNodes, |
| | | stopSearching, |
| | | findCluster, |
| | | updateClusterName, |
| | | joinCluster, |
| | | leave, |
| | | getVrrp, |
| | | setVrrp, |
| | | createESNode, |
| | | addESNode, |
| | | getEsClusterInfo |
| | | } from "@/api/clusterManage"; |
| | | |
| | | import { |
| | | getDevInfo |
| | | } from "@/api/system"; |
| | | import cloudNode from "./CloudNode"; |
| | | import serfDiagram from "@/components/serfDiagram"; |
| | | import ipInput from "@/components/subComponents/IPInput"; |
| | | import { isIPv4 } from "@/scripts/validate"; |
| | | export default { |
| | | components: { |
| | | serfDiagram, |
| | | ipInput, |
| | | cloudNode |
| | | }, |
| | | data() { |
| | | const checkPwd = (rule, value, callback) => { |
| | | if (!value) { |
| | | return callback(new Error("密码不能为空")); |
| | | } |
| | | setTimeout(() => { |
| | | if (value.length != 6) { |
| | | callback(new Error("密码应为6位!")); |
| | | } else { |
| | | callback(); |
| | | } |
| | | }, 1000); |
| | | }; |
| | | |
| | | return { |
| | | activeName: "1", |
| | | sActiveName: "s-first", |
| | | clusterid: "", |
| | | esNodeIp: "", |
| | | esNodeType: "", |
| | | clusterpwd2: "", |
| | | sClusterip: "", |
| | | ruleForm: { |
| | | clustername: "", |
| | | clusterpwd: "", |
| | | virtualIp: "" |
| | | }, |
| | | vrIpForm: { |
| | | enable: true, |
| | | //serve_port: "", |
| | | serve_port: null, |
| | | virtual_ip: "" |
| | | }, |
| | | manageForm: { |
| | | clustername: "测试集群1", |
| | | clusterpwd: "123456", |
| | | virtualip: "192.168.1.188" |
| | | }, |
| | | joinForm: { |
| | | clusterid: "", |
| | | clusterip: "", |
| | | clusterpwd: "" |
| | | }, |
| | | rules: { |
| | | clustername: [ |
| | | { required: true, message: "请输入集群名称", trigger: "change" } |
| | | ], |
| | | clusterpwd: [{ validator: checkPwd, trigger: "change" }], |
| | | virtualIp: [ |
| | | { required: true, validator: isIPv4, trigger: "change" } |
| | | ] |
| | | }, |
| | | // vrIpRules: { |
| | | // virtualIp: [ |
| | | // { required: true, message: "请输入虚拟IP", trigger: "change" } |
| | | // ] |
| | | // }, |
| | | joinRules: { |
| | | clusterid: [ |
| | | { required: true, message: "请输入集群ID", trigger: "change" }, |
| | | ], |
| | | clusterip: [ |
| | | { required: true, validator: isIPv4, trigger: "change" } |
| | | ], |
| | | clusterpwd: [ |
| | | { validator: checkPwd, trigger: "change" } |
| | | ] |
| | | }, |
| | | esNodes: [], |
| | | scheduleId: "", |
| | | isHasColony: false, |
| | | isSearch: false, |
| | | currentCluster: {}, |
| | | searchNum: "", |
| | | loading: false, |
| | | searchDis: false, |
| | | agentName: "", |
| | | members: [], |
| | | innerNodes: [], |
| | | intervalTimer: null, |
| | | joinLoading: false, |
| | | showJoinConfirm: false |
| | | }; |
| | | }, |
| | | mounted() { |
| | | this.findCluster(); |
| | | let _this = this; |
| | | this.intervalTimer = setInterval(() => { |
| | | _this.findCluster(); |
| | | }, 30000); |
| | | //this.getEsClusterNodes(); |
| | | }, |
| | | beforeDestroy() { |
| | | clearInterval(this.intervalTimer); |
| | | }, |
| | | methods: { |
| | | checkPsd(psd) { |
| | | return psd.trim().length === 6 |
| | | }, |
| | | // cleanValue() { |
| | | // this.members = []; |
| | | // }, |
| | | // sHandleClick(tab, event) { |
| | | // console.log(tab, event); |
| | | // }, |
| | | submitForm(formName) { |
| | | this.$refs[formName].validate(valid => { |
| | | if (valid) { |
| | | //alert("submit!"); |
| | | let json = { |
| | | clusterId: this.clusterid, |
| | | clusterName: this.ruleForm.clustername, |
| | | password: this.ruleForm.clusterpwd, |
| | | virtualIp: this.ruleForm.virtualIp |
| | | }; |
| | | this.createCluster(json).then(() => { |
| | | this.findCluster(); |
| | | }); |
| | | } else { |
| | | console.log("error submit!!"); |
| | | return false; |
| | | } |
| | | }); |
| | | }, |
| | | |
| | | // saveForm(formName) { |
| | | // this.$refs[formName].validate(valid => { |
| | | // if (valid) { |
| | | // alert("submit!"); |
| | | // let json = { |
| | | // enable: this.vrIpForm.enable, |
| | | // serve_port: this.vrIpForm.serve_port, |
| | | // virtual_ip: this.vrIpForm.virtual_ip, |
| | | |
| | | // }; |
| | | // setVrrp(json).then(() => { |
| | | // this.getVrrpInfo(); |
| | | // }); |
| | | // } else { |
| | | // console.log("error submit!!"); |
| | | // return false; |
| | | // } |
| | | // }); |
| | | // }, |
| | | |
| | | join(formName) { |
| | | let _this = this; |
| | | this.$refs[formName].validate(valid => { |
| | | if (valid) { |
| | | _this.joinLoading = true; |
| | | // if (Object.keys(this.currentCluster).length === 0) { |
| | | // this.$notify({ |
| | | // type: "info", |
| | | // duration: 1000, |
| | | // message: "请先选择一个集群节点" |
| | | // }); |
| | | // _this.joinLoading = false; |
| | | // return true; |
| | | // } |
| | | let nodeIps = this.members.map(i => { |
| | | return i.Address; |
| | | }); |
| | | let json = { |
| | | //clusterId: this.currentCluster.cluster_id, |
| | | clusterId: this.joinForm.clusterid, |
| | | password: this.joinForm.clusterpwd, |
| | | nodeIps: [this.joinForm.clusterip] |
| | | }; |
| | | this.joinCluster(json).then(() => { |
| | | _this.joinLoading = false; |
| | | this.findCluster(); |
| | | }).catch(e => { |
| | | console.log(e); |
| | | _this.joinLoading = false; |
| | | }); |
| | | } else { |
| | | console.log("error submit!!"); |
| | | return false; |
| | | } |
| | | }); |
| | | }, |
| | | async createCluster(json) { |
| | | let res = await createSerfCluster(json); |
| | | console.log(res, "创建集群"); |
| | | this.$notify({ |
| | | title: res.success ? "成功" : "失败", |
| | | message: res.msg, |
| | | type: res.success ? "success" : "error" |
| | | }); |
| | | }, |
| | | async randomPwd() { |
| | | let res = await randomPwd(); |
| | | if (res && res.success) { |
| | | this.ruleForm.clusterpwd = res.data; |
| | | } |
| | | }, |
| | | async searchColony() { |
| | | this.isSearch = true; |
| | | this.$refs["joinForm"].clearValidate(); |
| | | this.$refs["joinForm"].validateField('clusterpwd'); |
| | | if (this.checkPsd(this.joinForm.clusterpwd)) { |
| | | this.members = []; |
| | | let json = { |
| | | password: this.joinForm.clusterpwd, |
| | | //ip: this.joinForm.clusterip |
| | | }; |
| | | |
| | | this.search(json) |
| | | .then(() => { |
| | | this.setSchedule(); |
| | | // this.searchDis = false; |
| | | // this.loading = false; |
| | | }) |
| | | .catch(() => { |
| | | this.searchDis = false; |
| | | this.loading = false; |
| | | this.isSearch = false; |
| | | }); |
| | | } else { |
| | | this.searchDis = false; |
| | | this.loading = false; |
| | | this.isSearch = false; |
| | | return false; |
| | | } |
| | | //}); |
| | | }, |
| | | async search(json) { |
| | | let res = await search(json); |
| | | if (res && res.success) { |
| | | console.log(res, "搜索集群"); |
| | | this.searchNum = res.data; |
| | | } |
| | | this.searchDis = true; |
| | | this.loading = true; |
| | | window.setTimeout(() => { |
| | | this.stopSearch(); |
| | | }, 10 * 1000); |
| | | }, |
| | | //搜索集群 |
| | | async getSearchNodes() { |
| | | let res = await getSearchNodes(); |
| | | if (res && res.success) { |
| | | let list = res.data.map(i => { |
| | | let obj = {}; |
| | | obj.cluster_id = i.clusterID ? i.clusterID : ""; |
| | | obj.create_time = i.create_time ? i.create_time : ""; |
| | | obj.id = i.nodeID ? i.nodeID : ""; |
| | | obj.node_id = i.nodeID ? i.nodeID : ""; |
| | | obj.Address = i.nodeAddress ? i.nodeAddress : ""; |
| | | obj.nodeName = i.nodeAddress ? i.nodeAddress : ""; |
| | | obj.role = i.role ? i.role : "pc"; |
| | | return obj; |
| | | }); |
| | | list.map(i => { |
| | | let found = this.members.find(element => { |
| | | return element.node_id === i.node_id; |
| | | }); |
| | | if (found === undefined) { |
| | | this.members.push(i); |
| | | } |
| | | }); |
| | | } |
| | | }, |
| | | setSchedule() { |
| | | this.scheduleId = window.setInterval(() => { |
| | | this.getSearchNodes(); |
| | | }, 1000); |
| | | }, |
| | | async stopSearch() { |
| | | if (!this.loading) { |
| | | return true; |
| | | } |
| | | stopSearching({ |
| | | searchNum: this.searchNum |
| | | }).then((res) => { |
| | | console.log(res, '正常结束') |
| | | this.loading = false; |
| | | this.searchDis = false; |
| | | window.clearInterval(this.scheduleId); |
| | | }).catch((err) => { |
| | | console.log(err, '报错结束') |
| | | this.$notify({ |
| | | type: 'error', |
| | | duration: 1000, |
| | | message: '停止搜索报错!' |
| | | }) |
| | | // window.setTimeout(()=>{ |
| | | // this.loading = false; |
| | | // this.searchDis = false; |
| | | // window.clearInterval(this.scheduleId); |
| | | // },2000) |
| | | }) |
| | | }, |
| | | async findCluster() { |
| | | let res = await findCluster(); |
| | | if (res && res.success) { |
| | | if (res.data && res.data.clusterId) { |
| | | this.isHasColony = true; |
| | | this.activeName = "3"; |
| | | this.clusterid = res.data.clusterId; |
| | | this.ruleForm.clustername = res.data.clusterName; |
| | | this.ruleForm.clusterpwd = '******'; |
| | | this.ruleForm.virtualIp = res.data.virtualIp |
| | | //let list = res.data.nodes.map(i => { |
| | | this.isSearch = false; |
| | | this.innerNodes = res.data.nodes.map(i => { |
| | | let obj = {}; |
| | | obj.device_type = i.device_type; |
| | | obj.workType = i.device_type.substr(2, 2); |
| | | obj.hardwareType = i.device_type.substr(4, 2); |
| | | obj.cluster_id = i.cluster_id; |
| | | obj.clusterName = res.data.clusterName; |
| | | obj.create_time = i.create_time; |
| | | obj.id = i.id; |
| | | obj.node_id = i.node_id; |
| | | obj.node_ip = i.node_ip; |
| | | obj.nodeName = i.node_name; |
| | | obj.Address = i.node_ip; |
| | | obj.role = i.drift_state ? i.drift_state : "pc"; |
| | | return obj; |
| | | }); |
| | | |
| | | //this.members = this.members.concat(list); |
| | | console.log(this.members) |
| | | } else { |
| | | this.isHasColony = false; |
| | | // this.activeName = '1' |
| | | } |
| | | } |
| | | }, |
| | | // getVrrpInfo() { |
| | | // getVrrp().then(res => { |
| | | // if (res.success) { |
| | | // this.vrIpForm.virtual_ip = res.data.virtual_ip; |
| | | // this.vrIpForm.enable = res.data.enable; |
| | | // } |
| | | // }).catch(e => { |
| | | // console.log(e) |
| | | // }) |
| | | // }, |
| | | async updateCluster() { |
| | | if (this.ruleForm.clustername === "") { |
| | | this.$message({ |
| | | type: "error", |
| | | message: "集群名称不能为空" |
| | | }) |
| | | |
| | | return |
| | | } |
| | | |
| | | let res = await updateClusterName({ |
| | | clusterName: this.ruleForm.clustername, |
| | | virtualIp: this.ruleForm.virtualIp |
| | | }); |
| | | this.$notify({ |
| | | title: res.success ? "成功" : "失败", |
| | | message: res.msg, |
| | | type: res.success ? "success" : "error" |
| | | }); |
| | | }, |
| | | async joinCluster(json) { |
| | | let res = await joinCluster(json); |
| | | if (res.success) { |
| | | this.members = [] |
| | | } |
| | | this.$notify({ |
| | | title: res.success ? "成功" : "失败", |
| | | message: res.msg, |
| | | type: res.success ? "success" : "error" |
| | | }); |
| | | }, |
| | | leave() { |
| | | this.$confirm(`确定退出集群吗?`, { |
| | | center: true, |
| | | cancelButtonClass: "comfirm-class-cancle", |
| | | confirmButtonClass: "comfirm-class-sure" |
| | | }).then(async () => { |
| | | let res = await leave(); |
| | | this.$notify({ |
| | | title: res.success ? "成功" : "失败", |
| | | message: res.msg, |
| | | type: res.success ? "success" : "error" |
| | | }); |
| | | if (res && res.success) { |
| | | this.ruleForm.clustername = ""; |
| | | this.ruleForm.clusterpwd = "" |
| | | this.clusterid = ""; |
| | | this.isHasColony = false; |
| | | this.activeName = "1"; |
| | | this.members = []; |
| | | this.innerNodes = []; |
| | | } |
| | | }).catch(() => { |
| | | this.ruleForm.clustername = ""; |
| | | this.ruleForm.clusterpwd = "" |
| | | this.clusterid = ""; |
| | | this.isHasColony = false; |
| | | this.activeName = "1"; |
| | | this.members = []; |
| | | this.innerNodes = []; |
| | | }); |
| | | |
| | | }, |
| | | joinNode(event, node) { |
| | | console.log('join', node) |
| | | let _this = this; |
| | | this.currentCluster.cluster_id = node.cluster_id; |
| | | if (this.activeName === "3") { |
| | | this.manageForm.clustername = node.clusterName; |
| | | this.clusterid = node.cluster_id; |
| | | return; |
| | | } |
| | | if (this.activeName === "2") { |
| | | if (_this.showJoinConfirm) return; |
| | | |
| | | this.$confirm("是否要加入节点 " + node.nodeName + "?", "加入集群", { |
| | | confirmButtonText: "确定", |
| | | cancelButtonText: "取消", |
| | | type: "success" |
| | | }) |
| | | .then(() => { |
| | | _this.showJoinConfirm = true; |
| | | let json = { |
| | | //clusterId: this.currentCluster.cluster_id, |
| | | clusterId: node.cluster_id, |
| | | password: this.joinForm.clusterpwd, |
| | | nodeIps: [node.Address] |
| | | }; |
| | | this.joinCluster(json).then(() => { |
| | | _this.showJoinConfirm = false; |
| | | this.findCluster(); |
| | | }).catch(e => { |
| | | console.log(e); |
| | | _this.showJoinConfirm = false; |
| | | }); |
| | | }).catch(e => { |
| | | console.log(e) |
| | | }); |
| | | |
| | | // this.$refs["joinForm"].validate(valid => { |
| | | // if (valid) { |
| | | // if (_this.showJoinConfirm) return; |
| | | // _this.showJoinConfirm = true; |
| | | // this.$confirm("是否要加入节点 " + node.nodeName + "?", "加入集群", { |
| | | // confirmButtonText: "确定", |
| | | // cancelButtonText: "取消", |
| | | // type: "success" |
| | | // }) |
| | | // .then(() => { |
| | | |
| | | // console.log(this.currentCluster, '选择的集群节点') |
| | | // this.join("joinForm"); |
| | | // _this.showJoinConfirm = false; |
| | | // }) |
| | | // .catch(() => { |
| | | // this.$notify({ |
| | | // type: "info", |
| | | // duration: 1000, |
| | | // message: "已取消" |
| | | // }); |
| | | // _this.showJoinConfirm = false; |
| | | // }); |
| | | // } else { |
| | | // console.log("error submit!!"); |
| | | // return false; |
| | | // } |
| | | // }); |
| | | } |
| | | }, |
| | | generatePassword() { |
| | | var chars = |
| | | "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; |
| | | var uuid = []; |
| | | |
| | | for (let i = 0; i < 6; i++) { |
| | | uuid[i] = chars[0 | (Math.random() * 50)]; |
| | | } |
| | | |
| | | this.ruleForm.clusterpwd = uuid.join(""); |
| | | }, |
| | | |
| | | async getEsClusterNodes() { |
| | | let rsp = await getDevInfo(); |
| | | let hostIpAddr = ""; |
| | | if (rsp && rsp.success) { |
| | | hostIpAddr = rsp.data.ip; |
| | | } |
| | | |
| | | if (hostIpAddr.length) { |
| | | rsp = await getEsClusterInfo({ ip: hostIpAddr }); |
| | | if (rsp && rsp.success) { |
| | | this.esNodes = rsp.data.map(el => { |
| | | return { |
| | | // buildDate: "2018-06-11T23:38:03.357887Z", |
| | | buildDate: el.buildDate.split("T")[0] + " " + el.buildDate.split("T")[1].slice(0, 8), |
| | | ip: el.ip, |
| | | name: el.name, |
| | | nodeType: el.nodeType, |
| | | } |
| | | }) |
| | | |
| | | if (this.esNodes.length) { |
| | | this.sActiveName = 's-third'; |
| | | } |
| | | } |
| | | } |
| | | }, |
| | | createEsCluster() { |
| | | createESNode().then(rsp => { |
| | | if (rsp && rsp.success) { |
| | | this.$message({ |
| | | type: "success", |
| | | duration: 2000, |
| | | message: "创建成功" |
| | | }); |
| | | |
| | | this.getSearchNodes(); |
| | | } else { |
| | | this.$message({ |
| | | type: "error", |
| | | duration: 2000, |
| | | message: rsp.msg |
| | | }); |
| | | } |
| | | }).catch(rsp => { |
| | | this.$message({ |
| | | type: "error", |
| | | duration: 2000, |
| | | message: rsp.msg |
| | | }); |
| | | }) |
| | | }, |
| | | joinESCluster() { |
| | | if (!this.esNodeIp.length) { |
| | | this.$message({ |
| | | type: "error", |
| | | duration: 2000, |
| | | message: "请输入正确的ip地址" |
| | | }); |
| | | return; |
| | | } |
| | | |
| | | addESNode({ ip: this.esNodeIp, option: this.esNodeType ? "1" : "2" }).then(rsp => { |
| | | if (rsp && rsp.success) { |
| | | this.$message({ |
| | | type: "success", |
| | | duration: 2000, |
| | | message: "加入成功" |
| | | }); |
| | | |
| | | this.getSearchNodes(); |
| | | } else { |
| | | this.$message({ |
| | | type: "error", |
| | | duration: 2000, |
| | | message: rsp.msg |
| | | }); |
| | | } |
| | | }).catch(rsp => { |
| | | this.$message({ |
| | | type: "error", |
| | | duration: 2000, |
| | | message: rsp.msg |
| | | }); |
| | | }) |
| | | }, |
| | | onIpBlur(ip) { |
| | | //this.vrIpForm.virtual_ip = ip; |
| | | this.ruleForm.virtualIp = ip; |
| | | console.log(this.ruleForm.virtualIp) |
| | | } |
| | | |
| | | }, |
| | | |
| | | created() { } |
| | | |
| | | }; |
| | | </script> |
| | | <style lang="scss"> |
| | | .s-cluster-management { |
| | | width: 100%; |
| | | height: 100%; |
| | | overflow: auto; |
| | | .el-form-item { |
| | | width: 500px; |
| | | } |
| | | .el-form-item.is-required:not(.is-no-asterisk) > .el-form-item__label:before, |
| | | .el-form-item.is-required:not(.is-no-asterisk) |
| | | .el-form-item__label-wrap |
| | | > .el-form-item__label:before { |
| | | display: none; |
| | | } |
| | | .ip-input-comp { |
| | | width: 400px; |
| | | max-width: 400px; |
| | | } |
| | | .el-button { |
| | | float: right; |
| | | } |
| | | .el-form-item__content { |
| | | text-align: left; |
| | | |
| | | input { |
| | | max-width: 400px !important; |
| | | } |
| | | } |
| | | |
| | | #e-alaycluster, |
| | | #e-dbcluster { |
| | | .el-tabs__header { |
| | | border: 0px solid #dcdfe6; |
| | | .el-tabs__item { |
| | | padding: 5px 50px; |
| | | height: 50px; |
| | | font-family: PingFangSC-Regular; |
| | | font-size: 14px; |
| | | color: #222222; |
| | | text-align: center; |
| | | border: 0px solid transparent; |
| | | } |
| | | .el-tabs__item:nth-child(2) { |
| | | padding-left: 50px; |
| | | } |
| | | .el-tabs__item:last-child { |
| | | padding-right: 50px; |
| | | } |
| | | .el-tabs__item.is-active { |
| | | color: #ff7733; |
| | | font-weight: bold; |
| | | // border-right-color: #fff; |
| | | // border-left-color: #fff; |
| | | } |
| | | .el-tabs__item:not(.is-disabled):hover { |
| | | color: #ff7733; |
| | | } |
| | | } |
| | | .el-tabs__active-bar { |
| | | background-color: #ff7733; |
| | | } |
| | | .el-form-item__content { |
| | | text-align: left; |
| | | input { |
| | | max-width: 420px; |
| | | } |
| | | } |
| | | } |
| | | |
| | | #h-alaycluster { |
| | | .el-form-item__content { |
| | | text-align: left; |
| | | // input { |
| | | // max-width: 360px; |
| | | // } |
| | | } |
| | | } |
| | | } |
| | | .ui-top-view { |
| | | height: 30px; |
| | | line-height: 30px; |
| | | } |
| | | </style> |
| New file |
| | |
| | | <template> |
| | | <div class="s-log-management"> |
| | | <div class="top"> |
| | | <b>日志类型:</b> |
| | | <el-select v-model="logValue" placeholder="请选择" size="small"> |
| | | <el-option |
| | | v-for="item in logOptions" |
| | | :key="item.value" |
| | | :label="item.label" |
| | | :value="item.value" |
| | | ></el-option> |
| | | </el-select> |
| | | <b>时间:</b> |
| | | <el-date-picker |
| | | v-model="timeValue" |
| | | type="datetimerange" |
| | | size="small" |
| | | range-separator="至" |
| | | start-placeholder="开始日期" |
| | | end-placeholder="结束日期" |
| | | ></el-date-picker> |
| | | <el-input |
| | | v-model="searchValue" |
| | | placeholder="请输入内容" |
| | | clearable |
| | | style="width: 150px;margin: 0px 10px;" |
| | | size="small" |
| | | ></el-input> |
| | | <el-button type="primary" size="small">搜索</el-button> |
| | | <el-button type="danger" size="small" @click="delSelected">批量删除</el-button> |
| | | <el-button type="text" size="small" style="font-size: 13px;font-weight: 600;">导出</el-button> |
| | | </div> |
| | | <div class="foot-table s-table"> |
| | | <el-table |
| | | ref="multipleTable" |
| | | highlight-current-row |
| | | :data="tableData" |
| | | style="width: 100%" |
| | | :header-cell-style="{background:'#f8f8f8',color:'#222222'}" |
| | | @selection-change="handleSelectionChange" |
| | | > |
| | | <el-table-column type="selection" width="55"></el-table-column> |
| | | <el-table-column :align="'center'" sortable prop="index" label="序号"></el-table-column> |
| | | <el-table-column :align="'center'" sortable prop="logtype" label="日志类型"></el-table-column> |
| | | <el-table-column :align="'center'" sortable prop="username" label="用户名"></el-table-column> |
| | | <el-table-column :align="'center'" sortable prop="ipaddress" label="IP地址"></el-table-column> |
| | | <el-table-column :align="'center'" sortable prop="operation" label="操作功能"></el-table-column> |
| | | <el-table-column :align="'center'" sortable prop="operatetime" label="操作时间"></el-table-column> |
| | | <el-table-column :align="'center'" sortable prop="operateinfo" label="操作信息"></el-table-column> |
| | | <el-table-column label="操作" :align="'center'"> |
| | | <template slot-scope="scope"> |
| | | <el-button |
| | | type="text" |
| | | style="color: red;font-size:16px" |
| | | @click="handleDelete(scope.$index, scope.row)" |
| | | icon="el-icon-delete" |
| | | ></el-button> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | | </div> |
| | | </div> |
| | | </template> |
| | | |
| | | <script> |
| | | export default { |
| | | data() { |
| | | return { |
| | | tableData: [ |
| | | { |
| | | index: "1", |
| | | logtype: "异常", |
| | | username: "admin", |
| | | ipaddress: "192.168.10.110", |
| | | operation: "添加摄像机", |
| | | operatetime: "2019-5-31 16:38:21", |
| | | operateinfo: "添加操作" |
| | | }, |
| | | { |
| | | index: "2", |
| | | logtype: "信息", |
| | | username: "admin", |
| | | ipaddress: "192.168.10.108", |
| | | operation: "删除摄像机", |
| | | operatetime: "2019-5-31 16:38:21", |
| | | operateinfo: "添加操作" |
| | | }, |
| | | { |
| | | index: "3", |
| | | logtype: "操作", |
| | | username: "admin", |
| | | ipaddress: "192.168.10.110", |
| | | operation: "添加摄像机", |
| | | operatetime: "2019-5-31 16:38:21", |
| | | operateinfo: "添加操作" |
| | | }, |
| | | { |
| | | index: "4", |
| | | logtype: "异常", |
| | | username: "admin", |
| | | ipaddress: "192.168.10.110", |
| | | operation: "添加摄像机", |
| | | operatetime: "2019-5-31 16:38:21", |
| | | operateinfo: "添加操作" |
| | | }, |
| | | { |
| | | index: "5", |
| | | logtype: "异常", |
| | | username: "admin", |
| | | ipaddress: "192.168.10.110", |
| | | operation: "删除摄像机", |
| | | operatetime: "2019-5-31 16:38:21", |
| | | operateinfo: "添加操作" |
| | | }, |
| | | { |
| | | index: "6", |
| | | logtype: "异常", |
| | | username: "admin", |
| | | ipaddress: "192.168.10.110", |
| | | operation: "添加摄像机", |
| | | operatetime: "2019-5-31 16:38:21", |
| | | operateinfo: "添加操作" |
| | | } |
| | | ], |
| | | multipleSelection: [], |
| | | logOptions: [ |
| | | { |
| | | value: "全部类型", |
| | | label: "全部类型" |
| | | }, |
| | | { |
| | | value: "其他类型", |
| | | label: "其他类型" |
| | | } |
| | | ], |
| | | logValue: "全部类型", |
| | | timeValue: [ |
| | | new Date(2000, 10, 10, 10, 10), |
| | | new Date(2000, 10, 11, 10, 10) |
| | | ], |
| | | searchValue: "" |
| | | }; |
| | | }, |
| | | methods: { |
| | | handleDelete(index, row) { |
| | | console.log(index, row); |
| | | }, |
| | | handleSelectionChange(val) { |
| | | this.multipleSelection = val; |
| | | }, |
| | | delSelected() { |
| | | console.log(this.multipleSelection); |
| | | } |
| | | } |
| | | }; |
| | | </script> |
| | | <style lang="scss"> |
| | | .s-log-management { |
| | | height: 100%; |
| | | width: 100%; |
| | | .top { |
| | | width: 100%; |
| | | margin-top: 10px; |
| | | margin-bottom: 20px; |
| | | overflow-y: auto; |
| | | min-width: 1156px; |
| | | height: 40px; |
| | | text-align: left; |
| | | b { |
| | | padding: 0px 10px; |
| | | } |
| | | } |
| | | .export { |
| | | display: inline-block; |
| | | padding-right: 10px; |
| | | box-sizing: border-box; |
| | | margin-top: 20px; |
| | | b:hover { |
| | | color: #2249b4; |
| | | } |
| | | } |
| | | .clear-searching { |
| | | cursor: pointer; |
| | | text-decoration: underline; |
| | | width: 40px; |
| | | font-size: 13px; |
| | | color: #3d68e1; |
| | | } |
| | | } |
| | | </style> |
| New file |
| | |
| | | <template> |
| | | <div class="s-radio-set"> |
| | | <div class="add-btn"> |
| | | <el-button size="mini" type="primary" @click="handleAdd()">添加</el-button> |
| | | </div> |
| | | <el-table |
| | | border |
| | | highlight-current-row |
| | | :data="tableData" |
| | | style="width: 100%; margin-top:40px; color:#000" |
| | | :header-cell-style="{background:'#f8f8f8',color:'#222222'}" |
| | | > |
| | | <el-table-column align="center" type="index" label="序号" width="100px"></el-table-column> |
| | | |
| | | <el-table-column :align="'center'" label="广播名称"> |
| | | <template slot-scope="{row}"> |
| | | <el-input v-if="row.edit" :autofocus="row.edit" v-model="row.radiosName" size="small" /> |
| | | <span v-else>{{ row.radiosName }}</span> |
| | | </template> |
| | | </el-table-column> |
| | | |
| | | <el-table-column :align="'center'" label="IP地址"> |
| | | <template slot-scope="{row}"> |
| | | <el-input v-if="row.edit" v-model="row.ipAddress" size="small" /> |
| | | <span v-else>{{ row.ipAddress }}</span> |
| | | </template> |
| | | </el-table-column> |
| | | |
| | | <el-table-column :align="'center'" label="连接测试"> |
| | | <template slot-scope="{row}"> |
| | | <i v-show="row.isCon" class="el-icon-success" style="color:green; font-size:18px"></i> |
| | | |
| | | <el-button type="text" @click="handleTest(row)">连接测试</el-button> |
| | | </template> |
| | | </el-table-column> |
| | | |
| | | <el-table-column label="操作" :align="'center'"> |
| | | <template slot-scope="scope"> |
| | | <template v-if="scope.row.edit"> |
| | | <el-button size="mini" type="info" @click="handleCancel(scope.row)">取消</el-button> |
| | | <el-button size="mini" type="primary" @click="handleSave(scope.row)">保存</el-button> |
| | | </template> |
| | | <template v-else> |
| | | <el-button |
| | | type="text" |
| | | style="color: black;font-size:18px" |
| | | @click="handleEdit(scope.row)" |
| | | icon="el-icon-edit" |
| | | ></el-button> |
| | | <el-button |
| | | type="text" |
| | | style="color: red;font-size:18px" |
| | | @click="handleDelete(scope.$index)" |
| | | icon="el-icon-delete" |
| | | ></el-button> |
| | | </template> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | | </div> |
| | | </template> |
| | | |
| | | <script> |
| | | export default { |
| | | filters: { |
| | | isCon(r) { |
| | | return r.isCon ? r.isCon : false |
| | | } |
| | | }, |
| | | data() { |
| | | return { |
| | | radioName: "", |
| | | ipAddress: "", |
| | | tableData: [ |
| | | { |
| | | index: "1", |
| | | radiosName: "操场", |
| | | ipAddress: "192.168.1.101", |
| | | edit: false, |
| | | isCon: false |
| | | }, |
| | | { |
| | | edit: false, |
| | | index: "2", |
| | | radiosName: "教室", |
| | | ipAddress: "192.168.12.61", |
| | | isCon: false |
| | | }, |
| | | { |
| | | edit: false, |
| | | index: "3", |
| | | radiosName: "保安室", |
| | | ipAddress: "192.168.13.121", |
| | | isCon: false |
| | | } |
| | | ] |
| | | }; |
| | | }, |
| | | mounted() { |
| | | this.testAll() |
| | | }, |
| | | methods: { |
| | | testAll() { |
| | | this.tableData.forEach(l => { |
| | | this.$set(l, "isCon", false) |
| | | }) |
| | | }, |
| | | handleEdit(row) { |
| | | console.log(row); |
| | | row.edit = true; |
| | | }, |
| | | handleCancel(row) { |
| | | row.edit = false; |
| | | console.log(row); |
| | | }, |
| | | handleDelete(index) { |
| | | this.$confirm("确认删除该广播吗?", { |
| | | center: true, |
| | | cancelButtonClass: "comfirm-class-cancle", |
| | | confirmButtonClass: "comfirm-class-sure" |
| | | }) |
| | | .then(() => { |
| | | this.tableData.splice(index, 1) |
| | | this.$notify({ |
| | | type: "success", |
| | | message: "删除成功!" |
| | | }); |
| | | }) |
| | | .catch(() => { }); |
| | | }, |
| | | handleSave(row) { |
| | | console.log(row); |
| | | row.edit = false; |
| | | this.$notify({ |
| | | message: "保存成功", |
| | | type: "success" |
| | | }); |
| | | }, |
| | | handleTest(row) { |
| | | this.$set(row, 'isCon', true) |
| | | }, |
| | | handleAdd() { |
| | | this.tableData.push({ |
| | | radiosName: "", |
| | | ipAddress: "", |
| | | edit: true, |
| | | isCon: false |
| | | }) |
| | | } |
| | | } |
| | | }; |
| | | </script> |
| | | <style lang="scss"> |
| | | .s-radio-set { |
| | | width: 100%; |
| | | height: 100%; |
| | | .el-dialog { |
| | | border-radius: 8px; |
| | | border: 1px solid #ccc; |
| | | .el-dialog__header { |
| | | border-bottom: 1px solid #ccc; |
| | | } |
| | | } |
| | | |
| | | .add-btn { |
| | | float: right; |
| | | margin-bottom: 7px; |
| | | } |
| | | } |
| | | .e-message { |
| | | width: 331px; |
| | | } |
| | | .e-confirm { |
| | | border-color: #ff0000 !important; |
| | | background-color: #ff0000 !important; |
| | | } |
| | | .e-confirm:hover { |
| | | border-color: #f83131d6 !important; |
| | | background-color: #f83131d6 !important; |
| | | } |
| | | .e-cancel { |
| | | border-color: #eaeaea !important; |
| | | background-color: #eaeaea !important; |
| | | } |
| | | .e-cancel:hover { |
| | | border-color: #e9e9e9 !important; |
| | | background-color: #e9e9e9 !important; |
| | | } |
| | | </style> |
| New file |
| | |
| | | <template>
|
| | | <el-tabs
|
| | | id="systemMaintenance"
|
| | | v-model="activeName"
|
| | | v-loading="loading"
|
| | | :element-loading-text="loadingText"
|
| | | >
|
| | | <el-tab-pane label="设备维护" name="first" v-if="isShow('videoSystem:sysManage:sysfix')">
|
| | | <div class="s-system-maintenance">
|
| | | <div class="box-card">
|
| | | <div class="ui-top-view">
|
| | | <div class="ui-top-title">重启</div>
|
| | | </div>
|
| | | <el-divider></el-divider>
|
| | |
|
| | | <div class="box-card-content">
|
| | | <el-row>
|
| | | <el-col :span="1">
|
| | | <el-button type="primary" size="small" style="width:80px" @click="reboot">重启</el-button>
|
| | | </el-col>
|
| | | <el-col :span="23">
|
| | | <b class="card-text">重启节点</b>
|
| | | </el-col>
|
| | | </el-row>
|
| | | <el-row style="margin-top:20px">
|
| | | <el-col>
|
| | | <vue-cron :expression="rebootCron" @update="setRebootCron" />
|
| | | </el-col>
|
| | | </el-row>
|
| | | </div>
|
| | | </div>
|
| | | <!--
|
| | | <div class="box-card">
|
| | | <div class="ui-top-view">
|
| | | <div class="ui-top-title">恢复默认值</div>
|
| | | </div>
|
| | | <el-divider></el-divider>
|
| | |
|
| | | <div class="box-card-content">
|
| | | <el-row>
|
| | | <el-col :span="1">
|
| | | <el-button type="primary" size="small">简单恢复</el-button>
|
| | | </el-col>
|
| | | <el-col :span="23">
|
| | | <b class="card-text">简单恢复设备参数</b>
|
| | | </el-col>
|
| | | </el-row>
|
| | | <el-row style="margin-top:20px">
|
| | | <el-col :span="1">
|
| | | <el-button type="primary" size="small">完全恢复</el-button>
|
| | | </el-col>
|
| | | <el-col :span="23">
|
| | | <b class="card-text">完全恢复设备参数到出厂设置</b>
|
| | | </el-col>
|
| | | </el-row>
|
| | | </div>
|
| | | </div>
|
| | | |
| | | <div class="box-card">
|
| | | <div class="ui-top-view">
|
| | | <div class="ui-top-title">参数导入导出</div>
|
| | | </div>
|
| | | <el-divider></el-divider>
|
| | |
|
| | | <div class="box-card-content">
|
| | | <el-row :gutter="4">
|
| | | <el-col :span="1">
|
| | | <el-button type="info" size="small" style="width:80px">导入</el-button>
|
| | | </el-col>
|
| | | <el-col :span="3" style="padding-left:30px">
|
| | | <el-input placeholder="上传参数文件" size="small" :readonly="true">
|
| | | <el-upload slot="suffix" action="https://jsonplaceholder.typicode.com/posts/">
|
| | | <el-button
|
| | | type="text"
|
| | | icon="el-icon-upload2"
|
| | | size="small"
|
| | | style="font-size:18px; color:#0088ff"
|
| | | ></el-button>
|
| | | </el-upload>
|
| | | </el-input>
|
| | | </el-col>
|
| | | </el-row>
|
| | | <el-row style="margin-top:20px">
|
| | | <el-col :span="1">
|
| | | <el-button type="primary" size="small">设备参数</el-button>
|
| | | </el-col>
|
| | | <el-col :span="23">
|
| | | <b class="card-text">参数导出</b>
|
| | | </el-col>
|
| | | </el-row>
|
| | | </div>
|
| | | </div>
|
| | | -->
|
| | | <div class="box-card">
|
| | | <div class="ui-top-view">
|
| | | <div class="ui-top-title">升级</div>
|
| | | </div>
|
| | | </div>
|
| | | <el-divider></el-divider>
|
| | | <div class="box-card-content">
|
| | | <el-row :gutter="4">
|
| | | <el-col :span="6">
|
| | | <file-uploader
|
| | | single
|
| | | uploadPlaceholder="上传升级文件"
|
| | | url="/data/api-v/sysset/patchUpdate"
|
| | | @complete="onFileUpload"
|
| | | @file-added="onFileAdded"
|
| | | />
|
| | | </el-col>
|
| | | <el-col :span="2">
|
| | | <el-button
|
| | | type="primary"
|
| | | size="small"
|
| | | style="width:80px"
|
| | | @click="upgrade"
|
| | | :disabled="!fileAdded"
|
| | | :loading="upgrading"
|
| | | >升级</el-button>
|
| | | </el-col>
|
| | | <el-col :span="16" class="upload-msg">
|
| | | <span v-html="patchUpdateStatus"></span>
|
| | | </el-col>
|
| | | </el-row>
|
| | | </div>
|
| | | </div>
|
| | | </el-tab-pane>
|
| | | <el-tab-pane label="数据库维护" name="second" v-if="isShow('videoSystem:sysManage:dbfix')">
|
| | | <div class="box"> |
| | | <p class="title">
|
| | | <label>数据清理</label>
|
| | | </p> |
| | | <div class="range">
|
| | | <div class="left">
|
| | | <p>选择数据范围:</p>
|
| | | </div> |
| | | <div class="middle">
|
| | | <el-date-picker
|
| | | v-model="dataRange"
|
| | | type="daterange"
|
| | | range-separator="至"
|
| | | start-placeholder="开始日期"
|
| | | end-placeholder="结束日期"
|
| | | style="height:38px"
|
| | | :picker-options="pickerOptions"
|
| | | ></el-date-picker>
|
| | | </div>
|
| | | <div class="right">
|
| | | <el-button @click="deleteData" style="height:38px;background:#ff0000;color:white">删除数据</el-button>
|
| | | </div> |
| | | </div> |
| | | <div class="tip">
|
| | | <i class="iconfont icontishi-zhuyi"></i>
|
| | | <p class="zhuyi">请注意,按以上日期范围删除的数据不可恢复,立即生效,请谨慎操作</p>
|
| | | </div> |
| | | </div> |
| | | </el-tab-pane> |
| | | </el-tabs> |
| | |
|
| | | </template>
|
| | |
|
| | | <script>
|
| | | import { rebootServer, getDevInfo, getRebootTask, setRebootTask, fileUpload, doUpgrade,deleteDate } from "@/api/system"
|
| | | import VueCron from "@/components/subComponents/VueCron"
|
| | | import FileUploader from "@/components/subComponents/FileUpload/index"
|
| | |
|
| | | export default {
|
| | | components: {
|
| | | VueCron,
|
| | | FileUploader
|
| | | },
|
| | | data() {
|
| | | return {
|
| | | timer: null,
|
| | | buttonAuthority: sessionStorage.getItem("buttonAuthoritys") || [],
|
| | | rebootCron: "",
|
| | | activeName: "first",
|
| | | restartValue: "不重启",
|
| | | restartTimeValue: new Date(2019, 9, 10, 18, 40),
|
| | | loading: false,
|
| | | loadingText: '',
|
| | | probeSum: 0,
|
| | | patchUpdateStatus: "",
|
| | | dataRange: [
|
| | | this.$moment().format("YYYY-MM-DD HH:mm:ss"),
|
| | | this.$moment().format("YYYY-MM-DD HH:mm:ss")
|
| | | ],
|
| | | fileUploadUrl: fileUpload,
|
| | | patchFile: {},
|
| | | pickerOptions: {
|
| | | disabledDate(time) {
|
| | | var day = new Date()
|
| | | day.setTime(day.getTime() - 24 * 60 * 60 * 1000)
|
| | | return time.getTime() > day;
|
| | | },
|
| | | },
|
| | | upgrading: false,
|
| | | fileAdded: false
|
| | | };
|
| | | },
|
| | | mounted() {
|
| | | this.getRebootCron()
|
| | | if (!this.isShow('videoSystem:sysManage:sysfix')) {
|
| | | console.log("默认显示数据库维护")
|
| | | this.activeName = "second"
|
| | | }
|
| | | },
|
| | | computed: {
|
| | | isAdmin() {
|
| | | if (
|
| | | sessionStorage.getItem('userInfo') &&
|
| | | sessionStorage.getItem('userInfo') !== ''
|
| | | ) {
|
| | | let loginName = JSON.parse(sessionStorage.getItem('userInfo')).username
|
| | | return (
|
| | | loginName === 'superadmin' || loginName === 'basic'
|
| | | )
|
| | | }
|
| | | return false;
|
| | | }
|
| | | },
|
| | | methods: {
|
| | | isShow (authority) {
|
| | | if (this.isAdmin) {
|
| | | return true
|
| | | } else if (
|
| | | this.buttonAuthority.indexOf(',' + authority + ',') > -1
|
| | | ) {
|
| | | return true
|
| | | } else {
|
| | | return false
|
| | | }
|
| | | },
|
| | | format(array) {
|
| | | return [
|
| | | this.$moment(array[0]).format("YYYY-MM-DD"),
|
| | | this.$moment(array[1]).format("YYYY-MM-DD")
|
| | | ];
|
| | | },
|
| | | getRebootCron() {
|
| | | getRebootTask().then(rsp => {
|
| | | this.rebootCron = rsp.data
|
| | | })
|
| | | },
|
| | | setRebootCron(value) {
|
| | | this.rebootCron = value
|
| | | setRebootTask({ task: value }).then(rsp => {
|
| | | if (rsp && rsp.success) {
|
| | | this.$notify({
|
| | | type: "success",
|
| | | message: "配置成功"
|
| | | })
|
| | | }
|
| | | }).catch(err => {
|
| | | this.$notify({
|
| | | type: "error",
|
| | | message: "配置失败"
|
| | | })
|
| | | })
|
| | | },
|
| | | reboot() {
|
| | | this.$confirm('确定要重启该节点吗?', {
|
| | | center: true,
|
| | | cancelButtonClass: 'comfirm-class-cancle',
|
| | | confirmButtonClass: 'comfirm-class-sure'
|
| | | }).then(() => {
|
| | | this.loading = true;
|
| | | this.loadingText = "智能计算节点正在重启,请耐心等待..."
|
| | | rebootServer().then(rsp => {
|
| | | this.probeServer(this.reLogin)
|
| | | }).catch(err => {
|
| | | if (err.status == 400) {
|
| | | this.loading = false;
|
| | | this.$notify({
|
| | | type: "error",
|
| | | message: "重启计算节点失败"
|
| | | })
|
| | | } else {
|
| | | this.probeServer(this.reLogin)
|
| | | }
|
| | | })
|
| | | })
|
| | | },
|
| | | deleteData() {
|
| | | var timeRange = this.format(this.dataRange);
|
| | | var showStartTime = timeRange[0]
|
| | | var showEndTime = timeRange[1]
|
| | | console.log("时间:",showStartTime,showEndTime)
|
| | | this.$confirm("提示:"+showStartTime+" 至 "+showEndTime+" 产生的全部数据将被删除,此操作立即生效,不可恢复,是否删除?", {
|
| | | center: true,
|
| | | cancelButtonClass: "comfirm-class-cancle",
|
| | | confirmButtonClass: "comfirm-class-sure"
|
| | | }).then(() => {
|
| | | this.loading = true
|
| | | this.loadingText = "正在删除数据,请稍候!"
|
| | | var param = {
|
| | | startTime: showStartTime,
|
| | | endTime: showEndTime
|
| | | }
|
| | | deleteDate(param).then(resp => {
|
| | | if (resp.success) {
|
| | | this.$message({
|
| | | type: "success",
|
| | | message: "删除数据成功"
|
| | | })
|
| | | this.loading = false
|
| | | }
|
| | | }).catch(err => {
|
| | | this.$message({
|
| | | type: "error",
|
| | | message: "删除数据失败!"
|
| | | })
|
| | | this.loading = false
|
| | | })
|
| | |
|
| | | }).catch(() => {
|
| | | console.log("取消了!")
|
| | | })
|
| | | },
|
| | | reLogin() {
|
| | | this.$router.push("/")
|
| | | },
|
| | | probeServer(callback) {
|
| | | this.probeSum++;
|
| | | let _this = this
|
| | | if (this.probeSum > 60) {
|
| | | this.$confirm('连接服务器失败, 请刷新页面或联系管理员', '失败', {
|
| | | type: 'error',
|
| | | cancelButtonClass: 'comfirm-class-cancle',
|
| | | confirmButtonClass: 'comfirm-class-sure'
|
| | | }).then(() => {
|
| | | // _this.$router.push("/")
|
| | | callback()
|
| | | })
|
| | | return
|
| | | }
|
| | |
|
| | | this.timer = setTimeout(() => {
|
| | | getDevInfo().then(() => {
|
| | | // _this.$router.push("/")
|
| | | callback()
|
| | | }).catch(err => {
|
| | | _this.probeServer(callback)
|
| | | })
|
| | | }, 10000)
|
| | | },
|
| | | onFileUpload(file) {
|
| | | this.patchUpdateStatus = `<span style="color:green">上传成功, 点击升级按钮开始升级</span>`
|
| | | this.patchFile = { ...file }
|
| | | this.fileAdded = true
|
| | | },
|
| | | onFileAdded() {
|
| | | this.patchUpdateStatus = ""
|
| | | },
|
| | | upgrade() {
|
| | | this.upgrading = true
|
| | | this.patchUpdateStatus = `<span style="color:red">正在升级...</span>`
|
| | | doUpgrade(this.patchFile).then(rsp => {
|
| | | this.upgrading = false
|
| | |
|
| | | if (rsp && rsp.success) {
|
| | | clearTimeout(this.timer)
|
| | | this.doneUpgrade()
|
| | | }
|
| | | }).catch(err => {
|
| | | if (err.code) {
|
| | | this.upgrading = false
|
| | | this.patchUpdateStatus = `<span style="color:red">${err.data}</span>`
|
| | | clearTimeout(this.timer)
|
| | | } else {
|
| | | this.probeServer(this.doneUpgrade)
|
| | | }
|
| | | })
|
| | | },
|
| | | doneUpgrade() {
|
| | | this.upgrading = false
|
| | | this.patchUpdateStatus = `<span style="color:green">升级成功</span>`
|
| | | let _this = this
|
| | | this.$confirm('升级成功, 请重新登录系统', '成功', {
|
| | | type: 'success',
|
| | | cancelButtonClass: 'comfirm-class-cancle',
|
| | | confirmButtonClass: 'comfirm-class-sure'
|
| | | }).then(() => {
|
| | | _this.reLogin()
|
| | | })
|
| | | }
|
| | | }
|
| | | };
|
| | | </script>
|
| | | <style lang="scss">
|
| | | .s-system-maintenance {
|
| | | width: 100%;
|
| | | height: 100%;
|
| | | .box-card {
|
| | | text-align: left;
|
| | | height: auto;
|
| | | margin: 10px 0px;
|
| | | .box-card-content {
|
| | | padding-bottom: 40px;
|
| | | .card-text {
|
| | | padding: 0 30px;
|
| | | line-height: 32px;
|
| | | }
|
| | | }
|
| | | }
|
| | |
|
| | | .upload-icon {
|
| | | font-size: 18px;
|
| | | color: #0088ff;
|
| | | }
|
| | | .upload-msg {
|
| | | padding-left: 10px;
|
| | | text-align: left;
|
| | | span {
|
| | | line-height: 32px;
|
| | | font-size: 13px;
|
| | | }
|
| | | }
|
| | | }
|
| | | .box{
|
| | | width: 50%;
|
| | | min-width: 700px;
|
| | | height: 270px;
|
| | | border: 1px solid #eee;
|
| | | .title {
|
| | | font-size:20px;
|
| | | font-weight: bold;
|
| | | text-align: left;
|
| | | padding: 20px;
|
| | | border-bottom: 1px solid #eee;
|
| | | }
|
| | | .range {
|
| | | width: 100%;
|
| | | padding-top: 30px;
|
| | | height: 38px;
|
| | | .left {
|
| | | width: 120px;
|
| | | float: left;
|
| | | text-align: right;
|
| | | font-size: 14px;
|
| | | p {
|
| | | height: 38px;
|
| | | line-height: 38px;
|
| | | }
|
| | | }
|
| | | .middle {
|
| | | width: 50%;
|
| | | min-width: 400px;
|
| | | height: 38px;
|
| | | float: left;
|
| | | }
|
| | | .right {
|
| | | width: 20%;
|
| | | height: 38px;
|
| | | float: left;
|
| | | }
|
| | | }
|
| | | .tip {
|
| | | width: 100%;
|
| | | padding: 30px 0px 0px 30px;
|
| | | height: 34px;
|
| | |
|
| | | .zhuyi {
|
| | | font-size: 14px;
|
| | | height: 34px;
|
| | | line-height: 34px;
|
| | | margin-left: 20px;
|
| | | float: left;
|
| | | }
|
| | | i {
|
| | | font-size: 32px;
|
| | | color: #e99038;
|
| | | float: left;
|
| | | }
|
| | | }
|
| | | }
|
| | | #systemMaintenance{
|
| | |
|
| | | .el-tabs__header {
|
| | | border: 0px solid #dcdfe6;
|
| | | .el-tabs__item {
|
| | | padding: 5px 50px;
|
| | | height: 50px;
|
| | | font-family: PingFangSC-Regular;
|
| | | font-size: 14px;
|
| | | color: #222222;
|
| | | text-align: center;
|
| | | border: 0px solid transparent;
|
| | | }
|
| | | .el-tabs__item:nth-child(2) {
|
| | | padding-left: 50px;
|
| | | }
|
| | | .el-tabs__item:last-child {
|
| | | padding-right: 50px;
|
| | | }
|
| | | .el-tabs__item.is-active {
|
| | | color: #ff7733;
|
| | | font-weight: bold;
|
| | | // border-right-color: #fff;
|
| | | // border-left-color: #fff;
|
| | | }
|
| | | .el-tabs__item:not(.is-disabled):hover {
|
| | | color: #ff7733;
|
| | | }
|
| | | |
| | | }
|
| | | .el-tabs__active-bar {
|
| | | background-color: #ff7733;
|
| | | }
|
| | | .el-tabs__content {
|
| | | padding-left: 15px !important;
|
| | | }
|
| | | }
|
| | | </style>
|
| | |
| | | <template> |
| | | <div class="container" v-if="!showWelcome"> |
| | | <div class="container-left"> |
| | | <div |
| | | class="left-card" |
| | | :class="activeIndex == index ? 'left-card-active' : ''" |
| | | v-for="(item, index) in menuArr" |
| | | :key="index" |
| | | @click="openMenu(item.name, index)" |
| | | > |
| | | <span class="icon iconfont"></span> |
| | | <span class="card-text">{{ item.name }}</span> |
| | | </div> |
| | | </div> |
| | | |
| | | <div |
| | | class="container-center" |
| | | v-if="activePage == '账户' || activePage == '日期时间'" |
| | | > |
| | | <div class="account-left" v-if="activePage == '账户'"> |
| | | <div class="account-list"> |
| | | <div |
| | | class="account-card" |
| | | :class="activeAccountIndex == index ? 'account-card-active' : ''" |
| | | v-for="(item, index) in accountArr" |
| | | :key="index" |
| | | ref="account-card" |
| | | @click="openAccount(item, index)" |
| | | > |
| | | <div class="touxiang"> |
| | | <img |
| | | v-if="item.headpic" |
| | | :src="`data:image/png;base64,${item.headpic}`" |
| | | alt="" |
| | | /> |
| | | |
| | | </div> |
| | | <span class="user-name">{{ item.username }}</span> |
| | | </div> |
| | | </div> |
| | | <div class="add-account"> |
| | | <span class="icon iconfont" @click="showAddAccount"></span> |
| | | </div> |
| | | </div> |
| | | <div class="datetime-left" v-if="activePage == '日期时间'"> |
| | | <div class="time-card"> |
| | | <div class="head"> |
| | | <span class="icon iconfont"></span> |
| | | <span>设备时间</span> |
| | | </div> |
| | | <div class="time-main">{{ equipmentTime }}</div> |
| | | <div class="date-bot"> |
| | | <span class="year">{{ equipmentDate }}</span> |
| | | <span class="week">{{ weekday }}</span> |
| | | </div> |
| | | </div> |
| | | <div class="line"> |
| | | <div class="name">NTP校时</div> |
| | | <el-switch |
| | | v-model="isNtp" |
| | | @change="changeSwitch('isNtp')" |
| | | active-color="rgba(61, 104, 225, 1)" |
| | | > |
| | | </el-switch> |
| | | </div> |
| | | |
| | | <div class="line"> |
| | | <div class="name">手动校对</div> |
| | | <el-switch |
| | | v-model="isManual" |
| | | @change="changeSwitch('isManual')" |
| | | active-color="rgba(61, 104, 225, 1)" |
| | | > |
| | | </el-switch> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | <div |
| | | class="container-right" |
| | | v-if="activePage == '账户' || activePage == '日期时间'" |
| | | > |
| | | <div class="account-right" v-if="activePage == '账户'"> |
| | | <div |
| | | class="account-content" |
| | | v-if="inAccountDetail == false && isAddAccount == false" |
| | | > |
| | | <div class="content-top"> |
| | | <div class="touxiang-big"> |
| | | <img |
| | | v-if="activeAccountItem.headpic" |
| | | :src="`data:image/png;base64,${activeAccountItem.headpic}`" |
| | | alt="" |
| | | /> |
| | | </div> |
| | | <div class="user-desc"> |
| | | <div class="username"> |
| | | <span class="icon iconfont" style="margin-right: 5px" |
| | | ></span |
| | | > |
| | | <span>{{ activeAccountItem.username }}</span> |
| | | </div> |
| | | <div class="nickname"> |
| | | <span>昵称:</span> |
| | | <span v-show="!showInputNickName">{{ |
| | | activeAccountItem.nickname |
| | | }}</span> |
| | | <input |
| | | type="text" |
| | | class="input-nick" |
| | | ref="input-nick" |
| | | v-show="showInputNickName" |
| | | v-model="inputNickName" |
| | | @blur="hideInputNick" |
| | | @keydown.enter="blurInputNick" |
| | | /> |
| | | <span class="icon iconfont" @click="editNickName" |
| | | ></span |
| | | > |
| | | </div> |
| | | <div class="user-role"> |
| | | {{ |
| | | activeAccountItem.sysRoles.length |
| | | ? activeAccountItem.sysRoles[0].name |
| | | : "" |
| | | }} |
| | | </div> |
| | | </div> |
| | | </div> |
| | | <div class="list-btn"> |
| | | <div class="item-btn" @click="showChangePassword">修改密码</div> |
| | | <div class="item-btn" @click="deleteAccount">删除账户</div> |
| | | <div class="item-btn" @click="openPermission">权限设置</div> |
| | | </div> |
| | | </div> |
| | | |
| | | <div class="change-pw" v-if="inAccountDetail && isChangePw"> |
| | | <div class="title">修改密码</div> |
| | | <el-form |
| | | :model="passwordForm" |
| | | :rules="pwRules" |
| | | ref="passwordForm" |
| | | class="password-form" |
| | | > |
| | | <el-form-item prop="curPassword"> |
| | | <div class="p-title">当前密码:</div> |
| | | |
| | | <el-input |
| | | placeholder="必填" |
| | | v-model="passwordForm.curPassword" |
| | | show-password |
| | | ></el-input> |
| | | </el-form-item> |
| | | <el-form-item prop="newPassword"> |
| | | <div class="p-title">新密码:</div> |
| | | <el-input |
| | | placeholder="必填" |
| | | v-model="passwordForm.newPassword" |
| | | show-password |
| | | ></el-input> |
| | | </el-form-item> |
| | | <el-form-item prop="confirmPassword"> |
| | | <div class="p-title">确认密码:</div> |
| | | <el-input |
| | | placeholder="必填" |
| | | v-model="passwordForm.confirmPassword" |
| | | show-password |
| | | ></el-input> |
| | | </el-form-item> |
| | | </el-form> |
| | | <div class="btns"> |
| | | <div class="cancel" @click="cancelPassword">取消</div> |
| | | <div class="ok" @click="SaveNewPassword('passwordForm')">保存</div> |
| | | </div> |
| | | </div> |
| | | |
| | | <div class="permission" v-if="inAccountDetail && isSetPermission"> |
| | | <div class="title">权限管理</div> |
| | | |
| | | <div class="line-wrap" v-for="item in sysMenus" :key="item.id"> |
| | | <div class="line"> |
| | | <div class="name">{{ item.name }}</div> |
| | | <el-switch |
| | | v-model="item.selected" |
| | | active-color="rgba(61, 104, 225, 1)" |
| | | @change="fatherChange(item)" |
| | | > |
| | | </el-switch> |
| | | </div> |
| | | <div v-if="item.children"> |
| | | <div |
| | | class="line" |
| | | style="margin-left: 55px" |
| | | v-for="x in item.children" |
| | | :key="x.id" |
| | | > |
| | | <div class="name">{{ x.name }}</div> |
| | | <el-switch |
| | | v-model="x.selected" |
| | | active-color="rgba(61, 104, 225, 1)" |
| | | @change="childrenChange(item)" |
| | | > |
| | | </el-switch> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | <div class="btns"> |
| | | <div class="cancel" @click="cancelSet">取消</div> |
| | | <div class="ok" @click="saveAuth">保存</div> |
| | | </div> |
| | | </div> |
| | | |
| | | <div class="add-account-page" v-if="isAddAccount"> |
| | | <div class="title">添加账户</div> |
| | | <div class="upload-group"> |
| | | <div |
| | | class="upload-jpg" |
| | | :class=" |
| | | selectedPic == index? 'upload-jpg-border' : '' |
| | | " |
| | | v-for="(item, index) in jpgArr" |
| | | :key="index" |
| | | @click="pickHeadDefPic(item, index)" |
| | | > |
| | | <img |
| | | v-if="item" |
| | | :src="`data:image/png;base64,${item.path}`" |
| | | alt="" |
| | | srcset="" |
| | | /> |
| | | <div class="img-mask" v-if="selectedPic == index"> |
| | | <span class="icon iconfont enable"></span> |
| | | </div> |
| | | </div> |
| | | <!-- <el-upload |
| | | class="upload-demo" |
| | | action="https://jsonplaceholder.typicode.com/posts/" |
| | | :show-file-list="false" |
| | | :http-request="uploadUserPic" |
| | | > |
| | | <div v-if="loadedPic == ''" class="upload-jpg-up">上传</div> |
| | | </el-upload> --> |
| | | </div> |
| | | <div class="fill-group"> |
| | | <el-form |
| | | :model="addForm" |
| | | :rules="rules" |
| | | ref="addForm" |
| | | class="add-form" |
| | | > |
| | | <el-form-item prop="userName"> |
| | | <div class="p-title">用户名:</div> |
| | | <el-input |
| | | placeholder="必填" |
| | | v-model="addForm.userName" |
| | | ></el-input> |
| | | </el-form-item> |
| | | <el-form-item prop="roleId"> |
| | | <div class="p-title">角色:</div> |
| | | <el-select v-model="addForm.roleId" placeholder="请选择角色"> |
| | | <el-option |
| | | v-for="(item, i) in roleList" |
| | | :key="i" |
| | | :label="item.name" |
| | | :value="item.id" |
| | | ></el-option> |
| | | </el-select> |
| | | </el-form-item> |
| | | <el-form-item prop="nickName"> |
| | | <div class="p-title">昵称:</div> |
| | | <el-input |
| | | placeholder="选填" |
| | | v-model="addForm.nickName" |
| | | ></el-input> |
| | | </el-form-item> |
| | | <el-form-item prop="password"> |
| | | <div class="p-title">密码:</div> |
| | | <el-input |
| | | placeholder="必填" |
| | | v-model="addForm.password" |
| | | show-password |
| | | ></el-input> |
| | | </el-form-item> |
| | | <el-form-item prop="confirmPassword"> |
| | | <div class="p-title">确认密码:</div> |
| | | <el-input |
| | | placeholder="必填" |
| | | v-model="addForm.confirmPassword" |
| | | show-password |
| | | ></el-input> |
| | | </el-form-item> |
| | | </el-form> |
| | | </div> |
| | | <div class="btns"> |
| | | <div class="cancel" @click="cancelAdd">取消</div> |
| | | <div class="ok" @click="saveAddAccount('addForm')">保存</div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | |
| | | <div class="datetime-right" v-if="activePage == '日期时间'"> |
| | | <div class="ntp-time" v-if="isNtp"> |
| | | <el-form label-width="160px"> |
| | | <el-form-item label="服务器地址"> |
| | | <!-- :disabled="syncType === '2'" --> |
| | | <ip-input |
| | | :ip="ntpServer" |
| | | @on-blur="ntpServer = arguments[0]" |
| | | ></ip-input> |
| | | </el-form-item> |
| | | |
| | | <el-form-item label="校时时间间隔(分钟)"> |
| | | <div class="right"> |
| | | <el-input-number |
| | | v-model.number="timeInterval" |
| | | :min="1" |
| | | :max="60" |
| | | placeholder="请输入" |
| | | size="small" |
| | | :controls="false" |
| | | ></el-input-number> |
| | | <el-button |
| | | type="text" |
| | | @click="testNTP" |
| | | :loading="ntpTestLoading" |
| | | >测试</el-button |
| | | > |
| | | </div> |
| | | </el-form-item> |
| | | </el-form> |
| | | </div> |
| | | |
| | | <div class="manual-time" v-if="isManual"> |
| | | <switchBar |
| | | :barName="`同步本计算机时间`" |
| | | @switchChange="syncBrowser" |
| | | :value="isSyncBrowser" |
| | | ></switchBar> |
| | | |
| | | <div class="clock-wrap"> |
| | | <div class="clock"> |
| | | <div class="hour"> |
| | | <div class="dnum" @click="showInput('Hour')"> |
| | | <span v-show="!showHourInput">{{ syncHour }}</span> |
| | | <input |
| | | class="input-box" |
| | | v-show="showHourInput" |
| | | ref="iptHour" |
| | | oninput="value=value.replace(/[^\d]/g,'');if(value.length>2)value=value.slice(0,2);if(+value>23)value='23'" |
| | | type="text" |
| | | v-model="inputHour" |
| | | @blur="hideInput('Hour')" |
| | | @keydown.enter="hideInput('Hour')" |
| | | /> |
| | | </div> |
| | | <div class="control"> |
| | | <span class="icon iconfont" @click="plusOne('hrs')" |
| | | ></span |
| | | > |
| | | <span class="icon iconfont fanzhuan" @click="minusOne('hrs')" |
| | | ></span |
| | | > |
| | | </div> |
| | | </div> |
| | | <div class="sep">:</div> |
| | | <div class="mins"> |
| | | <div class="dnum" @click="showInput('Min')"> |
| | | <span v-show="!showMinInput">{{ syncMin }}</span> |
| | | <input |
| | | class="input-box" |
| | | v-show="showMinInput" |
| | | ref="iptMin" |
| | | oninput="value=value.replace(/[^\d]/g,'');if(value.length>2)value=value.slice(0,2);if(+value>59)value='59'" |
| | | type="text" |
| | | v-model="inputMin" |
| | | @blur="hideInput('Min')" |
| | | @keydown.enter="hideInput('Min')" |
| | | /> |
| | | </div> |
| | | <div class="control"> |
| | | <span class="icon iconfont" @click="plusOne('min')" |
| | | ></span |
| | | > |
| | | <span class="icon iconfont fanzhuan" @click="minusOne('min')" |
| | | ></span |
| | | > |
| | | </div> |
| | | </div> |
| | | <div class="sep">:</div> |
| | | <div class="mins"> |
| | | <div class="dnum" @click="showInput('Sec')"> |
| | | <span v-show="!showSecInput">{{ syncSec }}</span> |
| | | <input |
| | | class="input-box" |
| | | v-show="showSecInput" |
| | | ref="iptSec" |
| | | oninput="value=value.replace(/[^\d]/g,'');if(value.length>2)value=value.slice(0,2);if(+value>59)value='59'" |
| | | type="text" |
| | | v-model="inputSec" |
| | | @blur="hideInput('Sec')" |
| | | @keydown.enter="hideInput('Sec')" |
| | | /> |
| | | </div> |
| | | <div class="control"> |
| | | <span class="icon iconfont" @click="plusOne('sec')" |
| | | ></span |
| | | > |
| | | <span class="icon iconfont fanzhuan" @click="minusOne('sec')" |
| | | ></span |
| | | > |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | |
| | | <div class="adjust-bar"> |
| | | <div class="minus" @click="minusOne('yrs')">-</div> |
| | | <div class="middle" @click="showInput('Yrs')"> |
| | | <span v-show="!showYrsInput">{{ syncYrs }}</span> |
| | | <input |
| | | class="input-box" |
| | | v-show="showYrsInput" |
| | | ref="iptYrs" |
| | | oninput="value=value.replace(/[^\d]/g,'');if(value.length>4)value=value.slice(0,4);" |
| | | type="text" |
| | | v-model="inputYrs" |
| | | @blur="hideInput('Yrs')" |
| | | @keydown.enter="hideInput('Yrs')" |
| | | /> |
| | | 年 |
| | | </div> |
| | | <div class="plus" @click="plusOne('yrs')">+</div> |
| | | </div> |
| | | <div class="adjust-bar"> |
| | | <div class="minus" @click="minusOne('mth')">-</div> |
| | | <div class="middle" @click="showInput('Month')"> |
| | | <span v-show="!showMonthInput">{{ syncMonth }}</span> |
| | | <input |
| | | class="input-box" |
| | | v-show="showMonthInput" |
| | | ref="iptMonth" |
| | | oninput="value=value.replace(/[^\d]/g,'');if(value.length>2)value=value.slice(0,2);if(+value>12)value='12'" |
| | | type="text" |
| | | v-model="inputMonth" |
| | | @blur="hideInput('Month')" |
| | | @keydown.enter="hideInput('Month')" |
| | | /> |
| | | 月 |
| | | </div> |
| | | |
| | | <div class="plus" @click="plusOne('mth')">+</div> |
| | | </div> |
| | | <div class="adjust-bar"> |
| | | <div class="minus" @click="minusOne('day')">-</div> |
| | | <div class="middle" @click="showInput('Day')"> |
| | | <span v-show="!showDayInput">{{ syncDay }}</span> |
| | | <input |
| | | class="input-box" |
| | | v-show="showDayInput" |
| | | ref="iptDay" |
| | | oninput="value=value.replace(/[^\d]/g,'');if(value.length>2)value=value.slice(0,2);if(+value>31)value='31'" |
| | | type="text" |
| | | v-model="inputDay" |
| | | @blur="hideInput('Day')" |
| | | @keydown.enter="hideInput('Day')" |
| | | /> |
| | | 日 |
| | | </div> |
| | | <div class="plus" @click="plusOne('day')">+</div> |
| | | </div> |
| | | </div> |
| | | |
| | | <div class="btns"> |
| | | <div class="cancel" @click="cancelPassword">取消</div> |
| | | <div class="ok" @click="submitClock">保存</div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | |
| | | <clusterManagement |
| | | v-if="activePage == '集群管理'" |
| | | style="width: 100%" |
| | | ></clusterManagement> |
| | | <netSettings |
| | | v-if="activePage == '网络设置'" |
| | | style="width: 100%" |
| | | ></netSettings> |
| | | <keyboardLanguage |
| | | v-if="activePage == '键盘和语言'" |
| | | style="width: 100%" |
| | | ></keyboardLanguage> |
| | | <generalSettings |
| | | v-if="activePage == '通用设置'" |
| | | style="width: 100%" |
| | | ></generalSettings> |
| | | </div> |
| | | <div class="welcome-page" v-else> |
| | | <div class="child" @click="openWelcome('账户',0)"> |
| | | <div class="child-info"> |
| | | <span class="icon iconfont welcome-icon"></span> |
| | | <span class="welcome-title">账户</span> |
| | | </div> |
| | | </div> |
| | | <div class="child" @click="openWelcome('日期时间',1)"> |
| | | <div class="child-info"> |
| | | <span class="icon iconfont welcome-icon"></span> |
| | | <span class="welcome-title">日期时间</span> |
| | | </div> |
| | | </div> |
| | | <div class="child" @click="openWelcome('集群管理',2)"> |
| | | <div class="child-info"> |
| | | <span class="icon iconfont welcome-icon"></span> |
| | | <span class="welcome-title">集群管理</span> |
| | | </div> |
| | | </div> |
| | | <div class="child" @click="openWelcome('网络设置',3)"> |
| | | <div class="child-info"> |
| | | <span class="icon iconfont welcome-icon"></span> |
| | | <span class="welcome-title">网络设置</span> |
| | | </div> |
| | | </div> |
| | | <div class="child" @click="openWelcome('键盘和语言',4)"> |
| | | <div class="child-info"> |
| | | <span class="icon iconfont welcome-icon"></span> |
| | | <span class="welcome-title">键盘和语言</span> |
| | | </div> |
| | | </div> |
| | | <div class="child" @click="openWelcome('通用设置',5)"> |
| | | <div class="child-info"> |
| | | <span class="icon iconfont welcome-icon"></span> |
| | | <span class="welcome-title">通用设置</span> |
| | | </div> |
| | | </div> |
| | | <div class="s-system-manage"> |
| | | <basic-setting v-show="activeName === 'basic'"></basic-setting> |
| | | </div> |
| | | </template> |
| | | |
| | | <script> |
| | | import { getClockInfo, saveClockInfo, testNTPserver } from "@/api/system"; |
| | | import { |
| | | uploadHeadPic, |
| | | addUser, |
| | | getUsers, |
| | | updateUser, |
| | | updataUser, |
| | | updatePassword, |
| | | deleteUser, |
| | | getUserMenus, |
| | | defHeadPics, |
| | | getRoles, |
| | | } from "@/api/user"; |
| | | import switchBar from "../components/switchBar"; |
| | | import ipInput from "@/components/subComponents/IPInput"; |
| | | import clusterManagement from "../views/clusterManagement"; |
| | | import netSettings from "../views/NetSettings"; |
| | | import keyboardLanguage from "../views/keyboardLanguage"; |
| | | import generalSettings from "../views/generalSettings"; |
| | | import BasicSetting from "../components/BasicSetting"; |
| | | |
| | | export default { |
| | | name: "settings", |
| | | name: 'settings', |
| | | components: { |
| | | switchBar, |
| | | ipInput, |
| | | clusterManagement, |
| | | netSettings, |
| | | keyboardLanguage, |
| | | generalSettings, |
| | | BasicSetting |
| | | }, |
| | | data() { |
| | | var validatePass2 = (rule, value, callback) => { |
| | | if (value === "") { |
| | | callback(new Error("请再次输入密码")); |
| | | } else if (value !== this.addForm.password) { |
| | | callback(new Error("两次输入密码不一致!")); |
| | | } else { |
| | | callback(); |
| | | } |
| | | }; |
| | | var validatePass4 = (rule, value, callback) => { |
| | | if (value === "") { |
| | | callback(new Error("请再次输入密码")); |
| | | } else if (value !== this.passwordForm.newPassword) { |
| | | callback(new Error("两次输入密码不一致!")); |
| | | } else { |
| | | callback(); |
| | | } |
| | | }; |
| | | return { |
| | | showAccount: true, |
| | | syncYrs: "", |
| | | activeAccountItem: {}, |
| | | syncMonth: "", |
| | | syncHour: "", |
| | | showWelcome: true, |
| | | syncDay: "", |
| | | syncMin: "", |
| | | syncSec: "00", |
| | | isSyncBrowser: false, |
| | | showDateTime: false, |
| | | isAddAccount: false, |
| | | isCount: false, |
| | | isCalculate: false, |
| | | browserTimer: null, |
| | | timezone: "", |
| | | isRealtime: false, |
| | | inputNickName: "", |
| | | showHourInput: false, |
| | | showMinInput: false, |
| | | showSecInput: false, |
| | | showYrsInput: false, |
| | | showMonthInput: false, |
| | | selectedPic: null, |
| | | showDayInput: false, |
| | | loadedPic: "", |
| | | cameraInfo: false, |
| | | dependentScene: false, |
| | | timestamp: 0, |
| | | inAccountDetail: false, |
| | | isChangePw: false, |
| | | isSetPermission: false, |
| | | timeInterval: 10, |
| | | ntpServer: "", |
| | | syncType: "1", |
| | | equipmentTime: "", |
| | | equipmentDate: "", |
| | | roleList: [], |
| | | ntpTestLoading: false, |
| | | settime: "", |
| | | weekday: "", |
| | | menuArr: [ |
| | | { name: "账户" }, |
| | | { name: "日期时间" }, |
| | | { name: "集群管理" }, |
| | | { name: "网络设置" }, |
| | | { name: "键盘和语言" }, |
| | | { name: "通用设置" }, |
| | | ], |
| | | accountArr: [], |
| | | jpgArr: [], |
| | | isManual: false, |
| | | isNtp: true, |
| | | activePage: "账户", |
| | | activeIndex: 0, |
| | | clockTimer: null, |
| | | inputHour: "", |
| | | inputMin: "", |
| | | inputSec: "", |
| | | inputYrs: "", |
| | | showInputNickName: false, |
| | | inputMonth: "", |
| | | inputDay: "", |
| | | passwordForm: { |
| | | curPassword: "", |
| | | newPassword: "", |
| | | confirmPassword: "", |
| | | }, |
| | | activeAccountIndex: 0, |
| | | sysMenus: [], |
| | | addForm: { |
| | | userName: "", |
| | | nickName: "", |
| | | password: "", |
| | | headpic: "", |
| | | confirmPassword: "", |
| | | roleId: "", |
| | | }, |
| | | rules: { |
| | | userName: [ |
| | | { required: true, message: "请输入用户名", trigger: "blur" }, |
| | | { |
| | | min: 3, |
| | | max: 10, |
| | | message: "长度在 3 到 10 个字符", |
| | | trigger: "blur", |
| | | }, |
| | | ], |
| | | password: [ |
| | | { required: true, message: "请输入密码", trigger: "blur" }, |
| | | { min: 6, message: "长度至少为 6 位", trigger: "blur" }, |
| | | ], |
| | | confirmPassword: [{ validator: validatePass2, trigger: "blur" }], |
| | | }, |
| | | pwRules: { |
| | | // pw: [{ validator: validatePass3, trigger: "blur" }], |
| | | curPassword: [ |
| | | { required: true, message: "请输入密码", trigger: "blur" }, |
| | | { min: 6, message: "长度至少为 6 位", trigger: "blur" }, |
| | | ], |
| | | newPassword: [ |
| | | { required: true, message: "请输入密码", trigger: "blur" }, |
| | | { min: 6, message: "长度至少为 6 位", trigger: "blur" }, |
| | | ], |
| | | confirmPassword: [{ validator: validatePass4, trigger: "blur" }], |
| | | }, |
| | | }; |
| | | }, |
| | | beforeDestroy() { |
| | | clearTimeout(this.clockTimer); |
| | | clearInterval(this.browserTimer); |
| | | }, |
| | | mounted() { |
| | | this.fetchUserList(); |
| | | this.fetchDefHeadPic(); |
| | | }, |
| | | methods: { |
| | | fetchDefHeadPic() { |
| | | defHeadPics().then((res) => { |
| | | this.jpgArr = res.data; |
| | | }); |
| | | }, |
| | | fetchUserList(showLast = false) { |
| | | getUsers().then((res) => { |
| | | this.accountArr = res.data; |
| | | if (this.accountArr.length) { |
| | | this.activeAccountItem = this.accountArr[0]; |
| | | this.activeAccountIndex = 0; |
| | | } |
| | | if (showLast) { |
| | | this.cancelAdd(); |
| | | const lastIdx = this.accountArr.length - 1; |
| | | this.openAccount(this.accountArr[lastIdx], lastIdx); |
| | | } |
| | | }); |
| | | }, |
| | | blurInputNick() { |
| | | this.$refs["input-nick"].blur(); |
| | | }, |
| | | editNickName() { |
| | | this.showInputNickName = true; |
| | | this.inputNickName = this.activeAccountItem.nickname; |
| | | this.$refs["input-nick"].focus(); |
| | | }, |
| | | hideInputNick() { |
| | | this.showInputNickName = false; |
| | | updateUser({ |
| | | id: this.activeAccountItem.id, |
| | | nickname: this.inputNickName, |
| | | }).then((res) => { |
| | | this.$message.success(res.msg); |
| | | this.fetchUserList(true); |
| | | }); |
| | | }, |
| | | openAccount(item, i) { |
| | | this.activeAccountItem = item; |
| | | this.activeAccountIndex = i; |
| | | this.inAccountDetail = false; |
| | | this.cancelSet(); |
| | | this.fetchMenu(); |
| | | }, |
| | | minusOne(typ) { |
| | | this.isSyncBrowser = false; |
| | | this.syncBrowser(false); |
| | | let num; |
| | | switch (typ) { |
| | | case "hrs": |
| | | num = +this.syncHour - 1; |
| | | if (num == -1) { |
| | | num = 23; |
| | | } |
| | | this.syncHour = this.padZero(num); |
| | | break; |
| | | case "min": |
| | | num = +this.syncMin - 1; |
| | | if (num == -1) { |
| | | num = 59; |
| | | } |
| | | this.syncMin = this.padZero(num); |
| | | break; |
| | | case "sec": |
| | | num = +this.syncSec + 1; |
| | | if (num == -1) { |
| | | num = 59; |
| | | } |
| | | this.syncSec = this.padZero(num); |
| | | break; |
| | | case "yrs": |
| | | num = +this.syncYrs - 1; |
| | | this.syncYrs = this.padZero(num); |
| | | break; |
| | | case "mth": |
| | | num = +this.syncMonth - 1; |
| | | if (num == 0) { |
| | | num = 12; |
| | | this.minusOne("yrs"); |
| | | } |
| | | this.syncMonth = this.padZero(num); |
| | | break; |
| | | case "day": |
| | | num = +this.syncDay - 1; |
| | | if (num == 0) { |
| | | this.minusOne("mth"); |
| | | const maxDay = new Date( |
| | | +this.syncYrs, |
| | | +this.syncMonth, |
| | | 0 |
| | | ).getDate(); |
| | | num = maxDay; |
| | | } |
| | | this.syncDay = this.padZero(num); |
| | | break; |
| | | default: |
| | | break; |
| | | } |
| | | }, |
| | | fatherChange(item) { |
| | | item.children.forEach((x) => { |
| | | x.selected = item.selected; |
| | | }); |
| | | }, |
| | | childrenChange(item) { |
| | | let isAllSelected = item.children.every((x) => x.selected == true); |
| | | item.selected = isAllSelected; |
| | | }, |
| | | plusOne(typ) { |
| | | this.isSyncBrowser = false; |
| | | this.syncBrowser(false); |
| | | let num; |
| | | switch (typ) { |
| | | case "hrs": |
| | | num = +this.syncHour + 1; |
| | | if (num == 24) { |
| | | num = 0; |
| | | } |
| | | this.syncHour = this.padZero(num); |
| | | break; |
| | | case "min": |
| | | num = +this.syncMin + 1; |
| | | if (num == 60) { |
| | | num = 0; |
| | | } |
| | | this.syncMin = this.padZero(num); |
| | | break; |
| | | case "sec": |
| | | num = +this.syncSec + 1; |
| | | if (num == 60) { |
| | | num = 0; |
| | | } |
| | | this.syncSec = this.padZero(num); |
| | | break; |
| | | case "yrs": |
| | | num = +this.syncYrs + 1; |
| | | this.syncYrs = this.padZero(num); |
| | | break; |
| | | case "mth": |
| | | num = +this.syncMonth + 1; |
| | | if (num == 13) { |
| | | num = 1; |
| | | } |
| | | this.syncMonth = this.padZero(num); |
| | | break; |
| | | case "day": |
| | | num = +this.syncDay + 1; |
| | | const maxDay = new Date(+this.syncYrs, +this.syncMonth, 0).getDate(); |
| | | if (num > maxDay) { |
| | | num = 1; |
| | | } |
| | | this.syncDay = this.padZero(num); |
| | | break; |
| | | default: |
| | | break; |
| | | } |
| | | }, |
| | | submitClock() { |
| | | if (this.syncType === "1") { |
| | | if (this.ntpServer === "" || this.ntpServer === "...") { |
| | | this.$notify({ |
| | | type: "error", |
| | | message: "NTP 服务器地址不能为空", |
| | | }); |
| | | return false; |
| | | } else if (this.timeInterval === "") { |
| | | this.timeInterval = 1; |
| | | } |
| | | } else if (this.isSyncBrowser) { |
| | | if (this.settime === "") { |
| | | this.$notify({ |
| | | type: "error", |
| | | message: "设置时间不能为空", |
| | | }); |
| | | return false; |
| | | } |
| | | } else { |
| | | this.settime = `${this.syncYrs}-${this.syncMonth}-${this.syncDay} ${this.syncHour}:${this.syncMin}:${this.syncSec}`; |
| | | } |
| | | saveClockInfo({ |
| | | timeZone: this.timezone, |
| | | ntp: this.syncType === "1", |
| | | ntpServer: this.ntpServer, |
| | | interval: this.timeInterval, |
| | | newTime: this.settime, |
| | | }).then((rsp) => { |
| | | if (rsp && rsp.success) { |
| | | this.$notify({ |
| | | type: "success", |
| | | message: "设置成功", |
| | | }); |
| | | } |
| | | this.initClockConf(); |
| | | }); |
| | | }, |
| | | flatGetArr(arr, res) { |
| | | for (const item of arr) { |
| | | if (item.selected) res.push(item.id); |
| | | if (item.children) this.flatGetArr(item.children, res); |
| | | } |
| | | }, |
| | | saveAuth() { |
| | | let arr = []; |
| | | this.flatGetArr(this.sysMenus, arr); |
| | | updataUser({ |
| | | id: this.activeAccountItem.id, |
| | | menuIds: arr, |
| | | }).then((res) => { |
| | | if (res.success) { |
| | | this.$message.success(res.msg); |
| | | this.cancelSet(); |
| | | } |
| | | }); |
| | | }, |
| | | formatTime(number, format) { |
| | | var formateArr = ["Y", "M", "D", "h", "m", "s"]; |
| | | var returnArr = []; |
| | | var date = new Date(number * 1000); |
| | | returnArr.push(date.getFullYear()); |
| | | returnArr.push(this.formatNumber(date.getMonth() + 1)); |
| | | returnArr.push(this.formatNumber(date.getDate())); |
| | | returnArr.push(this.formatNumber(date.getHours())); |
| | | returnArr.push(this.formatNumber(date.getMinutes())); |
| | | returnArr.push(this.formatNumber(date.getSeconds())); |
| | | this.weekday = "星期" + "日一二三四五六".charAt(date.getDay()); |
| | | for (var i in returnArr) { |
| | | format = format.replace(formateArr[i], returnArr[i]); |
| | | } |
| | | return format; |
| | | }, |
| | | padZero(n) { |
| | | n = +n; |
| | | return n < 10 ? "0" + n : "" + n; |
| | | }, |
| | | formatNumber(n) { |
| | | n = n.toString(); |
| | | return n[1] ? n : "0" + n; |
| | | }, |
| | | // uploadUserPic(params) { |
| | | // let param = new FormData(); |
| | | // param.append("file", params.file); |
| | | // uploadHeadPic(param).then((res) => { |
| | | // this.jpgArr.push(res.data); |
| | | // this.loadedPic = res.data; |
| | | // }); |
| | | // }, |
| | | initClockConf(ntpTest = false) { |
| | | getClockInfo().then((rsp) => { |
| | | if (rsp && rsp.success) { |
| | | this.timezone = rsp.data.time_zone; |
| | | if (!ntpTest) { |
| | | this.syncType = rsp.data.ntp ? "1" : "2"; |
| | | this.isNtp = rsp.data.ntp; |
| | | this.isManual = !rsp.data.ntp; |
| | | } |
| | | if (rsp.data.ntp) { |
| | | this.ntpServer = rsp.data.ntp_server; |
| | | this.timeInterval = rsp.data.interval; |
| | | } |
| | | this.timestamp = rsp.data.local_time; |
| | | if (this.clockTimer === null) { |
| | | this.runClock(); |
| | | if (this.isManual) this.parseTime(); |
| | | } |
| | | } |
| | | }); |
| | | }, |
| | | openMenu(name, i) { |
| | | this.activePage = name; |
| | | this.activeIndex = i; |
| | | if (this.activePage == "日期时间") { |
| | | this.initClockConf(); |
| | | } |
| | | }, |
| | | openWelcome(name,i){ |
| | | this.showWelcome = false |
| | | this.openMenu(name,i) |
| | | }, |
| | | showInput(typ) { |
| | | this[`show${typ}Input`] = true; |
| | | this.$nextTick(() => { |
| | | this.$refs[`ipt${typ}`].focus(); |
| | | }); |
| | | }, |
| | | hideInput(typ) { |
| | | if (this[`input${typ}`]) { |
| | | this[`sync${typ}`] = this.padZero(this[`input${typ}`]); |
| | | } |
| | | this[`show${typ}Input`] = false; |
| | | this[`input${typ}`] = ""; |
| | | }, |
| | | syncBrowser(enable) { |
| | | this.isSyncBrowser = enable; |
| | | if (!enable) { |
| | | clearInterval(this.browserTimer); |
| | | } else { |
| | | this.browserTimer = setInterval(() => { |
| | | let timestamp = new Date().getTime() / 1000; |
| | | this.settime = this.formatTime(timestamp, "Y-M-D h:m:s"); |
| | | let [arr1, arr2] = this.settime.split(" "); |
| | | [this.syncYrs, this.syncMonth, this.syncDay] = arr1.split("-"); |
| | | [this.syncHour, this.syncMin, this.syncSec] = arr2.split(":"); |
| | | }, 1000); |
| | | } |
| | | }, |
| | | showAddAccount() { |
| | | this.inAccountDetail = false; |
| | | this.isAddAccount = true; |
| | | getRoles().then((res) => { |
| | | if (res.success) { |
| | | this.roleList = res.data; |
| | | } |
| | | }); |
| | | }, |
| | | cancelAdd() { |
| | | this.inAccountDetail = false; |
| | | this.isAddAccount = false; |
| | | this.$refs["addForm"].resetFields(); |
| | | this.selectedPic = null; |
| | | }, |
| | | cancelPassword() { |
| | | this.isChangePw = false; |
| | | this.inAccountDetail = false; |
| | | this.$refs["passwordForm"].resetFields(); |
| | | }, |
| | | SaveNewPassword(formName) { |
| | | this.$refs[formName].validate((valid) => { |
| | | if (valid) { |
| | | updatePassword({ |
| | | oldPwd: this.passwordForm.curPassword, |
| | | newPwd: this.passwordForm.newPassword, |
| | | }).then( |
| | | (res) => { |
| | | if (res.success) { |
| | | this.$message.success(res.msg); |
| | | this.cancelPassword(); |
| | | } |
| | | }, |
| | | (err) => { |
| | | this.$message.warning("保存失败," + err.msg); |
| | | } |
| | | ); |
| | | } |
| | | }); |
| | | }, |
| | | saveAddAccount(formName) { |
| | | this.$refs[formName].validate((valid) => { |
| | | if (valid) { |
| | | let data = { |
| | | username: this.addForm.userName, |
| | | password: this.addForm.password, |
| | | nickname: this.addForm.nickName, |
| | | headpic: this.addForm.headpic, |
| | | }; |
| | | addUser(data).then( |
| | | (res) => { |
| | | this.$message.success(res.data); |
| | | this.fetchUserList(true); |
| | | }, |
| | | (err) => { |
| | | this.$message.warning("保存失败," + err.msg); |
| | | } |
| | | ); |
| | | } else { |
| | | console.log("error submit!!"); |
| | | return false; |
| | | } |
| | | }); |
| | | }, |
| | | pickHeadDefPic(item, i) { |
| | | this.addForm.headpic = item.path; |
| | | this.selectedPic = i; |
| | | }, |
| | | testNTP() { |
| | | this.ntpTestLoading = true; |
| | | testNTPserver({ server: this.ntpServer }) |
| | | .then((rsp) => { |
| | | if (rsp && rsp.success) { |
| | | this.$notify({ |
| | | type: "success", |
| | | message: "时间同步成功", |
| | | }); |
| | | } else { |
| | | this.$notify({ |
| | | type: "error", |
| | | message: "时间同步失败", |
| | | }); |
| | | } |
| | | this.ntpTestLoading = false; |
| | | this.initClockConf(true); |
| | | }) |
| | | .catch((err) => { |
| | | this.$notify({ |
| | | type: "error", |
| | | message: "时间同步失败,请检查服务器ip", |
| | | }); |
| | | this.ntpTestLoading = false; |
| | | }); |
| | | }, |
| | | cancelSet() { |
| | | this.isSetPermission = false; |
| | | this.inAccountDetail = false; |
| | | this.sysMenus = []; |
| | | }, |
| | | showChangePassword() { |
| | | this.isChangePw = true; |
| | | this.inAccountDetail = true; |
| | | }, |
| | | runClock() { |
| | | const str = this.formatTime(++this.timestamp, "Y-M-D h:m:s"); |
| | | [this.equipmentDate, this.equipmentTime] = str.split(" "); |
| | | this.clockTimer = setTimeout(() => { |
| | | this.runClock(); |
| | | }, 1000); |
| | | }, |
| | | deleteAccount() { |
| | | this.$confirm("您是否确认删除账户?", "删除账户", { |
| | | confirmButtonText: "确定", |
| | | cancelButtonText: "取消", |
| | | }) |
| | | .then(() => { |
| | | let obj = { |
| | | ids: [this.activeAccountItem.id], |
| | | }; |
| | | deleteUser(obj).then((res) => { |
| | | if (res.success) { |
| | | this.fetchUserList(); |
| | | this.$message({ |
| | | type: "success", |
| | | message: "删除成功!", |
| | | }); |
| | | } else { |
| | | this.$message.warning("删除失败"); |
| | | } |
| | | }); |
| | | }) |
| | | .catch(() => {}); |
| | | }, |
| | | fetchMenu() { |
| | | getUserMenus({ |
| | | userId: this.activeAccountItem.id, |
| | | }).then((res) => { |
| | | if (res && res.success) { |
| | | this.sysMenus = res.data; |
| | | } |
| | | }); |
| | | }, |
| | | openPermission() { |
| | | this.inAccountDetail = true; |
| | | this.isSetPermission = true; |
| | | if (this.sysMenus.length == 0) { |
| | | this.fetchMenu(); |
| | | } |
| | | }, |
| | | parseTime() { |
| | | [this.syncYrs, this.syncMonth, this.syncDay] = this.equipmentDate.split( |
| | | "-" |
| | | ); |
| | | [this.syncHour, this.syncMin, this.syncSec] = this.equipmentTime.split( |
| | | ":" |
| | | ); |
| | | }, |
| | | changeSwitch(str) { |
| | | if (str == "isNtp") { |
| | | this.isManual = !this[str]; |
| | | } else { |
| | | this.isNtp = !this[str]; |
| | | } |
| | | this.syncType = this.isNtp ? "1" : "2"; |
| | | if (this.isManual) this.parseTime(); |
| | | }, |
| | | activeName: "basic", |
| | | buttonAuthority: sessionStorage.getItem("buttonAuthoritys") || [], |
| | | loginName: JSON.parse(sessionStorage.getItem("userInfo")).username || "用户名" |
| | | } |
| | | }, |
| | | computed: { |
| | | isShowAddAccount() { |
| | | const info = JSON.parse(sessionStorage.getItem("userInfo")); |
| | | return true; |
| | | isAdmin() { |
| | | if ( |
| | | sessionStorage.getItem("userInfo") && |
| | | sessionStorage.getItem("userInfo") !== "" |
| | | ) { |
| | | let loginName = JSON.parse(sessionStorage.getItem("userInfo")).username; |
| | | return loginName === "superadmin" || loginName === "basic"; |
| | | } |
| | | return false; |
| | | } |
| | | }, |
| | | methods: { |
| | | isShow(authority) { |
| | | if (this.isAdmin) { |
| | | return true; |
| | | } else if (this.buttonAuthority.indexOf("," + authority + ",") > -1) { |
| | | return true; |
| | | } else { |
| | | return false; |
| | | } |
| | | }, |
| | | }, |
| | | created() { |
| | | if (this.isShow('videoSystem:base')) { |
| | | this.activeName = "basic" |
| | | } else if (this.isShow('videoSystem:permission')) { |
| | | this.activeName = "user" |
| | | } else if (this.isShow('videoSystem:broadcast')) { |
| | | this.activeName = "radio" |
| | | } else if (this.isShow('videoSystem:eventPush')) { |
| | | this.activeName = "event" |
| | | } else if (this.isShow('videoSystem:logManage')) { |
| | | this.activeName = "log" |
| | | } else if (this.isShow('videoSystem:sysManage')) { |
| | | this.activeName = "system" |
| | | } |
| | | }, |
| | | }; |
| | | </script> |
| | | <style lang="scss"> |
| | | .welcome-page { |
| | | width: 100%; |
| | | .s-system-manage { |
| | | width: 100% !important; |
| | | min-width: 1067px; |
| | | height: 100%; |
| | | background-color: #f5f5f5; |
| | | display: -ms-flexbox; |
| | | padding: 0 50px; |
| | | -webkit-box-sizing: border-box; |
| | | box-sizing: border-box; |
| | | .child { |
| | | padding: 10px; |
| | | background-color: #f8f9fb; |
| | | .s-system-manage-breadcrumb { |
| | | height: 5%; |
| | | box-sizing: border-box; |
| | | background-color: white; |
| | | -webkit-box-flex: 0; |
| | | -ms-flex: 0 0 33.3%; |
| | | /* flex: 0 0 16%; */ |
| | | float: left; |
| | | width: 250px; |
| | | height: 200px; |
| | | margin: 50px 57px 30px 57px; |
| | | border-radius: 20px; |
| | | display: flex; |
| | | justify-content: center; |
| | | align-items: center; |
| | | cursor: pointer; |
| | | .child-info { |
| | | display: flex; |
| | | flex-direction: column; |
| | | height: 62%; |
| | | justify-content: space-around; |
| | | .welcome-icon { |
| | | font-size: 72px; |
| | | border: 1px solid #e4e7ed; |
| | | box-shadow: #e4e7ed 0px 0px 9px inset; |
| | | box-shadow: #e4e7ed 0px 0px 9px inset; |
| | | border-radius: 5px; |
| | | } |
| | | |
| | | .el-tabs--border-card { |
| | | border: 0px solid #dcdfe6; |
| | | -webkit-box-shadow: none; |
| | | box-shadow: none; |
| | | .el-tabs__header { |
| | | border: 0px solid #dcdfe6; |
| | | .el-tabs__item { |
| | | padding: 5px 50px; |
| | | height: 50px; |
| | | font-family: PingFangSC-Regular; |
| | | font-size: 15px; |
| | | color: #222222; |
| | | text-align: center; |
| | | border: 0px solid transparent; |
| | | } |
| | | .welcome-title { |
| | | font-size: 18px; |
| | | .el-tabs__item:nth-child(2) { |
| | | padding-left: 50px !important; |
| | | } |
| | | .el-tabs__item:last-child { |
| | | padding-right: 50px !important; |
| | | } |
| | | .el-tabs__item.is-active { |
| | | color: #3d68e1; |
| | | |
| | | // border-right-color: #fff; |
| | | // border-left-color: #fff; |
| | | } |
| | | .el-tabs__item:not(.is-disabled):hover { |
| | | color: #3d68e1; |
| | | } |
| | | } |
| | | } |
| | | .child:hover { |
| | | -moz-box-shadow: 5px 5px 10px #ddd; |
| | | -webkit-box-shadow: 5px 5px 10px #ddd; |
| | | box-shadow: 5px 5px 10px #ddd; |
| | | transform: translate3d(0,-2.5px,0); |
| | | transition: all 0.3s; |
| | | } |
| | | } |
| | | .container { |
| | | height: 100%; |
| | | display: flex; |
| | | flex-direction: row; |
| | | flex: 1; |
| | | flex-basis: auto; |
| | | box-sizing: border-box; |
| | | .container-left { |
| | | height: 100%; |
| | | width: 230px; |
| | | overflow: auto; |
| | | .el-tabs__header { |
| | | margin-bottom: 0; |
| | | } |
| | | .el-tabs__content { |
| | | height: calc(100% - 64px); |
| | | box-sizing: border-box; |
| | | flex-shrink: 0; |
| | | padding: 10px; |
| | | border-right: 5px solid rgba(248, 248, 248, 1); |
| | | box-sizing: border-box; |
| | | .left-card { |
| | | height: 55px; |
| | | cursor: pointer; |
| | | border-radius: 12px; |
| | | margin-bottom: 10px; |
| | | display: flex; |
| | | align-items: center; |
| | | .iconfont { |
| | | margin-left: 25px; |
| | | margin-right: 10px; |
| | | font-size: 24px; |
| | | } |
| | | .card-text { |
| | | overflow-y: auto; |
| | | padding: 20px 40px !important; |
| | | background: #fff; |
| | | .el-tab-pane { |
| | | width: 100%; |
| | | .s-title { |
| | | text-align: left; |
| | | padding: 15px 0px; |
| | | font-size: 16px; |
| | | } |
| | | } |
| | | .left-card-active { |
| | | background-color: rgba(61, 104, 225, 1); |
| | | color: #fff; |
| | | } |
| | | .left-card:hover { |
| | | background-color: rgba(61, 104, 225, 1); |
| | | color: #fff; |
| | | } |
| | | } |
| | | .container-center { |
| | | height: 100%; |
| | | width: 280px; |
| | | overflow: auto; |
| | | flex-shrink: 0; |
| | | padding: 10px; |
| | | border-right: 5px solid rgba(248, 248, 248, 1); |
| | | box-sizing: border-box; |
| | | .account-left { |
| | | .add-account { |
| | | color: rgba(61, 104, 225, 1); |
| | | margin-top: 30px; |
| | | .iconfont { |
| | | cursor: pointer; |
| | | font-size: 32px; |
| | | } |
| | | } |
| | | .account-card { |
| | | height: 50px; |
| | | background-color: rgba(248, 248, 248, 1); |
| | | margin-bottom: 10px; |
| | | display: flex; |
| | | align-items: center; |
| | | padding: 0 20px; |
| | | box-sizing: border-box; |
| | | border-radius: 10px; |
| | | cursor: pointer; |
| | | .touxiang { |
| | | height: 35px; |
| | | width: 35px; |
| | | background-color: bisque; |
| | | border-radius: 17.5px; |
| | | img { |
| | | border: none; |
| | | |
| | | height: 35px; |
| | | width: 35px; |
| | | border-radius: 17.5px; |
| | | } |
| | | } |
| | | .user-name { |
| | | margin-left: 10px; |
| | | font-size: 14px; |
| | | } |
| | | } |
| | | |
| | | .account-card-active { |
| | | background-color: rgba(61, 104, 225, 1); |
| | | color: #fff; |
| | | } |
| | | } |
| | | .datetime-left { |
| | | .time-card { |
| | | height: 105px; |
| | | background-color: rgba(248, 248, 248, 1); |
| | | margin-bottom: 30px; |
| | | border-radius: 10px; |
| | | .head { |
| | | height: 30px; |
| | | line-height: 30px; |
| | | text-align: left; |
| | | box-sizing: border-box; |
| | | padding: 0 10px; |
| | | font-size: 14px; |
| | | .icon { |
| | | margin-right: 5px; |
| | | color: rgba(61, 104, 225, 1); |
| | | } |
| | | } |
| | | .time-main { |
| | | height: 42px; |
| | | line-height: 42px; |
| | | font-family: Consolas; |
| | | font-size: 36px; |
| | | } |
| | | .date-bot { |
| | | height: 25px; |
| | | font-size: 14px; |
| | | line-height: 25px; |
| | | color: #868686; |
| | | display: flex; |
| | | justify-content: space-evenly; |
| | | } |
| | | } |
| | | .line { |
| | | display: flex; |
| | | align-items: center; |
| | | height: 50px; |
| | | padding: 0 25px; |
| | | background-color: rgba(248, 248, 248, 1); |
| | | justify-content: space-between; |
| | | border-radius: 12px; |
| | | margin-bottom: 10px; |
| | | .name { |
| | | font-size: 14px; |
| | | } |
| | | } |
| | | } |
| | | .s-table { |
| | | border: 1px solid #e8e8e9; |
| | | margin-top: 40px; |
| | | } |
| | | .container-right { |
| | | flex: 1; |
| | | flex-basis: auto; |
| | | overflow: auto; |
| | | box-sizing: border-box; |
| | | |
| | | .ui-top-title { |
| | | padding-bottom: 10px; |
| | | /* border-bottom: 1px solid #ebebeb; */ |
| | | position: relative; |
| | | text-align: left; |
| | | padding-left: 15px; |
| | | font-size: 16px; |
| | | font-weight: bold; |
| | | } |
| | | |
| | | padding: 20px 40px; |
| | | .account-right { |
| | | .account-content { |
| | | .content-top { |
| | | height: 120px; |
| | | width: 350px; |
| | | margin: 0 auto; |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: center; |
| | | margin-bottom: 20px; |
| | | .touxiang-big { |
| | | width: 100px; |
| | | height: 100px; |
| | | background-color: bisque; |
| | | border-radius: 50px; |
| | | img { |
| | | border: none; |
| | | .ui-top-title:before { |
| | | content: " "; |
| | | border-left: 4px solid #f53d3d; |
| | | display: inline-block; |
| | | height: 16px; |
| | | position: absolute; |
| | | top: 50%; |
| | | left: 0; |
| | | margin-top: -13px; |
| | | } |
| | | |
| | | width: 100px; |
| | | height: 100px; |
| | | border-radius: 50px; |
| | | } |
| | | } |
| | | .user-desc { |
| | | height: 100px; |
| | | display: flex; |
| | | flex-direction: column; |
| | | align-items: baseline; |
| | | min-width: 200px; |
| | | .username { |
| | | margin: 5px 15px; |
| | | height: 30px; |
| | | line-height: 30px; |
| | | // width: 90px; |
| | | text-align: left; |
| | | font-size: 15px; |
| | | display: flex; |
| | | align-items: center; |
| | | } |
| | | .nickname { |
| | | margin: 5px 15px; |
| | | font-size: 14px; |
| | | .input-nick { |
| | | width: 50px; |
| | | margin-right: 5px; |
| | | } |
| | | .iconfont { |
| | | font-size: 14px; |
| | | margin-left: 5px; |
| | | cursor: pointer; |
| | | } |
| | | } |
| | | .user-role { |
| | | margin: 5px 0 0 15px; |
| | | font-size: 14px; |
| | | color: darkseagreen; |
| | | } |
| | | } |
| | | } |
| | | .list-btn { |
| | | display: flex; |
| | | |
| | | flex-direction: column; |
| | | align-items: center; |
| | | .item-btn { |
| | | width: 500px; |
| | | height: 45px; |
| | | background-color: #f0f0f0; |
| | | margin-bottom: 15px; |
| | | border-radius: 10px; |
| | | line-height: 45px; |
| | | font-size: 15px; |
| | | cursor: pointer; |
| | | } |
| | | .item-btn:hover { |
| | | color: rgba(255, 153, 102, 1); |
| | | } |
| | | } |
| | | } |
| | | .title { |
| | | height: 30px; |
| | | line-height: 30px; |
| | | /* background-color: aliceblue; */ |
| | | margin-bottom: 10px; |
| | | font-size: 16px; |
| | | font-weight: 600; |
| | | } |
| | | .change-pw { |
| | | .p-title { |
| | | text-align: left; |
| | | font-size: 15px; |
| | | margin-top: 5px; |
| | | } |
| | | } |
| | | .el-form-item { |
| | | margin-bottom: 0; |
| | | .el-input__inner { |
| | | background-color: rgba(240, 240, 240, 1); |
| | | border: none; |
| | | border-radius: 12px; |
| | | height: 45px; |
| | | padding: 0 20px; |
| | | font-size: 15px; |
| | | } |
| | | .el-input__clear { |
| | | color: dimgray; |
| | | font-size: 17px; |
| | | line-height: 45px; |
| | | } |
| | | .el-input__suffix { |
| | | right: 1px; |
| | | top: -0.5px; |
| | | width: 45px; |
| | | // background-color: rgba(61, 104, 225, 1); |
| | | /* color: white; */ |
| | | border-radius: 12px; |
| | | } |
| | | } |
| | | .permission { |
| | | .line { |
| | | display: flex; |
| | | align-items: center; |
| | | height: 50px; |
| | | padding: 0 25px; |
| | | background-color: rgba(248, 248, 248, 1); |
| | | justify-content: space-between; |
| | | border-radius: 12px; |
| | | margin-bottom: 10px; |
| | | .name { |
| | | font-size: 14px; |
| | | } |
| | | } |
| | | } |
| | | |
| | | .add-account-page { |
| | | .upload-group { |
| | | height: 120px; |
| | | width: 360px; |
| | | margin: 0 auto; |
| | | overflow: hidden; |
| | | .upload-jpg { |
| | | position: relative; |
| | | height: 48px; |
| | | width: 48px; |
| | | float: left; |
| | | margin: 0 10px; |
| | | margin-bottom: 10px; |
| | | background-color: rgba(242, 242, 242, 1); |
| | | border: 2px solid transparent; |
| | | border-radius: 50%; |
| | | cursor: pointer; |
| | | img { |
| | | height: 48px; |
| | | width: 48px; |
| | | border-radius: 50%; |
| | | } |
| | | .img-mask { |
| | | position: absolute; |
| | | left: 0; |
| | | top: 0; |
| | | height: 48px; |
| | | width: 48px; |
| | | background-color: rgba(0, 0, 0, 0.3); |
| | | color: white; |
| | | border-radius: 50%; |
| | | display: flex; |
| | | justify-content: center; |
| | | align-items: center; |
| | | .selected { |
| | | font-size: 22px; |
| | | } |
| | | } |
| | | } |
| | | .upload-jpg-border { |
| | | border: 2px solid cornflowerblue; |
| | | } |
| | | .upload-jpg-up { |
| | | height: 48px; |
| | | width: 48px; |
| | | float: left; |
| | | display: flex; |
| | | background-color: rgba(242, 242, 242, 1); |
| | | border: 2px solid transparent; |
| | | border-radius: 50%; |
| | | |
| | | justify-content: center; |
| | | align-items: center; |
| | | font-size: 12px; |
| | | cursor: pointer; |
| | | } |
| | | } |
| | | .fill-group { |
| | | .p-title { |
| | | height: 34px; |
| | | text-align: left; |
| | | } |
| | | .el-form-item { |
| | | .el-select { |
| | | width: 100%; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| | | .datetime-right { |
| | | .el-form-item.is-required:not(.is-no-asterisk) |
| | | > .el-form-item__label:before, |
| | | .el-form-item.is-required:not(.is-no-asterisk) |
| | | .el-form-item__label-wrap |
| | | > .el-form-item__label:before { |
| | | display: none; |
| | | } |
| | | .el-form-item { |
| | | margin-bottom: 10px; |
| | | height: 50px; |
| | | background: #f8f8f8; |
| | | padding: 4px 20px; |
| | | -webkit-box-sizing: border-box; |
| | | box-sizing: border-box; |
| | | border-radius: 10px; |
| | | .el-form-item__label { |
| | | text-align: left; |
| | | line-height: 42px; |
| | | } |
| | | } |
| | | .el-form-item__content { |
| | | line-height: 40px; |
| | | position: relative; |
| | | font-size: 14px; |
| | | margin-bottom: 10px; |
| | | } |
| | | .ip-input-container { |
| | | max-width: none !important; |
| | | } |
| | | .ntp-time { |
| | | .right { |
| | | display: flex; |
| | | align-items: baseline; |
| | | .el-input-number--small { |
| | | width: 100%; |
| | | } |
| | | .el-button--text { |
| | | margin-left: 10px; |
| | | text-decoration: underline; |
| | | } |
| | | } |
| | | .ntp-bar { |
| | | height: 40px; |
| | | background-color: rgba(248, 248, 248, 1); |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: space-between; |
| | | padding: 0 10px; |
| | | border-radius: 10px; |
| | | margin-bottom: 10px; |
| | | .title { |
| | | min-width: 70px; |
| | | } |
| | | .input-area { |
| | | width: 450px; |
| | | height: 30px; |
| | | background-color: rgba(240, 240, 240, 1); |
| | | border-radius: 10px; |
| | | line-height: 30px; |
| | | font-size: 14px; |
| | | } |
| | | } |
| | | .int-bar { |
| | | height: 40px; |
| | | background-color: rgba(248, 248, 248, 1); |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: space-between; |
| | | padding: 0 10px; |
| | | border-radius: 10px; |
| | | margin-bottom: 10px; |
| | | .title { |
| | | min-width: 130px; |
| | | } |
| | | .right { |
| | | width: 450px; |
| | | display: flex; |
| | | align-items: center; |
| | | height: 30px; |
| | | |
| | | .input-area { |
| | | // width: 410px; |
| | | background-color: rgba(240, 240, 240, 1); |
| | | border-radius: 10px; |
| | | line-height: 30px; |
| | | width: -webkit-fill-available; |
| | | |
| | | font-size: 14px; |
| | | } |
| | | .test { |
| | | width: 40px; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | .manual-time { |
| | | .clock-wrap { |
| | | height: 75px; |
| | | |
| | | background-color: #f8f8f8; |
| | | display: flex; |
| | | justify-content: center; |
| | | align-items: center; |
| | | margin-bottom: 10px; |
| | | border-radius: 10px; |
| | | .clock { |
| | | display: flex; |
| | | align-items: center; |
| | | height: 90px; |
| | | justify-content: space-evenly; |
| | | .iconfont { |
| | | cursor: pointer; |
| | | color: rgba(134, 134, 134, 1); |
| | | } |
| | | .iconfont:hover { |
| | | background-color: gainsboro; |
| | | } |
| | | .hour { |
| | | background-color: rgba(240, 240, 240, 1); |
| | | display: flex; |
| | | align-items: center; |
| | | width: 100px; |
| | | height: 50px; |
| | | justify-content: space-evenly; |
| | | border-radius: 10px; |
| | | } |
| | | .dnum { |
| | | width: 40px; |
| | | height: 40px; |
| | | line-height: 40px; |
| | | font-size: 34px; |
| | | font-family: Consolas; |
| | | display: flex; |
| | | align-items: center; |
| | | .input-box { |
| | | width: inherit; |
| | | border: none; |
| | | border-radius: 5px; |
| | | height: 35px; |
| | | font-size: 28px; |
| | | text-align: center; |
| | | } |
| | | |
| | | .input-box:focus { |
| | | outline: none; |
| | | } |
| | | } |
| | | .control { |
| | | width: 20px; |
| | | .fanzhuan { |
| | | display: inline-block; |
| | | -moz-transform: scaleY(-1); |
| | | -webkit-transform: scaleY(-1); |
| | | -o-transform: scaleY(-1); |
| | | transform: scaleY(-1); |
| | | } |
| | | } |
| | | .sep { |
| | | font-family: Consolas; |
| | | width: 40px; |
| | | font-size: 34px; |
| | | height: 40px; |
| | | line-height: 40px; |
| | | } |
| | | .mins { |
| | | background-color: #f0f0f0; |
| | | display: flex; |
| | | align-items: center; |
| | | width: 110px; |
| | | height: 50px; |
| | | justify-content: space-evenly; |
| | | border-radius: 10px; |
| | | } |
| | | } |
| | | } |
| | | .adjust-bar { |
| | | display: flex; |
| | | justify-content: space-between; |
| | | align-items: center; |
| | | margin-bottom: 10px; |
| | | border-radius: 10px; |
| | | height: 50px; |
| | | background-color: rgba(248, 248, 248, 1); |
| | | .middle { |
| | | font-size: 14px; |
| | | } |
| | | .input-box { |
| | | width: 80px; |
| | | border: none; |
| | | border-radius: 5px; |
| | | height: 25px; |
| | | font-size: 18px; |
| | | text-align: center; |
| | | } |
| | | |
| | | .input-box:focus { |
| | | outline: none; |
| | | } |
| | | .minus { |
| | | width: 50px; |
| | | height: 50px; |
| | | background-color: #f0f0f0; |
| | | font-size: 35px; |
| | | border-radius: 10px; |
| | | cursor: pointer; |
| | | line-height: 50px; |
| | | color: rgba(134, 134, 134, 1); |
| | | } |
| | | .plus { |
| | | width: 50px; |
| | | height: 50px; |
| | | cursor: pointer; |
| | | background-color: #f0f0f0; |
| | | font-size: 35px; |
| | | border-radius: 10px; |
| | | line-height: 50px; |
| | | color: rgba(134, 134, 134, 1); |
| | | } |
| | | } |
| | | } |
| | | } |
| | | .btns { |
| | | display: flex; |
| | | justify-content: space-between; |
| | | margin-top: 20px; |
| | | |
| | | .cancel { |
| | | height: 40px; |
| | | width: 48%; |
| | | cursor: pointer; |
| | | border-radius: 8px; |
| | | background-color: rgba(240, 240, 240, 1); |
| | | line-height: 40px; |
| | | font-size: 14px; |
| | | } |
| | | .ok { |
| | | height: 40px; |
| | | width: 48%; |
| | | cursor: pointer; |
| | | border-radius: 8px; |
| | | background-color: rgba(61, 104, 225, 1); |
| | | color: #fff; |
| | | line-height: 40px; |
| | | font-size: 14px; |
| | | } |
| | | } |
| | | .el-button--text { |
| | | color: #3d68e1; |
| | | text-decoration: underline; |
| | | } |
| | | } |
| | | </style> |
| | | |
| | | |
| New file |
| | |
| | | <template> |
| | | <div class="cloud"> |
| | | <div class="inner"> |
| | | <div class="rect"> |
| | | <serfDiagram |
| | | ref="inside-nodes" |
| | | :members="insideNodes" |
| | | :agent="agentName" |
| | | :sizeX="insideSizeX" |
| | | :sizeY="insideSizeY" |
| | | :startX="insideStartX" |
| | | :isShowHover="true" |
| | | class="inside-nodes" |
| | | ></serfDiagram> |
| | | </div> |
| | | </div> |
| | | <div class="outer" v-if="outsideNodes.length"> |
| | | <serfDiagram |
| | | ref="outer-nodes" |
| | | :members="outsideNodes" |
| | | :agent="agentName" |
| | | :sizeX="280" |
| | | :sizeY="370" |
| | | :startX="60" |
| | | class="outer-nodes" |
| | | ></serfDiagram> |
| | | </div> |
| | | </div> |
| | | </template> |
| | | <script> |
| | | import SerfDiagram from "@/components/serfDiagram"; |
| | | export default { |
| | | name: "cloudNode", |
| | | props: { |
| | | nodes: Array, |
| | | }, |
| | | components: { |
| | | SerfDiagram, |
| | | }, |
| | | data() { |
| | | return { |
| | | agentName: "", |
| | | nodeIcons: [], |
| | | //insideNodes: [], |
| | | BaseWidth: 150, |
| | | BaseHeight: 70, |
| | | minWidth: 0, |
| | | minHeight: 0, |
| | | }; |
| | | }, |
| | | mounted() { |
| | | console.log(this.nodes); |
| | | //this.getInsideNodes(); |
| | | }, |
| | | methods: { |
| | | getRandom(index) { |
| | | if (index % 2 == 0) { |
| | | return Math.random() * 20; |
| | | } else { |
| | | return Math.random() * 50; |
| | | } |
| | | }, |
| | | getInsideNodes() { |
| | | let arr = this.nodes.filter( |
| | | (item) => item.hardwareType == "01" || item.hardwareType == "02" |
| | | ); |
| | | let len = arr.length; |
| | | let lefts = []; |
| | | let tops = []; |
| | | this.insideNodes = arr.map((item, index) => { |
| | | lefts.push((20 - len) * (index + 1) + this.getRandom(index)); |
| | | tops.push(30 * (index + 1)); |
| | | return { |
| | | l: 10 + this.getRandom(index), |
| | | t: 30 * (index + 1), |
| | | nodeName: item.nodeName, |
| | | id: item.id, |
| | | workType: item.workType, |
| | | }; |
| | | }); |
| | | this.minWidth = Math.max(...lefts) - Math.min(...lefts); |
| | | this.minHeight = Math.max(...tops) - Math.min(...tops); |
| | | console.log("w,h", this.minWidth, this.minHeight); |
| | | }, |
| | | }, |
| | | computed: { |
| | | cloudPic() { |
| | | return "/images/settings/cloud.png"; |
| | | }, |
| | | insideNodes() { |
| | | return this.nodes.filter( |
| | | (item) => item.hardwareType == "01" || item.hardwareType == "02" |
| | | ); |
| | | }, |
| | | insideSizeX() { |
| | | return 160 + 200 * 0.2 * this.insideNodes.length <= 400 |
| | | ? 160 + 200 * 0.2 * this.insideNodes.length |
| | | : 400; |
| | | }, |
| | | insideSizeY() { |
| | | return 140 + 200 * 0.2 * this.insideNodes.length <= 380 |
| | | ? 140 + 200 * 0.2 * this.insideNodes.length |
| | | : 380; |
| | | }, |
| | | insideStartX() { |
| | | return this.insideSizeX / 3; |
| | | }, |
| | | outsideNodes() { |
| | | return this.nodes.filter((item) => item.hardwareType == "03"); |
| | | }, |
| | | }, |
| | | }; |
| | | </script> |
| | | <style lang="scss"> |
| | | .cloud { |
| | | width: 100%; |
| | | display: flex; |
| | | .inner { |
| | | background: url("/images/settings/easy-cloud.png") no-repeat; |
| | | background-size: 100%; |
| | | margin-top: -55px; |
| | | margin-left: 55px; |
| | | |
| | | .rect { |
| | | position: relative; |
| | | margin: 130px 100px 70px; |
| | | .node { |
| | | position: absolute; |
| | | .node-icon { |
| | | width: 40px; |
| | | height: 40px; |
| | | } |
| | | .node-name { |
| | | font-size: 14px; |
| | | color: #333; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | .outer { |
| | | width: 40%; |
| | | position: relative; |
| | | text-align: left; |
| | | .node { |
| | | position: absolute; |
| | | } |
| | | } |
| | | } |
| | | </style> |
| New file |
| | |
| | | <template> |
| | | <div class="container" v-if="!showWelcome"> |
| | | <div class="container-left"> |
| | | <div |
| | | class="left-card" |
| | | :class="activeIndex == index ? 'left-card-active' : ''" |
| | | v-for="(item, index) in menuArr" |
| | | :key="index" |
| | | @click="openMenu(item.name, index)" |
| | | > |
| | | <span class="icon iconfont"></span> |
| | | <span class="card-text">{{ item.name }}</span> |
| | | </div> |
| | | </div> |
| | | |
| | | <div |
| | | class="container-center" |
| | | v-if="activePage == '账户' || activePage == '日期时间'" |
| | | > |
| | | <div class="account-left" v-if="activePage == '账户'"> |
| | | <div class="account-list"> |
| | | <div |
| | | class="account-card" |
| | | :class="activeAccountIndex == index ? 'account-card-active' : ''" |
| | | v-for="(item, index) in accountArr" |
| | | :key="index" |
| | | ref="account-card" |
| | | @click="openAccount(item, index)" |
| | | > |
| | | <div class="touxiang"> |
| | | <img |
| | | v-if="item.headpic" |
| | | :src="`data:image/png;base64,${item.headpic}`" |
| | | alt="" |
| | | /> |
| | | |
| | | </div> |
| | | <span class="user-name">{{ item.username }}</span> |
| | | </div> |
| | | </div> |
| | | <div class="add-account"> |
| | | <span class="icon iconfont" @click="showAddAccount"></span> |
| | | </div> |
| | | </div> |
| | | <div class="datetime-left" v-if="activePage == '日期时间'"> |
| | | <div class="time-card"> |
| | | <div class="head"> |
| | | <span class="icon iconfont"></span> |
| | | <span>设备时间</span> |
| | | </div> |
| | | <div class="time-main">{{ equipmentTime }}</div> |
| | | <div class="date-bot"> |
| | | <span class="year">{{ equipmentDate }}</span> |
| | | <span class="week">{{ weekday }}</span> |
| | | </div> |
| | | </div> |
| | | <div class="line"> |
| | | <div class="name">NTP校时</div> |
| | | <el-switch |
| | | v-model="isNtp" |
| | | @change="changeSwitch('isNtp')" |
| | | active-color="rgba(61, 104, 225, 1)" |
| | | > |
| | | </el-switch> |
| | | </div> |
| | | |
| | | <div class="line"> |
| | | <div class="name">手动校对</div> |
| | | <el-switch |
| | | v-model="isManual" |
| | | @change="changeSwitch('isManual')" |
| | | active-color="rgba(61, 104, 225, 1)" |
| | | > |
| | | </el-switch> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | <div |
| | | class="container-right" |
| | | v-if="activePage == '账户' || activePage == '日期时间'" |
| | | > |
| | | <div class="account-right" v-if="activePage == '账户'"> |
| | | <div |
| | | class="account-content" |
| | | v-if="inAccountDetail == false && isAddAccount == false" |
| | | > |
| | | <div class="content-top"> |
| | | <div class="touxiang-big"> |
| | | <img |
| | | v-if="activeAccountItem.headpic" |
| | | :src="`data:image/png;base64,${activeAccountItem.headpic}`" |
| | | alt="" |
| | | /> |
| | | </div> |
| | | <div class="user-desc"> |
| | | <div class="username"> |
| | | <span class="icon iconfont" style="margin-right: 5px" |
| | | ></span |
| | | > |
| | | <span>{{ activeAccountItem.username }}</span> |
| | | </div> |
| | | <div class="nickname"> |
| | | <span>昵称:</span> |
| | | <span v-show="!showInputNickName">{{ |
| | | activeAccountItem.nickname |
| | | }}</span> |
| | | <input |
| | | type="text" |
| | | class="input-nick" |
| | | ref="input-nick" |
| | | v-show="showInputNickName" |
| | | v-model="inputNickName" |
| | | @blur="hideInputNick" |
| | | @keydown.enter="blurInputNick" |
| | | /> |
| | | <span class="icon iconfont" @click="editNickName" |
| | | ></span |
| | | > |
| | | </div> |
| | | <div class="user-role"> |
| | | {{ |
| | | activeAccountItem.sysRoles.length |
| | | ? activeAccountItem.sysRoles[0].name |
| | | : "" |
| | | }} |
| | | </div> |
| | | </div> |
| | | </div> |
| | | <div class="list-btn"> |
| | | <div class="item-btn" @click="showChangePassword">修改密码</div> |
| | | <div class="item-btn" @click="deleteAccount">删除账户</div> |
| | | <div class="item-btn" @click="openPermission">权限设置</div> |
| | | </div> |
| | | </div> |
| | | |
| | | <div class="change-pw" v-if="inAccountDetail && isChangePw"> |
| | | <div class="title">修改密码</div> |
| | | <el-form |
| | | :model="passwordForm" |
| | | :rules="pwRules" |
| | | ref="passwordForm" |
| | | class="password-form" |
| | | > |
| | | <el-form-item prop="curPassword"> |
| | | <div class="p-title">当前密码:</div> |
| | | |
| | | <el-input |
| | | placeholder="必填" |
| | | v-model="passwordForm.curPassword" |
| | | show-password |
| | | ></el-input> |
| | | </el-form-item> |
| | | <el-form-item prop="newPassword"> |
| | | <div class="p-title">新密码:</div> |
| | | <el-input |
| | | placeholder="必填" |
| | | v-model="passwordForm.newPassword" |
| | | show-password |
| | | ></el-input> |
| | | </el-form-item> |
| | | <el-form-item prop="confirmPassword"> |
| | | <div class="p-title">确认密码:</div> |
| | | <el-input |
| | | placeholder="必填" |
| | | v-model="passwordForm.confirmPassword" |
| | | show-password |
| | | ></el-input> |
| | | </el-form-item> |
| | | </el-form> |
| | | <div class="btns"> |
| | | <div class="cancel" @click="cancelPassword">取消</div> |
| | | <div class="ok" @click="SaveNewPassword('passwordForm')">保存</div> |
| | | </div> |
| | | </div> |
| | | |
| | | <div class="permission" v-if="inAccountDetail && isSetPermission"> |
| | | <div class="title">权限管理</div> |
| | | |
| | | <div class="line-wrap" v-for="item in sysMenus" :key="item.id"> |
| | | <div class="line"> |
| | | <div class="name">{{ item.name }}</div> |
| | | <el-switch |
| | | v-model="item.selected" |
| | | active-color="rgba(61, 104, 225, 1)" |
| | | @change="fatherChange(item)" |
| | | > |
| | | </el-switch> |
| | | </div> |
| | | <div v-if="item.children"> |
| | | <div |
| | | class="line" |
| | | style="margin-left: 55px" |
| | | v-for="x in item.children" |
| | | :key="x.id" |
| | | > |
| | | <div class="name">{{ x.name }}</div> |
| | | <el-switch |
| | | v-model="x.selected" |
| | | active-color="rgba(61, 104, 225, 1)" |
| | | @change="childrenChange(item)" |
| | | > |
| | | </el-switch> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | <div class="btns"> |
| | | <div class="cancel" @click="cancelSet">取消</div> |
| | | <div class="ok" @click="saveAuth">保存</div> |
| | | </div> |
| | | </div> |
| | | |
| | | <div class="add-account-page" v-if="isAddAccount"> |
| | | <div class="title">添加账户</div> |
| | | <div class="upload-group"> |
| | | <div |
| | | class="upload-jpg" |
| | | :class=" |
| | | selectedPic == index? 'upload-jpg-border' : '' |
| | | " |
| | | v-for="(item, index) in jpgArr" |
| | | :key="index" |
| | | @click="pickHeadDefPic(item, index)" |
| | | > |
| | | <img |
| | | v-if="item" |
| | | :src="`data:image/png;base64,${item.path}`" |
| | | alt="" |
| | | srcset="" |
| | | /> |
| | | <div class="img-mask" v-if="selectedPic == index"> |
| | | <span class="icon iconfont enable"></span> |
| | | </div> |
| | | </div> |
| | | <!-- <el-upload |
| | | class="upload-demo" |
| | | action="https://jsonplaceholder.typicode.com/posts/" |
| | | :show-file-list="false" |
| | | :http-request="uploadUserPic" |
| | | > |
| | | <div v-if="loadedPic == ''" class="upload-jpg-up">上传</div> |
| | | </el-upload> --> |
| | | </div> |
| | | <div class="fill-group"> |
| | | <el-form |
| | | :model="addForm" |
| | | :rules="rules" |
| | | ref="addForm" |
| | | class="add-form" |
| | | > |
| | | <el-form-item prop="userName"> |
| | | <div class="p-title">用户名:</div> |
| | | <el-input |
| | | placeholder="必填" |
| | | v-model="addForm.userName" |
| | | ></el-input> |
| | | </el-form-item> |
| | | <el-form-item prop="roleId"> |
| | | <div class="p-title">角色:</div> |
| | | <el-select v-model="addForm.roleId" placeholder="请选择角色"> |
| | | <el-option |
| | | v-for="(item, i) in roleList" |
| | | :key="i" |
| | | :label="item.name" |
| | | :value="item.id" |
| | | ></el-option> |
| | | </el-select> |
| | | </el-form-item> |
| | | <el-form-item prop="nickName"> |
| | | <div class="p-title">昵称:</div> |
| | | <el-input |
| | | placeholder="选填" |
| | | v-model="addForm.nickName" |
| | | ></el-input> |
| | | </el-form-item> |
| | | <el-form-item prop="password"> |
| | | <div class="p-title">密码:</div> |
| | | <el-input |
| | | placeholder="必填" |
| | | v-model="addForm.password" |
| | | show-password |
| | | ></el-input> |
| | | </el-form-item> |
| | | <el-form-item prop="confirmPassword"> |
| | | <div class="p-title">确认密码:</div> |
| | | <el-input |
| | | placeholder="必填" |
| | | v-model="addForm.confirmPassword" |
| | | show-password |
| | | ></el-input> |
| | | </el-form-item> |
| | | </el-form> |
| | | </div> |
| | | <div class="btns"> |
| | | <div class="cancel" @click="cancelAdd">取消</div> |
| | | <div class="ok" @click="saveAddAccount('addForm')">保存</div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | |
| | | <div class="datetime-right" v-if="activePage == '日期时间'"> |
| | | <div class="ntp-time" v-if="isNtp"> |
| | | <el-form label-width="160px"> |
| | | <el-form-item label="服务器地址"> |
| | | <!-- :disabled="syncType === '2'" --> |
| | | <ip-input |
| | | :ip="ntpServer" |
| | | @on-blur="ntpServer = arguments[0]" |
| | | ></ip-input> |
| | | </el-form-item> |
| | | |
| | | <el-form-item label="校时时间间隔(分钟)"> |
| | | <div class="right"> |
| | | <el-input-number |
| | | v-model.number="timeInterval" |
| | | :min="1" |
| | | :max="60" |
| | | placeholder="请输入" |
| | | size="small" |
| | | :controls="false" |
| | | ></el-input-number> |
| | | <el-button |
| | | type="text" |
| | | @click="testNTP" |
| | | :loading="ntpTestLoading" |
| | | >测试</el-button |
| | | > |
| | | </div> |
| | | </el-form-item> |
| | | </el-form> |
| | | </div> |
| | | |
| | | <div class="manual-time" v-if="isManual"> |
| | | <switchBar |
| | | :barName="`同步本计算机时间`" |
| | | @switchChange="syncBrowser" |
| | | :value="isSyncBrowser" |
| | | ></switchBar> |
| | | |
| | | <div class="clock-wrap"> |
| | | <div class="clock"> |
| | | <div class="hour"> |
| | | <div class="dnum" @click="showInput('Hour')"> |
| | | <span v-show="!showHourInput">{{ syncHour }}</span> |
| | | <input |
| | | class="input-box" |
| | | v-show="showHourInput" |
| | | ref="iptHour" |
| | | oninput="value=value.replace(/[^\d]/g,'');if(value.length>2)value=value.slice(0,2);if(+value>23)value='23'" |
| | | type="text" |
| | | v-model="inputHour" |
| | | @blur="hideInput('Hour')" |
| | | @keydown.enter="hideInput('Hour')" |
| | | /> |
| | | </div> |
| | | <div class="control"> |
| | | <span class="icon iconfont" @click="plusOne('hrs')" |
| | | ></span |
| | | > |
| | | <span class="icon iconfont fanzhuan" @click="minusOne('hrs')" |
| | | ></span |
| | | > |
| | | </div> |
| | | </div> |
| | | <div class="sep">:</div> |
| | | <div class="mins"> |
| | | <div class="dnum" @click="showInput('Min')"> |
| | | <span v-show="!showMinInput">{{ syncMin }}</span> |
| | | <input |
| | | class="input-box" |
| | | v-show="showMinInput" |
| | | ref="iptMin" |
| | | oninput="value=value.replace(/[^\d]/g,'');if(value.length>2)value=value.slice(0,2);if(+value>59)value='59'" |
| | | type="text" |
| | | v-model="inputMin" |
| | | @blur="hideInput('Min')" |
| | | @keydown.enter="hideInput('Min')" |
| | | /> |
| | | </div> |
| | | <div class="control"> |
| | | <span class="icon iconfont" @click="plusOne('min')" |
| | | ></span |
| | | > |
| | | <span class="icon iconfont fanzhuan" @click="minusOne('min')" |
| | | ></span |
| | | > |
| | | </div> |
| | | </div> |
| | | <div class="sep">:</div> |
| | | <div class="mins"> |
| | | <div class="dnum" @click="showInput('Sec')"> |
| | | <span v-show="!showSecInput">{{ syncSec }}</span> |
| | | <input |
| | | class="input-box" |
| | | v-show="showSecInput" |
| | | ref="iptSec" |
| | | oninput="value=value.replace(/[^\d]/g,'');if(value.length>2)value=value.slice(0,2);if(+value>59)value='59'" |
| | | type="text" |
| | | v-model="inputSec" |
| | | @blur="hideInput('Sec')" |
| | | @keydown.enter="hideInput('Sec')" |
| | | /> |
| | | </div> |
| | | <div class="control"> |
| | | <span class="icon iconfont" @click="plusOne('sec')" |
| | | ></span |
| | | > |
| | | <span class="icon iconfont fanzhuan" @click="minusOne('sec')" |
| | | ></span |
| | | > |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | |
| | | <div class="adjust-bar"> |
| | | <div class="minus" @click="minusOne('yrs')">-</div> |
| | | <div class="middle" @click="showInput('Yrs')"> |
| | | <span v-show="!showYrsInput">{{ syncYrs }}</span> |
| | | <input |
| | | class="input-box" |
| | | v-show="showYrsInput" |
| | | ref="iptYrs" |
| | | oninput="value=value.replace(/[^\d]/g,'');if(value.length>4)value=value.slice(0,4);" |
| | | type="text" |
| | | v-model="inputYrs" |
| | | @blur="hideInput('Yrs')" |
| | | @keydown.enter="hideInput('Yrs')" |
| | | /> |
| | | 年 |
| | | </div> |
| | | <div class="plus" @click="plusOne('yrs')">+</div> |
| | | </div> |
| | | <div class="adjust-bar"> |
| | | <div class="minus" @click="minusOne('mth')">-</div> |
| | | <div class="middle" @click="showInput('Month')"> |
| | | <span v-show="!showMonthInput">{{ syncMonth }}</span> |
| | | <input |
| | | class="input-box" |
| | | v-show="showMonthInput" |
| | | ref="iptMonth" |
| | | oninput="value=value.replace(/[^\d]/g,'');if(value.length>2)value=value.slice(0,2);if(+value>12)value='12'" |
| | | type="text" |
| | | v-model="inputMonth" |
| | | @blur="hideInput('Month')" |
| | | @keydown.enter="hideInput('Month')" |
| | | /> |
| | | 月 |
| | | </div> |
| | | |
| | | <div class="plus" @click="plusOne('mth')">+</div> |
| | | </div> |
| | | <div class="adjust-bar"> |
| | | <div class="minus" @click="minusOne('day')">-</div> |
| | | <div class="middle" @click="showInput('Day')"> |
| | | <span v-show="!showDayInput">{{ syncDay }}</span> |
| | | <input |
| | | class="input-box" |
| | | v-show="showDayInput" |
| | | ref="iptDay" |
| | | oninput="value=value.replace(/[^\d]/g,'');if(value.length>2)value=value.slice(0,2);if(+value>31)value='31'" |
| | | type="text" |
| | | v-model="inputDay" |
| | | @blur="hideInput('Day')" |
| | | @keydown.enter="hideInput('Day')" |
| | | /> |
| | | 日 |
| | | </div> |
| | | <div class="plus" @click="plusOne('day')">+</div> |
| | | </div> |
| | | </div> |
| | | |
| | | <div class="btns"> |
| | | <div class="cancel" @click="cancelPassword">取消</div> |
| | | <div class="ok" @click="submitClock">保存</div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | |
| | | <clusterManagement |
| | | v-if="activePage == '集群管理'" |
| | | style="width: 100%" |
| | | ></clusterManagement> |
| | | <netSettings |
| | | v-if="activePage == '网络设置'" |
| | | style="width: 100%" |
| | | ></netSettings> |
| | | <keyboardLanguage |
| | | v-if="activePage == '键盘和语言'" |
| | | style="width: 100%" |
| | | ></keyboardLanguage> |
| | | <generalSettings |
| | | v-if="activePage == '通用设置'" |
| | | style="width: 100%" |
| | | ></generalSettings> |
| | | </div> |
| | | <div class="welcome-page" v-else> |
| | | <div class="child" @click="openWelcome('账户',0)"> |
| | | <div class="child-info"> |
| | | <span class="icon iconfont welcome-icon"></span> |
| | | <span class="welcome-title">账户</span> |
| | | </div> |
| | | </div> |
| | | <div class="child" @click="openWelcome('日期时间',1)"> |
| | | <div class="child-info"> |
| | | <span class="icon iconfont welcome-icon"></span> |
| | | <span class="welcome-title">日期时间</span> |
| | | </div> |
| | | </div> |
| | | <div class="child" @click="openWelcome('集群管理',2)"> |
| | | <div class="child-info"> |
| | | <span class="icon iconfont welcome-icon"></span> |
| | | <span class="welcome-title">集群管理</span> |
| | | </div> |
| | | </div> |
| | | <div class="child" @click="openWelcome('网络设置',3)"> |
| | | <div class="child-info"> |
| | | <span class="icon iconfont welcome-icon"></span> |
| | | <span class="welcome-title">网络设置</span> |
| | | </div> |
| | | </div> |
| | | <div class="child" @click="openWelcome('键盘和语言',4)"> |
| | | <div class="child-info"> |
| | | <span class="icon iconfont welcome-icon"></span> |
| | | <span class="welcome-title">键盘和语言</span> |
| | | </div> |
| | | </div> |
| | | <div class="child" @click="openWelcome('通用设置',5)"> |
| | | <div class="child-info"> |
| | | <span class="icon iconfont welcome-icon"></span> |
| | | <span class="welcome-title">通用设置</span> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </template> |
| | | |
| | | <script> |
| | | import { getClockInfo, saveClockInfo, testNTPserver } from "@/api/system"; |
| | | import { |
| | | uploadHeadPic, |
| | | addUser, |
| | | getUsers, |
| | | updateUser, |
| | | updataUser, |
| | | updatePassword, |
| | | deleteUser, |
| | | getUserMenus, |
| | | defHeadPics, |
| | | getRoles, |
| | | } from "@/api/user"; |
| | | import switchBar from "../components/switchBar"; |
| | | import ipInput from "@/components/subComponents/IPInput"; |
| | | import clusterManagement from "../views/clusterManagement"; |
| | | import netSettings from "../views/NetSettings"; |
| | | import keyboardLanguage from "../views/keyboardLanguage"; |
| | | import generalSettings from "../views/generalSettings"; |
| | | export default { |
| | | name: "settings", |
| | | components: { |
| | | switchBar, |
| | | ipInput, |
| | | clusterManagement, |
| | | netSettings, |
| | | keyboardLanguage, |
| | | generalSettings, |
| | | }, |
| | | data() { |
| | | var validatePass2 = (rule, value, callback) => { |
| | | if (value === "") { |
| | | callback(new Error("请再次输入密码")); |
| | | } else if (value !== this.addForm.password) { |
| | | callback(new Error("两次输入密码不一致!")); |
| | | } else { |
| | | callback(); |
| | | } |
| | | }; |
| | | var validatePass4 = (rule, value, callback) => { |
| | | if (value === "") { |
| | | callback(new Error("请再次输入密码")); |
| | | } else if (value !== this.passwordForm.newPassword) { |
| | | callback(new Error("两次输入密码不一致!")); |
| | | } else { |
| | | callback(); |
| | | } |
| | | }; |
| | | return { |
| | | showAccount: true, |
| | | syncYrs: "", |
| | | activeAccountItem: {}, |
| | | syncMonth: "", |
| | | syncHour: "", |
| | | showWelcome: true, |
| | | syncDay: "", |
| | | syncMin: "", |
| | | syncSec: "00", |
| | | isSyncBrowser: false, |
| | | showDateTime: false, |
| | | isAddAccount: false, |
| | | isCount: false, |
| | | isCalculate: false, |
| | | browserTimer: null, |
| | | timezone: "", |
| | | isRealtime: false, |
| | | inputNickName: "", |
| | | showHourInput: false, |
| | | showMinInput: false, |
| | | showSecInput: false, |
| | | showYrsInput: false, |
| | | showMonthInput: false, |
| | | selectedPic: null, |
| | | showDayInput: false, |
| | | loadedPic: "", |
| | | cameraInfo: false, |
| | | dependentScene: false, |
| | | timestamp: 0, |
| | | inAccountDetail: false, |
| | | isChangePw: false, |
| | | isSetPermission: false, |
| | | timeInterval: 10, |
| | | ntpServer: "", |
| | | syncType: "1", |
| | | equipmentTime: "", |
| | | equipmentDate: "", |
| | | roleList: [], |
| | | ntpTestLoading: false, |
| | | settime: "", |
| | | weekday: "", |
| | | menuArr: [ |
| | | { name: "账户" }, |
| | | { name: "日期时间" }, |
| | | { name: "集群管理" }, |
| | | { name: "网络设置" }, |
| | | { name: "键盘和语言" }, |
| | | { name: "通用设置" }, |
| | | ], |
| | | accountArr: [], |
| | | jpgArr: [], |
| | | isManual: false, |
| | | isNtp: true, |
| | | activePage: "账户", |
| | | activeIndex: 0, |
| | | clockTimer: null, |
| | | inputHour: "", |
| | | inputMin: "", |
| | | inputSec: "", |
| | | inputYrs: "", |
| | | showInputNickName: false, |
| | | inputMonth: "", |
| | | inputDay: "", |
| | | passwordForm: { |
| | | curPassword: "", |
| | | newPassword: "", |
| | | confirmPassword: "", |
| | | }, |
| | | activeAccountIndex: 0, |
| | | sysMenus: [], |
| | | addForm: { |
| | | userName: "", |
| | | nickName: "", |
| | | password: "", |
| | | headpic: "", |
| | | confirmPassword: "", |
| | | roleId: "", |
| | | }, |
| | | rules: { |
| | | userName: [ |
| | | { required: true, message: "请输入用户名", trigger: "blur" }, |
| | | { |
| | | min: 3, |
| | | max: 10, |
| | | message: "长度在 3 到 10 个字符", |
| | | trigger: "blur", |
| | | }, |
| | | ], |
| | | password: [ |
| | | { required: true, message: "请输入密码", trigger: "blur" }, |
| | | { min: 6, message: "长度至少为 6 位", trigger: "blur" }, |
| | | ], |
| | | confirmPassword: [{ validator: validatePass2, trigger: "blur" }], |
| | | }, |
| | | pwRules: { |
| | | // pw: [{ validator: validatePass3, trigger: "blur" }], |
| | | curPassword: [ |
| | | { required: true, message: "请输入密码", trigger: "blur" }, |
| | | { min: 6, message: "长度至少为 6 位", trigger: "blur" }, |
| | | ], |
| | | newPassword: [ |
| | | { required: true, message: "请输入密码", trigger: "blur" }, |
| | | { min: 6, message: "长度至少为 6 位", trigger: "blur" }, |
| | | ], |
| | | confirmPassword: [{ validator: validatePass4, trigger: "blur" }], |
| | | }, |
| | | }; |
| | | }, |
| | | beforeDestroy() { |
| | | clearTimeout(this.clockTimer); |
| | | clearInterval(this.browserTimer); |
| | | }, |
| | | mounted() { |
| | | this.fetchUserList(); |
| | | this.fetchDefHeadPic(); |
| | | }, |
| | | methods: { |
| | | fetchDefHeadPic() { |
| | | defHeadPics().then((res) => { |
| | | this.jpgArr = res.data; |
| | | }); |
| | | }, |
| | | fetchUserList(showLast = false) { |
| | | getUsers().then((res) => { |
| | | this.accountArr = res.data; |
| | | if (this.accountArr.length) { |
| | | this.activeAccountItem = this.accountArr[0]; |
| | | this.activeAccountIndex = 0; |
| | | } |
| | | if (showLast) { |
| | | this.cancelAdd(); |
| | | const lastIdx = this.accountArr.length - 1; |
| | | this.openAccount(this.accountArr[lastIdx], lastIdx); |
| | | } |
| | | }); |
| | | }, |
| | | blurInputNick() { |
| | | this.$refs["input-nick"].blur(); |
| | | }, |
| | | editNickName() { |
| | | this.showInputNickName = true; |
| | | this.inputNickName = this.activeAccountItem.nickname; |
| | | this.$refs["input-nick"].focus(); |
| | | }, |
| | | hideInputNick() { |
| | | this.showInputNickName = false; |
| | | updateUser({ |
| | | id: this.activeAccountItem.id, |
| | | nickname: this.inputNickName, |
| | | }).then((res) => { |
| | | this.$message.success(res.msg); |
| | | this.fetchUserList(true); |
| | | }); |
| | | }, |
| | | openAccount(item, i) { |
| | | this.activeAccountItem = item; |
| | | this.activeAccountIndex = i; |
| | | this.inAccountDetail = false; |
| | | this.cancelSet(); |
| | | this.fetchMenu(); |
| | | }, |
| | | minusOne(typ) { |
| | | this.isSyncBrowser = false; |
| | | this.syncBrowser(false); |
| | | let num; |
| | | switch (typ) { |
| | | case "hrs": |
| | | num = +this.syncHour - 1; |
| | | if (num == -1) { |
| | | num = 23; |
| | | } |
| | | this.syncHour = this.padZero(num); |
| | | break; |
| | | case "min": |
| | | num = +this.syncMin - 1; |
| | | if (num == -1) { |
| | | num = 59; |
| | | } |
| | | this.syncMin = this.padZero(num); |
| | | break; |
| | | case "sec": |
| | | num = +this.syncSec + 1; |
| | | if (num == -1) { |
| | | num = 59; |
| | | } |
| | | this.syncSec = this.padZero(num); |
| | | break; |
| | | case "yrs": |
| | | num = +this.syncYrs - 1; |
| | | this.syncYrs = this.padZero(num); |
| | | break; |
| | | case "mth": |
| | | num = +this.syncMonth - 1; |
| | | if (num == 0) { |
| | | num = 12; |
| | | this.minusOne("yrs"); |
| | | } |
| | | this.syncMonth = this.padZero(num); |
| | | break; |
| | | case "day": |
| | | num = +this.syncDay - 1; |
| | | if (num == 0) { |
| | | this.minusOne("mth"); |
| | | const maxDay = new Date( |
| | | +this.syncYrs, |
| | | +this.syncMonth, |
| | | 0 |
| | | ).getDate(); |
| | | num = maxDay; |
| | | } |
| | | this.syncDay = this.padZero(num); |
| | | break; |
| | | default: |
| | | break; |
| | | } |
| | | }, |
| | | fatherChange(item) { |
| | | item.children.forEach((x) => { |
| | | x.selected = item.selected; |
| | | }); |
| | | }, |
| | | childrenChange(item) { |
| | | let isAllSelected = item.children.every((x) => x.selected == true); |
| | | item.selected = isAllSelected; |
| | | }, |
| | | plusOne(typ) { |
| | | this.isSyncBrowser = false; |
| | | this.syncBrowser(false); |
| | | let num; |
| | | switch (typ) { |
| | | case "hrs": |
| | | num = +this.syncHour + 1; |
| | | if (num == 24) { |
| | | num = 0; |
| | | } |
| | | this.syncHour = this.padZero(num); |
| | | break; |
| | | case "min": |
| | | num = +this.syncMin + 1; |
| | | if (num == 60) { |
| | | num = 0; |
| | | } |
| | | this.syncMin = this.padZero(num); |
| | | break; |
| | | case "sec": |
| | | num = +this.syncSec + 1; |
| | | if (num == 60) { |
| | | num = 0; |
| | | } |
| | | this.syncSec = this.padZero(num); |
| | | break; |
| | | case "yrs": |
| | | num = +this.syncYrs + 1; |
| | | this.syncYrs = this.padZero(num); |
| | | break; |
| | | case "mth": |
| | | num = +this.syncMonth + 1; |
| | | if (num == 13) { |
| | | num = 1; |
| | | } |
| | | this.syncMonth = this.padZero(num); |
| | | break; |
| | | case "day": |
| | | num = +this.syncDay + 1; |
| | | const maxDay = new Date(+this.syncYrs, +this.syncMonth, 0).getDate(); |
| | | if (num > maxDay) { |
| | | num = 1; |
| | | } |
| | | this.syncDay = this.padZero(num); |
| | | break; |
| | | default: |
| | | break; |
| | | } |
| | | }, |
| | | submitClock() { |
| | | if (this.syncType === "1") { |
| | | if (this.ntpServer === "" || this.ntpServer === "...") { |
| | | this.$notify({ |
| | | type: "error", |
| | | message: "NTP 服务器地址不能为空", |
| | | }); |
| | | return false; |
| | | } else if (this.timeInterval === "") { |
| | | this.timeInterval = 1; |
| | | } |
| | | } else if (this.isSyncBrowser) { |
| | | if (this.settime === "") { |
| | | this.$notify({ |
| | | type: "error", |
| | | message: "设置时间不能为空", |
| | | }); |
| | | return false; |
| | | } |
| | | } else { |
| | | this.settime = `${this.syncYrs}-${this.syncMonth}-${this.syncDay} ${this.syncHour}:${this.syncMin}:${this.syncSec}`; |
| | | } |
| | | saveClockInfo({ |
| | | timeZone: this.timezone, |
| | | ntp: this.syncType === "1", |
| | | ntpServer: this.ntpServer, |
| | | interval: this.timeInterval, |
| | | newTime: this.settime, |
| | | }).then((rsp) => { |
| | | if (rsp && rsp.success) { |
| | | this.$notify({ |
| | | type: "success", |
| | | message: "设置成功", |
| | | }); |
| | | } |
| | | this.initClockConf(); |
| | | }); |
| | | }, |
| | | flatGetArr(arr, res) { |
| | | for (const item of arr) { |
| | | if (item.selected) res.push(item.id); |
| | | if (item.children) this.flatGetArr(item.children, res); |
| | | } |
| | | }, |
| | | saveAuth() { |
| | | let arr = []; |
| | | this.flatGetArr(this.sysMenus, arr); |
| | | updataUser({ |
| | | id: this.activeAccountItem.id, |
| | | menuIds: arr, |
| | | }).then((res) => { |
| | | if (res.success) { |
| | | this.$message.success(res.msg); |
| | | this.cancelSet(); |
| | | } |
| | | }); |
| | | }, |
| | | formatTime(number, format) { |
| | | var formateArr = ["Y", "M", "D", "h", "m", "s"]; |
| | | var returnArr = []; |
| | | var date = new Date(number * 1000); |
| | | returnArr.push(date.getFullYear()); |
| | | returnArr.push(this.formatNumber(date.getMonth() + 1)); |
| | | returnArr.push(this.formatNumber(date.getDate())); |
| | | returnArr.push(this.formatNumber(date.getHours())); |
| | | returnArr.push(this.formatNumber(date.getMinutes())); |
| | | returnArr.push(this.formatNumber(date.getSeconds())); |
| | | this.weekday = "星期" + "日一二三四五六".charAt(date.getDay()); |
| | | for (var i in returnArr) { |
| | | format = format.replace(formateArr[i], returnArr[i]); |
| | | } |
| | | return format; |
| | | }, |
| | | padZero(n) { |
| | | n = +n; |
| | | return n < 10 ? "0" + n : "" + n; |
| | | }, |
| | | formatNumber(n) { |
| | | n = n.toString(); |
| | | return n[1] ? n : "0" + n; |
| | | }, |
| | | // uploadUserPic(params) { |
| | | // let param = new FormData(); |
| | | // param.append("file", params.file); |
| | | // uploadHeadPic(param).then((res) => { |
| | | // this.jpgArr.push(res.data); |
| | | // this.loadedPic = res.data; |
| | | // }); |
| | | // }, |
| | | initClockConf(ntpTest = false) { |
| | | getClockInfo().then((rsp) => { |
| | | if (rsp && rsp.success) { |
| | | this.timezone = rsp.data.time_zone; |
| | | if (!ntpTest) { |
| | | this.syncType = rsp.data.ntp ? "1" : "2"; |
| | | this.isNtp = rsp.data.ntp; |
| | | this.isManual = !rsp.data.ntp; |
| | | } |
| | | if (rsp.data.ntp) { |
| | | this.ntpServer = rsp.data.ntp_server; |
| | | this.timeInterval = rsp.data.interval; |
| | | } |
| | | this.timestamp = rsp.data.local_time; |
| | | if (this.clockTimer === null) { |
| | | this.runClock(); |
| | | if (this.isManual) this.parseTime(); |
| | | } |
| | | } |
| | | }); |
| | | }, |
| | | openMenu(name, i) { |
| | | this.activePage = name; |
| | | this.activeIndex = i; |
| | | if (this.activePage == "日期时间") { |
| | | this.initClockConf(); |
| | | } |
| | | }, |
| | | openWelcome(name,i){ |
| | | this.showWelcome = false |
| | | this.openMenu(name,i) |
| | | }, |
| | | showInput(typ) { |
| | | this[`show${typ}Input`] = true; |
| | | this.$nextTick(() => { |
| | | this.$refs[`ipt${typ}`].focus(); |
| | | }); |
| | | }, |
| | | hideInput(typ) { |
| | | if (this[`input${typ}`]) { |
| | | this[`sync${typ}`] = this.padZero(this[`input${typ}`]); |
| | | } |
| | | this[`show${typ}Input`] = false; |
| | | this[`input${typ}`] = ""; |
| | | }, |
| | | syncBrowser(enable) { |
| | | this.isSyncBrowser = enable; |
| | | if (!enable) { |
| | | clearInterval(this.browserTimer); |
| | | } else { |
| | | this.browserTimer = setInterval(() => { |
| | | let timestamp = new Date().getTime() / 1000; |
| | | this.settime = this.formatTime(timestamp, "Y-M-D h:m:s"); |
| | | let [arr1, arr2] = this.settime.split(" "); |
| | | [this.syncYrs, this.syncMonth, this.syncDay] = arr1.split("-"); |
| | | [this.syncHour, this.syncMin, this.syncSec] = arr2.split(":"); |
| | | }, 1000); |
| | | } |
| | | }, |
| | | showAddAccount() { |
| | | this.inAccountDetail = false; |
| | | this.isAddAccount = true; |
| | | getRoles().then((res) => { |
| | | if (res.success) { |
| | | this.roleList = res.data; |
| | | } |
| | | }); |
| | | }, |
| | | cancelAdd() { |
| | | this.inAccountDetail = false; |
| | | this.isAddAccount = false; |
| | | this.$refs["addForm"].resetFields(); |
| | | this.selectedPic = null; |
| | | }, |
| | | cancelPassword() { |
| | | this.isChangePw = false; |
| | | this.inAccountDetail = false; |
| | | this.$refs["passwordForm"].resetFields(); |
| | | }, |
| | | SaveNewPassword(formName) { |
| | | this.$refs[formName].validate((valid) => { |
| | | if (valid) { |
| | | updatePassword({ |
| | | oldPwd: this.passwordForm.curPassword, |
| | | newPwd: this.passwordForm.newPassword, |
| | | }).then( |
| | | (res) => { |
| | | if (res.success) { |
| | | this.$message.success(res.msg); |
| | | this.cancelPassword(); |
| | | } |
| | | }, |
| | | (err) => { |
| | | this.$message.warning("保存失败," + err.msg); |
| | | } |
| | | ); |
| | | } |
| | | }); |
| | | }, |
| | | saveAddAccount(formName) { |
| | | this.$refs[formName].validate((valid) => { |
| | | if (valid) { |
| | | let data = { |
| | | username: this.addForm.userName, |
| | | password: this.addForm.password, |
| | | nickname: this.addForm.nickName, |
| | | headpic: this.addForm.headpic, |
| | | }; |
| | | addUser(data).then( |
| | | (res) => { |
| | | this.$message.success(res.data); |
| | | this.fetchUserList(true); |
| | | }, |
| | | (err) => { |
| | | this.$message.warning("保存失败," + err.msg); |
| | | } |
| | | ); |
| | | } else { |
| | | console.log("error submit!!"); |
| | | return false; |
| | | } |
| | | }); |
| | | }, |
| | | pickHeadDefPic(item, i) { |
| | | this.addForm.headpic = item.path; |
| | | this.selectedPic = i; |
| | | }, |
| | | testNTP() { |
| | | this.ntpTestLoading = true; |
| | | testNTPserver({ server: this.ntpServer }) |
| | | .then((rsp) => { |
| | | if (rsp && rsp.success) { |
| | | this.$notify({ |
| | | type: "success", |
| | | message: "时间同步成功", |
| | | }); |
| | | } else { |
| | | this.$notify({ |
| | | type: "error", |
| | | message: "时间同步失败", |
| | | }); |
| | | } |
| | | this.ntpTestLoading = false; |
| | | this.initClockConf(true); |
| | | }) |
| | | .catch((err) => { |
| | | this.$notify({ |
| | | type: "error", |
| | | message: "时间同步失败,请检查服务器ip", |
| | | }); |
| | | this.ntpTestLoading = false; |
| | | }); |
| | | }, |
| | | cancelSet() { |
| | | this.isSetPermission = false; |
| | | this.inAccountDetail = false; |
| | | this.sysMenus = []; |
| | | }, |
| | | showChangePassword() { |
| | | this.isChangePw = true; |
| | | this.inAccountDetail = true; |
| | | }, |
| | | runClock() { |
| | | const str = this.formatTime(++this.timestamp, "Y-M-D h:m:s"); |
| | | [this.equipmentDate, this.equipmentTime] = str.split(" "); |
| | | this.clockTimer = setTimeout(() => { |
| | | this.runClock(); |
| | | }, 1000); |
| | | }, |
| | | deleteAccount() { |
| | | this.$confirm("您是否确认删除账户?", "删除账户", { |
| | | confirmButtonText: "确定", |
| | | cancelButtonText: "取消", |
| | | }) |
| | | .then(() => { |
| | | let obj = { |
| | | ids: [this.activeAccountItem.id], |
| | | }; |
| | | deleteUser(obj).then((res) => { |
| | | if (res.success) { |
| | | this.fetchUserList(); |
| | | this.$message({ |
| | | type: "success", |
| | | message: "删除成功!", |
| | | }); |
| | | } else { |
| | | this.$message.warning("删除失败"); |
| | | } |
| | | }); |
| | | }) |
| | | .catch(() => {}); |
| | | }, |
| | | fetchMenu() { |
| | | getUserMenus({ |
| | | userId: this.activeAccountItem.id, |
| | | }).then((res) => { |
| | | if (res && res.success) { |
| | | this.sysMenus = res.data; |
| | | } |
| | | }); |
| | | }, |
| | | openPermission() { |
| | | this.inAccountDetail = true; |
| | | this.isSetPermission = true; |
| | | if (this.sysMenus.length == 0) { |
| | | this.fetchMenu(); |
| | | } |
| | | }, |
| | | parseTime() { |
| | | [this.syncYrs, this.syncMonth, this.syncDay] = this.equipmentDate.split( |
| | | "-" |
| | | ); |
| | | [this.syncHour, this.syncMin, this.syncSec] = this.equipmentTime.split( |
| | | ":" |
| | | ); |
| | | }, |
| | | changeSwitch(str) { |
| | | if (str == "isNtp") { |
| | | this.isManual = !this[str]; |
| | | } else { |
| | | this.isNtp = !this[str]; |
| | | } |
| | | this.syncType = this.isNtp ? "1" : "2"; |
| | | if (this.isManual) this.parseTime(); |
| | | }, |
| | | }, |
| | | computed: { |
| | | isShowAddAccount() { |
| | | const info = JSON.parse(sessionStorage.getItem("userInfo")); |
| | | return true; |
| | | }, |
| | | }, |
| | | }; |
| | | </script> |
| | | <style lang="scss"> |
| | | .welcome-page { |
| | | width: 100%; |
| | | height: 100%; |
| | | background-color: #f5f5f5; |
| | | display: -ms-flexbox; |
| | | padding: 0 50px; |
| | | -webkit-box-sizing: border-box; |
| | | box-sizing: border-box; |
| | | .child { |
| | | box-sizing: border-box; |
| | | background-color: white; |
| | | -webkit-box-flex: 0; |
| | | -ms-flex: 0 0 33.3%; |
| | | /* flex: 0 0 16%; */ |
| | | float: left; |
| | | width: 250px; |
| | | height: 200px; |
| | | margin: 50px 57px 30px 57px; |
| | | border-radius: 20px; |
| | | display: flex; |
| | | justify-content: center; |
| | | align-items: center; |
| | | cursor: pointer; |
| | | .child-info { |
| | | display: flex; |
| | | flex-direction: column; |
| | | height: 62%; |
| | | justify-content: space-around; |
| | | .welcome-icon { |
| | | font-size: 72px; |
| | | } |
| | | .welcome-title { |
| | | font-size: 18px; |
| | | } |
| | | } |
| | | } |
| | | .child:hover { |
| | | -moz-box-shadow: 5px 5px 10px #ddd; |
| | | -webkit-box-shadow: 5px 5px 10px #ddd; |
| | | box-shadow: 5px 5px 10px #ddd; |
| | | transform: translate3d(0,-2.5px,0); |
| | | transition: all 0.3s; |
| | | } |
| | | } |
| | | .container { |
| | | height: 100%; |
| | | display: flex; |
| | | flex-direction: row; |
| | | flex: 1; |
| | | flex-basis: auto; |
| | | box-sizing: border-box; |
| | | .container-left { |
| | | height: 100%; |
| | | width: 230px; |
| | | overflow: auto; |
| | | box-sizing: border-box; |
| | | flex-shrink: 0; |
| | | padding: 10px; |
| | | border-right: 5px solid rgba(248, 248, 248, 1); |
| | | box-sizing: border-box; |
| | | .left-card { |
| | | height: 55px; |
| | | cursor: pointer; |
| | | border-radius: 12px; |
| | | margin-bottom: 10px; |
| | | display: flex; |
| | | align-items: center; |
| | | .iconfont { |
| | | margin-left: 25px; |
| | | margin-right: 10px; |
| | | font-size: 24px; |
| | | } |
| | | .card-text { |
| | | font-size: 16px; |
| | | } |
| | | } |
| | | .left-card-active { |
| | | background-color: rgba(61, 104, 225, 1); |
| | | color: #fff; |
| | | } |
| | | .left-card:hover { |
| | | background-color: rgba(61, 104, 225, 1); |
| | | color: #fff; |
| | | } |
| | | } |
| | | .container-center { |
| | | height: 100%; |
| | | width: 280px; |
| | | overflow: auto; |
| | | flex-shrink: 0; |
| | | padding: 10px; |
| | | border-right: 5px solid rgba(248, 248, 248, 1); |
| | | box-sizing: border-box; |
| | | .account-left { |
| | | .add-account { |
| | | color: rgba(61, 104, 225, 1); |
| | | margin-top: 30px; |
| | | .iconfont { |
| | | cursor: pointer; |
| | | font-size: 32px; |
| | | } |
| | | } |
| | | .account-card { |
| | | height: 50px; |
| | | background-color: rgba(248, 248, 248, 1); |
| | | margin-bottom: 10px; |
| | | display: flex; |
| | | align-items: center; |
| | | padding: 0 20px; |
| | | box-sizing: border-box; |
| | | border-radius: 10px; |
| | | cursor: pointer; |
| | | .touxiang { |
| | | height: 35px; |
| | | width: 35px; |
| | | background-color: bisque; |
| | | border-radius: 17.5px; |
| | | img { |
| | | border: none; |
| | | |
| | | height: 35px; |
| | | width: 35px; |
| | | border-radius: 17.5px; |
| | | } |
| | | } |
| | | .user-name { |
| | | margin-left: 10px; |
| | | font-size: 14px; |
| | | } |
| | | } |
| | | |
| | | .account-card-active { |
| | | background-color: rgba(61, 104, 225, 1); |
| | | color: #fff; |
| | | } |
| | | } |
| | | .datetime-left { |
| | | .time-card { |
| | | height: 105px; |
| | | background-color: rgba(248, 248, 248, 1); |
| | | margin-bottom: 30px; |
| | | border-radius: 10px; |
| | | .head { |
| | | height: 30px; |
| | | line-height: 30px; |
| | | text-align: left; |
| | | box-sizing: border-box; |
| | | padding: 0 10px; |
| | | font-size: 14px; |
| | | .icon { |
| | | margin-right: 5px; |
| | | color: rgba(61, 104, 225, 1); |
| | | } |
| | | } |
| | | .time-main { |
| | | height: 42px; |
| | | line-height: 42px; |
| | | font-family: Consolas; |
| | | font-size: 36px; |
| | | } |
| | | .date-bot { |
| | | height: 25px; |
| | | font-size: 14px; |
| | | line-height: 25px; |
| | | color: #868686; |
| | | display: flex; |
| | | justify-content: space-evenly; |
| | | } |
| | | } |
| | | .line { |
| | | display: flex; |
| | | align-items: center; |
| | | height: 50px; |
| | | padding: 0 25px; |
| | | background-color: rgba(248, 248, 248, 1); |
| | | justify-content: space-between; |
| | | border-radius: 12px; |
| | | margin-bottom: 10px; |
| | | .name { |
| | | font-size: 14px; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | .container-right { |
| | | flex: 1; |
| | | flex-basis: auto; |
| | | overflow: auto; |
| | | box-sizing: border-box; |
| | | position: relative; |
| | | |
| | | padding: 20px 40px; |
| | | .account-right { |
| | | .account-content { |
| | | .content-top { |
| | | height: 120px; |
| | | width: 350px; |
| | | margin: 0 auto; |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: center; |
| | | margin-bottom: 20px; |
| | | .touxiang-big { |
| | | width: 100px; |
| | | height: 100px; |
| | | background-color: bisque; |
| | | border-radius: 50px; |
| | | img { |
| | | border: none; |
| | | |
| | | width: 100px; |
| | | height: 100px; |
| | | border-radius: 50px; |
| | | } |
| | | } |
| | | .user-desc { |
| | | height: 100px; |
| | | display: flex; |
| | | flex-direction: column; |
| | | align-items: baseline; |
| | | min-width: 200px; |
| | | .username { |
| | | margin: 5px 15px; |
| | | height: 30px; |
| | | line-height: 30px; |
| | | // width: 90px; |
| | | text-align: left; |
| | | font-size: 15px; |
| | | display: flex; |
| | | align-items: center; |
| | | } |
| | | .nickname { |
| | | margin: 5px 15px; |
| | | font-size: 14px; |
| | | .input-nick { |
| | | width: 50px; |
| | | margin-right: 5px; |
| | | } |
| | | .iconfont { |
| | | font-size: 14px; |
| | | margin-left: 5px; |
| | | cursor: pointer; |
| | | } |
| | | } |
| | | .user-role { |
| | | margin: 5px 0 0 15px; |
| | | font-size: 14px; |
| | | color: darkseagreen; |
| | | } |
| | | } |
| | | } |
| | | .list-btn { |
| | | display: flex; |
| | | |
| | | flex-direction: column; |
| | | align-items: center; |
| | | .item-btn { |
| | | width: 500px; |
| | | height: 45px; |
| | | background-color: #f0f0f0; |
| | | margin-bottom: 15px; |
| | | border-radius: 10px; |
| | | line-height: 45px; |
| | | font-size: 15px; |
| | | cursor: pointer; |
| | | } |
| | | .item-btn:hover { |
| | | color: rgba(255, 153, 102, 1); |
| | | } |
| | | } |
| | | } |
| | | .title { |
| | | height: 30px; |
| | | line-height: 30px; |
| | | /* background-color: aliceblue; */ |
| | | margin-bottom: 10px; |
| | | font-size: 16px; |
| | | font-weight: 600; |
| | | } |
| | | .change-pw { |
| | | .p-title { |
| | | text-align: left; |
| | | font-size: 15px; |
| | | margin-top: 5px; |
| | | } |
| | | } |
| | | .el-form-item { |
| | | margin-bottom: 0; |
| | | .el-input__inner { |
| | | background-color: rgba(240, 240, 240, 1); |
| | | border: none; |
| | | border-radius: 12px; |
| | | height: 45px; |
| | | padding: 0 20px; |
| | | font-size: 15px; |
| | | } |
| | | .el-input__clear { |
| | | color: dimgray; |
| | | font-size: 17px; |
| | | line-height: 45px; |
| | | } |
| | | .el-input__suffix { |
| | | right: 1px; |
| | | top: -0.5px; |
| | | width: 45px; |
| | | // background-color: rgba(61, 104, 225, 1); |
| | | /* color: white; */ |
| | | border-radius: 12px; |
| | | } |
| | | } |
| | | .permission { |
| | | .line { |
| | | display: flex; |
| | | align-items: center; |
| | | height: 50px; |
| | | padding: 0 25px; |
| | | background-color: rgba(248, 248, 248, 1); |
| | | justify-content: space-between; |
| | | border-radius: 12px; |
| | | margin-bottom: 10px; |
| | | .name { |
| | | font-size: 14px; |
| | | } |
| | | } |
| | | } |
| | | |
| | | .add-account-page { |
| | | .upload-group { |
| | | height: 120px; |
| | | width: 360px; |
| | | margin: 0 auto; |
| | | overflow: hidden; |
| | | .upload-jpg { |
| | | position: relative; |
| | | height: 48px; |
| | | width: 48px; |
| | | float: left; |
| | | margin: 0 10px; |
| | | margin-bottom: 10px; |
| | | background-color: rgba(242, 242, 242, 1); |
| | | border: 2px solid transparent; |
| | | border-radius: 50%; |
| | | cursor: pointer; |
| | | img { |
| | | height: 48px; |
| | | width: 48px; |
| | | border-radius: 50%; |
| | | } |
| | | .img-mask { |
| | | position: absolute; |
| | | left: 0; |
| | | top: 0; |
| | | height: 48px; |
| | | width: 48px; |
| | | background-color: rgba(0, 0, 0, 0.3); |
| | | color: white; |
| | | border-radius: 50%; |
| | | display: flex; |
| | | justify-content: center; |
| | | align-items: center; |
| | | .selected { |
| | | font-size: 22px; |
| | | } |
| | | } |
| | | } |
| | | .upload-jpg-border { |
| | | border: 2px solid cornflowerblue; |
| | | } |
| | | .upload-jpg-up { |
| | | height: 48px; |
| | | width: 48px; |
| | | float: left; |
| | | display: flex; |
| | | background-color: rgba(242, 242, 242, 1); |
| | | border: 2px solid transparent; |
| | | border-radius: 50%; |
| | | |
| | | justify-content: center; |
| | | align-items: center; |
| | | font-size: 12px; |
| | | cursor: pointer; |
| | | } |
| | | } |
| | | .fill-group { |
| | | .p-title { |
| | | height: 34px; |
| | | text-align: left; |
| | | } |
| | | .el-form-item { |
| | | .el-select { |
| | | width: 100%; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| | | .datetime-right { |
| | | .el-form-item.is-required:not(.is-no-asterisk) |
| | | > .el-form-item__label:before, |
| | | .el-form-item.is-required:not(.is-no-asterisk) |
| | | .el-form-item__label-wrap |
| | | > .el-form-item__label:before { |
| | | display: none; |
| | | } |
| | | .el-form-item { |
| | | margin-bottom: 10px; |
| | | height: 50px; |
| | | background: #f8f8f8; |
| | | padding: 4px 20px; |
| | | -webkit-box-sizing: border-box; |
| | | box-sizing: border-box; |
| | | border-radius: 10px; |
| | | .el-form-item__label { |
| | | text-align: left; |
| | | line-height: 42px; |
| | | } |
| | | } |
| | | .el-form-item__content { |
| | | line-height: 40px; |
| | | position: relative; |
| | | font-size: 14px; |
| | | margin-bottom: 10px; |
| | | } |
| | | .ip-input-container { |
| | | max-width: none !important; |
| | | } |
| | | .ntp-time { |
| | | .right { |
| | | display: flex; |
| | | align-items: baseline; |
| | | .el-input-number--small { |
| | | width: 100%; |
| | | } |
| | | .el-button--text { |
| | | margin-left: 10px; |
| | | text-decoration: underline; |
| | | } |
| | | } |
| | | .ntp-bar { |
| | | height: 40px; |
| | | background-color: rgba(248, 248, 248, 1); |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: space-between; |
| | | padding: 0 10px; |
| | | border-radius: 10px; |
| | | margin-bottom: 10px; |
| | | .title { |
| | | min-width: 70px; |
| | | } |
| | | .input-area { |
| | | width: 450px; |
| | | height: 30px; |
| | | background-color: rgba(240, 240, 240, 1); |
| | | border-radius: 10px; |
| | | line-height: 30px; |
| | | font-size: 14px; |
| | | } |
| | | } |
| | | .int-bar { |
| | | height: 40px; |
| | | background-color: rgba(248, 248, 248, 1); |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: space-between; |
| | | padding: 0 10px; |
| | | border-radius: 10px; |
| | | margin-bottom: 10px; |
| | | .title { |
| | | min-width: 130px; |
| | | } |
| | | .right { |
| | | width: 450px; |
| | | display: flex; |
| | | align-items: center; |
| | | height: 30px; |
| | | |
| | | .input-area { |
| | | // width: 410px; |
| | | background-color: rgba(240, 240, 240, 1); |
| | | border-radius: 10px; |
| | | line-height: 30px; |
| | | width: -webkit-fill-available; |
| | | |
| | | font-size: 14px; |
| | | } |
| | | .test { |
| | | width: 40px; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | .manual-time { |
| | | .clock-wrap { |
| | | height: 75px; |
| | | |
| | | background-color: #f8f8f8; |
| | | display: flex; |
| | | justify-content: center; |
| | | align-items: center; |
| | | margin-bottom: 10px; |
| | | border-radius: 10px; |
| | | .clock { |
| | | display: flex; |
| | | align-items: center; |
| | | height: 90px; |
| | | justify-content: space-evenly; |
| | | .iconfont { |
| | | cursor: pointer; |
| | | color: rgba(134, 134, 134, 1); |
| | | } |
| | | .iconfont:hover { |
| | | background-color: gainsboro; |
| | | } |
| | | .hour { |
| | | background-color: rgba(240, 240, 240, 1); |
| | | display: flex; |
| | | align-items: center; |
| | | width: 100px; |
| | | height: 50px; |
| | | justify-content: space-evenly; |
| | | border-radius: 10px; |
| | | } |
| | | .dnum { |
| | | width: 40px; |
| | | height: 40px; |
| | | line-height: 40px; |
| | | font-size: 34px; |
| | | font-family: Consolas; |
| | | display: flex; |
| | | align-items: center; |
| | | .input-box { |
| | | width: inherit; |
| | | border: none; |
| | | border-radius: 5px; |
| | | height: 35px; |
| | | font-size: 28px; |
| | | text-align: center; |
| | | } |
| | | |
| | | .input-box:focus { |
| | | outline: none; |
| | | } |
| | | } |
| | | .control { |
| | | width: 20px; |
| | | .fanzhuan { |
| | | display: inline-block; |
| | | -moz-transform: scaleY(-1); |
| | | -webkit-transform: scaleY(-1); |
| | | -o-transform: scaleY(-1); |
| | | transform: scaleY(-1); |
| | | } |
| | | } |
| | | .sep { |
| | | font-family: Consolas; |
| | | width: 40px; |
| | | font-size: 34px; |
| | | height: 40px; |
| | | line-height: 40px; |
| | | } |
| | | .mins { |
| | | background-color: #f0f0f0; |
| | | display: flex; |
| | | align-items: center; |
| | | width: 110px; |
| | | height: 50px; |
| | | justify-content: space-evenly; |
| | | border-radius: 10px; |
| | | } |
| | | } |
| | | } |
| | | .adjust-bar { |
| | | display: flex; |
| | | justify-content: space-between; |
| | | align-items: center; |
| | | margin-bottom: 10px; |
| | | border-radius: 10px; |
| | | height: 50px; |
| | | background-color: rgba(248, 248, 248, 1); |
| | | .middle { |
| | | font-size: 14px; |
| | | } |
| | | .input-box { |
| | | width: 80px; |
| | | border: none; |
| | | border-radius: 5px; |
| | | height: 25px; |
| | | font-size: 18px; |
| | | text-align: center; |
| | | } |
| | | |
| | | .input-box:focus { |
| | | outline: none; |
| | | } |
| | | .minus { |
| | | width: 50px; |
| | | height: 50px; |
| | | background-color: #f0f0f0; |
| | | font-size: 35px; |
| | | border-radius: 10px; |
| | | cursor: pointer; |
| | | line-height: 50px; |
| | | color: rgba(134, 134, 134, 1); |
| | | } |
| | | .plus { |
| | | width: 50px; |
| | | height: 50px; |
| | | cursor: pointer; |
| | | background-color: #f0f0f0; |
| | | font-size: 35px; |
| | | border-radius: 10px; |
| | | line-height: 50px; |
| | | color: rgba(134, 134, 134, 1); |
| | | } |
| | | } |
| | | } |
| | | } |
| | | .btns { |
| | | display: flex; |
| | | justify-content: space-between; |
| | | margin-top: 20px; |
| | | |
| | | .cancel { |
| | | height: 40px; |
| | | width: 48%; |
| | | cursor: pointer; |
| | | border-radius: 8px; |
| | | background-color: rgba(240, 240, 240, 1); |
| | | line-height: 40px; |
| | | font-size: 14px; |
| | | } |
| | | .ok { |
| | | height: 40px; |
| | | width: 48%; |
| | | cursor: pointer; |
| | | border-radius: 8px; |
| | | background-color: rgba(61, 104, 225, 1); |
| | | color: #fff; |
| | | line-height: 40px; |
| | | font-size: 14px; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | </style> |
| | | |
| | | |
| New file |
| | |
| | | import Vue from 'vue'; |
| | | import App from './App.vue'; |
| | | |
| | | import ElementUI from 'element-ui'; |
| | | import 'element-ui/lib/theme-chalk/index.css'; |
| | | import "@/assets/css/element-variables.scss"; |
| | | Vue.use(ElementUI) |
| | | |
| | | new Vue({ |
| | | el: '#app', |
| | | render: h => h(App) |
| | | }) |