feat(管理后台): 新增线路编辑器拖拽平移并修复代理下Socket连接问题

调整socket.io传输顺序优先使用轮询以适配代理服务器,新增可视化线路编辑器拖拽平移功能,修复多处CSS布局问题并更新静态资源缓存版本。
This commit is contained in:
2026-06-21 11:21:09 +08:00
parent 7fea8807b8
commit b1cb84f736
5 changed files with 86 additions and 10 deletions
+52 -1
View File
@@ -35,7 +35,9 @@ createApp({
});
const connected = ref(false);
const socket = io({ transports: ['websocket', 'polling'], upgrade: false });
// Prefer polling first so admin remains connected even when the proxy
// does not support WebSocket upgrades reliably.
const socket = io({ transports: ['polling', 'websocket'] });
// Data State
const stations = ref([]);
@@ -100,6 +102,15 @@ createApp({
const showFareModal = ref(false);
const currentFare = reactive({ exists: false, cost_regular: 0, cost_express: 0 });
const draggingStationIndex = ref(null);
const visualLineViewport = ref(null);
const lineViewportPan = reactive({
active: false,
startX: 0,
startY: 0,
scrollLeft: 0,
scrollTop: 0,
moved: false
});
const showStationModal = ref(false);
const stationForm = reactive({ code: '', name: '', en_name: '', transfer_enabled: false, transfer_to: [] });
const stationFormOriginalCode = ref('');
@@ -654,6 +665,36 @@ createApp({
draggingStationIndex.value = null;
};
const startLineViewportPan = (event) => {
const viewport = visualLineViewport.value;
if (!viewport) return;
if (event.button !== 0) return;
if (event.target && event.target.closest('.station-node')) return;
lineViewportPan.active = true;
lineViewportPan.moved = false;
lineViewportPan.startX = event.clientX;
lineViewportPan.startY = event.clientY;
lineViewportPan.scrollLeft = viewport.scrollLeft;
lineViewportPan.scrollTop = viewport.scrollTop;
};
const moveLineViewportPan = (event) => {
if (!lineViewportPan.active) return;
const viewport = visualLineViewport.value;
if (!viewport) return;
const deltaX = event.clientX - lineViewportPan.startX;
const deltaY = event.clientY - lineViewportPan.startY;
if (Math.abs(deltaX) > 2 || Math.abs(deltaY) > 2) {
lineViewportPan.moved = true;
}
viewport.scrollLeft = lineViewportPan.scrollLeft - deltaX;
viewport.scrollTop = lineViewportPan.scrollTop - deltaY;
};
const endLineViewportPan = () => {
lineViewportPan.active = false;
};
// --- Order Management ---
const fetchOrders = async () => {
if (loadingState.orders) return;
@@ -1171,6 +1212,10 @@ createApp({
};
const handleStationClick = async (code) => {
if (lineViewportPan.moved) {
lineViewportPan.moved = false;
return;
}
if (stationEditMode.value) {
openStationModal(code);
return;
@@ -1398,6 +1443,7 @@ createApp({
startIcCardSync();
}
appMouseupHandler = async () => {
endLineViewportPan();
if (draggingStationIndex.value !== null) {
if (selectedLine.value) {
try {
@@ -1428,6 +1474,10 @@ createApp({
// Computed
const recentLogs = computed(() => logs.value);
const orderList = computed(() => orders.value);
const lineEditorSvgWidth = computed(() => {
const count = Array.isArray(selectedLine.value?.stations) ? selectedLine.value.stations.length : 0;
return Math.max(960, 100 + Math.max(0, count - 1) * 120 + 120);
});
const lastSyncText = computed(() => lastSyncAt.value ? formatTime(lastSyncAt.value) : '尚未同步');
const isViewBusy = computed(() => {
if (loadingState.core) return true;
@@ -1520,6 +1570,7 @@ createApp({
// Management
selectedLine, fareMode, stationEditMode, fareSelection, showFareModal, currentFare, availableStations,
visualLineViewport, lineViewportPan, lineEditorSvgWidth, startLineViewportPan, moveLineViewportPan,
selectLine, createLine, deleteLine, deleteStation, updateLineInfo, getFareText,
isStationInLine, addStationToLine, removeStationFromLine,
handleStationClick, isStationSelected,