|
|
|
@ -4,11 +4,11 @@ |
|
|
|
<header class="board-header"> |
|
|
|
<img src="~@/assets/img/cclbai.png" alt="CCL" class="board-logo"> |
|
|
|
<div class="board-title"> |
|
|
|
<h1>海安 · {{ boardTitle }} |
|
|
|
<h1>{{ boardTitle }} |
|
|
|
<!-- 连接灯与业务状态分开:绿灯已连接,红灯断线闪烁,黄灯建连中,灰灯停用 - rqrq --> |
|
|
|
<span :class="['ws-status-dot', wsState]" :title="connectionText" role="status" :aria-label="connectionText"></span> |
|
|
|
</h1> |
|
|
|
<span>分拣位 {{ sortingStation }} · 工厂 {{ site || '未设置' }}</span> |
|
|
|
<!-- <span>分拣位 {{ sortingStation }} · 工厂 {{ site || '未设置' }}</span>--> |
|
|
|
</div> |
|
|
|
<time>{{ currentTime }}</time> |
|
|
|
</header> |
|
|
|
@ -19,11 +19,11 @@ |
|
|
|
<span>未完成 <strong class="pending-text">{{ pendingCount }}</strong></span> |
|
|
|
<span>已完成 <strong class="completed-text">{{ completedCount }}</strong></span> |
|
|
|
</div> |
|
|
|
<div class="summary-refresh"> |
|
|
|
<span class="connection-text">{{ connectionText }}</span> |
|
|
|
<span role="status">{{ displayMessage }}</span> |
|
|
|
<el-button size="small" :loading="queryLoading" :disabled="queryLoading || !siteReady || !pushEnabled" @click="fetchData(true)">刷新</el-button> |
|
|
|
</div> |
|
|
|
<!-- <div class="summary-refresh">--> |
|
|
|
<!-- <span class="connection-text">{{ connectionText }}</span>--> |
|
|
|
<!-- <span role="status">{{ displayMessage }}</span>--> |
|
|
|
<!-- <el-button size="small" :loading="queryLoading" :disabled="queryLoading || !siteReady || !pushEnabled" @click="fetchData(true)">刷新</el-button>--> |
|
|
|
<!-- </div>--> |
|
|
|
</section> |
|
|
|
|
|
|
|
<!-- 固定高度容器配合粘性表头;数据返回后按实际溢出滚动,鼠标进入暂停便于核对 - rqrq --> |
|
|
|
@ -53,15 +53,13 @@ |
|
|
|
<td><span :class="['status-badge', item.status === '已完成' ? 'completed' : 'pending']">{{ item.status }}</span></td> |
|
|
|
<td class="row-message" :title="item.message">{{ item.message || '-' }}</td> |
|
|
|
</tr> |
|
|
|
<tr v-if="visibleRows.length === 0"> |
|
|
|
<td colspan="8" class="empty-message" :class="{ 'is-error': !available || stale }">{{ displayMessage }}</td> |
|
|
|
</tr> |
|
|
|
<!-- 未返回任务时表体留白,不展示空数据或异常提示;连接状态由标题指示灯表示 - rqrq --> |
|
|
|
</tbody> |
|
|
|
</table> |
|
|
|
</div> |
|
|
|
|
|
|
|
<footer class="board-footer"> |
|
|
|
<span>{{ pushEnabled ? 'WebSocket 实时推送 · 每轮间隔 5 秒' : '海安看板未启用' }}</span> |
|
|
|
<!-- <span>{{ pushEnabled ? 'WebSocket 实时推送 · 每轮间隔 5 秒' : '海安看板未启用' }}</span>--> |
|
|
|
<span>数据更新时间:{{ updatedTime }}</span> |
|
|
|
</footer> |
|
|
|
</div> |
|
|
|
@ -117,12 +115,10 @@ export default { |
|
|
|
}, |
|
|
|
watch: { |
|
|
|
// 同组件切换四个人工路由时清空旧数据并递增请求版本,迟到响应不能覆盖新位置 - rqrq |
|
|
|
'$route.fullPath' () { this.initializeBoard() }, |
|
|
|
// 工厂变化立即断开旧订阅,禁止继续消费旧工厂数据 - rqrq |
|
|
|
'$store.state.user.site' () { this.initializeBoard() } |
|
|
|
'$route.fullPath' () { this.initializeBoard() } |
|
|
|
}, |
|
|
|
mounted () { |
|
|
|
// 先初始化显式site再查询,初始化失败仅展示错误,不使用默认工厂发请求 - rqrq |
|
|
|
// 海安专用屏先初始化固定工厂54再查询,直接访问无需登录或补充地址参数 - rqrq |
|
|
|
this.initializeBoard() |
|
|
|
this.clockTimer = setInterval(() => { this.now = Date.now() }, 1000) |
|
|
|
// 每30秒只复查配置,关闭时不查业务数据;配置重启生效后页面自动建立或关闭连接 - rqrq |
|
|
|
@ -138,7 +134,7 @@ export default { |
|
|
|
clearInterval(this.scrollTimer) |
|
|
|
}, |
|
|
|
methods: { |
|
|
|
// 固定屏支持URL显式site=54;登录态已有其他工厂则拒绝覆盖,防止看板改坏当前会话 - rqrq |
|
|
|
// 专用屏独立使用工厂54,不读取或修改登录工厂;兼容site=54地址,错误工厂参数仍拒绝查询 - rqrq |
|
|
|
initializeBoard () { |
|
|
|
this.requestVersion++ |
|
|
|
this.disconnectWebSocket() |
|
|
|
@ -152,25 +148,17 @@ export default { |
|
|
|
this.updatedAt = 0 |
|
|
|
this.lastReceivedAt = 0 |
|
|
|
this.siteReady = false |
|
|
|
this.site = '' |
|
|
|
this.site = '54' |
|
|
|
// 人工共用页仅接收R1H-R4H,错误路由不得请求自动分拣数据 - rqrq |
|
|
|
if (!['R1H', 'R2H', 'R3H', 'R4H'].includes(this.sortingStation)) { |
|
|
|
this.message = '人工看板仅支持 R1H–R4H 分拣位' |
|
|
|
return |
|
|
|
} |
|
|
|
const storeSite = String(this.$store.state.user.site || '').trim() |
|
|
|
const querySite = this.$route.query.site |
|
|
|
if (querySite !== undefined && (typeof querySite !== 'string' || querySite.trim() !== '54')) { |
|
|
|
this.message = '海安看板的工厂参数必须为 site=54' |
|
|
|
return |
|
|
|
} |
|
|
|
const site = querySite === undefined ? storeSite : querySite.trim() |
|
|
|
if (site !== '54' || (storeSite && storeSite !== '54')) { |
|
|
|
this.message = '请使用海安工厂打开看板;独立屏地址需带 ?site=54' |
|
|
|
return |
|
|
|
} |
|
|
|
this.$store.commit('user/updateSite', site) |
|
|
|
this.site = site |
|
|
|
this.siteReady = true |
|
|
|
this.message = '正在获取分拣数据…' |
|
|
|
this.$nextTick(() => { |
|
|
|
@ -184,7 +172,8 @@ export default { |
|
|
|
const version = this.requestVersion |
|
|
|
this.configLoading = true |
|
|
|
try { |
|
|
|
const { data } = await getSortingBoardConfig({ site: this.$store.state.user.site }) |
|
|
|
// 显式传本屏工厂54读取开关,避免未登录或登录其他工厂时查错配置 - rqrq |
|
|
|
const { data } = await getSortingBoardConfig({ site: this.site }) |
|
|
|
if (version !== this.requestVersion) return |
|
|
|
if (!data || data.code !== 0 || !data.row || data.row.site !== this.site) throw new Error('配置查询失败') |
|
|
|
this.pushEnabled = data.row.enabled === true |
|
|
|
@ -251,8 +240,8 @@ export default { |
|
|
|
// HTTP手动刷新与推送按相同结构消费,完整核对site/位置;异常与空任务分开显示 - rqrq |
|
|
|
applyBoard (data) { |
|
|
|
if (!this.pushEnabled) return |
|
|
|
const site = String(this.$store.state.user.site || '').trim() |
|
|
|
if (!data || data.code !== 0 || !data.row || site !== this.site || data.row.site !== site || data.row.sortingStation !== this.sortingStation) { |
|
|
|
// 响应必须属于本屏固定工厂及分拣位,登录工厂变化不影响独立屏 - rqrq |
|
|
|
if (!data || data.code !== 0 || !data.row || data.row.site !== this.site || data.row.sortingStation !== this.sortingStation) { |
|
|
|
this.available = false |
|
|
|
this.rows = [] |
|
|
|
this.message = '看板数据校验失败,请检查工厂和分拣位' |
|
|
|
@ -271,14 +260,11 @@ export default { |
|
|
|
const version = this.requestVersion |
|
|
|
const dataVersion = this.dataVersion |
|
|
|
const station = this.sortingStation |
|
|
|
const site = String(this.$store.state.user.site || '').trim() |
|
|
|
if (site !== this.site) { |
|
|
|
this.initializeBoard() |
|
|
|
return |
|
|
|
} |
|
|
|
// 与配置查询及WebSocket主题使用同一本屏工厂,刷新不依赖登录态 - rqrq |
|
|
|
const site = this.site |
|
|
|
this.queryLoading = true |
|
|
|
try { |
|
|
|
const { data } = await getManualSortingBoard({ site: this.$store.state.user.site, sortingStation: station }) |
|
|
|
const { data } = await getManualSortingBoard({ site, sortingStation: station }) |
|
|
|
if (version !== this.requestVersion || !this.pushEnabled || dataVersion !== this.dataVersion) return |
|
|
|
if (!data || data.code !== 0 || !data.row) { |
|
|
|
this.rows = [] |
|
|
|
|