| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| |
|
| | import React from 'react'; |
| | import { Button, Progress, Tag, Typography } from '@douyinfe/semi-ui'; |
| | import { |
| | Palette, |
| | ZoomIn, |
| | Shuffle, |
| | Move, |
| | FileText, |
| | Blend, |
| | Upload, |
| | Minimize2, |
| | RotateCcw, |
| | PaintBucket, |
| | Focus, |
| | Move3D, |
| | Monitor, |
| | UserCheck, |
| | HelpCircle, |
| | CheckCircle, |
| | Clock, |
| | Copy, |
| | FileX, |
| | Pause, |
| | XCircle, |
| | Loader, |
| | AlertCircle, |
| | Hash, |
| | Video, |
| | } from 'lucide-react'; |
| |
|
| | const colors = [ |
| | 'amber', |
| | 'blue', |
| | 'cyan', |
| | 'green', |
| | 'grey', |
| | 'indigo', |
| | 'light-blue', |
| | 'lime', |
| | 'orange', |
| | 'pink', |
| | 'purple', |
| | 'red', |
| | 'teal', |
| | 'violet', |
| | 'yellow', |
| | ]; |
| |
|
| | |
| | function renderType(type, t) { |
| | switch (type) { |
| | case 'IMAGINE': |
| | return ( |
| | <Tag color='blue' shape='circle' prefixIcon={<Palette size={14} />}> |
| | {t('绘图')} |
| | </Tag> |
| | ); |
| | case 'UPSCALE': |
| | return ( |
| | <Tag color='orange' shape='circle' prefixIcon={<ZoomIn size={14} />}> |
| | {t('放大')} |
| | </Tag> |
| | ); |
| | case 'VIDEO': |
| | return ( |
| | <Tag color='orange' shape='circle' prefixIcon={<Video size={14} />}> |
| | {t('视频')} |
| | </Tag> |
| | ); |
| | case 'EDITS': |
| | return ( |
| | <Tag color='orange' shape='circle' prefixIcon={<Video size={14} />}> |
| | {t('编辑')} |
| | </Tag> |
| | ); |
| | case 'VARIATION': |
| | return ( |
| | <Tag color='purple' shape='circle' prefixIcon={<Shuffle size={14} />}> |
| | {t('变换')} |
| | </Tag> |
| | ); |
| | case 'HIGH_VARIATION': |
| | return ( |
| | <Tag color='purple' shape='circle' prefixIcon={<Shuffle size={14} />}> |
| | {t('强变换')} |
| | </Tag> |
| | ); |
| | case 'LOW_VARIATION': |
| | return ( |
| | <Tag color='purple' shape='circle' prefixIcon={<Shuffle size={14} />}> |
| | {t('弱变换')} |
| | </Tag> |
| | ); |
| | case 'PAN': |
| | return ( |
| | <Tag color='cyan' shape='circle' prefixIcon={<Move size={14} />}> |
| | {t('平移')} |
| | </Tag> |
| | ); |
| | case 'DESCRIBE': |
| | return ( |
| | <Tag color='yellow' shape='circle' prefixIcon={<FileText size={14} />}> |
| | {t('图生文')} |
| | </Tag> |
| | ); |
| | case 'BLEND': |
| | return ( |
| | <Tag color='lime' shape='circle' prefixIcon={<Blend size={14} />}> |
| | {t('图混合')} |
| | </Tag> |
| | ); |
| | case 'UPLOAD': |
| | return ( |
| | <Tag color='blue' shape='circle' prefixIcon={<Upload size={14} />}> |
| | 上传文件 |
| | </Tag> |
| | ); |
| | case 'SHORTEN': |
| | return ( |
| | <Tag color='pink' shape='circle' prefixIcon={<Minimize2 size={14} />}> |
| | {t('缩词')} |
| | </Tag> |
| | ); |
| | case 'REROLL': |
| | return ( |
| | <Tag color='indigo' shape='circle' prefixIcon={<RotateCcw size={14} />}> |
| | {t('重绘')} |
| | </Tag> |
| | ); |
| | case 'INPAINT': |
| | return ( |
| | <Tag |
| | color='violet' |
| | shape='circle' |
| | prefixIcon={<PaintBucket size={14} />} |
| | > |
| | {t('局部重绘-提交')} |
| | </Tag> |
| | ); |
| | case 'ZOOM': |
| | return ( |
| | <Tag color='teal' shape='circle' prefixIcon={<Focus size={14} />}> |
| | {t('变焦')} |
| | </Tag> |
| | ); |
| | case 'CUSTOM_ZOOM': |
| | return ( |
| | <Tag color='teal' shape='circle' prefixIcon={<Move3D size={14} />}> |
| | {t('自定义变焦-提交')} |
| | </Tag> |
| | ); |
| | case 'MODAL': |
| | return ( |
| | <Tag color='green' shape='circle' prefixIcon={<Monitor size={14} />}> |
| | {t('窗口处理')} |
| | </Tag> |
| | ); |
| | case 'SWAP_FACE': |
| | return ( |
| | <Tag |
| | color='light-green' |
| | shape='circle' |
| | prefixIcon={<UserCheck size={14} />} |
| | > |
| | {t('换脸')} |
| | </Tag> |
| | ); |
| | default: |
| | return ( |
| | <Tag color='white' shape='circle' prefixIcon={<HelpCircle size={14} />}> |
| | {t('未知')} |
| | </Tag> |
| | ); |
| | } |
| | } |
| |
|
| | function renderCode(code, t) { |
| | switch (code) { |
| | case 1: |
| | return ( |
| | <Tag |
| | color='green' |
| | shape='circle' |
| | prefixIcon={<CheckCircle size={14} />} |
| | > |
| | {t('已提交')} |
| | </Tag> |
| | ); |
| | case 21: |
| | return ( |
| | <Tag color='lime' shape='circle' prefixIcon={<Clock size={14} />}> |
| | {t('等待中')} |
| | </Tag> |
| | ); |
| | case 22: |
| | return ( |
| | <Tag color='orange' shape='circle' prefixIcon={<Copy size={14} />}> |
| | {t('重复提交')} |
| | </Tag> |
| | ); |
| | case 0: |
| | return ( |
| | <Tag color='yellow' shape='circle' prefixIcon={<FileX size={14} />}> |
| | {t('未提交')} |
| | </Tag> |
| | ); |
| | default: |
| | return ( |
| | <Tag color='white' shape='circle' prefixIcon={<HelpCircle size={14} />}> |
| | {t('未知')} |
| | </Tag> |
| | ); |
| | } |
| | } |
| |
|
| | function renderStatus(type, t) { |
| | switch (type) { |
| | case 'SUCCESS': |
| | return ( |
| | <Tag |
| | color='green' |
| | shape='circle' |
| | prefixIcon={<CheckCircle size={14} />} |
| | > |
| | {t('成功')} |
| | </Tag> |
| | ); |
| | case 'NOT_START': |
| | return ( |
| | <Tag color='grey' shape='circle' prefixIcon={<Pause size={14} />}> |
| | {t('未启动')} |
| | </Tag> |
| | ); |
| | case 'SUBMITTED': |
| | return ( |
| | <Tag color='yellow' shape='circle' prefixIcon={<Clock size={14} />}> |
| | {t('队列中')} |
| | </Tag> |
| | ); |
| | case 'IN_PROGRESS': |
| | return ( |
| | <Tag color='blue' shape='circle' prefixIcon={<Loader size={14} />}> |
| | {t('执行中')} |
| | </Tag> |
| | ); |
| | case 'FAILURE': |
| | return ( |
| | <Tag color='red' shape='circle' prefixIcon={<XCircle size={14} />}> |
| | {t('失败')} |
| | </Tag> |
| | ); |
| | case 'MODAL': |
| | return ( |
| | <Tag |
| | color='yellow' |
| | shape='circle' |
| | prefixIcon={<AlertCircle size={14} />} |
| | > |
| | {t('窗口等待')} |
| | </Tag> |
| | ); |
| | default: |
| | return ( |
| | <Tag color='white' shape='circle' prefixIcon={<HelpCircle size={14} />}> |
| | {t('未知')} |
| | </Tag> |
| | ); |
| | } |
| | } |
| |
|
| | const renderTimestamp = (timestampInSeconds) => { |
| | const date = new Date(timestampInSeconds * 1000); |
| | const year = date.getFullYear(); |
| | const month = ('0' + (date.getMonth() + 1)).slice(-2); |
| | const day = ('0' + date.getDate()).slice(-2); |
| | const hours = ('0' + date.getHours()).slice(-2); |
| | const minutes = ('0' + date.getMinutes()).slice(-2); |
| | const seconds = ('0' + date.getSeconds()).slice(-2); |
| |
|
| | return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`; |
| | }; |
| |
|
| | function renderDuration(submit_time, finishTime, t) { |
| | if (!submit_time || !finishTime) return 'N/A'; |
| |
|
| | const start = new Date(submit_time); |
| | const finish = new Date(finishTime); |
| | const durationMs = finish - start; |
| | const durationSec = (durationMs / 1000).toFixed(1); |
| | const color = durationSec > 60 ? 'red' : 'green'; |
| |
|
| | return ( |
| | <Tag color={color} shape='circle' prefixIcon={<Clock size={14} />}> |
| | {durationSec} {t('秒')} |
| | </Tag> |
| | ); |
| | } |
| |
|
| | export const getMjLogsColumns = ({ |
| | t, |
| | COLUMN_KEYS, |
| | copyText, |
| | openContentModal, |
| | openImageModal, |
| | isAdminUser, |
| | }) => { |
| | return [ |
| | { |
| | key: COLUMN_KEYS.SUBMIT_TIME, |
| | title: t('提交时间'), |
| | dataIndex: 'submit_time', |
| | render: (text, record, index) => { |
| | return <div>{renderTimestamp(text / 1000)}</div>; |
| | }, |
| | }, |
| | { |
| | key: COLUMN_KEYS.DURATION, |
| | title: t('花费时间'), |
| | dataIndex: 'finish_time', |
| | render: (finish, record) => { |
| | return renderDuration(record.submit_time, finish, t); |
| | }, |
| | }, |
| | { |
| | key: COLUMN_KEYS.CHANNEL, |
| | title: t('渠道'), |
| | dataIndex: 'channel_id', |
| | render: (text, record, index) => { |
| | return isAdminUser ? ( |
| | <div> |
| | <Tag |
| | color={colors[parseInt(text) % colors.length]} |
| | shape='circle' |
| | prefixIcon={<Hash size={14} />} |
| | onClick={() => { |
| | copyText(text); |
| | }} |
| | > |
| | {' '} |
| | {text}{' '} |
| | </Tag> |
| | </div> |
| | ) : ( |
| | <></> |
| | ); |
| | }, |
| | }, |
| | { |
| | key: COLUMN_KEYS.TYPE, |
| | title: t('类型'), |
| | dataIndex: 'action', |
| | render: (text, record, index) => { |
| | return <div>{renderType(text, t)}</div>; |
| | }, |
| | }, |
| | { |
| | key: COLUMN_KEYS.TASK_ID, |
| | title: t('任务ID'), |
| | dataIndex: 'mj_id', |
| | render: (text, record, index) => { |
| | return <div>{text}</div>; |
| | }, |
| | }, |
| | { |
| | key: COLUMN_KEYS.SUBMIT_RESULT, |
| | title: t('提交结果'), |
| | dataIndex: 'code', |
| | render: (text, record, index) => { |
| | return isAdminUser ? <div>{renderCode(text, t)}</div> : <></>; |
| | }, |
| | }, |
| | { |
| | key: COLUMN_KEYS.TASK_STATUS, |
| | title: t('任务状态'), |
| | dataIndex: 'status', |
| | render: (text, record, index) => { |
| | return <div>{renderStatus(text, t)}</div>; |
| | }, |
| | }, |
| | { |
| | key: COLUMN_KEYS.PROGRESS, |
| | title: t('进度'), |
| | dataIndex: 'progress', |
| | render: (text, record, index) => { |
| | return ( |
| | <div> |
| | { |
| | <Progress |
| | stroke={ |
| | record.status === 'FAILURE' |
| | ? 'var(--semi-color-warning)' |
| | : null |
| | } |
| | percent={text ? parseInt(text.replace('%', '')) : 0} |
| | showInfo={true} |
| | aria-label='drawing progress' |
| | style={{ minWidth: '160px' }} |
| | /> |
| | } |
| | </div> |
| | ); |
| | }, |
| | }, |
| | { |
| | key: COLUMN_KEYS.IMAGE, |
| | title: t('结果图片'), |
| | dataIndex: 'image_url', |
| | render: (text, record, index) => { |
| | if (!text) { |
| | return t('无'); |
| | } |
| | return ( |
| | <Button |
| | size='small' |
| | onClick={() => { |
| | openImageModal(text); |
| | }} |
| | > |
| | {t('查看图片')} |
| | </Button> |
| | ); |
| | }, |
| | }, |
| | { |
| | key: COLUMN_KEYS.PROMPT, |
| | title: 'Prompt', |
| | dataIndex: 'prompt', |
| | render: (text, record, index) => { |
| | if (!text) { |
| | return t('无'); |
| | } |
| |
|
| | return ( |
| | <Typography.Text |
| | ellipsis={{ showTooltip: true }} |
| | style={{ width: 100 }} |
| | onClick={() => { |
| | openContentModal(text); |
| | }} |
| | > |
| | {text} |
| | </Typography.Text> |
| | ); |
| | }, |
| | }, |
| | { |
| | key: COLUMN_KEYS.PROMPT_EN, |
| | title: 'PromptEn', |
| | dataIndex: 'prompt_en', |
| | render: (text, record, index) => { |
| | if (!text) { |
| | return t('无'); |
| | } |
| |
|
| | return ( |
| | <Typography.Text |
| | ellipsis={{ showTooltip: true }} |
| | style={{ width: 100 }} |
| | onClick={() => { |
| | openContentModal(text); |
| | }} |
| | > |
| | {text} |
| | </Typography.Text> |
| | ); |
| | }, |
| | }, |
| | { |
| | key: COLUMN_KEYS.FAIL_REASON, |
| | title: t('失败原因'), |
| | dataIndex: 'fail_reason', |
| | fixed: 'right', |
| | render: (text, record, index) => { |
| | if (!text) { |
| | return t('无'); |
| | } |
| |
|
| | return ( |
| | <Typography.Text |
| | ellipsis={{ showTooltip: true }} |
| | style={{ width: 100 }} |
| | onClick={() => { |
| | openContentModal(text); |
| | }} |
| | > |
| | {text} |
| | </Typography.Text> |
| | ); |
| | }, |
| | }, |
| | ]; |
| | }; |
| |
|