feat(web,installer): 更新下载源、升级资源缓存版本、本地化界面并新增管理功能
- 更新 update_machine.lua 和 installer.lua 中的远程资源下载地址,从旧云存储链接切换为 Gitea 仓库提交镜像地址 - 新增双向闸机专用安装脚本 installer_bi.lua - 为所有网页HTML文件更新静态资源的缓存版本号,避免浏览器加载过期的静态文件缓存 - 修复登录页面的乱码文本,替换为标准简体中文内容,修正ICP备案标识文本 - 新增管理后台概览板块、快捷操作按钮,优化IC卡管理界面与响应式布局样式
This commit is contained in:
@@ -0,0 +1,164 @@
|
||||
local URL_ERROR = "http://cloud.fse-media.group/d/API/TicketMachine/error.dfpwm?sign=DvQ39wQDN6Cej4KPhAkM3JyXPM466koan6w9CckPxWU=:0"
|
||||
local URL_PASS = "http://cloud.fse-media.group/d/API/TicketMachine/pass.dfpwm?sign=ZJfGDYnaxQU4JrGSh4NDzKZtjq3eMjYh9KHmMSAMKZA=:0"
|
||||
local URL_GATE = "http://cloud.fse-media.group/d/API/TicketMachine/gate.lua?sign=OWy1wKkKhUhpnxXKeX6fRLePSg1XcaQgWOLvQbMuHRQ=:0"
|
||||
|
||||
local CONFIG_PATH = "gate_config.json"
|
||||
|
||||
local function trim(s)
|
||||
return (tostring(s or ""):gsub("^%s+", ""):gsub("%s+$", ""))
|
||||
end
|
||||
|
||||
local function splitCsv(s)
|
||||
local out = {}
|
||||
s = trim(s)
|
||||
if #s == 0 then return out end
|
||||
for part in s:gmatch("[^,/%s]+") do
|
||||
local v = trim(part)
|
||||
if #v > 0 then table.insert(out, v) end
|
||||
end
|
||||
return out
|
||||
end
|
||||
|
||||
local function writeFile(path, content, binary)
|
||||
local mode = binary and "wb" or "w"
|
||||
local f = fs.open(path, mode)
|
||||
if not f then return false end
|
||||
f.write(content)
|
||||
f.close()
|
||||
return true
|
||||
end
|
||||
|
||||
local function prompt(label)
|
||||
term.write(label)
|
||||
return trim(read() or "")
|
||||
end
|
||||
|
||||
local function promptOptionalUrl(label)
|
||||
local raw = prompt(label)
|
||||
raw = trim(raw)
|
||||
if #raw == 0 then return nil end
|
||||
return raw
|
||||
end
|
||||
|
||||
local function httpGet(url)
|
||||
if not http then return false, "HTTP API disabled" end
|
||||
local okReq, err = pcall(function()
|
||||
http.request({ url = url, method = "GET" })
|
||||
end)
|
||||
if not okReq then return false, tostring(err) end
|
||||
|
||||
while true do
|
||||
local ev, p1, p2, p3 = os.pullEvent()
|
||||
if ev == "http_success" and p1 == url then
|
||||
local res = p2
|
||||
if type(res) == "table" and type(res.readAll) == "function" then
|
||||
local data = res.readAll()
|
||||
res.close()
|
||||
return true, data
|
||||
end
|
||||
return false, "invalid http response"
|
||||
end
|
||||
if ev == "http_failure" and p1 == url then
|
||||
local err = p2
|
||||
local res = p3
|
||||
if type(p2) == "table" and type(p2.readAll) == "function" then
|
||||
res = p2
|
||||
err = p3
|
||||
end
|
||||
if type(res) == "table" and type(res.readAll) == "function" then
|
||||
local data = res.readAll()
|
||||
res.close()
|
||||
return false, data
|
||||
end
|
||||
return false, tostring(err or "http_failure")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function download(url, path, binary)
|
||||
print("Downloading: " .. path)
|
||||
local ok, data = httpGet(url)
|
||||
if not ok then
|
||||
print("Download failed: " .. tostring(data or ""))
|
||||
return false
|
||||
end
|
||||
if not writeFile(path, data, binary) then
|
||||
print("Write failed: " .. path)
|
||||
return false
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
local function normalizeMode(raw)
|
||||
return (trim(raw):lower() == "exit") and "exit" or "entry"
|
||||
end
|
||||
|
||||
term.clear()
|
||||
term.setCursorPos(1, 1)
|
||||
print("Bidirectional Ticket Gate Installer")
|
||||
print("")
|
||||
|
||||
local stationsRaw = prompt("Station codes (comma or slash): ")
|
||||
local stationCodes = splitCsv(stationsRaw)
|
||||
if #stationCodes == 0 then
|
||||
print("No station codes provided.")
|
||||
return
|
||||
end
|
||||
|
||||
print("")
|
||||
print("Set mode for each side (front/back).")
|
||||
local frontRaw = prompt("Front mode (entry/exit): ")
|
||||
local backRaw = prompt("Back mode (entry/exit): ")
|
||||
local frontMode = normalizeMode(frontRaw)
|
||||
local backMode = normalizeMode(backRaw)
|
||||
local frontStationCode = trim(prompt("Front station code (default first code): "))
|
||||
local backStationCode = trim(prompt("Back station code (default first code): "))
|
||||
if #frontStationCode == 0 then frontStationCode = stationCodes[1] end
|
||||
if #backStationCode == 0 then backStationCode = stationCodes[1] end
|
||||
|
||||
print("")
|
||||
print("Optional server config for ticket / IC card checks.")
|
||||
local ticketServerUrl = promptOptionalUrl("Ticket check URL (blank=auto): ")
|
||||
local cardServerUrl = promptOptionalUrl("IC card check URL (blank=same server): ")
|
||||
|
||||
local cfg = {
|
||||
station_codes = stationCodes,
|
||||
station_code = stationCodes[1],
|
||||
side_modes = {
|
||||
front = frontMode,
|
||||
back = backMode,
|
||||
},
|
||||
side_station_codes = {
|
||||
front = frontStationCode,
|
||||
back = backStationCode,
|
||||
}
|
||||
}
|
||||
if ticketServerUrl then cfg.server_url = ticketServerUrl end
|
||||
if cardServerUrl then cfg.card_server_url = cardServerUrl end
|
||||
local okCfg, cfgJson = pcall(textutils.serializeJSON, cfg)
|
||||
if not okCfg then
|
||||
print("Config serialize failed.")
|
||||
return
|
||||
end
|
||||
if not writeFile(CONFIG_PATH, cfgJson, false) then
|
||||
print("Failed to write config.")
|
||||
return
|
||||
end
|
||||
|
||||
if not download(URL_PASS, "pass.dfpwm", true) then return end
|
||||
if not download(URL_ERROR, "error.dfpwm", true) then return end
|
||||
|
||||
local okGate, gateCode = httpGet(URL_GATE)
|
||||
if not okGate then
|
||||
print("Download failed: startup")
|
||||
return
|
||||
end
|
||||
|
||||
writeFile("startup.lua", gateCode, false)
|
||||
writeFile("startup", gateCode, false)
|
||||
|
||||
print("")
|
||||
print("Done.")
|
||||
print("This gate now supports tickets and IC cards.")
|
||||
print("Attach ticket_inspection_machine on FRONT and BACK.")
|
||||
print("Reboot the computer to start the gate.")
|
||||
Reference in New Issue
Block a user