From 7580ec45804d2b8837fd12d1df7e8863caf1cfb6 Mon Sep 17 00:00:00 2001 From: cyfung1031 <44498510+cyfung1031@users.noreply.github.com> Date: Sun, 1 Feb 2026 20:09:44 +0900 Subject: [PATCH 1/8] =?UTF-8?q?[v1.3]=20=E4=BF=AE=E6=AD=A3React=E9=87=8D?= =?UTF-8?q?=E7=BB=98=E9=97=AE=E9=A2=98=20=EF=BC=88ScriptCard=20&=20ScriptT?= =?UTF-8?q?able=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/locales/ach-UG/translation.json | 1 + src/locales/de-DE/translation.json | 1 + src/locales/en-US/translation.json | 1 + src/locales/ja-JP/translation.json | 1 + src/locales/ru-RU/translation.json | 1 + src/locales/vi-VN/translation.json | 1 + src/locales/zh-CN/translation.json | 1 + src/locales/zh-TW/translation.json | 1 + .../options/routes/ScriptList/ScriptCard.tsx | 802 ++++++----- .../options/routes/ScriptList/ScriptTable.tsx | 1196 +++++++++-------- .../options/routes/ScriptList/Sidebar.tsx | 4 +- src/pages/options/routes/ScriptList/hooks.tsx | 715 +++------- src/pages/options/routes/ScriptList/index.tsx | 313 +++-- src/pages/store/favicons.ts | 10 +- src/types/main.d.ts | 1 + 15 files changed, 1481 insertions(+), 1568 deletions(-) diff --git a/src/locales/ach-UG/translation.json b/src/locales/ach-UG/translation.json index 2f55cc216..566bb58c6 100644 --- a/src/locales/ach-UG/translation.json +++ b/src/locales/ach-UG/translation.json @@ -150,6 +150,7 @@ "starting_script": "crwdns8176:0crwdne8176:0", "starting_updates": "crwdns8178:0crwdne8178:0", "script_started": "crwdns8180:0crwdne8180:0", + "operation_failed": "Operation failed", "batch_operations": "crwdns8182:0crwdne8182:0", "export": "crwdns8184:0crwdne8184:0", "delete": "crwdns8186:0crwdne8186:0", diff --git a/src/locales/de-DE/translation.json b/src/locales/de-DE/translation.json index 7f4825819..8798615b4 100644 --- a/src/locales/de-DE/translation.json +++ b/src/locales/de-DE/translation.json @@ -151,6 +151,7 @@ "starting_script": "Skript wird gestartet...", "starting_updates": "Batch-Update wird gestartet...", "script_started": "Skript gestartet", + "operation_failed": "Vorgang fehlgeschlagen", "batch_operations": "Batch-Operationen", "export": "Exportieren", "delete": "Löschen", diff --git a/src/locales/en-US/translation.json b/src/locales/en-US/translation.json index 60207ea02..b5f166730 100644 --- a/src/locales/en-US/translation.json +++ b/src/locales/en-US/translation.json @@ -151,6 +151,7 @@ "starting_script": "Starting Script...", "starting_updates": "Starting Batch Updates...", "script_started": "Script Started", + "operation_failed": "Operation failed", "batch_operations": "Batch Operations", "export": "Export", "delete": "Delete", diff --git a/src/locales/ja-JP/translation.json b/src/locales/ja-JP/translation.json index f3ec26acd..576ecece3 100644 --- a/src/locales/ja-JP/translation.json +++ b/src/locales/ja-JP/translation.json @@ -151,6 +151,7 @@ "starting_script": "スクリプトを開始中...", "starting_updates": "一括更新を開始中...", "script_started": "スクリプトが開始しました", + "operation_failed": "操作に失敗しました", "batch_operations": "一括操作", "export": "エクスポート", "delete": "削除", diff --git a/src/locales/ru-RU/translation.json b/src/locales/ru-RU/translation.json index aa85bd6a5..686dfb114 100644 --- a/src/locales/ru-RU/translation.json +++ b/src/locales/ru-RU/translation.json @@ -151,6 +151,7 @@ "starting_script": "Запуск скрипта...", "starting_updates": "Массовое обновление...", "script_started": "Скрипт запущен", + "operation_failed": "Операция не выполнена", "batch_operations": "Пакетные операции", "export": "Экспорт", "delete": "Удалить", diff --git a/src/locales/vi-VN/translation.json b/src/locales/vi-VN/translation.json index 63588d1b8..c22a4e37d 100644 --- a/src/locales/vi-VN/translation.json +++ b/src/locales/vi-VN/translation.json @@ -151,6 +151,7 @@ "starting_script": "Đang khởi động script...", "starting_updates": "Đang khởi động cập nhật hàng loạt...", "script_started": "Script đã khởi động", + "operation_failed": "Thao tác thất bại", "batch_operations": "Thao tác hàng loạt", "export": "Xuất", "delete": "Xóa", diff --git a/src/locales/zh-CN/translation.json b/src/locales/zh-CN/translation.json index c0c17ec9d..8fb49086e 100644 --- a/src/locales/zh-CN/translation.json +++ b/src/locales/zh-CN/translation.json @@ -151,6 +151,7 @@ "starting_script": "正在启动脚本...", "starting_updates": "正在批量更新...", "script_started": "脚本已启动", + "operation_failed": "操作失败", "batch_operations": "批量操作", "export": "导出", "delete": "删除", diff --git a/src/locales/zh-TW/translation.json b/src/locales/zh-TW/translation.json index b528171e0..906278042 100644 --- a/src/locales/zh-TW/translation.json +++ b/src/locales/zh-TW/translation.json @@ -151,6 +151,7 @@ "starting_script": "正在啟動腳本...", "starting_updates": "正在批次更新...", "script_started": "腳本已啟動", + "operation_failed": "操作失敗", "batch_operations": "批次操作", "export": "匯出", "delete": "刪除", diff --git a/src/pages/options/routes/ScriptList/ScriptCard.tsx b/src/pages/options/routes/ScriptList/ScriptCard.tsx index c79675706..5bda473d9 100644 --- a/src/pages/options/routes/ScriptList/ScriptCard.tsx +++ b/src/pages/options/routes/ScriptList/ScriptCard.tsx @@ -1,4 +1,4 @@ -import React, { useMemo } from "react"; +import React, { createContext, useCallback, useContext, useMemo } from "react"; import { Avatar, Button, Card, Divider, Popconfirm, Space, Tag, Tooltip, Typography } from "@arco-design/web-react"; import { Link, useNavigate } from "react-router-dom"; import { IconClockCircle, IconDragDotVertical } from "@arco-design/web-react/icon"; @@ -24,14 +24,72 @@ import { useTranslation } from "react-i18next"; import { VscLayoutSidebarLeft, VscLayoutSidebarLeftOff } from "react-icons/vsc"; import { FaThList } from "react-icons/fa"; import type { DragEndEvent } from "@dnd-kit/core"; -import { DndContext, KeyboardSensor, PointerSensor, useSensor, useSensors } from "@dnd-kit/core"; +import { closestCenter, DndContext, KeyboardSensor, PointerSensor, useSensor, useSensors } from "@dnd-kit/core"; import { rectSortingStrategy, SortableContext, sortableKeyboardCoordinates, useSortable } from "@dnd-kit/sortable"; import { CSS } from "@dnd-kit/utilities"; import { useAppContext } from "@App/pages/store/AppContext"; -import type { SetSearchRequest } from "./hooks"; +import { type SearchFilterRequest } from "./SearchFilter"; import type { SearchType } from "@App/app/service/service_worker/types"; -const { Text } = Typography; +type DragCtx = Pick, "listeners" | "setActivatorNodeRef"> | null; +export const SortableDragCtx = createContext(null); + +function composeRefs(...refs: React.Ref[]): (node: T | null) => void { + return (node) => { + for (const ref of refs) { + if (typeof ref === "function") { + ref(node); + } else if (ref) { + (ref as React.MutableRefObject).current = node; + } + } + }; +} + +const DraggableEntry = React.forwardRef>( + ({ record, ...rest }, ref) => { + const sortable = useSortable({ id: record.uuid }); + const { setNodeRef, transform, transition, listeners, setActivatorNodeRef } = sortable; + + const style = { + transform: CSS.Transform.toString(transform), + transition, + }; + + const mergedRef = React.useMemo(() => composeRefs(setNodeRef, ref), [setNodeRef, ref]); + + const ctxValue = useMemo( + () => ({ + listeners: listeners, + setActivatorNodeRef: setActivatorNodeRef, + }), + [listeners, setActivatorNodeRef] + ); + + return ( + +
+ + ); + } +); +DraggableEntry.displayName = "DraggableEntry"; + +const DragHandle = () => { + const sortable = useContext(SortableDragCtx); + + const { listeners, setActivatorNodeRef } = sortable || {}; + + return !setActivatorNodeRef ? ( + + + + ) : ( + + + + ); +}; interface ScriptCardItemProps { item: ScriptLoading; @@ -56,15 +114,6 @@ export const ScriptCardItem = React.memo( handleConfig, handleRunStop, }: ScriptCardItemProps) => { - const { attributes, listeners, setNodeRef, transform, transition } = useSortable({ - id: item.uuid, - }); - - const style = { - transform: CSS.Transform.toString(transform), - transition, - }; - const { t } = useTranslation(); const navigate = useNavigate(); @@ -106,210 +155,211 @@ export const ScriptCardItem = React.memo( }), }; + // console.log("Rendered - " + item.name); // 用于检查垃圾React有否过度更新 + return ( - -
-
-
-
- -
- - +
+ +
+
+
+
+ - {i18nName(item)} - +
+ + + {i18nName(item)} + +
+ + {tags.length > 0 && ( + + {tags.map((tag) => ( + + {tag} + + ))} + + )} +
+
+ { + updateScripts([item.uuid], { enableLoading: true }); + requestEnableScript({ uuid: item.uuid, enable: checked }); + }} + /> +
+ +
- - {tags.length > 0 && ( - - {tags.map((tag) => ( - - {tag} - - ))} - - )} -
-
- { - updateScripts([item.uuid], { enableLoading: true }); - requestEnableScript({ uuid: item.uuid, enable: checked }); - }} - /> -
- -
-
-
- - {/* 版本和更新时间 */} -
- {item.metadata.version && ( -
- - {t("version")} - {": "} - - {item.metadata.version[0]}
- )} -
- - {t("last_updated")} - {": "} - - -
-
- {/* 运行状态 */} -
- {item.type !== SCRIPT_TYPE_NORMAL && ( -
- - } - color="blue" - bordered - style={{ cursor: "pointer" }} - onClick={toLogger} - > - {item.runStatus === SCRIPT_RUN_STATUS_RUNNING ? t("running") : t("completed")} - - + {/* 版本和更新时间 */} +
+ {item.metadata.version && ( +
+ + {t("version")} + {": "} + + {item.metadata.version[0]} +
+ )} +
+ + {t("last_updated")} + {": "} + + +
- )} - -
-
- {item.type === SCRIPT_TYPE_NORMAL && ( - - {favoriteMemo.trimmed.map((fav) => ( - { - if (fav.website) { - window.open(fav.website, "_blank"); + {/* 运行状态 */} +
+ {item.type !== SCRIPT_TYPE_NORMAL && ( +
+ - ))} - {favoriteMemo.originalLen > 8 && {"..."}} - - )} - -
-
- {/* 操作按钮 */} -
- -
-
- {item.type !== SCRIPT_TYPE_NORMAL && ( - - )} -
-
- - - - - {item.config && ( - + > + } + color="blue" + bordered + style={{ cursor: "pointer" }} + onClick={toLogger} + > + {item.runStatus === SCRIPT_RUN_STATUS_RUNNING ? t("running") : t("completed")} + + +
)} - {item.metadata.cloudcat && ( - + +
+ +
+ {item.type === SCRIPT_TYPE_NORMAL && ( + + {favoriteMemo.trimmed.map((fav) => ( + { + if (fav.website) { + window.open(fav.website, "_blank"); + } + }} + /> + ))} + {favoriteMemo.originalLen > 8 && {"..."}} + )} - } - onOk={() => handleDelete(item)} - > - - - + +
+
+ {/* 操作按钮 */} +
+ +
+
+ {item.type !== SCRIPT_TYPE_NORMAL && ( + + )} +
+
+ + + + + {item.config && ( + + )} + {item.metadata.cloudcat && ( + + )} + } + onOk={() => handleDelete(item)} + > + + + +
+
-
+
-
+ ); }, (prevProps, nextProps) => { @@ -323,13 +373,13 @@ interface ScriptCardProps { scriptList: ScriptLoading[]; scriptListSortOrder: (params: { active: string; over: string }) => void; sidebarOpen: boolean; - setSidebarOpen: React.Dispatch>; + setSidebarOpen: ReactStateSetter; setViewMode: (mode: "card" | "table") => void; updateScripts: (uuids: string[], data: Partial