| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
|
|
|
|
| import { useState, useEffect } from 'react';
|
| import { useTranslation } from 'react-i18next';
|
| import { Modal } from '@douyinfe/semi-ui';
|
| import {
|
| API,
|
| copy,
|
| isAdmin,
|
| showError,
|
| showSuccess,
|
| timestamp2string,
|
| } from '../../helpers';
|
| import { ITEMS_PER_PAGE } from '../../constants';
|
| import { useTableCompactMode } from '../common/useTableCompactMode';
|
|
|
| export const useTaskLogsData = () => {
|
| const { t } = useTranslation();
|
|
|
|
|
| const COLUMN_KEYS = {
|
| SUBMIT_TIME: 'submit_time',
|
| FINISH_TIME: 'finish_time',
|
| DURATION: 'duration',
|
| CHANNEL: 'channel',
|
| PLATFORM: 'platform',
|
| TYPE: 'type',
|
| TASK_ID: 'task_id',
|
| TASK_STATUS: 'task_status',
|
| PROGRESS: 'progress',
|
| FAIL_REASON: 'fail_reason',
|
| RESULT_URL: 'result_url',
|
| };
|
|
|
|
|
| const [logs, setLogs] = useState([]);
|
| const [loading, setLoading] = useState(false);
|
| const [activePage, setActivePage] = useState(1);
|
| const [logCount, setLogCount] = useState(0);
|
| const [pageSize, setPageSize] = useState(ITEMS_PER_PAGE);
|
|
|
|
|
| const isAdminUser = isAdmin();
|
|
|
| const STORAGE_KEY = isAdminUser
|
| ? 'task-logs-table-columns-admin'
|
| : 'task-logs-table-columns-user';
|
|
|
|
|
| const [isModalOpen, setIsModalOpen] = useState(false);
|
| const [modalContent, setModalContent] = useState('');
|
|
|
|
|
| const [isVideoModalOpen, setIsVideoModalOpen] = useState(false);
|
| const [videoUrl, setVideoUrl] = useState('');
|
|
|
|
|
| const [formApi, setFormApi] = useState(null);
|
| let now = new Date();
|
| let zeroNow = new Date(now.getFullYear(), now.getMonth(), now.getDate());
|
|
|
| const formInitValues = {
|
| channel_id: '',
|
| task_id: '',
|
| dateRange: [
|
| timestamp2string(zeroNow.getTime() / 1000),
|
| timestamp2string(now.getTime() / 1000 + 3600),
|
| ],
|
| };
|
|
|
|
|
| const [visibleColumns, setVisibleColumns] = useState({});
|
| const [showColumnSelector, setShowColumnSelector] = useState(false);
|
|
|
|
|
| const [compactMode, setCompactMode] = useTableCompactMode('taskLogs');
|
|
|
|
|
| useEffect(() => {
|
| const savedColumns = localStorage.getItem(STORAGE_KEY);
|
| if (savedColumns) {
|
| try {
|
| const parsed = JSON.parse(savedColumns);
|
| const defaults = getDefaultColumnVisibility();
|
| const merged = { ...defaults, ...parsed };
|
|
|
|
|
| if (!isAdminUser) {
|
| merged[COLUMN_KEYS.CHANNEL] = false;
|
| }
|
| setVisibleColumns(merged);
|
| } catch (e) {
|
| console.error('Failed to parse saved column preferences', e);
|
| initDefaultColumns();
|
| }
|
| } else {
|
| initDefaultColumns();
|
| }
|
| }, []);
|
|
|
|
|
| const getDefaultColumnVisibility = () => {
|
| return {
|
| [COLUMN_KEYS.SUBMIT_TIME]: true,
|
| [COLUMN_KEYS.FINISH_TIME]: true,
|
| [COLUMN_KEYS.DURATION]: true,
|
| [COLUMN_KEYS.CHANNEL]: isAdminUser,
|
| [COLUMN_KEYS.PLATFORM]: true,
|
| [COLUMN_KEYS.TYPE]: true,
|
| [COLUMN_KEYS.TASK_ID]: true,
|
| [COLUMN_KEYS.TASK_STATUS]: true,
|
| [COLUMN_KEYS.PROGRESS]: true,
|
| [COLUMN_KEYS.FAIL_REASON]: true,
|
| [COLUMN_KEYS.RESULT_URL]: true,
|
| };
|
| };
|
|
|
|
|
| const initDefaultColumns = () => {
|
| const defaults = getDefaultColumnVisibility();
|
| setVisibleColumns(defaults);
|
| localStorage.setItem(STORAGE_KEY, JSON.stringify(defaults));
|
| };
|
|
|
|
|
| const handleColumnVisibilityChange = (columnKey, checked) => {
|
| const updatedColumns = { ...visibleColumns, [columnKey]: checked };
|
| setVisibleColumns(updatedColumns);
|
| };
|
|
|
|
|
| const handleSelectAll = (checked) => {
|
| const allKeys = Object.keys(COLUMN_KEYS).map((key) => COLUMN_KEYS[key]);
|
| const updatedColumns = {};
|
|
|
| allKeys.forEach((key) => {
|
| if (key === COLUMN_KEYS.CHANNEL && !isAdminUser) {
|
| updatedColumns[key] = false;
|
| } else {
|
| updatedColumns[key] = checked;
|
| }
|
| });
|
|
|
| setVisibleColumns(updatedColumns);
|
| };
|
|
|
|
|
| useEffect(() => {
|
| if (Object.keys(visibleColumns).length > 0) {
|
| localStorage.setItem(STORAGE_KEY, JSON.stringify(visibleColumns));
|
| }
|
| }, [visibleColumns]);
|
|
|
|
|
| const getFormValues = () => {
|
| const formValues = formApi ? formApi.getValues() : {};
|
|
|
|
|
| let start_timestamp = timestamp2string(zeroNow.getTime() / 1000);
|
| let end_timestamp = timestamp2string(now.getTime() / 1000 + 3600);
|
|
|
| if (
|
| formValues.dateRange &&
|
| Array.isArray(formValues.dateRange) &&
|
| formValues.dateRange.length === 2
|
| ) {
|
| start_timestamp = formValues.dateRange[0];
|
| end_timestamp = formValues.dateRange[1];
|
| }
|
|
|
| return {
|
| channel_id: formValues.channel_id || '',
|
| task_id: formValues.task_id || '',
|
| start_timestamp,
|
| end_timestamp,
|
| };
|
| };
|
|
|
|
|
| const enrichLogs = (items) => {
|
| return items.map((log) => ({
|
| ...log,
|
| timestamp2string: timestamp2string(log.created_at),
|
| key: '' + log.id,
|
| }));
|
| };
|
|
|
|
|
| const syncPageData = (payload) => {
|
| const items = enrichLogs(payload.items || []);
|
| setLogs(items);
|
| setLogCount(payload.total || 0);
|
| setActivePage(payload.page || 1);
|
| setPageSize(payload.page_size || pageSize);
|
| };
|
|
|
|
|
| const loadLogs = async (page = 1, size = pageSize) => {
|
| setLoading(true);
|
| const { channel_id, task_id, start_timestamp, end_timestamp } =
|
| getFormValues();
|
| let localStartTimestamp = parseInt(Date.parse(start_timestamp) / 1000);
|
| let localEndTimestamp = parseInt(Date.parse(end_timestamp) / 1000);
|
| let url = isAdminUser
|
| ? `/api/task/?p=${page}&page_size=${size}&channel_id=${channel_id}&task_id=${task_id}&start_timestamp=${localStartTimestamp}&end_timestamp=${localEndTimestamp}`
|
| : `/api/task/self?p=${page}&page_size=${size}&task_id=${task_id}&start_timestamp=${localStartTimestamp}&end_timestamp=${localEndTimestamp}`;
|
| const res = await API.get(url);
|
| const { success, message, data } = res.data;
|
| if (success) {
|
| syncPageData(data);
|
| } else {
|
| showError(message);
|
| }
|
| setLoading(false);
|
| };
|
|
|
|
|
| const handlePageChange = (page) => {
|
| loadLogs(page, pageSize).then();
|
| };
|
|
|
| const handlePageSizeChange = async (size) => {
|
| localStorage.setItem('task-page-size', size + '');
|
| await loadLogs(1, size);
|
| };
|
|
|
|
|
| const refresh = async () => {
|
| await loadLogs(1, pageSize);
|
| };
|
|
|
|
|
| const copyText = async (text) => {
|
| if (await copy(text)) {
|
| showSuccess(t('已复制:') + text);
|
| } else {
|
| Modal.error({ title: t('无法复制到剪贴板,请手动复制'), content: text });
|
| }
|
| };
|
|
|
|
|
| const openContentModal = (content) => {
|
| setModalContent(content);
|
| setIsModalOpen(true);
|
| };
|
|
|
|
|
| const openVideoModal = (url) => {
|
| setVideoUrl(url);
|
| setIsVideoModalOpen(true);
|
| };
|
|
|
|
|
| useEffect(() => {
|
| const localPageSize =
|
| parseInt(localStorage.getItem('task-page-size')) || ITEMS_PER_PAGE;
|
| setPageSize(localPageSize);
|
| loadLogs(1, localPageSize).then();
|
| }, []);
|
|
|
| return {
|
|
|
| logs,
|
| loading,
|
| activePage,
|
| logCount,
|
| pageSize,
|
| isAdminUser,
|
|
|
|
|
| isModalOpen,
|
| setIsModalOpen,
|
| modalContent,
|
|
|
|
|
| isVideoModalOpen,
|
| setIsVideoModalOpen,
|
| videoUrl,
|
|
|
|
|
| formApi,
|
| setFormApi,
|
| formInitValues,
|
| getFormValues,
|
|
|
|
|
| visibleColumns,
|
| showColumnSelector,
|
| setShowColumnSelector,
|
| handleColumnVisibilityChange,
|
| handleSelectAll,
|
| initDefaultColumns,
|
| COLUMN_KEYS,
|
|
|
|
|
| compactMode,
|
| setCompactMode,
|
|
|
|
|
| loadLogs,
|
| handlePageChange,
|
| handlePageSizeChange,
|
| refresh,
|
| copyText,
|
| openContentModal,
|
| openVideoModal,
|
| enrichLogs,
|
| syncPageData,
|
|
|
|
|
| t,
|
| };
|
| };
|
|
|