| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225 |
- <template>
- <div class="tsb-device-shell">
- <div v-if="!currentDeviceSn" class="workspace-empty app-container">
- <el-empty description="请从首页选择已登录设备">
- <el-button type="primary" size="small" @click="goHomeIndex">前往首页</el-button>
- </el-empty>
- </div>
- <template v-else>
- <div class="device-tabs-bar">
- <div
- v-for="item in openedDevices"
- :key="item.deviceSn"
- class="device-tab"
- :class="{ active: isActiveTab(item) }"
- @click="switchDevice(item)"
- >
- <span class="tab-label">SN {{ item.deviceSn }}</span>
- <i
- class="el-icon-close tab-close"
- @click.stop="closeDevice(item)"
- />
- </div>
- <el-button type="text" size="mini" class="add-device-btn" @click="goHomeIndex">
- <i class="el-icon-plus" /> 选择设备
- </el-button>
- </div>
- <div v-if="!isHomePage" class="sub-toolbar">
- <el-button type="text" icon="el-icon-back" @click="goDeviceHome">返回功能菜单</el-button>
- <span class="sub-title">{{ subPageTitle }}</span>
- <span class="sub-sn">设备 SN:{{ currentDeviceSn }}</span>
- </div>
- <keep-alive>
- <component :is="panelComponent" :key="panelCacheKey" :bound-device-sn="currentDeviceSn" />
- </keep-alive>
- </template>
- </div>
- </template>
- <script>
- import tsbWebSocket from '@/utils/tsbWebSocket'
- import { ensureWorkspaceTag } from '@/utils/tsbWorkspaceNav'
- import { buildDeviceSession, clearTsbDeviceSession, hasTsbDeviceSession, saveTsbDeviceSession } from '@/utils/tsbDeviceSession'
- import DeviceHome from './home'
- import TaxPage from '@/views/app-common/tax/index'
- const PANEL_COMPONENTS = {
- home: DeviceHome,
- tax: TaxPage
- }
- const PANEL_TITLES = {
- home: '设备功能',
- tax: '报税口'
- }
- export default {
- name: 'TsbDeviceShell',
- components: { DeviceHome, TaxPage },
- computed: {
- openedDevices() {
- return this.$store.getters.tsbOpenedDevices || []
- },
- currentDeviceSn() {
- return this.$store.getters.tsbCurrentDeviceSn
- },
- currentPanel() {
- return this.$store.getters.tsbCurrentPanel
- },
- isHomePage() {
- return this.currentPanel === 'home'
- },
- subPageTitle() {
- return PANEL_TITLES[this.currentPanel] || ''
- },
- panelComponent() {
- return PANEL_COMPONENTS[this.currentPanel] || DeviceHome
- },
- panelCacheKey() {
- return `${this.currentDeviceSn}-${this.currentPanel}`
- }
- },
- created() {
- if (!hasTsbDeviceSession() || !this.openedDevices.length) {
- this.$store.commit('tsb/SET_SESSION_CHECKED', false)
- this.$tab.closeOpenPage({ path: '/index' })
- return
- }
- this.ensureWsConnected()
- ensureWorkspaceTag()
- },
- activated() {
- if (!hasTsbDeviceSession() || !this.openedDevices.length) {
- return
- }
- this.ensureWsConnected()
- ensureWorkspaceTag()
- },
- methods: {
- ensureWsConnected() {
- const device = this.$store.getters.tsbCurrentDevice
- if (!device || device.deviceSn == null) {
- return
- }
- if (!tsbWebSocket.isConnected()) {
- tsbWebSocket.ensureCurrentDeviceConnection()
- }
- },
- isActiveTab(device) {
- return String(device.deviceSn) === String(this.currentDeviceSn)
- },
- switchDevice(device) {
- if (this.isActiveTab(device)) {
- return
- }
- tsbWebSocket.switchToDevice(device).catch(() => {})
- },
- closeDevice(device) {
- const closingCurrent = this.isActiveTab(device)
- const panelMap = { ...this.$store.state.tsb.devicePanelMap }
- delete panelMap[device.deviceSn]
- this.$store.commit('tsb/SET_DEVICE_PANEL_MAP', panelMap)
- this.$store.commit('tsb/REMOVE_OPENED_DEVICE', device.deviceSn)
- this.$store.commit('tsb/CLEAR_DEVICE_PAGE_FORM', String(device.deviceSn))
- tsbWebSocket.disconnectDevice(device.deviceSn)
- tsbWebSocket.onDeviceTabClosed(device.deviceSn)
- const remaining = this.$store.getters.tsbOpenedDevices
- if (!remaining.length) {
- clearTsbDeviceSession()
- tsbWebSocket.releaseWorkspaceSession()
- this.$store.commit('tsb/SET_SESSION_CHECKED', false)
- this.$tab.closeOpenPage({ path: '/index' })
- return
- }
- const current = this.$store.getters.tsbCurrentDevice
- saveTsbDeviceSession(buildDeviceSession(current, remaining, panelMap))
- if (closingCurrent) {
- const next = remaining[remaining.length - 1]
- tsbWebSocket.switchToDevice(next).catch(() => {})
- }
- },
- goDeviceHome() {
- const sn = this.currentDeviceSn
- if (sn != null) {
- this.$store.commit('tsb/SET_DEVICE_PANEL', { deviceSn: sn, panel: 'home' })
- this.persistPanelMap()
- }
- },
- goHomeIndex() {
- this.$router.push('/index')
- },
- persistPanelMap() {
- saveTsbDeviceSession(buildDeviceSession(
- this.$store.getters.tsbCurrentDevice,
- this.$store.getters.tsbOpenedDevices,
- this.$store.state.tsb.devicePanelMap
- ))
- }
- }
- }
- </script>
- <style scoped lang="scss">
- .tsb-device-shell {
- min-height: 100%;
- }
- .workspace-empty {
- padding-top: 48px;
- }
- .device-tabs-bar {
- display: flex;
- align-items: center;
- flex-wrap: wrap;
- gap: 8px;
- padding: 8px 12px;
- background: #f5f7fa;
- border-bottom: 1px solid #e4e7ed;
- }
- .device-tab {
- display: inline-flex;
- align-items: center;
- gap: 6px;
- padding: 6px 12px;
- border: 1px solid #dcdfe6;
- border-radius: 4px;
- background: #fff;
- cursor: pointer;
- font-size: 13px;
- transition: all 0.2s;
- &.active {
- color: #409eff;
- border-color: #409eff;
- background: #ecf5ff;
- }
- }
- .tab-close {
- font-size: 12px;
- color: #909399;
- &:hover {
- color: #f56c6c;
- }
- }
- .add-device-btn {
- margin-left: 4px;
- }
- .sub-toolbar {
- display: flex;
- align-items: center;
- gap: 12px;
- padding: 8px 16px;
- border-bottom: 1px solid #ebeef5;
- background: #fff;
- }
- .sub-title {
- font-weight: 600;
- font-size: 14px;
- }
- .sub-sn {
- margin-left: auto;
- color: #909399;
- font-size: 13px;
- }
- </style>
|