From 3eab4409e562a873d9bd7b047b3d0590901a6654 Mon Sep 17 00:00:00 2001
From: Junjie <fallin.jie@qq.com>
Date: 星期三, 11 三月 2026 11:06:49 +0800
Subject: [PATCH] #

---
 src/main/webapp/views/ai/diagnosis.html                        |    2 
 src/main/webapp/views/locMap/locMap.html                       |    2 
 src/main/webapp/views/role/role_power_detail.html              |    2 
 src/main/webapp/views/watch/console.html                       |    2 
 src/main/webapp/views/basStationDevice/basStationDevice.html   |    2 
 src/main/webapp/views/config/config.html                       |   43 +
 src/main/webapp/views/wrkMast/wrkMast.html                     |  830 ++++++++++++-------------
 src/main/webapp/views/basOutStationArea/basOutStationArea.html |    2 
 src/main/resources/i18n/en-US/legacy.properties                |  370 +++++++++++
 src/main/webapp/static/js/wrkMast/wrkMast.js                   |  319 +++++++++
 src/main/webapp/views/watch/console_pixijs.html                |    2 
 src/main/webapp/views/ai/llm_config.html                       |    2 
 src/main/webapp/views/password.html                            |    2 
 src/main/webapp/views/detail.html                              |    2 
 src/main/webapp/views/notifyReport/notifyReport.html           |    2 
 src/main/webapp/views/watch/stationColorConfig.html            |    2 
 src/main/webapp/views/watch/console_html.html                  |    2 
 src/main/webapp/views/index.html                               |   67 +
 src/main/webapp/static/js/config/config.js                     |  218 ++++++
 src/main/webapp/views/debugParam/debugParam.html               |    2 
 src/main/webapp/views/deviceLogs/deviceLogs.html               |    2 
 src/main/webapp/views/login.html                               |    2 
 22 files changed, 1,412 insertions(+), 467 deletions(-)

diff --git a/src/main/resources/i18n/en-US/legacy.properties b/src/main/resources/i18n/en-US/legacy.properties
index 63e8a9e..f289c42 100644
--- a/src/main/resources/i18n/en-US/legacy.properties
+++ b/src/main/resources/i18n/en-US/legacy.properties
@@ -181,8 +181,8 @@
 涓嶅彲淇敼=Not Editable
 閲嶈锛佷竴鑸敤浜庡悗鍙扮櫥鍏�=Important: usually used for admin login
 褰撳墠瑙掕壊涓嶅彲鏇存敼涓哄叾瀹冭鑹�=Current role cannot be changed
-鎵嬫満鍙�:=Phone:
-鐢ㄦ埛鍚�:=Username:
+鎵嬫満鍙穃:=Phone:
+鐢ㄦ埛鍚峔:=Username:
 杈撳叆鎵嬫満鍙�=Enter phone number
 杈撳叆鐢ㄦ埛鍚�=Enter username
 閲嶇疆瀵嗙爜=Reset Password
@@ -525,8 +525,8 @@
 ConveyorCommand鍒嗘闀垮害=Conveyor Command Segment Length
 绔欑偣鐐规渶澶т换鍔℃暟閲忎笂闄�=Max Tasks Per Station
 Stations鐐规渶澶ask鏁伴噺涓婇檺=Max Tasks Per Station
-鍐峰嵈鍒�: -=Cooldown Until: -
-鏈�杩戦敊璇�: -=Latest Error: -
+鍐峰嵈鍒癨:-=Cooldown Until: -
+鏈�杩戦敊璇痋:-=Latest Error: -
 鏁呴殰鍒囨崲寮�鍚�=Failover Enabled
 Failover寮�鍚�=Failover Enabled
 棰濆害鍒囨崲寮�鍚�=Quota Switch Enabled
@@ -539,10 +539,10 @@
 Success 0 / Failed 0 / 杩炵画Failed 0=Success 0 / Failed 0 / Consecutive Failures 0
 Success 7 / Failed 2 / 杩炵画Failed 0=Success 7 / Failed 2 / Consecutive Failures 0
 Success 8 / Failed 0 / 杩炵画Failed 0=Success 8 / Failed 0 / Consecutive Failures 0
-蹇呭~锛屼緥濡�: https://dashscope.aliyuncs.com/compatible-mode/v1=Required, for example: https://dashscope.aliyuncs.com/compatible-mode/v1
-Required锛屼緥濡�: https://dashscope.aliyuncs.com/compatible-mode/v1=Required, for example: https://dashscope.aliyuncs.com/compatible-mode/v1
-鏈�杩戦敊璇�:=Latest Error:
-鍐峰嵈鍒�:=Cooldown Until:
+蹇呭~锛屼緥濡俓: https\://dashscope.aliyuncs.com/compatible-mode/v1=Required, for example: https://dashscope.aliyuncs.com/compatible-mode/v1
+Required锛屼緥濡俓: https\://dashscope.aliyuncs.com/compatible-mode/v1=Required, for example: https://dashscope.aliyuncs.com/compatible-mode/v1
+鏈�杩戦敊璇痋:=Latest Error:
+鍐峰嵈鍒癨:=Cooldown Until:
 D.绌烘《/绌烘爤鏉�=D. Empty Tote/Pallet
 E.鍑哄叆涓撶敤杞ㄩ亾=E. Dedicated IO Rail
 W.绌挎杞︽瘝杞ㄩ亾=W. Shuttle Main Rail
@@ -705,3 +705,357 @@
 闃块噷鐧剧偧-kimi-k2.5=Alibaba Bailian - kimi-k2.5
 闃块噷鐧剧偧-glm-5=Alibaba Bailian - glm-5
 纭呭熀娴佸姩=SiliconFlow
+鎻愮ず=Prompt
+灏濊瘯=Attempt
+閿欒=Error
+绌洪棽=Idle
+鏃犵墿=Unloaded
+宸ヤ綔绫诲瀷=Work Type
+鑳藉嚭=Outbound Enabled
+鑳藉叆=Inbound Enabled
+鏂囦欢鏁�=File Count
+绫诲瀷\:=Type:
+璁惧缂栧彿\:=Device No.:
+鏂囦欢鏁癨:=File Count:
+鏃ュ織璇︽儏 -=Log Details -
+鏃ュ織鍙鍖� -=Device Logs -
+宸插垹闄�=Deleted
+鑰侀」鐩粛鍙户缁娇鐢ㄨ繖浠界‖浠朵俊鎭� JSON 鐢宠璁稿彲璇併��=Legacy projects can still use this hardware JSON to apply for a license.
+璇锋眰鐮佷腑宸插寘鍚」鐩悕绉帮紝鐩存帴鍙戠粰璁稿彲璇佹湇鍔$鍗冲彲銆�=The request code already contains the project name and can be sent directly to the license service.
+鏆傛棤璺敱閰嶇疆=No route configuration available
+鐐瑰嚮鍙充笂瑙掆�滄柊澧炶矾鐢扁�濆垱寤虹涓�鏉¢厤缃�=Click "Add Route" in the upper-right corner to create the first route.
+淇濆瓨鎴愬姛=Saved successfully
+淇濆瓨澶辫触=Save failed
+娴嬭瘯鎴愬姛=Test succeeded
+娴嬭瘯澶辫触=Test failed
+娴嬭瘯涓�...=Testing...
+瀵煎嚭鎴愬姛=Export succeeded
+瀵煎嚭澶辫触=Export failed
+瀵煎叆纭=Import Confirmation
+瀵煎叆澶辫触=Import failed
+瑕嗙洊瀵煎叆=Overwrite Import
+鍚堝苟瀵煎叆=Merge Import
+璇诲彇鏂囦欢澶辫触=Failed to read file
+JSON 鏍煎紡涓嶆纭�=Invalid JSON format
+鏈壘鍒板彲瀵煎叆鐨� routes=No importable routes found
+璇烽�夋嫨瀵煎叆鏂瑰紡锛氳鐩栧鍏ヤ細鍏堟竻绌虹幇鏈夎矾鐢憋紱鐐瑰嚮鈥滃悎骞跺鍏モ�濆垯鎸塈D鏇存柊鎴栨柊澧炪��=Choose an import mode: overwrite import clears existing routes first; merge import updates by ID or adds new routes.
+褰撳墠鏄湭淇濆瓨閰嶇疆锛屾祴璇曢�氳繃鍚庝粛闇�鍏堜繚瀛樻墠浼氱敓鏁�=This configuration is not saved yet. It still needs to be saved after a successful test to take effect.
+澶嶅埗澶辫触锛岃鎵嬪姩澶嶅埗=Copy failed. Please copy it manually.
+娌℃湁鍙鍒跺唴瀹�=Nothing to copy
+宸插鍒�=Copied
+API Key 涓虹┖=API key is empty
+API Key 宸插鍒�=API key copied
+鏃ュ織鍔犺浇澶辫触=Failed to load logs
+鍒犻櫎鎴愬姛=Deleted successfully
+鍒犻櫎澶辫触=Delete failed
+宸叉竻闄ゅ喎鍗�=Cooldown cleared
+宸叉竻绌�=Cleared
+娓呯┖鏃ュ織=Clear Logs
+娓呯┖澶辫触=Clear failed
+纭畾娓呯┖鍏ㄩ儴LLM璋冪敤鏃ュ織鍚楋紵=Are you sure you want to clear all LLM call logs?
+纭畾鍒犻櫎璇ヨ矾鐢卞悧锛�=Are you sure you want to delete this route?
+纭畾鍒犻櫎璇ユ棩蹇楀悧锛�=Are you sure you want to delete this log?
+瀵煎叆瀹屾垚锛氭柊澧�=Import completed: added
+瀵煎叆寮傚父鏄庣粏锛堟渶澶�20鏉★級=Import exception details (up to 20 items)
+鐘舵�佺爜=Status Code
+鍦烘櫙=Scene
+妯″瀷=Model
+璺敱=Route
+缁撴灉=Result
+鑰楁椂(ms)=Latency (ms)
+鑰楁椂\:=Latency:
+缁撴灉\:=Result:
+妯″瀷\:=Model:
+璺敱\:=Route:
+鍦烘櫙\:=Scene:
+鏃堕棿\:=Time:
+鐘舵�佺爜\:=Status Code:
+璇锋眰\:=Request:
+鍝嶅簲\:=Response:
+杩斿洖鐗囨\:=Response Snippet:
+鏈�杩戦敊璇痋:=Latest Error:
+鍐峰嵈鍒癨:=Cooldown Until:
+regex\:^鎴愬姛\s*(\d+)\s*\/\s*澶辫触\s*(\d+)\s*\/\s*杩炵画澶辫触\s*(\d+)$=Success $1 / Failed $2 / Consecutive Failures $3
+regex\:^鏃堕棿\:\s*(.+)$=Time: $1
+regex\:^鐘舵�佺爜\:\s*(.+)$=Status Code: $1
+regex\:^鑰楁椂\:\s*(.+)$=Latency: $1
+regex\:^缁撴灉\:\s*(.+)$=Result: $1
+regex\:^璺敱\:\s*(.+)$=Route: $1
+regex\:^妯″瀷\:\s*(.+)$=Model: $1
+regex\:^杩斿洖鐗囨\:\s*(.+)$=Response Snippet: $1
+regex\:^璇锋眰\:\s*(.+)$=Request: $1
+regex\:^鍝嶅簲\:\s*(.+)$=Response: $1
+regex\:^鏈�杩戦敊璇痋:\s*(.+)$=Latest Error: $1
+regex\:^鍐峰嵈鍒癨:\s*(.+)$=Cooldown Until: $1
+WCS AI 鍔╂墜=WCS AI Assistant
+AI 娣卞害鎬濊��=AI Deep Thinking
+绯荤粺宸℃銆佸紓甯搁棶绛斻�佸巻鍙蹭細璇�=System inspection, anomaly Q&A, and session history
+杩炴帴涓�=Connecting
+涓�閿贰妫�=One-click Inspection
+宸℃褰撳墠绯荤粺=Inspect Current System
+鏂颁細璇�=New Session
+閫夋嫨鍘嗗彶浼氳瘽=Select Session History
+鍚� AI 鍔╂墜鎻愰棶=Ask the AI Assistant
+鏀寔杩炵画杩介棶銆佸巻鍙蹭細璇濆垏鎹紝浠ュ強 AI 鎬濊�冭繃绋嬫姌鍙犲睍绀恒��=Supports follow-up questions, session switching, and collapsible AI reasoning.
+鏈粦瀹氬巻鍙蹭細璇�=No history session bound
+鏂板缓浼氳瘽锛岀瓑寰呴鏉℃秷鎭�=Create a new session and wait for the first message
+杈撳叆闂锛屾垨鍏堟墽琛屼竴娆″贰妫�=Enter a question, or run an inspection first
+AI 姝e湪鐢熸垚鍥炲...=AI is generating a response...
+AI 鍔╂墜=AI Assistant
+鐢ㄦ埛=User
+WCS 璇婃柇鍥炲=WCS Diagnostic Reply
+闂杈撳叆=Question Input
+瀹氫綅鍫嗗灈鏈哄紓甯�=Locate Crane Anomalies
+鍒嗘瀽鍫靛涓庣Н鍘�=Analyze Blockages and Backlogs
+杩介棶鏈�杩戝憡璀�=Ask About Recent Alarms
+璁� AI 涓诲姩姊崇悊璁惧銆佷换鍔″拰鏃ュ織锛岀粰鍑轰竴杞畬鏁村贰妫�銆�=Let AI review devices, tasks, and logs proactively and provide a full inspection.
+璁� AI 浼樺厛鍏虫敞宸ヤ綅鍫靛銆佷换鍔″爢绉拰鑺傛媿寮傚父銆�=Let AI focus on station blockages, task backlogs, and rhythm anomalies first.
+鎶婃渶杩戝紓甯镐簨浠跺帇缂╂垚鍙墽琛屾帓鏌ュ缓璁��=Condense recent anomalies into actionable troubleshooting steps.
+甯垜瀹氫綅褰撳墠鍫嗗灈鏈虹浉鍏崇殑寮傚父椋庨櫓锛屾寜鍙兘鎬т粠楂樺埌浣庡垪鍑恒��=Identify current crane-related risks and list them by likelihood.
+甯垜鎬荤粨鏈�杩戞渶鍊煎緱鍏虫敞鐨勫紓甯革紝骞剁粰鍑轰笅涓�姝ユ帓鏌ュ姩浣溿��=Summarize the most important recent anomalies and suggest next troubleshooting steps.
+缁撳悎杩戞湡鏃ュ織涓庝换鍔$姸鎬侊紝鍒ゆ柇鏄惁瀛樺湪鍫嗗灈鏈洪摼璺紓甯搞��=Determine whether there is any crane workflow anomaly based on recent logs and task status.
+渚嬪锛氭渶杩戝摢涓澶囨渶鍊煎緱浼樺厛鎺掓煡锛熷紓甯告槸鍚﹀拰鍫嗗灈鏈轰换鍔°�佸伐浣嶅牭濉炴垨鏃ュ織娉㈠姩鏈夊叧锛�=For example: which device should be checked first? Are the anomalies related to crane tasks, station blockage, or log fluctuation?
+璇烽噸鐐瑰垎鏋愬綋鍓嶆槸鍚﹀瓨鍦ㄥ伐浣嶅牭濉炪�佷换鍔$Н鍘嬫垨鑺傛媿寮傚父銆�=Please focus on whether there are station blockages, task backlogs, or rhythm anomalies.
+鍒犻櫎浼氳瘽澶辫触=Failed to delete session
+鍔犺浇 AI 浼氳瘽鍒楄〃澶辫触=Failed to load AI session list
+鍔犺浇浼氳瘽鍘嗗彶澶辫触=Failed to load session history
+璇婃柇涓�=Diagnosing
+鏈懡鍚嶄細璇�=Untitled Session
+鏈�杩戞洿鏂�=Updated Recently
+鍒氬垰鍒涘缓=Just created
+鍒氬垰鏇存柊=Just updated
+浼氳瘽宸茬粦瀹�=Session Bound
+涓存椂浼氳瘽=Temporary Session
+Enter 鍙戦�侊紝Shift+Enter 鎹㈣=Press Enter to send, Shift+Enter for a new line
+regex\:^(\d+)\s*涓細璇�$=$1 sessions
+regex\:^(\d+)\s*鍒嗛挓鍓�$=$1 minute(s) ago
+regex\:^(\d+)\s*灏忔椂鍓�$=$1 hour(s) ago
+琛ュ彂缁撴灉=Retry Result
+琛ュ彂澶辫触=Retry failed
+褰撳墠绛涢�夋潯浠朵笅娌℃湁閫氱煡鏃ュ織=No notification logs match the current filters
+鑾峰彇閫氱煡闃熷垪澶辫触=Failed to load notification queue
+鑾峰彇閫氱煡姒傝澶辫触=Failed to load notification overview
+鑾峰彇閫氱煡鏃ュ織澶辫触=Failed to load notification logs
+璇锋眰澶辫触=Request failed
+璇烽�夋嫨瑕佽ˉ鍙戠殑闃熷垪閫氱煡=Please select queue notifications to retry
+璇烽�夋嫨瑕佽ˉ鍙戠殑閫氱煡鏃ュ織=Please select notification logs to retry
+纭畾鎸夎鏃ュ織閲嶆柊琛ュ彂閫氱煡鍚楋紵=Retry this notification based on the selected log?
+纭畾琛ュ彂璇ラ槦鍒楅�氱煡鍚楋紵=Retry this queued notification?
+纭畾鎵归噺琛ュ彂閫変腑鐨勯槦鍒楅�氱煡鍚楋紵=Retry the selected queued notifications in batch?
+纭畾鎵归噺琛ュ彂閫変腑鐨勯�氱煡鏃ュ織鍚楋紵=Retry the selected notification logs in batch?
+纭畾鎵ц鎵嬪姩琛ュ彂鍚楋紵=Are you sure you want to retry manually?
+涓婄骇浠诲姟鍙�=Parent Task No.
+鎺ュ彛鍝嶅簲=API Response
+閫氱煡鎶ユ枃=Notification Payload
+寰呭彂閫�=Pending
+鍙戦�佹棩蹇�=Send Logs
+regex\:^宸查�塡s*(\d+)\s*鏉�$=Selected $1 item(s)
+regex\:^褰撳墠椤电锛歕s*(.+)$=Current Tab: $1
+璋冭壊鐩�=Palette
+鎭㈠榛樿=Restore Default
+淇濆瓨鍚庯紝鏂版墦寮�鐨勭洃鎺у湴鍥句細鐩存帴璇诲彇 Redis 閰嶇疆锛涘凡鎵撳紑椤甸潰鍒锋柊鍚庡嵆鍙敓鏁堛��=After saving, newly opened monitoring maps will read the Redis configuration directly. Refresh already opened pages to apply it.
+regex\:^榛樿鍊硷細\s*(.+)$=Default: $1
+鎿嶄綔鍖哄煙=Action Area
+regex\:^灞傦細\s*(.+)$=Level: $1
+regex\:^鎺掞細\s*(.+)$=Row: $1
+regex\:^鍒楋細\s*(.+)$=Bay: $1
+regex\:^搴撲綅鍙凤細\s*(.+)$=Location No.: $1
+regex\:^搴撲綅鐘舵�侊細\s*(.+)$=Location Status: $1
+regex\:^绔欑偣锛歕s*(.+)$=Station: $1
+regex\:^宸ヤ綔鍙凤細\s*(.+)$=Work No.: $1
+regex\:^宸ヤ綔绫诲瀷锛歕s*(.+)$=Work Type: $1
+regex\:^宸ヤ綔鐘舵�侊細\s*(.+)$=Work Status: $1
+regex\:^婧愮珯锛歕s*(.+)$=Source Station: $1
+regex\:^鐩爣绔欙細\s*(.+)$=Target Station: $1
+regex\:^婧愬簱浣嶏細\s*(.+)$=Source Location: $1
+regex\:^鐩爣搴撲綅锛歕s*(.+)$=Target Location: $1
+regex\:^鑷姩锛歕s*(.+)$=Auto: $1
+regex\:^鏈夌墿锛歕s*(.+)$=Loaded: $1
+regex\:^鑳藉叆锛歕s*(.+)$=Inbound Enabled: $1
+regex\:^鑳藉嚭锛歕s*(.+)$=Outbound Enabled: $1
+鍦板浘鍔犺浇澶辫触=Failed to load map
+妤煎眰淇℃伅鍔犺浇澶辫触=Failed to load floor information
+绔欑偣璇︽儏鍔犺浇澶辫触=Failed to load station details
+鍙屽伐浣�=Dual Station
+regex\:^璁惧\s*(.+)$=Device $1
+regex\:^鍖哄煙\s*(.+)$=Area $1
+regex\:^鍑哄簱绔欑偣\s*\((\d+)\)$=Outbound Stations ($1)
+鍏�=Total
+璺宠浆鏃堕棿=Jump Time
+閫夋嫨鏃堕棿=Select Time
+鍘嬬缉鐢熸垚杩涘害=Compression Progress
+涓嬭浇鎺ユ敹杩涘害=Download Receive Progress
+鏃ユ湡閫夋嫨=Date Selection
+閫変腑鏃ユ湡=Selected Date
+璁惧绫诲瀷=Device Type
+璧峰搴忓彿=Start Offset
+鏈�澶ф枃浠�=Max Files
+璁惧鍒楄〃=Device List
+鏆傛棤鏁版嵁锛岃鍏堥�夋嫨鏃ユ湡=No data. Please select a date first.
+鎾斁=Play
+鏆傚仠=Pause
+閲嶇疆=Reset
+璺宠浆=Jump
+鍊嶉��=Speed
+regex\:^鍏盶s*(\d+)\s*涓澶�$=Total $1 devices
+regex\:^涓嬭浇\((.+)\)$=Download ($1)
+regex\:^鍙鍖朶((.+)\)$=Visualize ($1)
+regex\:^鏈煡璁惧绫诲瀷\:\s*(.+)$=Unknown device type: $1
+涓嶅湪瀹氫綅=Off Position
+鍦ㄥ畾浣�=At Position
+鍒濆鍖栧け璐�=Initialization failed
+鍔犺浇鏃ユ湡澶辫触=Failed to load dates
+鍔犺浇璁惧澶辫触=Failed to load devices
+鍔犺浇鏁版嵁涓�...=Loading data...
+娌℃湁鎵惧埌鏃ュ織鏁版嵁=No log data found
+鐩爣鏃堕棿瓒呭嚭鏃ュ織鑼冨洿锛屽凡璺宠浆鑷崇粨鏉熸椂闂�=Target time exceeds the log range. Moved to the end time.
+璇疯緭鍏ヨ澶囩紪鍙�=Please enter the device number
+璇烽�夋嫨璁惧绫诲瀷=Please select a device type
+鏁版嵁宸插叏閮ㄥ姞杞�=All data loaded
+鏃犱换鍔�=No Task
+涓嬭浇澶辫触鎴栨湭鎵惧埌鏃ュ織=Download failed or logs not found
+宸插埌杈炬棩蹇楁湯灏撅紝鏃犳硶鍒拌揪鐩爣鏃堕棿=Reached the end of logs and cannot jump to the target time
+宸茶烦杞嚦鐩爣鏃堕棿=Jumped to the target time
+姝e湪璺宠浆鑷崇洰鏍囨椂闂� (鍔犺浇涓�)...=Jumping to the target time (loading)...
+淇濆瓨璇锋眰寮傚父=Save request exception
+鍔犺浇璇锋眰寮傚父=Load request exception
+regex\:^淇濆瓨澶辫触\:\s*(.+)$=Save failed: $1
+regex\:^鍔犺浇鏁版嵁澶辫触\:\s*(.+)$=Failed to load data: $1
+璇ュ叧鑱斿凡瀛樺湪=This mapping already exists
+纭畾鍒犻櫎璇ュ叧鑱斿悧?=Are you sure you want to delete this mapping?
+regex\:^宸插缓绔嬪叧鑱擻:\s*绔欑偣\s*(.+)$=Mapping created: Station $1
+璇ョ粦瀹氬凡瀛樺湪=This binding already exists
+璇疯緭鍏ュ尯鍩熺紪鐮佸拰鍚嶇О=Please enter the area code and name
+鍖哄煙宸插瓨鍦�=Area already exists
+regex\:^宸插缓绔嬬粦瀹歕:\s*绔欑偣\s*(.+)$=Binding created: Station $1
+淇濆瓨绔欑偣棰滆壊閰嶇疆澶辫触=Failed to save station color configuration
+鍔犺浇绔欑偣棰滆壊閰嶇疆澶辫触=Failed to load station color configuration
+棰滆壊鏍煎紡宸茶嚜鍔ㄤ慨姝d负鍗佸叚杩涘埗=Color format has been normalized to hexadecimal automatically
+宸叉仮澶嶉粯璁ら鑹�=Default colors restored
+绔欑偣棰滆壊閰嶇疆宸蹭繚瀛�=Station color configuration saved
+鐧诲綍澶辫触=Login failed
+纭畾鎵ц涓�閿縺娲诲悧锛�=Are you sure you want to activate now?
+绯荤粺鐧诲綍=System Login
+绯荤粺閰嶇疆淇℃伅=System Configuration
+瀵规帴WMS銆佽澶囦笌涓氬姟瑙勫垯=Integrates WMS, devices, and business rules
+缁熶竴缂栨帓鐜板満鎵ц浠诲姟=Unified orchestration of on-site execution tasks
+璇疯緭鍏ヨ处鍙峰拰瀵嗙爜杩涘叆绯荤粺銆�=Please enter your account and password to access the system.
+灏嗚鍙瘉鏈嶅姟绔繑鍥炵殑 license 瀛楁瀹屾暣绮樿创鍒拌繖閲屻��=Paste the full license field returned by the license service here.
+璁稿彲璇� Base64=License Base64
+鑷姩鍖栫珛浣撲粨搴撲笌鏅鸿兘鐗╂祦绯荤粺瑙e喅鏂规=Automated AS/RS and intelligent logistics system solutions
+浣滀笟銆佽澶囥�佹棩蹇楀叏閾捐矾鐣欑棔=End-to-end traceability across jobs, devices, and logs
+WCS绯荤粺璁╄澶囪皟搴︺�佷换鍔℃墽琛屼笌鐜板満鐩戞帶淇濇寔鍦ㄥ悓涓�濂椾笟鍔¢摼璺腑銆�=The WCS keeps device scheduling, task execution, and on-site monitoring within the same business workflow.
+瑙掕壊绠$悊=Role Management
+鏉冮檺绠$悊=Permission Management
+鑿滃崟鍒楄〃=Menu List
+鑿滃崟绛夌骇=Menu Level
+鐖剁骇鑿滃崟=Parent Menu
+璇疯緭鍏ョ紪鐮�=Please enter code
+璇疯緭鍏ュ悕绉�=Please enter name
+璇烽�夋嫨涓婄骇=Please select parent
+璇疯緭鍏ヨ彍鍗曠紪鐮�=Please enter menu code
+璇疯緭鍏ヨ彍鍗曞悕绉�=Please enter menu name
+璇疯緭鍏ユ帓搴�=Please enter sort order
+璇烽�夋嫨绫诲瀷=Please select type
+璇烽�夋嫨涓婄骇鑿滃崟=Please select parent menu
+璇烽�夋嫨鐘舵��=Please select status
+璇疯緭鍏ユ帴鍙e湴鍧�=Please enter API URL
+璇疯緭鍏ユ潈闄愬悕绉�=Please enter permission name
+璇烽�夋嫨鎵�灞炶彍鍗�=Please select menu
+鑿滃崟鏌ヨ澶辫触=Menu query failed
+鑿滃崟璇︽儏鍔犺浇澶辫触=Failed to load menu details
+鏉冮檺鍔犺浇澶辫触=Failed to load permissions
+鏉冮檺鏍戝姞杞藉け璐�=Failed to load permission tree
+鏉冮檺鍥炴樉澶辫触=Failed to load assigned permissions
+鏉冮檺淇濆瓨澶辫触=Failed to save permissions
+瑙掕壊鏌ヨ澶辫触=Role query failed
+瑙掕壊鍔犺浇澶辫触=Failed to load roles
+纭畾鍒犻櫎閫変腑瑙掕壊鍚楋紵=Delete selected roles?
+纭畾鍒犻櫎閫変腑鍑瘉鍚楋紵=Delete selected credentials?
+# Playwright audit supplement
+鍒楄缃�=Column Settings
+鍒涘缓鑰�=Creator
+涓昏=Primary
+缂� 鍙�=ID
+*缂� 鍙�=*ID
+寮� 甯� 鐮�=Error Code
+寮� 甯�=Error
+鐘� 鎬�=Status
+宸� 浣� 鍙�=Work No.
+澶� 娉�=Remarks
+浣� 涓�=Operation
+鍛� 浠�=Command
+鐩� 鏍� 绔�=Target Station
+婧� 绔�=Source Station
+婧� 绔� 鐐�=Source Station
+婧� 搴� 浣�=Source Location
+鏉� 鐮�=Barcode
+鍩哄噯鎺�=Base Row
+鍩哄噯鎺�-code=Base Row Code
+鍩哄噯鍒�=Base Bay
+鍩哄噯鍒�-code=Base Bay Code
+瀹� 鐜� 绫�=Implementation Class
+鏃ュ織ID=Log ID
+骞冲彴瀵嗛挜=Platform Key
+Time鎴�=Timestamp
+Exception鍐呭=Exception Content
+Menu鍒楄〃=Menu List
+灞曞紑All=Expand All
+Permissions绠$悊=Permission Management
+鍑瘉璁板綍=Credential Records
+鏍� 璇�=Identifier
+瀛� 鍏� 鍊�=Dictionary Value
+瀛楀吀鏂囨湰=Dictionary Text
+鏄惁Delete=Deleted
+绉� 鎴�=Tenant
+璐� 鍙�=Account
+瀵� 鐮�=Password
+鏄� 绉�=Nickname
+澶� 鍍�=Avatar
+宸� 鍙�=Employee No.
+鎬� 鍒�=Gender
+鎵� 鏈� 鍙�=Mobile No.
+閭� 绠�=Email
+Email楠岃瘉=Email Verified
+鎵�灞為儴闂�=Department
+鐪熷疄濮撳悕=Real Name
+韬唤璇佸彿=ID Card No.
+鍑虹敓鏃ユ湡=Birth Date
+涓汉绠�浠�=Biography
+鎵�灞炴満鏋�=Organization
+*瑙� 鑹�=*Role
+宸茶缃甈assword=Password Set
+Virtual Device鍒濆鍖朣tatus=Virtual Device Initialization Status
+Please enter鐢垫涓浆鐐�=Please enter the elevator transfer point
+Role绠$悊=Role Management
+灞曞紑闈㈡澘=Expand Panel
+鏀惰捣Actions=Collapse Actions
+淇℃伅=Information
+OKExportExcel鍚�=Export to Excel?
+鍏ㄩ��=Select All
+鑷�=to
+regex\:^Success\\s*(\\d+)\\s*/\\s*Failed\\s*(\\d+)\\s*/\\s*杩炵画Failed\\s*(\\d+)$=Success $1 / Failed $2 / Consecutive Failures $3
+regex\:^(\\d{1,2})鏃�$=Day $1
+regex\:^\\*[\\s銆�]*缂朳\\s銆�]*鍙�$=*ID
+regex\:^缂朳\\s銆�]*鍙�$=ID
+regex\:^寮俒\\s銆�]*甯�$=Error
+regex\:^鐘禰\\s銆�]*鎬�$=Status
+regex\:^宸\\s銆�]*浣淸\\s銆�]*鍙�$=Work No.
+regex\:^澶嘯\\s銆�]*娉�$=Remarks
+regex\:^浣淸\\s銆�]*涓�$=Operation
+regex\:^鍛絒\\s銆�]*浠�$=Command
+regex\:^鐩甗\\s銆�]*鏍嘯\\s銆�]*绔�$=Target Station
+regex\:^婧怺\\s銆�]*绔橻\\s銆�]*鐐�$=Source Station
+regex\:^婧怺\\s銆�]*绔�$=Source Station
+regex\:^婧怺\\s銆�]*搴揫\\s銆�]*浣�$=Source Location
+regex\:^鏉\\s銆�]*鐮�$=Barcode
+regex\:^璐\\s銆�]*鍙�$=Account
+regex\:^瀵哰\\s銆�]*鐮�$=Password
+regex\:^鏄礫\\s銆�]*绉�$=Nickname
+regex\:^澶碵\\s銆�]*鍍�$=Avatar
+regex\:^宸\\s銆�]*鍙�$=Employee No.
+regex\:^鎬\\s銆�]*鍒�$=Gender
+regex\:^閭甗\\s銆�]*绠�$=Email
+regex\:^鏍嘯\\s銆�]*璇�$=Identifier
+regex\:^绉焄\\s銆�]*鎴�$=Tenant
+regex\:^\\*[\\s銆�]*瑙抂\\s銆�]*鑹�$=*Role
diff --git a/src/main/webapp/static/js/config/config.js b/src/main/webapp/static/js/config/config.js
index 483f5c6..a3e61fe 100644
--- a/src/main/webapp/static/js/config/config.js
+++ b/src/main/webapp/static/js/config/config.js
@@ -850,6 +850,154 @@
         return result;
     }
 
+    fieldMeta = [
+        {
+            field: 'id',
+            columnName: 'id',
+            label: 'ID',
+            tableProp: 'id',
+            exportField: 'id',
+            kind: 'text',
+            valueType: 'number',
+            required: true,
+            primaryKey: true,
+            searchable: false,
+            sortable: true,
+            textarea: false,
+            minWidth: 90,
+            enumOptions: [],
+            foreignQuery: '',
+            checkboxActiveRaw: '1',
+            checkboxInactiveRaw: '0'
+        },
+        {
+            field: 'name',
+            columnName: 'name',
+            label: '鍚嶇О',
+            tableProp: 'name',
+            exportField: 'name',
+            kind: 'text',
+            valueType: 'string',
+            required: true,
+            primaryKey: false,
+            searchable: false,
+            sortable: false,
+            textarea: false,
+            minWidth: 180,
+            dialogSpan: 12,
+            enumOptions: [],
+            foreignQuery: '',
+            checkboxActiveRaw: 'Y',
+            checkboxInactiveRaw: 'N'
+        },
+        {
+            field: 'code',
+            columnName: 'code',
+            label: '缂栫爜',
+            tableProp: 'code',
+            exportField: 'code',
+            kind: 'text',
+            valueType: 'string',
+            required: true,
+            primaryKey: false,
+            searchable: true,
+            sortable: false,
+            textarea: false,
+            minWidth: 180,
+            dialogSpan: 12,
+            enumOptions: [],
+            foreignQuery: '',
+            checkboxActiveRaw: 'Y',
+            checkboxInactiveRaw: 'N'
+        },
+        {
+            field: 'value',
+            columnName: 'value',
+            label: '瀵瑰簲鍊�',
+            tableProp: 'value',
+            exportField: 'value',
+            kind: 'text',
+            valueType: 'string',
+            required: true,
+            primaryKey: false,
+            searchable: false,
+            sortable: false,
+            textarea: false,
+            minWidth: 220,
+            dialogSpan: 24,
+            enumOptions: [],
+            foreignQuery: '',
+            checkboxActiveRaw: 'Y',
+            checkboxInactiveRaw: 'N'
+        },
+        {
+            field: 'type',
+            columnName: 'type',
+            label: '绫诲瀷',
+            tableProp: 'type$',
+            exportField: 'type$',
+            kind: 'enum',
+            valueType: 'number',
+            required: true,
+            primaryKey: false,
+            searchable: false,
+            sortable: false,
+            textarea: false,
+            minWidth: 120,
+            dialogSpan: 12,
+            enumOptions: [
+                { rawValue: '1', label: 'String' },
+                { rawValue: '2', label: 'JSON' }
+            ],
+            foreignQuery: '',
+            checkboxActiveRaw: '1',
+            checkboxInactiveRaw: '0'
+        },
+        {
+            field: 'status',
+            columnName: 'status',
+            label: '鐘舵��',
+            tableProp: 'status$',
+            exportField: 'status$',
+            kind: 'enum',
+            valueType: 'number',
+            required: true,
+            primaryKey: false,
+            searchable: false,
+            sortable: false,
+            textarea: false,
+            minWidth: 120,
+            dialogSpan: 12,
+            enumOptions: [
+                { rawValue: '1', label: '姝e父' },
+                { rawValue: '0', label: '绂佺敤' }
+            ],
+            foreignQuery: '',
+            checkboxActiveRaw: '1',
+            checkboxInactiveRaw: '0'
+        },
+        {
+            field: 'selectType',
+            columnName: 'select_type',
+            label: '绛涢�夌被鍨�',
+            tableProp: 'selectType',
+            exportField: 'selectType',
+            kind: 'text',
+            valueType: 'string',
+            required: false,
+            primaryKey: false,
+            searchable: true,
+            sortable: false,
+            textarea: false,
+            minWidth: 140,
+            dialogSpan: 24,
+            enumOptions: [],
+            foreignQuery: '',
+            checkboxActiveRaw: 'Y',
+            checkboxInactiveRaw: 'N'
+        }
+    ];
+
     function isEmptyValue(value) {
         return value === null || value === undefined || value === '';
     }
@@ -877,11 +1025,17 @@
     }
 
     function isSearchableField(field) {
-        return !!field && field.kind !== 'image' && !field.textarea;
+        return !!field && field.searchable !== false && field.kind !== 'image' && !field.textarea;
     }
 
     function isSortableField(field) {
         if (!field) {
+            return false;
+        }
+        if (field.sortable === true) {
+            return true;
+        }
+        if (field.sortable === false) {
             return false;
         }
         if (field.primaryKey) {
@@ -1217,6 +1371,7 @@
                         mode: 'create',
                         submitting: false
                     },
+                    tableHeight: 420,
                     layoutTimer: null,
                     tableResizeHandler: null,
                     dialogForm: createFormDefaults(),
@@ -1270,16 +1425,14 @@
                         };
                     });
                 },
-                tableHeight: function () {
-                    return this.advancedFiltersVisible && this.hasAdvancedFilters
-                        ? 'calc(100vh - 390px)'
-                        : 'calc(100vh - 300px)';
-                },
                 formTarget: function () {
                     return this.dialogForm;
                 },
                 displayTarget: function () {
                     return this.dialogDisplay;
+                },
+                isDialogReadonly: function () {
+                    return this.dialog.mode === 'detail';
                 }
             },
             created: function () {
@@ -1304,12 +1457,26 @@
                 }
             },
             methods: $.extend({}, sharedMethods, {
+                calculateTableHeight: function () {
+                    var viewportHeight = window.innerHeight || document.documentElement.clientHeight || 860;
+                    var tableWrap = this.$refs.tableWrap;
+                    var pagerBar = this.$refs.pagerBar;
+                    if (!tableWrap) {
+                        this.tableHeight = Math.max(360, viewportHeight - (this.advancedFiltersVisible ? 360 : 300));
+                        return;
+                    }
+                    var tableTop = tableWrap.getBoundingClientRect().top;
+                    var pagerHeight = pagerBar ? pagerBar.offsetHeight : 56;
+                    var bottomGap = 56;
+                    this.tableHeight = Math.max(320, Math.floor(viewportHeight - tableTop - pagerHeight - bottomGap));
+                },
                 requestTableLayout: function (delay) {
                     var self = this;
                     if (self.layoutTimer) {
                         clearTimeout(self.layoutTimer);
                     }
                     self.$nextTick(function () {
+                        self.calculateTableHeight();
                         self.layoutTimer = setTimeout(function () {
                             var table = self.$refs.dataTable;
                             if (table && typeof table.doLayout === 'function') {
@@ -1475,8 +1642,23 @@
                         }
                     });
                 },
+                openDetailDialog: function (row) {
+                    var self = this;
+                    self.dialog.mode = 'detail';
+                    self.dialog.visible = true;
+                    self.$nextTick(function () {
+                        self.resetDialogState();
+                        fillFormFromRow(row, self.dialogForm, self.dialogDisplay);
+                        if (self.$refs.dialogForm) {
+                            self.$refs.dialogForm.clearValidate();
+                        }
+                    });
+                },
                 submitDialog: function () {
                     var self = this;
+                    if (self.dialog.mode === 'detail') {
+                        return;
+                    }
                     if (!self.$refs.dialogForm) {
                         return;
                     }
@@ -1589,6 +1771,30 @@
                             self.$message.error('瀵煎嚭澶辫触');
                         }
                     });
+                },
+                refreshCache: function () {
+                    var self = this;
+                    self.$confirm('纭畾鍒锋柊Redis缂撳瓨鍚楋紵', '鎻愮ず', { type: 'warning' }).then(function () {
+                        $.ajax({
+                            url: baseUrl + '/config/refreshCache',
+                            method: 'POST',
+                            headers: self.authHeaders(),
+                            success: function (res) {
+                                if (self.handleForbidden(res)) {
+                                    return;
+                                }
+                                if (!res || res.code !== 200) {
+                                    self.$message.error((res && res.msg) ? res.msg : '鍒锋柊缂撳瓨澶辫触');
+                                    return;
+                                }
+                                self.$message.success('鍒锋柊缂撳瓨鎴愬姛');
+                                self.loadTable();
+                            },
+                            error: function () {
+                                self.$message.error('鍒锋柊缂撳瓨澶辫触');
+                            }
+                        });
+                    }).catch(function () {});
                 }
             })
         });
diff --git a/src/main/webapp/static/js/wrkMast/wrkMast.js b/src/main/webapp/static/js/wrkMast/wrkMast.js
new file mode 100644
index 0000000..daa4b2b
--- /dev/null
+++ b/src/main/webapp/static/js/wrkMast/wrkMast.js
@@ -0,0 +1,319 @@
+(function () {
+    var COLUMN_STORAGE_KEY = "wrk-mast-visible-columns";
+
+    var DEFAULT_COLUMNS = [
+        { key: "wrkNo", prop: "wrkNo", label: "宸ヤ綔鍙�", width: 110, sortable: true, align: "center" },
+        { key: "wmsWrkNo", prop: "wmsWrkNo", label: "WMS浠诲姟鍙�", minWidth: 160, sortable: true },
+        { key: "wrkSts$", prop: "wrkSts$", label: "宸ヤ綔鐘舵��", minWidth: 120, sortable: true },
+        { key: "ioType$", prop: "ioType$", label: "浠诲姟绫诲瀷", minWidth: 120, sortable: true },
+        { key: "ioPri", prop: "ioPri", label: "浼樺厛绾�", width: 90, sortable: true, align: "center" },
+        { key: "sourceStaNo", prop: "sourceStaNo", label: "婧愮珯", width: 90, sortable: true, align: "center" },
+        { key: "staNo", prop: "staNo", label: "鐩爣绔�", width: 90, sortable: true, align: "center" },
+        { key: "sourceLocNo", prop: "sourceLocNo", label: "婧愬簱浣�", minWidth: 140, sortable: true },
+        { key: "locNo", prop: "locNo", label: "鐩爣搴撲綅", minWidth: 140, sortable: true },
+        { key: "modiTime$", prop: "modiTime$", label: "淇敼鏃堕棿", minWidth: 168, sortable: true },
+        { key: "barcode", prop: "barcode", label: "鎵樼洏鐮�", minWidth: 150, sortable: true },
+        { key: "crnNo", prop: "crnNo", label: "鍫嗗灈鏈�", width: 90, sortable: true, align: "center" },
+        { key: "dualCrnNo", prop: "dualCrnNo", label: "鍙屽伐浣嶅爢鍨涙満", minWidth: 120, sortable: true, align: "center" },
+        { key: "batch", prop: "batch", label: "鎵规", minWidth: 120, sortable: true },
+        { key: "batchSeq", prop: "batchSeq", label: "鎵规搴忓垪", width: 100, sortable: true, align: "center" },
+        { key: "systemMsg", prop: "systemMsg", label: "绯荤粺娑堟伅", minWidth: 220, sortable: false, showOverflow: false }
+    ];
+
+    function cloneSearchForm() {
+        return {
+            condition: "",
+            wrk_no: "",
+            wms_wrk_no: "",
+            loc_no: "",
+            source_loc_no: "",
+            crn_no: "",
+            dual_crn_no: ""
+        };
+    }
+
+    function loadStoredColumns() {
+        try {
+            var raw = localStorage.getItem(COLUMN_STORAGE_KEY);
+            var parsed = raw ? JSON.parse(raw) : null;
+            if (!parsed || !parsed.length) {
+                return DEFAULT_COLUMNS.map(function (column) { return column.key; });
+            }
+            return DEFAULT_COLUMNS.map(function (column) { return column.key; }).filter(function (key) {
+                return parsed.indexOf(key) > -1;
+            });
+        } catch (e) {
+            return DEFAULT_COLUMNS.map(function (column) { return column.key; });
+        }
+    }
+
+    function saveVisibleColumns(keys) {
+        localStorage.setItem(COLUMN_STORAGE_KEY, JSON.stringify(keys));
+    }
+
+    new Vue({
+        el: "#app",
+        data: function () {
+            return {
+                loading: false,
+                advancedVisible: false,
+                columnPopoverVisible: false,
+                tableData: [],
+                currentPage: 1,
+                pageSize: 30,
+                pageSizes: [16, 30, 50, 100, 150, 200],
+                pageTotal: 0,
+                tableHeight: 520,
+                searchForm: cloneSearchForm(),
+                sortState: {
+                    prop: "",
+                    order: ""
+                },
+                columnDefs: DEFAULT_COLUMNS,
+                visibleColumnKeys: loadStoredColumns(),
+                layoutTimer: null
+            };
+        },
+        computed: {
+            visibleColumns: function () {
+                var keys = this.visibleColumnKeys;
+                return this.columnDefs.filter(function (column) {
+                    return keys.indexOf(column.key) > -1;
+                });
+            },
+            tableRenderKey: function () {
+                return this.visibleColumnKeys.join("|");
+            }
+        },
+        created: function () {
+            this.loadList();
+        },
+        mounted: function () {
+            this.updateTableHeight();
+            window.addEventListener("resize", this.handleResize);
+        },
+        beforeDestroy: function () {
+            window.removeEventListener("resize", this.handleResize);
+            if (this.layoutTimer) {
+                clearTimeout(this.layoutTimer);
+                this.layoutTimer = null;
+            }
+        },
+        methods: {
+            buildQueryParams: function () {
+                var data = {
+                    curr: this.currentPage,
+                    limit: this.pageSize
+                };
+                var key;
+                for (key in this.searchForm) {
+                    if (Object.prototype.hasOwnProperty.call(this.searchForm, key) && this.searchForm[key] !== "" && this.searchForm[key] !== null) {
+                        data[key] = this.searchForm[key];
+                    }
+                }
+                if (this.sortState.prop && this.sortState.order) {
+                    data.orderByField = this.sortState.prop;
+                    data.orderByType = this.sortState.order === "ascending" ? "asc" : "desc";
+                }
+                return data;
+            },
+            loadList: function () {
+                var vm = this;
+                vm.loading = true;
+                $.ajax({
+                    url: baseUrl + "/wrkMast/list/auth",
+                    headers: { token: localStorage.getItem("token") },
+                    method: "GET",
+                    data: vm.buildQueryParams(),
+                    success: function (res) {
+                        if (res.code === 200) {
+                            vm.tableData = (res.data && res.data.records) || [];
+                            vm.pageTotal = (res.data && res.data.total) || 0;
+                            vm.scheduleTableLayout();
+                            return;
+                        }
+                        if (res.code === 403) {
+                            top.location.href = baseUrl + "/";
+                            return;
+                        }
+                        vm.$message.error(res.msg || "浠诲姟鍒楄〃鍔犺浇澶辫触");
+                    },
+                    error: function () {
+                        vm.$message.error("浠诲姟鍒楄〃鍔犺浇澶辫触");
+                    },
+                    complete: function () {
+                        vm.loading = false;
+                    }
+                });
+            },
+            handleSearch: function () {
+                this.currentPage = 1;
+                this.loadList();
+            },
+            handleReset: function () {
+                this.searchForm = cloneSearchForm();
+                this.currentPage = 1;
+                this.sortState = {
+                    prop: "",
+                    order: ""
+                };
+                this.loadList();
+                this.scheduleTableLayout();
+            },
+            toggleAdvanced: function () {
+                this.advancedVisible = !this.advancedVisible;
+                this.updateTableHeight();
+                this.scheduleTableLayout();
+            },
+            handleSizeChange: function (size) {
+                this.pageSize = size;
+                this.currentPage = 1;
+                this.loadList();
+            },
+            handleCurrentChange: function (page) {
+                this.currentPage = page;
+                this.loadList();
+            },
+            handleSortChange: function (sort) {
+                this.sortState = {
+                    prop: sort.prop || "",
+                    order: sort.order || ""
+                };
+                this.currentPage = 1;
+                this.loadList();
+            },
+            isColumnVisible: function (key) {
+                return this.visibleColumnKeys.indexOf(key) > -1;
+            },
+            toggleColumn: function (key, checked) {
+                var next = this.visibleColumnKeys.slice();
+                var index = next.indexOf(key);
+
+                if (checked && index === -1) {
+                    next.push(key);
+                }
+                if (!checked && index > -1) {
+                    if (next.length === 1) {
+                        this.$message.warning("鑷冲皯淇濈暀涓�鍒�");
+                        return;
+                    }
+                    next.splice(index, 1);
+                }
+
+                this.visibleColumnKeys = this.columnDefs.map(function (column) {
+                    return column.key;
+                }).filter(function (columnKey) {
+                    return next.indexOf(columnKey) > -1;
+                });
+                saveVisibleColumns(this.visibleColumnKeys);
+                this.scheduleTableLayout();
+            },
+            showAllColumns: function () {
+                this.visibleColumnKeys = this.columnDefs.map(function (column) {
+                    return column.key;
+                });
+                saveVisibleColumns(this.visibleColumnKeys);
+                this.scheduleTableLayout();
+            },
+            resetColumns: function () {
+                this.visibleColumnKeys = DEFAULT_COLUMNS.map(function (column) {
+                    return column.key;
+                });
+                saveVisibleColumns(this.visibleColumnKeys);
+                this.scheduleTableLayout();
+            },
+            handleRowCommand: function (command, row) {
+                if (command === "complete") {
+                    this.completeTask(row);
+                    return;
+                }
+                if (command === "cancel") {
+                    this.cancelTask(row);
+                }
+            },
+            completeTask: function (row) {
+                var vm = this;
+                vm.$confirm("纭畾瀹屾垚璇ヤ换鍔″悧锛�", "鎻愮ず", {
+                    type: "warning",
+                    confirmButtonText: "纭畾",
+                    cancelButtonText: "鍙栨秷"
+                }).then(function () {
+                    $.ajax({
+                        url: baseUrl + "/openapi/completeTask",
+                        contentType: "application/json",
+                        headers: { token: localStorage.getItem("token") },
+                        data: JSON.stringify({ wrkNo: row.wrkNo }),
+                        method: "POST",
+                        success: function (res) {
+                            if (res.code === 200) {
+                                vm.$message.success("瀹屾垚鎴愬姛");
+                                vm.loadList();
+                                return;
+                            }
+                            if (res.code === 403) {
+                                top.location.href = baseUrl + "/";
+                                return;
+                            }
+                            vm.$message.error(res.msg || "瀹屾垚澶辫触");
+                        },
+                        error: function () {
+                            vm.$message.error("瀹屾垚澶辫触");
+                        }
+                    });
+                }).catch(function () {});
+            },
+            cancelTask: function (row) {
+                var vm = this;
+                vm.$confirm("纭畾鍙栨秷璇ヤ换鍔″悧锛�", "鎻愮ず", {
+                    type: "warning",
+                    confirmButtonText: "纭畾",
+                    cancelButtonText: "鍙栨秷"
+                }).then(function () {
+                    $.ajax({
+                        url: baseUrl + "/openapi/cancelTask",
+                        contentType: "application/json",
+                        headers: { token: localStorage.getItem("token") },
+                        data: JSON.stringify({ wrkNo: row.wrkNo }),
+                        method: "POST",
+                        success: function (res) {
+                            if (res.code === 200) {
+                                vm.$message.success("鍙栨秷鎴愬姛");
+                                vm.loadList();
+                                return;
+                            }
+                            if (res.code === 403) {
+                                top.location.href = baseUrl + "/";
+                                return;
+                            }
+                            vm.$message.error(res.msg || "鍙栨秷澶辫触");
+                        },
+                        error: function () {
+                            vm.$message.error("鍙栨秷澶辫触");
+                        }
+                    });
+                }).catch(function () {});
+            },
+            updateTableHeight: function () {
+                var viewport = window.innerHeight || document.documentElement.clientHeight || 860;
+                this.tableHeight = Math.max(340, viewport - (this.advancedVisible ? 276 : 222));
+            },
+            scheduleTableLayout: function () {
+                var vm = this;
+                vm.updateTableHeight();
+                vm.$nextTick(function () {
+                    if (vm.layoutTimer) {
+                        clearTimeout(vm.layoutTimer);
+                    }
+                    vm.layoutTimer = setTimeout(function () {
+                        if (vm.$refs.dataTable && typeof vm.$refs.dataTable.doLayout === "function") {
+                            vm.$refs.dataTable.doLayout();
+                        }
+                    }, 50);
+                });
+            },
+            handleResize: function () {
+                this.scheduleTableLayout();
+            }
+        }
+    });
+})();
diff --git a/src/main/webapp/views/ai/diagnosis.html b/src/main/webapp/views/ai/diagnosis.html
index 70686ae..55bcd08 100644
--- a/src/main/webapp/views/ai/diagnosis.html
+++ b/src/main/webapp/views/ai/diagnosis.html
@@ -644,7 +644,7 @@
 
   <script type="text/javascript" src="../../static/vue/js/vue.min.js"></script>
   <script type="text/javascript" src="../../static/vue/element/element.js"></script>
-  <script type="text/javascript" src="../../static/js/common.js?v=20260309_i18n_fix1" charset="utf-8"></script>
+  <script type="text/javascript" src="../../static/js/common.js" charset="utf-8"></script>
   <script src="../../static/js/marked.min.js"></script>
   <script src="../../static/js/purify.min.js"></script>
   <script>
diff --git a/src/main/webapp/views/ai/llm_config.html b/src/main/webapp/views/ai/llm_config.html
index d6e2849..8d91b18 100644
--- a/src/main/webapp/views/ai/llm_config.html
+++ b/src/main/webapp/views/ai/llm_config.html
@@ -472,7 +472,7 @@
 
 <script type="text/javascript" src="../../static/vue/js/vue.min.js"></script>
 <script type="text/javascript" src="../../static/vue/element/element.js"></script>
-<script type="text/javascript" src="../../static/js/common.js?v=20260309_i18n_fix1" charset="utf-8"></script>
+<script type="text/javascript" src="../../static/js/common.js" charset="utf-8"></script>
 <script>
   new Vue({
     el: '#app',
diff --git a/src/main/webapp/views/basOutStationArea/basOutStationArea.html b/src/main/webapp/views/basOutStationArea/basOutStationArea.html
index 89b461d..5df0d5a 100644
--- a/src/main/webapp/views/basOutStationArea/basOutStationArea.html
+++ b/src/main/webapp/views/basOutStationArea/basOutStationArea.html
@@ -80,7 +80,7 @@
 <script type="text/javascript" src="../../static/js/jquery/jquery-3.3.1.min.js"></script>
 <script type="text/javascript" src="../../static/vue/js/vue.min.js"></script>
 <script type="text/javascript" src="../../static/vue/element/element.js"></script>
-<script type="text/javascript" src="../../static/js/common.js?v=20260309_i18n_fix1" charset="utf-8"></script>
+<script type="text/javascript" src="../../static/js/common.js" charset="utf-8"></script>
 <script type="text/javascript" src="../../static/js/basOutStationArea/basOutStationArea.js"></script>
 </body>
 </html>
diff --git a/src/main/webapp/views/basStationDevice/basStationDevice.html b/src/main/webapp/views/basStationDevice/basStationDevice.html
index fd4dd5a..3346886 100644
--- a/src/main/webapp/views/basStationDevice/basStationDevice.html
+++ b/src/main/webapp/views/basStationDevice/basStationDevice.html
@@ -263,7 +263,7 @@
 <script type="text/javascript" src="../../static/js/jquery/jquery-3.3.1.min.js"></script>
 <script type="text/javascript" src="../../static/vue/js/vue.min.js"></script>
 <script type="text/javascript" src="../../static/vue/element/element.js"></script>
-<script type="text/javascript" src="../../static/js/common.js?v=20260309_i18n_fix1" charset="utf-8"></script>
+<script type="text/javascript" src="../../static/js/common.js" charset="utf-8"></script>
 <script type="text/javascript" src="../../static/js/basStationDevice/basStationDevice.js"></script>
 </body>
 </html>
diff --git a/src/main/webapp/views/config/config.html b/src/main/webapp/views/config/config.html
index 02587dd..2c4bd10 100644
--- a/src/main/webapp/views/config/config.html
+++ b/src/main/webapp/views/config/config.html
@@ -22,6 +22,7 @@
         html,
         body {
             margin: 0;
+            height: 100%;
             min-height: 100%;
             color: var(--text-main);
             font-family: "Avenir Next", "PingFang SC", "Microsoft YaHei", sans-serif;
@@ -34,12 +35,16 @@
         .page-shell {
             max-width: 1700px;
             margin: 0 auto;
+            height: 100%;
             padding: 14px;
             box-sizing: border-box;
+            display: flex;
         }
 
         .card-shell {
             position: relative;
+            flex: 1 1 auto;
+            display: flex;
             border-radius: 24px;
             border: 1px solid var(--card-border);
             background:
@@ -53,6 +58,12 @@
         .card-body {
             position: relative;
             z-index: 1;
+            flex: 1 1 auto;
+            min-height: 0;
+            min-width: 0;
+            width: 100%;
+            display: flex;
+            flex-direction: column;
         }
 
         .list-toolbar {
@@ -164,6 +175,11 @@
 
         .table-wrap {
             padding: 10px 16px;
+            flex: 1 1 auto;
+            min-height: 0;
+            min-width: 0;
+            width: 100%;
+            display: flex;
         }
 
         .table-shell {
@@ -171,6 +187,11 @@
             overflow: hidden;
             border: 1px solid rgba(217, 227, 238, 0.98);
             background: rgba(255, 255, 255, 0.95);
+            flex: 1 1 auto;
+            min-height: 0;
+            min-width: 0;
+            width: 100%;
+            max-width: 100%;
         }
 
         .table-shell .el-table {
@@ -436,6 +457,7 @@
                             <el-button slot="reference" size="small" plain icon="el-icon-setting">鍒楄缃�</el-button>
                         </el-popover>
                         <el-button size="small" plain icon="el-icon-download" :loading="exporting" @click="exportRows">瀵煎嚭</el-button>
+                        <el-button size="small" plain type="warning" icon="el-icon-refresh-right" @click="refreshCache">鍒锋柊缂撳瓨</el-button>
                     </div>
                 </div>
             </div>
@@ -510,7 +532,7 @@
                 </div>
             </el-collapse-transition>
 
-            <div class="table-wrap">
+            <div ref="tableWrap" class="table-wrap">
                 <div class="table-shell">
                     <el-table
                         ref="dataTable"
@@ -552,8 +574,9 @@
                                 <span v-else>{{ valueOrDash(getTableValue(scope.row, field)) }}</span>
                             </template>
                         </el-table-column>
-                        <el-table-column label="鎿嶄綔" width="160" fixed="right" align="center">
+                        <el-table-column label="鎿嶄綔" width="190" fixed="right" align="center">
                             <template slot-scope="scope">
+                                <el-button type="text" @click="openDetailDialog(scope.row)">璇︽儏</el-button>
                                 <el-button type="text" @click="openEditDialog(scope.row)">淇敼</el-button>
                                 <el-button type="text" style="color:#f56c6c;" @click="removeRows([scope.row[primaryKeyField]])">鍒犻櫎</el-button>
                             </template>
@@ -562,7 +585,7 @@
                 </div>
             </div>
 
-            <div class="pager-bar">
+            <div ref="pagerBar" class="pager-bar">
                 <el-pagination
                     small
                     background
@@ -580,7 +603,7 @@
 
     <el-dialog
         class="dialog-panel"
-        :title="dialog.mode === 'create' ? '鏂板 Config' : '淇敼 Config'"
+        :title="dialog.mode === 'create' ? '鏂板 Config' : (dialog.mode === 'detail' ? '璇︽儏 Config' : '淇敼 Config')"
         :visible.sync="dialog.visible"
         width="760px"
         :close-on-click-modal="false">
@@ -594,7 +617,7 @@
                 <el-col
                     v-for="field in editableFields"
                     :key="'dialog-' + field.field"
-                    :span="field.textarea || field.kind === 'image' ? 24 : 12">
+                    :span="field.dialogSpan || (field.textarea || field.kind === 'image' ? 24 : 12)">
                     <el-form-item :label="field.label" :prop="field.field">
                         <el-date-picker
                             v-if="field.kind === 'date'"
@@ -602,12 +625,14 @@
                             type="datetime"
                             value-format="yyyy-MM-dd HH:mm:ss"
                             :placeholder="'璇烽�夋嫨' + field.label"
+                            :disabled="isDialogReadonly"
                             style="width: 100%;">
                         </el-date-picker>
                         <el-select
                             v-else-if="field.kind === 'enum'"
                             v-model="dialogForm[field.field]"
                             clearable
+                            :disabled="isDialogReadonly"
                             :placeholder="'璇烽�夋嫨' + field.label"
                             style="width: 100%;">
                             <el-option
@@ -622,6 +647,7 @@
                             v-model="dialogDisplay[field.field]"
                             :fetch-suggestions="getSuggestionFetcher(field)"
                             :placeholder="'璇疯緭鍏�' + field.label"
+                            :disabled="isDialogReadonly"
                             style="width: 100%;"
                             @select="handleForeignSelect(field, $event)"
                             @input="handleForeignInput(field)">
@@ -633,6 +659,7 @@
                         <el-switch
                             v-else-if="field.kind === 'checkbox'"
                             v-model="dialogForm[field.field]"
+                            :disabled="isDialogReadonly"
                             :active-value="normalizeOptionValue(field, field.checkboxActiveRaw)"
                             :inactive-value="normalizeOptionValue(field, field.checkboxInactiveRaw)"
                             active-color="#13ce66"
@@ -643,11 +670,13 @@
                             v-model.trim="dialogForm[field.field]"
                             type="textarea"
                             :rows="3"
+                            :disabled="isDialogReadonly"
                             :placeholder="'璇疯緭鍏�' + field.label">
                         </el-input>
                         <el-input
                             v-else
                             v-model.trim="dialogForm[field.field]"
+                            :disabled="isDialogReadonly"
                             :placeholder="'璇疯緭鍏�' + field.label">
                         </el-input>
                     </el-form-item>
@@ -656,7 +685,7 @@
         </el-form>
         <div slot="footer" class="dialog-footer">
             <el-button @click="dialog.visible = false">鍙栨秷</el-button>
-            <el-button type="primary" :loading="dialog.submitting" @click="submitDialog">淇濆瓨</el-button>
+            <el-button v-if="!isDialogReadonly" type="primary" :loading="dialog.submitting" @click="submitDialog">淇濆瓨</el-button>
         </div>
     </el-dialog>
 </div>
@@ -665,6 +694,6 @@
 <script type="text/javascript" src="../../static/js/common.js" charset="utf-8"></script>
 <script type="text/javascript" src="../../static/vue/js/vue.min.js"></script>
 <script type="text/javascript" src="../../static/vue/element/element.js"></script>
-<script type="text/javascript" src="../../static/js/config/config.js?v=20260310" charset="utf-8"></script>
+<script type="text/javascript" src="../../static/js/config/config.js" charset="utf-8"></script>
 </body>
 </html>
diff --git a/src/main/webapp/views/debugParam/debugParam.html b/src/main/webapp/views/debugParam/debugParam.html
index 7dd00a9..740f5fb 100644
--- a/src/main/webapp/views/debugParam/debugParam.html
+++ b/src/main/webapp/views/debugParam/debugParam.html
@@ -6,7 +6,7 @@
 		<title>璋冭瘯鍙傛暟</title>
 		<link rel="stylesheet" href="../../static/vue/element/element.css">
 		<script type="text/javascript" src="../../static/js/jquery/jquery-3.3.1.min.js"></script>
-		<script type="text/javascript" src="../../static/js/common.js?v=20260309_i18n_fix1"></script>
+		<script type="text/javascript" src="../../static/js/common.js"></script>
 		<script type="text/javascript" src="../../static/vue/js/vue.min.js"></script>
 		<script type="text/javascript" src="../../static/vue/element/element.js"></script>
 		<style>
diff --git a/src/main/webapp/views/detail.html b/src/main/webapp/views/detail.html
index e62b4ae..4985baa 100644
--- a/src/main/webapp/views/detail.html
+++ b/src/main/webapp/views/detail.html
@@ -275,7 +275,7 @@
 </body>
 <script type="text/javascript" src="../static/js/jquery/jquery-3.3.1.min.js"></script>
 <script type="text/javascript" src="../static/js/tools/md5.js"></script>
-<script type="text/javascript" src="../static/js/common.js?v=20260309_i18n_fix1"></script>
+<script type="text/javascript" src="../static/js/common.js"></script>
 <script type="text/javascript" src="../static/vue/js/vue.min.js"></script>
 <script type="text/javascript" src="../static/vue/element/element.js"></script>
 <script type="text/javascript" src="../static/js/detail/detail.js?v=20260310_detail_vue3"></script>
diff --git a/src/main/webapp/views/deviceLogs/deviceLogs.html b/src/main/webapp/views/deviceLogs/deviceLogs.html
index 1b9771a..2af2915 100644
--- a/src/main/webapp/views/deviceLogs/deviceLogs.html
+++ b/src/main/webapp/views/deviceLogs/deviceLogs.html
@@ -203,7 +203,7 @@
 </div>
 
 <script type="text/javascript" src="../../static/js/jquery/jquery-3.3.1.min.js"></script>
-<script type="text/javascript" src="../../static/js/common.js?v=20260309_i18n_fix1" charset="utf-8"></script>
+<script type="text/javascript" src="../../static/js/common.js" charset="utf-8"></script>
 <script src="../../static/vue/js/vue.min.js"></script>
 <script src="../../static/vue/element/element.js"></script>
 <script src="../../components/MonitorCardKit.js"></script>
diff --git a/src/main/webapp/views/index.html b/src/main/webapp/views/index.html
index 4e4ba07..37d8d39 100644
--- a/src/main/webapp/views/index.html
+++ b/src/main/webapp/views/index.html
@@ -858,7 +858,7 @@
 </div>
 
 <script type="text/javascript" src="../static/js/jquery/jquery-3.3.1.min.js"></script>
-<script type="text/javascript" src="../static/js/common.js?v=20260309_i18n_fix1"></script>
+<script type="text/javascript" src="../static/js/common.js"></script>
 <script type="text/javascript" src="../static/vue/js/vue.min.js"></script>
 <script type="text/javascript" src="../static/vue/element/element.js"></script>
 <script>
@@ -1136,17 +1136,7 @@
         PROFILE_TAB_CONFIG.title = profileConfig.title;
         PROFILE_TAB_CONFIG.group = profileConfig.group;
         for (i = 0; i < this.tabs.length; i++) {
-          if (this.isHomeTabUrl(this.tabs[i].url)) {
-            this.tabs[i].title = homeConfig.title;
-            this.tabs[i].group = homeConfig.group;
-            this.tabs[i].home = true;
-          } else if (this.resolveViewSrc(this.tabs[i].url) === this.resolveViewSrc(profileConfig.url)) {
-            this.tabs[i].title = profileConfig.title;
-            this.tabs[i].group = profileConfig.group;
-          } else {
-            this.tabs[i].title = this.translateTabTitle(this.tabs[i].title);
-            this.tabs[i].group = this.tl(this.tabs[i].group);
-          }
+          this.syncTabMeta(this.tabs[i], homeConfig, profileConfig);
         }
         this.updateDocumentTitle(this.activeTabTitle);
         this.persistTabs();
@@ -1183,6 +1173,56 @@
       },
       translateTabTitle: function (title) {
         return this.tl(title);
+      },
+      findMenuMeta: function (tab) {
+        var normalizedUrl;
+        var i;
+        var j;
+        var group;
+        var item;
+        if (!tab) {
+          return null;
+        }
+        normalizedUrl = this.resolveViewSrc(tab.url);
+        for (i = 0; i < this.menus.length; i++) {
+          group = this.menus[i];
+          for (j = 0; j < group.subMenu.length; j++) {
+            item = group.subMenu[j];
+            if ((tab.menuKey && item.tabKey === tab.menuKey) || item.url === normalizedUrl) {
+              return {
+                group: group,
+                item: item
+              };
+            }
+          }
+        }
+        return null;
+      },
+      syncTabMeta: function (tab, homeConfig, profileConfig) {
+        var menuMeta;
+        if (!tab) {
+          return;
+        }
+        if (this.isHomeTabUrl(tab.url)) {
+          tab.title = homeConfig.title;
+          tab.group = homeConfig.group;
+          tab.home = true;
+          return;
+        }
+        if (this.resolveViewSrc(tab.url) === this.resolveViewSrc(profileConfig.url)) {
+          tab.title = profileConfig.title;
+          tab.group = profileConfig.group;
+          return;
+        }
+        menuMeta = this.findMenuMeta(tab);
+        if (menuMeta) {
+          tab.title = menuMeta.item.name;
+          tab.group = menuMeta.group.menu;
+          tab.menuKey = menuMeta.item.tabKey || tab.menuKey;
+          return;
+        }
+        tab.title = this.translateTabTitle(tab.title);
+        tab.group = this.tl(tab.group);
       },
       updateDocumentTitle: function (title) {
         document.title = title + " - " + this.t("app.title");
@@ -1473,7 +1513,7 @@
         script = frameDocument.createElement("script");
         script.id = "wcs-i18n-bridge-script";
         script.type = "text/javascript";
-        script.src = baseUrl + "/static/js/common.js?v=20260309_i18n_fix1";
+        script.src = baseUrl + "/static/js/common.js";
         script.onload = applyFrameI18n;
         frameDocument.head.appendChild(script);
       },
@@ -1742,6 +1782,7 @@
             that.menuLoading = false;
             if (res.code === 200) {
               that.menus = that.normalizeMenuData(res.data || []);
+              that.refreshI18nState();
               that.syncMenuStateByUrl(that.activeTabUrl);
             } else if (res.code === 403) {
               top.location.href = baseUrl + "/login";
diff --git a/src/main/webapp/views/locMap/locMap.html b/src/main/webapp/views/locMap/locMap.html
index f54a265..fdd8960 100644
--- a/src/main/webapp/views/locMap/locMap.html
+++ b/src/main/webapp/views/locMap/locMap.html
@@ -5,7 +5,7 @@
   <title>搴撲綅鍦板浘</title>
   <link rel="stylesheet" href="../../static/vue/element/element.css">
   <script type="text/javascript" src="../../static/js/jquery/jquery-3.3.1.min.js"></script>
-  <script type="text/javascript" src="../../static/js/common.js?v=20260309_i18n_fix1"></script>
+  <script type="text/javascript" src="../../static/js/common.js"></script>
   <script type="text/javascript" src="../../static/vue/js/vue.min.js"></script>
   <script type="text/javascript" src="../../static/vue/element/element.js"></script>
   <script src="../../static/js/gsap.min.js"></script>
diff --git a/src/main/webapp/views/login.html b/src/main/webapp/views/login.html
index 01e5ad2..2c28dae 100644
--- a/src/main/webapp/views/login.html
+++ b/src/main/webapp/views/login.html
@@ -517,7 +517,7 @@
 </body>
 <script type="text/javascript" src="../static/js/jquery/jquery-3.3.1.min.js"></script>
 <script type="text/javascript" src="../static/js/tools/md5.js"></script>
-<script type="text/javascript" src="../static/js/common.js?v=20260309_i18n_fix1"></script>
+<script type="text/javascript" src="../static/js/common.js"></script>
 <script type="text/javascript" src="../static/vue/js/vue.min.js"></script>
 <script type="text/javascript" src="../static/vue/element/element.js"></script>
 <script type="text/javascript" src="../static/js/login/login.js?v=20260310_login_vue"></script>
diff --git a/src/main/webapp/views/notifyReport/notifyReport.html b/src/main/webapp/views/notifyReport/notifyReport.html
index 7c00400..b5cbb67 100644
--- a/src/main/webapp/views/notifyReport/notifyReport.html
+++ b/src/main/webapp/views/notifyReport/notifyReport.html
@@ -544,7 +544,7 @@
 
 <script type="text/javascript" src="../../static/vue/js/vue.min.js"></script>
 <script type="text/javascript" src="../../static/vue/element/element.js"></script>
-<script type="text/javascript" src="../../static/js/common.js?v=20260309_i18n_fix1" charset="utf-8"></script>
+<script type="text/javascript" src="../../static/js/common.js" charset="utf-8"></script>
 <script>
   new Vue({
     el: '#app',
diff --git a/src/main/webapp/views/password.html b/src/main/webapp/views/password.html
index 4963a89..452fa08 100644
--- a/src/main/webapp/views/password.html
+++ b/src/main/webapp/views/password.html
@@ -96,7 +96,7 @@
 </body>
 <script type="text/javascript" src="../static/js/jquery/jquery-3.3.1.min.js"></script>
 <script type="text/javascript" src="../static/js/tools/md5.js"></script>
-<script type="text/javascript" src="../static/js/common.js?v=20260309_i18n_fix1"></script>
+<script type="text/javascript" src="../static/js/common.js"></script>
 <script type="text/javascript" src="../static/vue/js/vue.min.js"></script>
 <script type="text/javascript" src="../static/vue/element/element.js"></script>
 <script type="text/javascript" src="../static/js/password/password.js?v=20260310_password_vue"></script>
diff --git a/src/main/webapp/views/role/role_power_detail.html b/src/main/webapp/views/role/role_power_detail.html
index 4347fcc..2395a2a 100644
--- a/src/main/webapp/views/role/role_power_detail.html
+++ b/src/main/webapp/views/role/role_power_detail.html
@@ -31,6 +31,6 @@
 </body>
 <script type="text/javascript" src="../../static/js/jquery/jquery-3.3.1.min.js"></script>
 <script type="text/javascript" src="../../static/layui/layui.js" charset="utf-8"></script>
-<script type="text/javascript" src="../../static/js/common.js?v=20260309_i18n_fix1"></script>
+<script type="text/javascript" src="../../static/js/common.js"></script>
 <script type="text/javascript" src="../../static/js/role/rolePower.js" charset="utf-8"></script>
 </html>
diff --git a/src/main/webapp/views/watch/console.html b/src/main/webapp/views/watch/console.html
index 63210b0..ddf1b39 100644
--- a/src/main/webapp/views/watch/console.html
+++ b/src/main/webapp/views/watch/console.html
@@ -508,7 +508,7 @@
 				</style>
 				<script type="text/javascript" src="../../static/js/jquery/jquery-3.3.1.min.js"></script>
 				<script type="text/javascript" src="../../static/js/handlebars/handlebars-v4.5.3.js"></script>
-			<script type="text/javascript" src="../../static/js/common.js?v=20260309_i18n_fix1"></script>
+			<script type="text/javascript" src="../../static/js/common.js"></script>
 			<script type="text/javascript" src="../../static/vue/js/vue.min.js"></script>
 			<script type="text/javascript" src="../../static/vue/element/element.js"></script>
 			<script src="../../static/js/gsap.min.js"></script>
diff --git a/src/main/webapp/views/watch/console_html.html b/src/main/webapp/views/watch/console_html.html
index 4499c09..37f7242 100644
--- a/src/main/webapp/views/watch/console_html.html
+++ b/src/main/webapp/views/watch/console_html.html
@@ -9,7 +9,7 @@
 		<script type="text/javascript" src="../../static/js/jquery/jquery-3.3.1.min.js"></script>
 		<script type="text/javascript" src="../../static/layui/layui.js"></script>
 		<script type="text/javascript" src="../../static/js/handlebars/handlebars-v4.5.3.js"></script>
-		<script type="text/javascript" src="../../static/js/common.js?v=20260309_i18n_fix1"></script>
+		<script type="text/javascript" src="../../static/js/common.js"></script>
 		<script type="text/javascript" src="../../static/vue/js/vue.min.js"></script>
 		<script type="text/javascript" src="../../static/vue/element/element.js"></script>
 	</head>
diff --git a/src/main/webapp/views/watch/console_pixijs.html b/src/main/webapp/views/watch/console_pixijs.html
index e4b7e49..9c7b52f 100644
--- a/src/main/webapp/views/watch/console_pixijs.html
+++ b/src/main/webapp/views/watch/console_pixijs.html
@@ -11,7 +11,7 @@
   <script type="text/javascript" src="../../static/js/jquery/jquery-3.3.1.min.js"></script>
   <script type="text/javascript" src="../../static/layui/layui.js"></script>
   <script type="text/javascript" src="../../static/js/handlebars/handlebars-v4.5.3.js"></script>
-  <script type="text/javascript" src="../../static/js/common.js?v=20260309_i18n_fix1"></script>
+  <script type="text/javascript" src="../../static/js/common.js"></script>
   <script type="text/javascript" src="../../static/vue/js/vue.min.js"></script>
   <script type="text/javascript" src="../../static/vue/element/element.js"></script>
   <script src="../../static/js/gsap.min.js"></script>
diff --git a/src/main/webapp/views/watch/stationColorConfig.html b/src/main/webapp/views/watch/stationColorConfig.html
index 7ab5755..ae24781 100644
--- a/src/main/webapp/views/watch/stationColorConfig.html
+++ b/src/main/webapp/views/watch/stationColorConfig.html
@@ -284,7 +284,7 @@
 <script type="text/javascript" src="../../static/js/jquery/jquery-3.3.1.min.js"></script>
 <script type="text/javascript" src="../../static/vue/js/vue.min.js"></script>
 <script type="text/javascript" src="../../static/vue/element/element.js"></script>
-<script type="text/javascript" src="../../static/js/common.js?v=20260309_i18n_fix1" charset="utf-8"></script>
+<script type="text/javascript" src="../../static/js/common.js" charset="utf-8"></script>
 <script type="text/javascript" src="../../static/js/watch/stationColorConfig.js" charset="utf-8"></script>
 </body>
 </html>
diff --git a/src/main/webapp/views/wrkMast/wrkMast.html b/src/main/webapp/views/wrkMast/wrkMast.html
index 390505e..dcd8808 100644
--- a/src/main/webapp/views/wrkMast/wrkMast.html
+++ b/src/main/webapp/views/wrkMast/wrkMast.html
@@ -1,425 +1,421 @@
 <!DOCTYPE html>
-<html lang="en">
+<html lang="zh-CN">
+<head>
+    <meta charset="UTF-8">
+    <title>浠诲姟绠$悊</title>
+    <meta name="renderer" content="webkit">
+    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
+    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
+    <link rel="stylesheet" href="../../static/vue/element/element.css">
+    <link rel="stylesheet" href="../../static/css/cool.css">
+    <style>
+        :root {
+            --card-bg: rgba(255, 255, 255, 0.94);
+            --card-border: rgba(216, 226, 238, 0.95);
+            --text-main: #243447;
+        }
 
-	<head>
-		<meta charset="UTF-8">
-		<title>浠诲姟绠$悊</title>
-		<link rel="stylesheet" href="../../static/vue/element/element.css">
-		<script type="text/javascript" src="../../static/js/jquery/jquery-3.3.1.min.js"></script>
-		<script type="text/javascript" src="../../static/js/common.js?v=20260309_i18n_fix1"></script>
-		<script type="text/javascript" src="../../static/vue/js/vue.min.js"></script>
-		<script type="text/javascript" src="../../static/vue/element/element.js"></script>
-		<style>
-			[v-cloak] {
-				display: none;
-			}
-			.el-table .success-row {
-				background: #b6ff8e;
-			}
-		</style>
-	</head>
+        [v-cloak] {
+            display: none;
+        }
 
-	<body>
-		<div id="app" v-cloak style="display: flex;justify-content: center;flex-wrap: wrap;">
-			<div style="width: 100%;">
-				<el-card class="box-card">
-					<el-form :inline="true" :model="tableSearchParam" class="demo-form-inline">
-						<el-form-item label="">
-							<el-input v-model="tableSearchParam.wrk_no" placeholder="宸ヤ綔鍙�"></el-input>
-						</el-form-item>
-						<el-form-item label="">
-							<el-input v-model="tableSearchParam.wms_wrk_no" placeholder="WMS宸ヤ綔鍙�"></el-input>
-						</el-form-item>
-						<el-form-item label="">
-							<el-input v-model="tableSearchParam.source_loc_no" placeholder="婧愬簱浣�"></el-input>
-						</el-form-item>
-						<el-form-item label="">
-							<el-input v-model="tableSearchParam.loc_no" placeholder="鐩爣搴撲綅"></el-input>
-						</el-form-item>
-						<el-form-item label="">
-							<el-input v-model="tableSearchParam.crn_no" placeholder="鍫嗗灈鏈�"></el-input>
-						</el-form-item>
-						<el-form-item label="">
-							<el-input v-model="tableSearchParam.dual_crn_no" placeholder="鍙屽伐浣嶅爢鍨涙満"></el-input>
-						</el-form-item>
-						<el-form-item>
-							<el-button type="primary" @click="getTableData">鏌ヨ</el-button>
-							<el-button type="primary" @click="resetParam">閲嶇疆</el-button>
-						</el-form-item>
-					</el-form>
-					<el-table ref="singleTable" :data="tableData" style="width: 100%;">
-						<el-table-column property="wrkNo" label="宸ヤ綔鍙�">
-						</el-table-column>
-						<el-table-column property="wmsWrkNo" label="WMS浠诲姟鍙�">
-						</el-table-column>
-						<el-table-column property="wrkSts$" label="宸ヤ綔鐘舵��">
-						</el-table-column>
-						<el-table-column property="ioType$" label="浠诲姟绫诲瀷">
-						</el-table-column>
-						<el-table-column property="ioPri" label="浼樺厛绾�">
-						</el-table-column>
-						<el-table-column property="sourceStaNo" label="婧愮珯">
-						</el-table-column>
-						<el-table-column property="staNo" label="鐩爣绔�">
-						</el-table-column>
-						<el-table-column property="sourceLocNo" label="婧愬簱浣�">
-						</el-table-column>
-						<el-table-column property="locNo" label="鐩爣搴撲綅">
-						</el-table-column>
-						<el-table-column property="modiTime$" label="鏃堕棿">
-						</el-table-column>
-						<el-table-column property="barcode" label="鎵樼洏鐮�">
-						</el-table-column>
-						<el-table-column property="crnNo" label="鍫嗗灈鏈�">
-						</el-table-column>
-						<el-table-column property="dualCrnNo" label="鍙屽伐浣嶅爢鍨涙満">
-						</el-table-column>
-						<el-table-column property="batch" label="鎵规">
-						</el-table-column>
-						<el-table-column property="batchSeq" label="鎵规搴忓垪">
-						</el-table-column>
-						<el-table-column property="systemMsg" label="绯荤粺娑堟伅">
-						</el-table-column>
-						<el-table-column label="鎿嶄綔" width="100">
-							<template slot-scope="scope">
-								<el-dropdown @command="(command)=>{handleCommand(command, scope.row)}">
-									<el-button icon="el-icon-more" size="mini" type="primary"></el-button>
-									<el-dropdown-menu slot="dropdown">
-<!--										<el-dropdown-item command="change">淇敼</el-dropdown-item>-->
-										<el-dropdown-item command="complete">瀹屾垚</el-dropdown-item>
-										<el-dropdown-item command="cancel">鍙栨秷</el-dropdown-item>
-<!--										<el-dropdown-item command="shuttleCommand">绌挎杞︽寚浠�</el-dropdown-item>-->
-									</el-dropdown-menu>
-								</el-dropdown>
-							</template>
-						</el-table-column>
-					</el-table>
+        html,
+        body {
+            margin: 0;
+            min-height: 100%;
+            color: var(--text-main);
+            font-family: "Avenir Next", "PingFang SC", "Microsoft YaHei", sans-serif;
+            background:
+                radial-gradient(1000px 420px at 0% -10%, rgba(44, 107, 193, 0.12), transparent 56%),
+                radial-gradient(900px 400px at 100% 0%, rgba(28, 150, 126, 0.10), transparent 58%),
+                linear-gradient(180deg, #f2f6fb 0%, #f8fafc 100%);
+        }
 
-					<div style="margin-top: 10px;">
-						<el-pagination @size-change="handleSizeChange" @current-change="handleCurrentChange"
-							:current-page="currentPage" :page-sizes="pageSizes" :page-size="pageSize"
-							layout="total, sizes, prev, pager, next, jumper" :total="pageTotal">
-						</el-pagination>
-					</div>
-				</el-card>
-			</div>
+        .page-shell {
+            max-width: 1800px;
+            margin: 0 auto;
+            padding: 14px;
+            box-sizing: border-box;
+        }
 
-			<el-dialog :title="shuttleCommandTitle" :visible.sync="shuttleCommandVisible">
-				<el-table ref="singleTable" :data="shuttleCommandData.commands" style="width: 100%;" :row-class-name="tableRowClassName">
-					<el-table-column property="mode$" label="鍛戒护绫诲瀷">
-					</el-table-column>
-					<el-table-column property="start" label="璧风偣">
-						<template slot-scope="scope">
-							<div v-if="scope.row.nodes">
-								x:{{ scope.row.nodes[0].x }}
-								y:{{ scope.row.nodes[0].y }}
-								z:{{ scope.row.nodes[0].z }}
-							</div>
-						</template>
-					</el-table-column>
-					<el-table-column property="target" label="缁堢偣">
-						<template slot-scope="scope">
-							<div v-if="scope.row.nodes">
-								x:{{ scope.row.nodes[scope.row.nodes.length-1].x }}
-								y:{{ scope.row.nodes[scope.row.nodes.length-1].y }}
-								z:{{ scope.row.nodes[scope.row.nodes.length-1].z }}
-							</div>
-						</template>
-					</el-table-column>
-					<el-table-column property="taskNo" label="浠诲姟鍙�">
-					</el-table-column>
-					<el-table-column property="shuttleNo" label="绌挎杞�">
-					</el-table-column>
-					<el-table-column property="complete" label="鏄惁瀹屾垚">
-						<template slot-scope="scope">
-							<el-switch
-									v-model="scope.row.complete"
-									active-color="#13ce66"
-									@change="changeComplete(scope)">
-							</el-switch>
-						</template>
-					</el-table-column>
-					<el-table-column label="鎿嶄綔" width="100">
-						<template slot-scope="scope">
-							<el-button @click="shuttleCommandRollback(scope)" size="mini">鍥為��鎸囦护</el-button>
-						</template>
-					</el-table-column>
-				</el-table>
-				<div slot="footer" class="dialog-footer">
-					<el-button @click="shuttleCommandVisible = false">鍏抽棴</el-button>
-				</div>
-			</el-dialog>
+        .card-shell {
+            position: relative;
+            border-radius: 24px;
+            border: 1px solid var(--card-border);
+            background:
+                radial-gradient(760px 220px at -8% 0%, rgba(43, 117, 196, 0.05), transparent 55%),
+                radial-gradient(680px 200px at 108% 10%, rgba(24, 150, 129, 0.05), transparent 58%),
+                var(--card-bg);
+            box-shadow: 0 16px 32px rgba(44, 67, 96, 0.08);
+            overflow: hidden;
+        }
 
-		</div>
-		<script>
-			var app = new Vue({
-				el: '#app',
-				data: {
-					tableData: [],
-					currentPage: 1,
-					pageSizes: [16, 30, 50, 100, 150, 200],
-					pageSize: 30,
-					pageTotal: 0,
-					tableSearchParam: {
-						wrk_no: null,
-						wms_wrk_no: null,
-					},
-					shuttleCommandVisible: false,
-					shuttleCommandData: {
-						assignCommand: {
-							commands: []
-						},
-						commandStep: 0
-					},
-					shuttleCommandWrkNo: null,
-					shuttleCommandLabelWidth: '80px',
-					shuttleCommandTitle: ''
-				},
-				created() {
-					this.init()
-				},
-				methods: {
-					init() {
-						this.getTableData()
-					},
-					getTableData() {
-						let that = this;
-						let data = JSON.parse(JSON.stringify(this.tableSearchParam))
-						data.curr = this.currentPage
-						data.limit = this.pageSize
-						if (this.tableSearchParam.datetime != null) {
-							data.datetime = null
-							data.create_time = this.tableSearchParam.datetime[0] + " - " + this.tableSearchParam.datetime[1]
-						}
-						$.ajax({
-							url: baseUrl + "/wrkMast/list/auth",
-							headers: {
-								'token': localStorage.getItem('token')
-							},
-							data: data,
-							dataType: 'json',
-							contentType: 'application/json;charset=UTF-8',
-							method: 'GET',
-							success: function(res) {
-								if (res.code == 200) {
-									that.tableData = res.data.records
-									that.pageTotal = res.data.total
-								} else if (res.code === 403) {
-									top.location.href = baseUrl + "/";
-								} else {
-									that.$message({
-										message: res.msg,
-										type: 'error'
-									});
-								}
-							}
-						});
-					},
-					handleSizeChange(val) {
-						console.log(`姣忛〉 ${val} 鏉);
-						this.pageSize = val
-						this.getTableData()
-					},
-					handleCurrentChange(val) {
-						console.log(`褰撳墠椤�: ${val}`);
-						this.currentPage = val
-						this.getTableData()
-					},
-					resetParam() {
-						this.tableSearchParam = {
-							task_no: null,
-							status: null,
-							wrk_no: null
-						}
-						this.getTableData()
-					},
-					handleCommand(command, row) {
-						switch (command) {
-							case "complete":
-								this.completeTask(row)
-								break;
-							case "cancel":
-								this.cancelTask(row)
-								break;
-							case "shuttleCommand":
-								this.showShuttleCommand(row.wrkNo)
-								break;
-						}
-					},
-					showShuttleCommand(wrkNo){
-						let that = this;
-						$.ajax({
-							url: baseUrl + "/shuttle/command/query",
-							headers: {
-								'token': localStorage.getItem('token')
-							},
-							data: {
-								wrkNo: wrkNo
-							},
-							method: 'GET',
-							success: function(res) {
-								if (res.code == 200) {
-									console.log(res)
-									that.shuttleCommandVisible = true;
-									that.shuttleCommandData = res.data;
-									that.shuttleCommandWrkNo = wrkNo;
-								} else if (res.code === 403) {
-									top.location.href = baseUrl + "/";
-								} else {
-									that.$message({
-										message: res.msg,
-										type: 'error'
-									});
-								}
-							}
-						});
-					},
-					completeTask(row) {
-						let that = this
-						this.$confirm('纭畾瀹屾垚璇ヤ换鍔″悧锛�', '鎻愮ず', {
-							confirmButtonText: '纭畾',
-							cancelButtonText: '鍙栨秷',
-							type: 'warning'
-						}).then(() => {
-							$.ajax({
-								url: baseUrl + "/openapi/completeTask",
-								contentType: 'application/json',
-								headers: {
-									'token': localStorage.getItem('token')
-								},
-								data: JSON.stringify({
-									wrkNo: row.wrkNo,
-								}),
-								method: 'POST',
-								success: function(res) {
-									if (res.code == 200) {
-										that.$message({
-											message: "瀹屾垚鎴愬姛",
-											type: 'success'
-										});
-										that.getTableData()
-									} else if (res.code === 403) {
-										top.location.href = baseUrl + "/";
-									} else {
-										that.$message({
-											message: res.msg,
-											type: 'error'
-										});
-									}
-								}
-							});
-						}).catch(() => {
-							// this.$message({
-							// 	type: 'info',
-							// 	message: '宸插彇娑堝垹闄�'
-							// });
-						});
-					},
-					cancelTask(row) {
-						let that = this
-						this.$confirm('纭畾鍙栨秷璇ヤ换鍔″悧锛�', '鎻愮ず', {
-							confirmButtonText: '纭畾',
-							cancelButtonText: '鍙栨秷',
-							type: 'warning'
-						}).then(() => {
-							$.ajax({
-								url: baseUrl + "/openapi/cancelTask",
-								contentType: 'application/json',
-								headers: {
-									'token': localStorage.getItem('token')
-								},
-								data: JSON.stringify({
-									wrkNo: row.wrkNo,
-								}),
-								method: 'POST',
-								success: function(res) {
-									if (res.code == 200) {
-										that.$message({
-											message: "鍙栨秷鎴愬姛",
-											type: 'success'
-										});
-										that.getTableData()
-									} else if (res.code === 403) {
-										top.location.href = baseUrl + "/";
-									} else {
-										that.$message({
-											message: res.msg,
-											type: 'error'
-										});
-									}
-								}
-							});
-						}).catch(() => {
-							// this.$message({
-							// 	type: 'info',
-							// 	message: '宸插彇娑堝垹闄�'
-							// });
-						});
-					},
-					tableRowClassName({row, rowIndex}) {
-						if (rowIndex === this.shuttleCommandData.commandStep) {
-							return 'success-row';
-						}
-						return '';
-					},
-					shuttleCommandRollback(scope) {
-						let that = this;
-						let idx = scope.$index;
-						$.ajax({
-							url: baseUrl + "/shuttle/command/rollback",
-							headers: {
-								'token': localStorage.getItem('token')
-							},
-							data: {
-								wrkNo: that.shuttleCommandWrkNo,
-								commandStep: idx
-							},
-							method: 'GET',
-							success: function(res) {
-								if (res.code == 200) {
-									that.showShuttleCommand(that.shuttleCommandWrkNo)
-								} else if (res.code === 403) {
-									top.location.href = baseUrl + "/";
-								} else {
-									that.$message({
-										message: res.msg,
-										type: 'error'
-									});
-								}
-							}
-						});
-					},
-					changeComplete(scope) {
-						let that = this;
-						let idx = scope.$index;
-						$.ajax({
-							url: baseUrl + "/shuttle/command/completeSwitch",
-							headers: {
-								'token': localStorage.getItem('token')
-							},
-							data: {
-								wrkNo: that.shuttleCommandWrkNo,
-								commandStep: idx,
-								complete: scope.row.complete ? 1 : 0
-							},
-							method: 'GET',
-							success: function(res) {
-								if (res.code == 200) {
-									that.showShuttleCommand(that.shuttleCommandWrkNo)
-								} else if (res.code === 403) {
-									top.location.href = baseUrl + "/";
-								} else {
-									that.$message({
-										message: res.msg,
-										type: 'error'
-									});
-								}
-							}
-						});
-					}
-				},
-			})
-		</script>
-	</body>
+        .list-toolbar {
+            padding: 12px 16px 10px;
+            border-bottom: 1px solid rgba(222, 230, 239, 0.92);
+        }
 
+        .toolbar-main {
+            display: flex;
+            align-items: flex-start;
+            justify-content: space-between;
+            gap: 8px;
+            flex-wrap: wrap;
+        }
+
+        .toolbar-left {
+            flex: 1 1 980px;
+            display: flex;
+            align-items: center;
+            gap: 8px;
+            flex-wrap: wrap;
+        }
+
+        .toolbar-search {
+            flex: 1 1 auto;
+            display: flex;
+            align-items: center;
+            gap: 8px;
+            flex-wrap: wrap;
+        }
+
+        .toolbar-search-item {
+            flex: 0 0 148px;
+            min-width: 148px;
+        }
+
+        .toolbar-search-item.keyword {
+            flex: 0 0 220px;
+            min-width: 220px;
+        }
+
+        .toolbar-query-actions,
+        .toolbar-ops {
+            display: flex;
+            gap: 8px;
+            flex-wrap: wrap;
+        }
+
+        .toolbar-ops {
+            justify-content: flex-end;
+        }
+
+        .list-toolbar .el-input__inner,
+        .advanced-panel .el-input__inner {
+            height: 32px;
+            line-height: 32px;
+        }
+
+        .list-toolbar .el-input__icon,
+        .advanced-panel .el-input__icon {
+            line-height: 32px;
+        }
+
+        .list-toolbar .el-button,
+        .advanced-panel .el-button {
+            padding: 8px 12px;
+            border-radius: 8px;
+        }
+
+        .advanced-panel {
+            padding: 10px 16px 12px;
+            border-bottom: 1px solid rgba(222, 230, 239, 0.92);
+            background: rgba(248, 251, 254, 0.78);
+        }
+
+        .advanced-grid {
+            display: grid;
+            grid-template-columns: repeat(4, minmax(0, 1fr));
+            gap: 8px;
+        }
+
+        .advanced-item {
+            min-width: 0;
+        }
+
+        .table-wrap {
+            padding: 10px 16px;
+        }
+
+        .table-shell {
+            border-radius: 20px;
+            overflow: hidden;
+            border: 1px solid rgba(217, 227, 238, 0.98);
+            background: rgba(255, 255, 255, 0.95);
+        }
+
+        .table-shell .el-table {
+            border-radius: 20px;
+            overflow: hidden;
+        }
+
+        .table-shell .el-table th {
+            background: #f7fafc;
+            color: #53677d;
+            font-weight: 700;
+        }
+
+        .table-shell .el-table .success-row > td {
+            background: rgba(101, 198, 141, 0.14);
+        }
+
+        .payload-cell {
+            display: inline-block;
+            max-width: 280px;
+            white-space: nowrap;
+            overflow: hidden;
+            text-overflow: ellipsis;
+        }
+
+        .pager-bar {
+            padding: 0 16px 16px;
+            display: flex;
+            align-items: center;
+            justify-content: flex-end;
+        }
+
+        .column-popover {
+            max-width: 320px;
+        }
+
+        .column-popover-head {
+            display: flex;
+            align-items: center;
+            justify-content: space-between;
+            gap: 12px;
+            margin-bottom: 10px;
+            font-size: 13px;
+            font-weight: 700;
+            color: var(--text-main);
+        }
+
+        .column-list {
+            display: grid;
+            grid-template-columns: repeat(2, minmax(0, 1fr));
+            gap: 8px 10px;
+            max-height: 280px;
+            overflow: auto;
+            padding-right: 4px;
+        }
+
+        .row-action-trigger {
+            min-width: 72px;
+            display: inline-flex;
+            align-items: center;
+            justify-content: center;
+        }
+
+        @media (max-width: 1600px) {
+            .advanced-grid {
+                grid-template-columns: repeat(3, minmax(0, 1fr));
+            }
+        }
+
+        @media (max-width: 1280px) {
+            .advanced-grid {
+                grid-template-columns: repeat(2, minmax(0, 1fr));
+            }
+        }
+
+        @media (max-width: 900px) {
+            .page-shell {
+                padding: 10px;
+            }
+
+            .list-toolbar,
+            .advanced-panel,
+            .table-wrap,
+            .pager-bar {
+                padding-left: 12px;
+                padding-right: 12px;
+            }
+
+            .toolbar-search-item,
+            .toolbar-search-item.keyword {
+                flex: 1 1 100%;
+                min-width: 100%;
+            }
+
+            .advanced-grid {
+                grid-template-columns: 1fr;
+            }
+        }
+    </style>
+</head>
+<body>
+<div id="app" class="page-shell" v-cloak>
+    <section class="card-shell">
+        <div class="list-toolbar">
+            <div class="toolbar-main">
+                <div class="toolbar-left">
+                    <div class="toolbar-search">
+                        <div class="toolbar-search-item keyword">
+                            <el-input
+                                v-model.trim="searchForm.condition"
+                                clearable
+                                size="small"
+                                placeholder="璇疯緭鍏ュ叧閿瓧"
+                                @keyup.enter.native="handleSearch">
+                            </el-input>
+                        </div>
+                        <div class="toolbar-search-item">
+                            <el-input
+                                v-model.trim="searchForm.wrk_no"
+                                clearable
+                                size="small"
+                                placeholder="宸ヤ綔鍙�"
+                                @keyup.enter.native="handleSearch">
+                            </el-input>
+                        </div>
+                        <div class="toolbar-search-item">
+                            <el-input
+                                v-model.trim="searchForm.wms_wrk_no"
+                                clearable
+                                size="small"
+                                placeholder="WMS浠诲姟鍙�"
+                                @keyup.enter.native="handleSearch">
+                            </el-input>
+                        </div>
+                        <div class="toolbar-search-item">
+                            <el-input
+                                v-model.trim="searchForm.loc_no"
+                                clearable
+                                size="small"
+                                placeholder="鐩爣搴撲綅"
+                                @keyup.enter.native="handleSearch">
+                            </el-input>
+                        </div>
+                        <div class="toolbar-query-actions">
+                            <el-button size="small" type="primary" icon="el-icon-search" @click="handleSearch">鎼滅储</el-button>
+                            <el-button size="small" plain icon="el-icon-refresh-left" @click="handleReset">閲嶇疆</el-button>
+                            <el-button size="small" plain :icon="advancedVisible ? 'el-icon-arrow-up' : 'el-icon-arrow-down'" @click="toggleAdvanced">
+                                {{ advancedVisible ? '鏀惰捣' : '绛涢��' }}
+                            </el-button>
+                        </div>
+                    </div>
+                </div>
+                <div class="toolbar-ops">
+                    <el-popover
+                        v-model="columnPopoverVisible"
+                        placement="bottom-end"
+                        width="320"
+                        trigger="click"
+                        popper-class="column-popover">
+                        <div class="column-popover-head">
+                            <span>鍒楄缃�</span>
+                            <div>
+                                <el-button type="text" size="mini" @click="showAllColumns">鍏ㄩ��</el-button>
+                                <el-button type="text" size="mini" @click="resetColumns">閲嶇疆</el-button>
+                            </div>
+                        </div>
+                        <div class="column-list">
+                            <el-checkbox
+                                v-for="column in columnDefs"
+                                :key="'column-' + column.key"
+                                :value="isColumnVisible(column.key)"
+                                @change="toggleColumn(column.key, $event)">
+                                {{ column.label }}
+                            </el-checkbox>
+                        </div>
+                        <el-button slot="reference" size="small" plain icon="el-icon-setting">鍒楄缃�</el-button>
+                    </el-popover>
+                    <el-button size="small" plain icon="el-icon-refresh" :loading="loading" @click="loadList">鍒锋柊</el-button>
+                </div>
+            </div>
+        </div>
+
+        <div v-show="advancedVisible" class="advanced-panel">
+            <div class="advanced-grid">
+                <div class="advanced-item">
+                    <el-input
+                        v-model.trim="searchForm.source_loc_no"
+                        clearable
+                        size="small"
+                        placeholder="婧愬簱浣�"
+                        @keyup.enter.native="handleSearch">
+                    </el-input>
+                </div>
+                <div class="advanced-item">
+                    <el-input
+                        v-model.trim="searchForm.crn_no"
+                        clearable
+                        size="small"
+                        placeholder="鍫嗗灈鏈�"
+                        @keyup.enter.native="handleSearch">
+                    </el-input>
+                </div>
+                <div class="advanced-item">
+                    <el-input
+                        v-model.trim="searchForm.dual_crn_no"
+                        clearable
+                        size="small"
+                        placeholder="鍙屽伐浣嶅爢鍨涙満"
+                        @keyup.enter.native="handleSearch">
+                    </el-input>
+                </div>
+            </div>
+        </div>
+
+        <div class="table-wrap">
+            <div class="table-shell">
+                <el-table
+                    ref="dataTable"
+                    :key="tableRenderKey"
+                    v-loading="loading"
+                    :data="tableData"
+                    border
+                    stripe
+                    :height="tableHeight"
+                    @sort-change="handleSortChange">
+                    <el-table-column
+                        v-for="column in visibleColumns"
+                        :key="column.key"
+                        :prop="column.prop"
+                        :label="column.label"
+                        :width="column.width"
+                        :min-width="column.minWidth"
+                        :sortable="column.sortable ? 'custom' : false"
+                        :show-overflow-tooltip="column.showOverflow !== false"
+                        :align="column.align || 'left'">
+                        <template v-if="column.key === 'systemMsg'" slot-scope="scope">
+                            <span class="payload-cell">{{ scope.row.systemMsg || '--' }}</span>
+                        </template>
+                    </el-table-column>
+                    <el-table-column label="鎿嶄綔" fixed="right" width="100" align="center">
+                        <template slot-scope="scope">
+                            <el-dropdown trigger="click" @command="handleRowCommand($event, scope.row)">
+                                <el-button size="mini" plain class="row-action-trigger">
+                                    鎿嶄綔<i class="el-icon-arrow-down el-icon--right"></i>
+                                </el-button>
+                                <el-dropdown-menu slot="dropdown">
+                                    <el-dropdown-item command="complete">瀹屾垚浠诲姟</el-dropdown-item>
+                                    <el-dropdown-item command="cancel" divided>鍙栨秷浠诲姟</el-dropdown-item>
+                                </el-dropdown-menu>
+                            </el-dropdown>
+                        </template>
+                    </el-table-column>
+                </el-table>
+            </div>
+        </div>
+
+        <div class="pager-bar">
+            <el-pagination
+                background
+                :current-page="currentPage"
+                :page-size="pageSize"
+                :page-sizes="pageSizes"
+                layout="total, sizes, prev, pager, next, jumper"
+                :total="pageTotal"
+                @size-change="handleSizeChange"
+                @current-change="handleCurrentChange">
+            </el-pagination>
+        </div>
+    </section>
+</div>
+</body>
+<script type="text/javascript" src="../../static/js/jquery/jquery-3.3.1.min.js"></script>
+<script type="text/javascript" src="../../static/js/common.js?v=20260309_i18n_fix1"></script>
+<script type="text/javascript" src="../../static/vue/js/vue.min.js"></script>
+<script type="text/javascript" src="../../static/vue/element/element.js"></script>
+<script type="text/javascript" src="../../static/js/wrkMast/wrkMast.js?v=20260311_wrk_mast_vue"></script>
 </html>

--
Gitblit v1.9.1