| | |
| | | <template> |
| | | <main class="visitor-page"> |
| | | <main class="visitor-page visitor-device-page"> |
| | | <section class="visitor-card"> |
| | | <header class="visitor-header"> |
| | | <h1>{{ pageTitle }}管理</h1> |
| | |
| | | default-expand-all |
| | | highlight-current |
| | | @node-click="handleAreaClick" |
| | | /> |
| | | > |
| | | <span slot-scope="{ node, data }" class="area-tree-node"> |
| | | <i :class="areaNodeIconClass(data)" /> |
| | | <span class="area-tree-label">{{ node.label }}</span> |
| | | </span> |
| | | </el-tree> |
| | | </aside> |
| | | |
| | | <section class="device-panel"> |
| | |
| | | </el-form> |
| | | |
| | | <div v-if="!isMiddlePlatformReadonly && hasDevicePerm('add')" class="visitor-toolbar"> |
| | | <el-button type="primary" @click="handleAdd">新增设备</el-button> |
| | | <el-button type="primary" icon="el-icon-plus" @click="handleAdd">新增设备</el-button> |
| | | </div> |
| | | |
| | | <el-table |
| | | v-loading="loading" |
| | | class="visitor-table" |
| | | :data="deviceList" |
| | | @selection-change="handleSelectionChange" |
| | | > |
| | | <el-table-column type="selection" width="48" align="center" /> |
| | | <el-table-column label="序号" width="64" align="center"> |
| | | <template slot-scope="scope">{{ scope.$index + 1 }}</template> |
| | | </el-table-column> |
| | | <el-table-column label="设备名称" prop="deviceName" min-width="120" show-overflow-tooltip /> |
| | | <el-table-column label="品牌" prop="brand" min-width="100" show-overflow-tooltip /> |
| | | <el-table-column label="设备ID" prop="deviceId" min-width="150" show-overflow-tooltip /> |
| | | <el-table-column v-if="deviceType === 'machine'" label="百度SDK指纹" prop="fingerprint" min-width="160" show-overflow-tooltip /> |
| | | <el-table-column label="所属区域" prop="areaName" min-width="130" show-overflow-tooltip /> |
| | | <el-table-column label="启用状态" align="center" width="100"> |
| | | <template slot-scope="scope"> |
| | |
| | | <el-button v-if="hasDevicePerm('edit')" type="text" @click="handleUpdate(scope.row)">编辑</el-button> |
| | | <el-dropdown v-if="hasAnyDevicePerm(['status', 'logout', 'remove'])" trigger="click" @command="command => handleMoreCommand(command, scope.row)"> |
| | | <el-button type="text">更多<i class="el-icon-arrow-down el-icon--right" /></el-button> |
| | | <el-dropdown-menu slot="dropdown"> |
| | | <el-dropdown-item v-if="hasDevicePerm('status')" command="status">{{ scope.row.enabled ? '禁用' : '启用' }}</el-dropdown-item> |
| | | <el-dropdown-item v-if="hasDevicePerm('logout')" command="logout">注销</el-dropdown-item> |
| | | <el-dropdown-item v-if="hasDevicePerm('remove')" command="delete" class="danger-item">删除</el-dropdown-item> |
| | | <el-dropdown-menu slot="dropdown" class="visitor-device-more-menu"> |
| | | <el-dropdown-item v-if="hasDevicePerm('logout')" command="logout"> |
| | | <i class="el-icon-refresh-left" />注销 |
| | | </el-dropdown-item> |
| | | <el-dropdown-item v-if="hasDevicePerm('status')" command="status"> |
| | | <i :class="scope.row.enabled ? 'el-icon-circle-close' : 'el-icon-view'" />{{ scope.row.enabled ? '禁用' : '启用' }} |
| | | </el-dropdown-item> |
| | | <el-dropdown-item v-if="hasDevicePerm('remove')" command="delete" class="danger-item"> |
| | | <i class="el-icon-delete" />删除 |
| | | </el-dropdown-item> |
| | | </el-dropdown-menu> |
| | | </el-dropdown> |
| | | </template> |
| | |
| | | </div> |
| | | </section> |
| | | |
| | | <el-dialog :title="title" :visible.sync="open" width="654px" append-to-body> |
| | | <el-form ref="form" :model="form" :rules="rules" label-width="92px"> |
| | | <el-dialog :title="title" :visible.sync="open" width="654px" append-to-body custom-class="visitor-device-dialog"> |
| | | <el-form ref="form" :model="form" :rules="rules" label-position="top"> |
| | | <el-form-item label="区域" prop="areaId"> |
| | | <el-cascader |
| | | v-model="form.areaId" |
| | | :options="areaTree" |
| | | :options="modalAreaOptions" |
| | | :props="areaCascaderProps" |
| | | clearable |
| | | filterable |
| | | placeholder="下拉菜单" |
| | | placeholder="请选择" |
| | | /> |
| | | </el-form-item> |
| | | <el-form-item label="设备名称" prop="deviceName"> |
| | |
| | | <el-input v-model="form.remark" placeholder="请输入" /> |
| | | </el-form-item> |
| | | <el-form-item label="启用状态" prop="enabled"> |
| | | <el-switch v-model="form.enabled" active-text="启用" inactive-text="禁用" /> |
| | | <el-switch v-model="form.enabled" active-color="#13ce66" inactive-color="#dcdfe6" /> |
| | | </el-form-item> |
| | | </el-form> |
| | | <div slot="footer" class="dialog-footer"> |
| | |
| | | // 目的:返回当前设备类型的页面标题前缀。 |
| | | pageTitle() { |
| | | return this.deviceType === 'door' ? '门禁' : '访客机' |
| | | }, |
| | | // 目的:弹窗区域选择只保留一级和二级,避免二级继续展开空面板。 |
| | | modalAreaOptions() { |
| | | return this.normalizeModalAreaOptions(this.areaTree) |
| | | } |
| | | }, |
| | | watch: { |
| | |
| | | this.areaTree = [] |
| | | }) |
| | | }, |
| | | // 目的:按弹窗交互要求移除二级以下区域和叶子节点空 children。 |
| | | normalizeModalAreaOptions(list, level = 1) { |
| | | return (list || []).map(item => { |
| | | const option = { |
| | | ...item |
| | | } |
| | | const children = Array.isArray(item.children) ? item.children : [] |
| | | if (level < 2 && children.length) { |
| | | option.children = this.normalizeModalAreaOptions(children, level + 1) |
| | | } else { |
| | | delete option.children |
| | | } |
| | | return option |
| | | }) |
| | | }, |
| | | // 目的:按当前设备类型和查询条件加载分页列表。 |
| | | getList() { |
| | | this.loading = true |
| | |
| | | // 目的:根据数据库在线状态枚举返回对应的标签样式。 |
| | | onlineClass(value) { |
| | | return onlineStatusClass(value) |
| | | }, |
| | | // 目的:根据区域是否有子级展示目录或文档图标,匹配区域树层级语义。 |
| | | areaNodeIconClass(data) { |
| | | const hasChildren = Array.isArray(data.children) && data.children.length > 0 |
| | | return hasChildren ? 'el-icon-folder area-tree-node-icon is-folder' : 'el-icon-document area-tree-node-icon is-file' |
| | | }, |
| | | // 目的:按区域名称关键字过滤区域树节点。 |
| | | filterAreaNode(value, data) { |
| | |
| | | } |
| | | } |
| | | </script> |
| | | |
| | | <style lang="scss"> |
| | | .visitor-device-dialog { |
| | | .el-dialog__body { |
| | | padding: 18px 24px 24px; |
| | | } |
| | | |
| | | .el-form { |
| | | padding: 0 8px; |
| | | } |
| | | |
| | | .el-form-item { |
| | | margin-bottom: 18px; |
| | | } |
| | | |
| | | .el-form-item__label { |
| | | padding: 0 0 8px; |
| | | color: #303133; |
| | | font-weight: 600; |
| | | line-height: 20px; |
| | | text-align: left; |
| | | } |
| | | |
| | | .el-form-item__content { |
| | | line-height: 1; |
| | | } |
| | | |
| | | .el-cascader, |
| | | .el-input, |
| | | .el-select { |
| | | width: 100%; |
| | | } |
| | | |
| | | .el-switch { |
| | | display: inline-flex; |
| | | align-items: center; |
| | | } |
| | | } |
| | | </style> |