i18n(feeder): replace all English UI text with Chinese
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
268c5f76af
commit
f8757a757e
|
|
@ -38,7 +38,7 @@
|
|||
</div>
|
||||
<div class="toolbar">
|
||||
<select id="pointSourceSelect"></select>
|
||||
<div class="muted" id="pointSourceNodeCount">Nodes: 0</div>
|
||||
<div class="muted" id="pointSourceNodeCount">节点: 0</div>
|
||||
<button id="browseNodes">加载节点</button>
|
||||
<button class="secondary" id="refreshTree">刷新树</button>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@
|
|||
</div>
|
||||
<div class="toolbar">
|
||||
<select id="pointSourceSelect"></select>
|
||||
<div class="muted" id="pointSourceNodeCount">Nodes: 0</div>
|
||||
<div class="muted" id="pointSourceNodeCount">节点: 0</div>
|
||||
<button id="browseNodes">加载节点</button>
|
||||
<button class="secondary" id="refreshTree">刷新树</button>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -105,8 +105,8 @@ function bindEvents() {
|
|||
dom.closeEquipmentModalBtn.addEventListener("click", closeEquipmentModal);
|
||||
dom.openPointModalBtn.addEventListener("click", openPointCreateModal);
|
||||
dom.pointSourceSelect.addEventListener("change", () => {
|
||||
dom.nodeTree.innerHTML = '<div class="muted">Click "Load Nodes" to fetch node tree</div>';
|
||||
dom.pointSourceNodeCount.textContent = "Nodes: 0";
|
||||
dom.nodeTree.innerHTML = '<div class="muted">点击"加载节点"获取节点树</div>';
|
||||
dom.pointSourceNodeCount.textContent = "节点: 0";
|
||||
});
|
||||
dom.browseNodesBtn.addEventListener("click", () => withStatus(browseAndLoadTree()));
|
||||
dom.refreshTreeBtn.addEventListener("click", () => withStatus(loadTree()));
|
||||
|
|
|
|||
|
|
@ -52,8 +52,8 @@ function formatTimeLabel(timestamp) {
|
|||
|
||||
export async function openChart(pointId, pointName) {
|
||||
state.chartPointId = pointId;
|
||||
state.chartPointName = pointName || "Point";
|
||||
dom.chartTitle.textContent = `${state.chartPointName} Chart`;
|
||||
state.chartPointName = pointName || "点位";
|
||||
dom.chartTitle.textContent = `${state.chartPointName} 趋势图`;
|
||||
|
||||
const items = await apiFetch(`/api/point/${pointId}/history?limit=120`);
|
||||
state.chartData = (items || [])
|
||||
|
|
@ -99,8 +99,8 @@ export function renderChart() {
|
|||
if (!state.chartData.length) {
|
||||
ctx.fillStyle = "#94a3b8";
|
||||
ctx.font = "14px Segoe UI";
|
||||
ctx.fillText("Click a point row to view its chart", 24, 40);
|
||||
dom.chartSummary.textContent = "Click a point row to view its chart";
|
||||
ctx.fillText("点击点位行查看图表", 24, 40);
|
||||
dom.chartSummary.textContent = "点击点位行查看图表";
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -158,9 +158,9 @@ export function renderChart() {
|
|||
ctx.translate(16, padding.top + plotHeight / 2);
|
||||
ctx.rotate(-Math.PI / 2);
|
||||
ctx.fillStyle = "#64748b";
|
||||
ctx.fillText("Value", 0, 0);
|
||||
ctx.fillText("数值", 0, 0);
|
||||
ctx.restore();
|
||||
ctx.fillText("Time", width / 2 - 12, height - 28);
|
||||
ctx.fillText("时间", width / 2 - 12, height - 28);
|
||||
|
||||
ctx.strokeStyle = "#2563eb";
|
||||
ctx.lineWidth = 2;
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@ function renderEquipmentUnitOptions(selected = "", target = dom.equipmentUnitId)
|
|||
}
|
||||
|
||||
export function renderBindingEquipmentOptions(selected = "", target = dom.bindingEquipmentId) {
|
||||
const options = ['<option value="">Unbound</option>'];
|
||||
const options = ['<option value="">未绑定</option>'];
|
||||
filteredEquipments().forEach((item) => {
|
||||
const equipment = equipmentOf(item);
|
||||
const isSelected = equipment.id === selected ? "selected" : "";
|
||||
|
|
@ -112,7 +112,7 @@ export function renderEquipments() {
|
|||
|
||||
const items = filteredEquipments();
|
||||
if (!items.length) {
|
||||
dom.equipmentList.innerHTML = '<div class="list-item"><div class="muted">No equipment</div></div>';
|
||||
dom.equipmentList.innerHTML = '<div class="list-item"><div class="muted">暂无设备</div></div>';
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -126,7 +126,7 @@ export function renderEquipments() {
|
|||
<span class="badge">${item.point_count ?? 0} pts</span>
|
||||
</div>
|
||||
<div>${equipment.name}</div>
|
||||
<div class="muted">${equipment.kind || "No type"}</div>
|
||||
<div class="muted">${equipment.kind || "未分类"}</div>
|
||||
<div class="muted">单元: ${currentUnitLabel(equipment.unit_id)}</div>
|
||||
<div class="row equipment-card-actions"></div>
|
||||
`;
|
||||
|
|
@ -141,7 +141,7 @@ export function renderEquipments() {
|
|||
|
||||
const editBtn = document.createElement("button");
|
||||
editBtn.className = "secondary";
|
||||
editBtn.textContent = "Edit";
|
||||
editBtn.textContent = "编辑";
|
||||
editBtn.addEventListener("click", (event) => {
|
||||
event.stopPropagation();
|
||||
openEditEquipmentModal(equipment);
|
||||
|
|
@ -149,7 +149,7 @@ export function renderEquipments() {
|
|||
|
||||
const deleteBtn = document.createElement("button");
|
||||
deleteBtn.className = "danger";
|
||||
deleteBtn.textContent = "Delete";
|
||||
deleteBtn.textContent = "删除";
|
||||
deleteBtn.addEventListener("click", (event) => {
|
||||
event.stopPropagation();
|
||||
deleteEquipment(equipment.id).catch((error) => {
|
||||
|
|
@ -218,7 +218,7 @@ export async function saveEquipment(event) {
|
|||
}
|
||||
|
||||
export async function deleteEquipment(equipmentId) {
|
||||
if (!window.confirm("Delete this equipment?")) {
|
||||
if (!window.confirm("确认删除该设备?")) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -58,7 +58,7 @@ export function renderOpsUnits() {
|
|||
const startBlocked = !isAutoOn && (runtime?.fault_locked || runtime?.manual_ack_required || runtime?.rem_local);
|
||||
const autoBtn = document.createElement("button");
|
||||
autoBtn.className = isAutoOn ? "danger" : "secondary";
|
||||
autoBtn.textContent = isAutoOn ? "Stop Auto" : "Start Auto";
|
||||
autoBtn.textContent = isAutoOn ? "停止自动" : "启动自动";
|
||||
autoBtn.disabled = startBlocked;
|
||||
autoBtn.title = startBlocked
|
||||
? (runtime?.fault_locked ? "设备故障中,无法启动自动控制"
|
||||
|
|
@ -75,7 +75,7 @@ export function renderOpsUnits() {
|
|||
if (runtime?.manual_ack_required) {
|
||||
const ackBtn = document.createElement("button");
|
||||
ackBtn.className = "danger";
|
||||
ackBtn.textContent = "Ack Fault";
|
||||
ackBtn.textContent = "故障确认";
|
||||
ackBtn.title = "人工确认解除故障锁定";
|
||||
ackBtn.addEventListener("click", (e) => {
|
||||
e.stopPropagation();
|
||||
|
|
@ -153,13 +153,13 @@ function renderOpsEquipments(equipments) {
|
|||
|
||||
const startBtn = document.createElement("button");
|
||||
startBtn.className = "secondary";
|
||||
startBtn.textContent = "Start";
|
||||
startBtn.textContent = "启动";
|
||||
startBtn.addEventListener("click", () =>
|
||||
apiFetch(`/api/control/equipment/${eq.id}/start`, { method: "POST" }).catch(() => {})
|
||||
);
|
||||
const stopBtn = document.createElement("button");
|
||||
stopBtn.className = "danger";
|
||||
stopBtn.textContent = "Stop";
|
||||
stopBtn.textContent = "停止";
|
||||
stopBtn.addEventListener("click", () =>
|
||||
apiFetch(`/api/control/equipment/${eq.id}/stop`, { method: "POST" }).catch(() => {})
|
||||
);
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ import { state } from "./state.js";
|
|||
|
||||
function updatePointSourceNodeCount() {
|
||||
const count = dom.nodeTree.querySelectorAll("details").length;
|
||||
dom.pointSourceNodeCount.textContent = `Nodes: ${count}`;
|
||||
dom.pointSourceNodeCount.textContent = `节点: ${count}`;
|
||||
}
|
||||
|
||||
export function formatValue(monitor) {
|
||||
|
|
@ -28,13 +28,13 @@ export function formatValue(monitor) {
|
|||
}
|
||||
|
||||
export function renderSelectedNodes() {
|
||||
dom.selectedCount.textContent = `Selected ${state.selectedNodeIds.size} nodes`;
|
||||
dom.selectedCount.textContent = `已选中 ${state.selectedNodeIds.size} 个节点`;
|
||||
}
|
||||
|
||||
export function updateSelectedPointSummary() {
|
||||
const count = state.selectedPointIds.size;
|
||||
dom.selectedPointCount.textContent = `Selected ${count} points`;
|
||||
dom.batchBindingSummary.textContent = `Selected ${count} points`;
|
||||
dom.selectedPointCount.textContent = `已选中 ${count} 个点位`;
|
||||
dom.batchBindingSummary.textContent = `已选中 ${count} 个点位`;
|
||||
dom.openBatchBindingBtn.disabled = count === 0;
|
||||
}
|
||||
|
||||
|
|
@ -42,16 +42,16 @@ export function updatePointFilterSummary() {
|
|||
const filters = [];
|
||||
if (state.selectedEquipmentId) {
|
||||
const equipment = state.equipmentMap.get(state.selectedEquipmentId);
|
||||
filters.push(`Equipment:${equipment?.name || equipment?.code || "Unknown"}`);
|
||||
filters.push(`设备:${equipment?.name || equipment?.code || "未知"}`);
|
||||
}
|
||||
if (state.selectedSourceId) {
|
||||
const source = state.sources.find((item) => item.id === state.selectedSourceId);
|
||||
filters.push(`Source:${source?.name || "Unknown"}`);
|
||||
filters.push(`数据源:${source?.name || "未知"}`);
|
||||
}
|
||||
|
||||
dom.pointFilterSummary.textContent = filters.length
|
||||
? `Current filter: ${filters.join(" / ")}`
|
||||
: "Current filter: All points";
|
||||
? `当前筛选: ${filters.join(" / ")}`
|
||||
: "当前筛选: 全部点位";
|
||||
}
|
||||
|
||||
export function clearSelectedPoints() {
|
||||
|
|
@ -102,8 +102,8 @@ export function openPointCreateModal() {
|
|||
if (dom.pointSourceSelect) {
|
||||
dom.pointSourceSelect.value = state.selectedSourceId || "";
|
||||
}
|
||||
dom.nodeTree.innerHTML = '<div class="muted">Select a source and load nodes</div>';
|
||||
dom.pointSourceNodeCount.textContent = "Nodes: 0";
|
||||
dom.nodeTree.innerHTML = '<div class="muted">选择数据源并加载节点</div>';
|
||||
dom.pointSourceNodeCount.textContent = "节点: 0";
|
||||
state.selectedNodeIds.clear();
|
||||
renderSelectedNodes();
|
||||
}
|
||||
|
|
@ -111,8 +111,8 @@ export function openPointCreateModal() {
|
|||
export async function loadTree() {
|
||||
const sourceId = dom.pointSourceSelect.value || state.selectedSourceId;
|
||||
if (!sourceId) {
|
||||
dom.nodeTree.innerHTML = '<div class="muted">Select a source</div>';
|
||||
dom.pointSourceNodeCount.textContent = "Nodes: 0";
|
||||
dom.nodeTree.innerHTML = '<div class="muted">请选择数据源</div>';
|
||||
dom.pointSourceNodeCount.textContent = "节点: 0";
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -126,7 +126,7 @@ export async function loadTree() {
|
|||
export async function browseAndLoadTree() {
|
||||
const sourceId = dom.pointSourceSelect.value || state.selectedSourceId;
|
||||
if (!sourceId) {
|
||||
throw new Error("Select a source first");
|
||||
throw new Error("请先选择数据源");
|
||||
}
|
||||
|
||||
state.selectedSourceId = sourceId;
|
||||
|
|
@ -178,7 +178,7 @@ export async function loadPoints() {
|
|||
dom.pointList.innerHTML = "";
|
||||
|
||||
if (!items.length) {
|
||||
dom.pointList.innerHTML = '<tr><td colspan="7" class="empty-state">No points</td></tr>';
|
||||
dom.pointList.innerHTML = '<tr><td colspan="7" class="empty-state">暂无点位</td></tr>';
|
||||
dom.pointsPageInfo.textContent = `${state.pointsPage} / 1`;
|
||||
clearSelectedPoints();
|
||||
updatePointFilterSummary();
|
||||
|
|
@ -207,7 +207,7 @@ export async function loadPoints() {
|
|||
<td><span class="badge quality-${(monitor?.quality || "unknown").toLowerCase()}">${(monitor?.quality || "unknown").toUpperCase()}</span></td>
|
||||
<td>
|
||||
<div class="point-meta">
|
||||
<div>${equipment ? equipment.name : '<span class="muted">Unbound</span>'}</div>
|
||||
<div>${equipment ? equipment.name : '<span class="muted">未绑定</span>'}</div>
|
||||
<div class="point-role">${point.signal_role || "--"}</div>
|
||||
</div>
|
||||
</td>
|
||||
|
|
@ -228,7 +228,7 @@ export async function loadPoints() {
|
|||
actionCell.className = "point-actions";
|
||||
const editBtn = document.createElement("button");
|
||||
editBtn.className = "secondary";
|
||||
editBtn.textContent = "Edit";
|
||||
editBtn.textContent = "编辑";
|
||||
editBtn.addEventListener("click", (event) => {
|
||||
event.stopPropagation();
|
||||
openPointBinding(point);
|
||||
|
|
@ -236,7 +236,7 @@ export async function loadPoints() {
|
|||
|
||||
const deleteBtn = document.createElement("button");
|
||||
deleteBtn.className = "danger";
|
||||
deleteBtn.textContent = "Delete";
|
||||
deleteBtn.textContent = "删除";
|
||||
deleteBtn.addEventListener("click", (event) => {
|
||||
event.stopPropagation();
|
||||
deletePoint(point.id).catch((error) => {
|
||||
|
|
@ -270,14 +270,14 @@ export function openPointBinding(point) {
|
|||
dom.bindingPointName.disabled = false;
|
||||
const modalTitle = dom.pointBindingModal.querySelector("h3");
|
||||
if (modalTitle) {
|
||||
modalTitle.textContent = "Edit Point";
|
||||
modalTitle.textContent = "编辑点位";
|
||||
}
|
||||
if (dom.clearPointBindingBtn) {
|
||||
dom.clearPointBindingBtn.textContent = "Clear Equipment";
|
||||
dom.clearPointBindingBtn.textContent = "清除设备";
|
||||
}
|
||||
const saveButton = dom.pointBindingForm?.querySelector('button[type="submit"]');
|
||||
if (saveButton) {
|
||||
saveButton.textContent = "Save";
|
||||
saveButton.textContent = "保存";
|
||||
}
|
||||
renderBindingEquipmentOptions(point.equipment_id || "");
|
||||
dom.bindingSignalRole.innerHTML = renderRoleOptions(point.signal_role || "");
|
||||
|
|
@ -353,7 +353,7 @@ export async function clearBatchBinding() {
|
|||
}
|
||||
|
||||
export async function deletePoint(pointId) {
|
||||
if (!window.confirm("Delete this point?")) {
|
||||
if (!window.confirm("确认删除该点位?")) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,17 +1,17 @@
|
|||
export const SIGNAL_ROLE_OPTIONS = [
|
||||
{ value: "", label: "Unset" },
|
||||
{ value: "rem", label: "REM Remote Enable" },
|
||||
{ value: "run", label: "RUN Running" },
|
||||
{ value: "flt", label: "FLT Fault" },
|
||||
{ value: "ii", label: "II Current" },
|
||||
{ value: "start_cmd", label: "Start Command" },
|
||||
{ value: "stop_cmd", label: "Stop Command" },
|
||||
{ value: "", label: "未设置" },
|
||||
{ value: "rem", label: "REM 远程使能" },
|
||||
{ value: "run", label: "RUN 运行" },
|
||||
{ value: "flt", label: "FLT 故障" },
|
||||
{ value: "ii", label: "II 电流" },
|
||||
{ value: "start_cmd", label: "启动命令" },
|
||||
{ value: "stop_cmd", label: "停止命令" },
|
||||
];
|
||||
|
||||
export const EQUIPMENT_KIND_OPTIONS = [
|
||||
{ value: "", label: "Unset" },
|
||||
{ value: "coal_feeder", label: "Coal Feeder" },
|
||||
{ value: "distributor", label: "Distributor" },
|
||||
{ value: "", label: "未设置" },
|
||||
{ value: "coal_feeder", label: "投煤器" },
|
||||
{ value: "distributor", label: "布料机" },
|
||||
];
|
||||
|
||||
export function renderRoleOptions(selected = "") {
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ function renderPointSourceOptions() {
|
|||
return;
|
||||
}
|
||||
|
||||
const options = ['<option value="">Select source</option>'];
|
||||
const options = ['<option value="">选择数据源</option>'];
|
||||
state.sources.forEach((source) => {
|
||||
const selected = source.id === state.selectedSourceId ? "selected" : "";
|
||||
options.push(`<option value="${source.id}" ${selected}>${source.name}</option>`);
|
||||
|
|
@ -41,7 +41,7 @@ export function renderSources() {
|
|||
|
||||
const editBtn = document.createElement("button");
|
||||
editBtn.className = "secondary";
|
||||
editBtn.textContent = "Edit";
|
||||
editBtn.textContent = "编辑";
|
||||
editBtn.addEventListener("click", (event) => {
|
||||
event.stopPropagation();
|
||||
dom.sourceId.value = source.id;
|
||||
|
|
@ -53,7 +53,7 @@ export function renderSources() {
|
|||
|
||||
const reconnectBtn = document.createElement("button");
|
||||
reconnectBtn.className = "secondary";
|
||||
reconnectBtn.textContent = "Reconnect";
|
||||
reconnectBtn.textContent = "重连";
|
||||
reconnectBtn.addEventListener("click", (event) => {
|
||||
event.stopPropagation();
|
||||
reconnectSource(source.id, source.name).catch((error) => {
|
||||
|
|
@ -63,7 +63,7 @@ export function renderSources() {
|
|||
|
||||
const deleteBtn = document.createElement("button");
|
||||
deleteBtn.className = "danger";
|
||||
deleteBtn.textContent = "Delete";
|
||||
deleteBtn.textContent = "删除";
|
||||
deleteBtn.addEventListener("click", (event) => {
|
||||
event.stopPropagation();
|
||||
deleteSource(source.id).catch((error) => {
|
||||
|
|
@ -118,14 +118,14 @@ export async function saveSource(event) {
|
|||
}
|
||||
|
||||
export async function reconnectSource(sourceId, name) {
|
||||
dom.statusText.textContent = `Reconnecting ${name || "Source"}...`;
|
||||
dom.statusText.textContent = `正在重连 ${name || "数据源"}...`;
|
||||
await apiFetch(`/api/source/${sourceId}/reconnect`, { method: "POST" });
|
||||
await loadSources();
|
||||
dom.statusText.textContent = "Ready";
|
||||
dom.statusText.textContent = "就绪";
|
||||
}
|
||||
|
||||
export async function deleteSource(sourceId) {
|
||||
if (!window.confirm("Delete this source?")) {
|
||||
if (!window.confirm("确认删除该数据源?")) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -125,8 +125,8 @@ function buildUnitCard(unit, mode) {
|
|||
<span class="badge ${unit.enabled ? "" : "offline"}">${unit.enabled ? "EN" : "DIS"}</span>
|
||||
</div>
|
||||
<div>${unit.name}</div>
|
||||
<div class="muted">设备 ${bound.length} 台 | Acc ${runtime ? Math.floor(runtime.display_acc_sec / 1000) : 0}s</div>
|
||||
<div class="muted">Run ${unit.run_time_sec}s / Stop ${unit.stop_time_sec}s / Acc ${unit.acc_time_sec}s / BL ${unit.bl_time_sec}s</div>
|
||||
<div class="muted">设备 ${bound.length} 台 | 累计 ${runtime ? Math.floor(runtime.display_acc_sec / 1000) : 0}s</div>
|
||||
<div class="muted">运行 ${unit.run_time_sec}s / 停止 ${unit.stop_time_sec}s / 累计 ${unit.acc_time_sec}s / 间隔 ${unit.bl_time_sec}s</div>
|
||||
${mode === "config" ? `<div class="unit-equipment-tags">${equipTags}</div>` : ""}
|
||||
<div class="row unit-card-actions"></div>
|
||||
`;
|
||||
|
|
@ -143,7 +143,7 @@ function buildUnitCard(unit, mode) {
|
|||
|
||||
const editBtn = document.createElement("button");
|
||||
editBtn.className = "secondary";
|
||||
editBtn.textContent = "Edit";
|
||||
editBtn.textContent = "编辑";
|
||||
editBtn.addEventListener("click", (event) => {
|
||||
event.stopPropagation();
|
||||
openEditUnitModal(unit);
|
||||
|
|
@ -151,7 +151,7 @@ function buildUnitCard(unit, mode) {
|
|||
|
||||
const deleteBtn = document.createElement("button");
|
||||
deleteBtn.className = "danger";
|
||||
deleteBtn.textContent = "Delete";
|
||||
deleteBtn.textContent = "删除";
|
||||
deleteBtn.addEventListener("click", (event) => {
|
||||
event.stopPropagation();
|
||||
deleteUnit(unit.id).catch((error) => {
|
||||
|
|
@ -240,7 +240,7 @@ export async function saveUnit(event) {
|
|||
}
|
||||
|
||||
export async function deleteUnit(unitId) {
|
||||
if (!window.confirm("Delete this unit?")) {
|
||||
if (!window.confirm("确认删除该单元?")) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue