delete: 删除项目中无用的文件
parent
6933f82ec0
commit
c80b7b0143
@ -1,281 +0,0 @@
|
||||
import React, { useState, useRef } from 'react';
|
||||
import {
|
||||
Typography,
|
||||
Card,
|
||||
Form,
|
||||
Select,
|
||||
Input,
|
||||
Grid,
|
||||
Space,
|
||||
Button,
|
||||
Message,
|
||||
} from '@arco-design/web-react';
|
||||
import { FormInstance } from '@arco-design/web-react/es/Form';
|
||||
import axios from 'axios';
|
||||
import useLocale from '@/utils/useLocale';
|
||||
import locale from './locale';
|
||||
import styles from './style/index.module.less';
|
||||
import './mock';
|
||||
|
||||
function GroupForm() {
|
||||
const t = useLocale(locale);
|
||||
const formRef = useRef<FormInstance>();
|
||||
const [loading, setLoading] = useState(false);
|
||||
|
||||
function submit(data) {
|
||||
setLoading(true);
|
||||
axios
|
||||
.post('/api/groupForm', {
|
||||
data,
|
||||
})
|
||||
.then(() => {
|
||||
Message.success(t['groupForm.submitSuccess']);
|
||||
})
|
||||
.finally(() => {
|
||||
setLoading(false);
|
||||
});
|
||||
}
|
||||
|
||||
function handleSubmit() {
|
||||
formRef.current.validate().then((values) => {
|
||||
submit(values);
|
||||
});
|
||||
}
|
||||
|
||||
function handleReset() {
|
||||
formRef.current.resetFields();
|
||||
}
|
||||
|
||||
return (
|
||||
<div className={styles.container}>
|
||||
<Form layout="vertical" ref={formRef} className={styles['form-group']}>
|
||||
<Card>
|
||||
<Typography.Title heading={6}>
|
||||
{t['groupForm.title.video']}
|
||||
</Typography.Title>
|
||||
<Grid.Row gutter={80}>
|
||||
<Grid.Col span={8}>
|
||||
<Form.Item
|
||||
label={t['groupForm.form.label.video.mode']}
|
||||
field="video.mode"
|
||||
initialValue={'custom'}
|
||||
>
|
||||
<Select placeholder={t['groupForm.placeholder.video.mode']}>
|
||||
<Select.Option value="custom">自定义</Select.Option>
|
||||
<Select.Option value="mode1">模式1</Select.Option>
|
||||
<Select.Option value="mode2">模式2</Select.Option>
|
||||
</Select>
|
||||
</Form.Item>
|
||||
</Grid.Col>
|
||||
<Grid.Col span={8}>
|
||||
<Form.Item
|
||||
label={t['groupForm.form.label.video.acquisition.resolution']}
|
||||
field="video.acquisition.resolution"
|
||||
>
|
||||
<Select
|
||||
placeholder={
|
||||
t['groupForm.placeholder.video.acquisition.resolution']
|
||||
}
|
||||
>
|
||||
<Select.Option value="resolution1">分辨率1</Select.Option>
|
||||
<Select.Option value="resolution2">分辨率2</Select.Option>
|
||||
<Select.Option value="resolution3">分辨率3</Select.Option>
|
||||
</Select>
|
||||
</Form.Item>
|
||||
</Grid.Col>
|
||||
<Grid.Col span={8}>
|
||||
<Form.Item
|
||||
label={t['groupForm.form.label.video.acquisition.frameRate']}
|
||||
field="video.acquisition.frameRate"
|
||||
>
|
||||
<Input
|
||||
placeholder={
|
||||
t['groupForm.placeholder.video.acquisition.frameRate']
|
||||
}
|
||||
addAfter="fps"
|
||||
/>
|
||||
</Form.Item>
|
||||
</Grid.Col>
|
||||
</Grid.Row>
|
||||
<Grid.Row gutter={80}>
|
||||
<Grid.Col span={8}>
|
||||
<Form.Item
|
||||
label={t['groupForm.form.label.video.encoding.resolution']}
|
||||
field="video.encoding.resolution"
|
||||
>
|
||||
<Select
|
||||
placeholder={
|
||||
t['groupForm.placeholder.video.encoding.resolution']
|
||||
}
|
||||
>
|
||||
<Select.Option value="resolution1">分辨率1</Select.Option>
|
||||
<Select.Option value="resolution2">分辨率2</Select.Option>
|
||||
<Select.Option value="resolution3">分辨率3</Select.Option>
|
||||
</Select>
|
||||
</Form.Item>
|
||||
</Grid.Col>
|
||||
<Grid.Col span={8}>
|
||||
<Form.Item
|
||||
label={t['groupForm.form.label.video.encoding.rate.min']}
|
||||
field="video.encoding.rate.min"
|
||||
>
|
||||
<Input
|
||||
placeholder={
|
||||
t['groupForm.placeholder.video.encoding.rate.min']
|
||||
}
|
||||
addAfter="bps"
|
||||
/>
|
||||
</Form.Item>
|
||||
</Grid.Col>
|
||||
<Grid.Col span={8}>
|
||||
<Form.Item
|
||||
label={t['groupForm.form.label.video.encoding.rate.max']}
|
||||
field="video.encoding.rate.max"
|
||||
>
|
||||
<Input
|
||||
placeholder={
|
||||
t['groupForm.placeholder.video.encoding.rate.max']
|
||||
}
|
||||
addAfter="bps"
|
||||
/>
|
||||
</Form.Item>
|
||||
</Grid.Col>
|
||||
</Grid.Row>
|
||||
<Grid.Row gutter={80}>
|
||||
<Grid.Col span={8}>
|
||||
<Form.Item
|
||||
label={t['groupForm.form.label.video.encoding.rate.default']}
|
||||
field="video.encoding.rate.default"
|
||||
>
|
||||
<Input
|
||||
placeholder={
|
||||
t['groupForm.placeholder.video.encoding.rate.default']
|
||||
}
|
||||
addAfter="bps"
|
||||
/>
|
||||
</Form.Item>
|
||||
</Grid.Col>
|
||||
<Grid.Col span={8}>
|
||||
<Form.Item
|
||||
label={t['groupForm.form.label.video.encoding.frameRate']}
|
||||
field="video.encoding.frameRate"
|
||||
>
|
||||
<Input
|
||||
placeholder={
|
||||
t['groupForm.placeholder.video.encoding.frameRate']
|
||||
}
|
||||
addAfter="fps"
|
||||
/>
|
||||
</Form.Item>
|
||||
</Grid.Col>
|
||||
<Grid.Col span={8}>
|
||||
<Form.Item
|
||||
label={t['groupForm.form.label.video.encoding.profile']}
|
||||
field="video.encoding.profile"
|
||||
>
|
||||
<Input
|
||||
placeholder={
|
||||
t['groupForm.placeholder.video.encoding.profile']
|
||||
}
|
||||
addAfter="bps"
|
||||
/>
|
||||
</Form.Item>
|
||||
</Grid.Col>
|
||||
</Grid.Row>
|
||||
</Card>
|
||||
<Card>
|
||||
<Typography.Title heading={6}>
|
||||
{t['groupForm.title.audio']}
|
||||
</Typography.Title>
|
||||
<Grid.Row gutter={80}>
|
||||
<Grid.Col span={8}>
|
||||
<Form.Item
|
||||
label={t['groupForm.form.label.audio.mode']}
|
||||
initialValue={'custom'}
|
||||
field="audio.mode"
|
||||
>
|
||||
<Select placeholder={t['groupForm.placeholder.audio.mode']}>
|
||||
<Select.Option value="custom">自定义</Select.Option>
|
||||
<Select.Option value="mode1">模式1</Select.Option>
|
||||
<Select.Option value="mode2">模式2</Select.Option>
|
||||
</Select>
|
||||
</Form.Item>
|
||||
</Grid.Col>
|
||||
<Grid.Col span={8}>
|
||||
<Form.Item
|
||||
label={t['groupForm.form.label.audio.acquisition.channels']}
|
||||
field="audio.acquisition.channels"
|
||||
>
|
||||
<Select
|
||||
placeholder={
|
||||
t['groupForm.placeholder.audio.acquisition.channels']
|
||||
}
|
||||
>
|
||||
<Select.Option value="1">1</Select.Option>
|
||||
<Select.Option value="2">2</Select.Option>
|
||||
<Select.Option value="3">3</Select.Option>
|
||||
</Select>
|
||||
</Form.Item>
|
||||
</Grid.Col>
|
||||
<Grid.Col span={8}>
|
||||
<Form.Item
|
||||
label={t['groupForm.form.label.audio.encoding.rate']}
|
||||
field="audio.encoding.rate"
|
||||
>
|
||||
<Input
|
||||
placeholder={t['groupForm.placeholder.audio.encoding.rate']}
|
||||
addAfter="bps"
|
||||
/>
|
||||
</Form.Item>
|
||||
</Grid.Col>
|
||||
</Grid.Row>
|
||||
<Grid.Row gutter={80}>
|
||||
<Grid.Col span={8}>
|
||||
<Form.Item
|
||||
label={t['groupForm.form.label.audio.encoding.profile']}
|
||||
field="audio.encoding.profile"
|
||||
>
|
||||
<Input
|
||||
placeholder={
|
||||
t['groupForm.placeholder.audio.encoding.profile']
|
||||
}
|
||||
addAfter="fps"
|
||||
/>
|
||||
</Form.Item>
|
||||
</Grid.Col>
|
||||
</Grid.Row>
|
||||
</Card>
|
||||
<Card style={{ marginBottom: '40px' }}>
|
||||
<Typography.Title heading={6}>
|
||||
{t['groupForm.title.explanation']}
|
||||
</Typography.Title>
|
||||
<Form.Item
|
||||
label={t['groupForm.form.label.explanation']}
|
||||
field="audio.explanation"
|
||||
>
|
||||
<Input.TextArea
|
||||
placeholder={t['groupForm.placeholder.explanation']}
|
||||
/>
|
||||
</Form.Item>
|
||||
</Card>
|
||||
</Form>
|
||||
<div className={styles.actions}>
|
||||
<Space>
|
||||
<Button onClick={handleReset} size="large">
|
||||
{t['groupForm.reset']}
|
||||
</Button>
|
||||
<Button
|
||||
type="primary"
|
||||
onClick={handleSubmit}
|
||||
loading={loading}
|
||||
size="large"
|
||||
>
|
||||
{t['groupForm.submit']}
|
||||
</Button>
|
||||
</Space>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default GroupForm;
|
||||
@ -1,11 +0,0 @@
|
||||
import Mock from 'mockjs';
|
||||
import setupMock from '@/utils/setupMock';
|
||||
|
||||
setupMock({
|
||||
setup: () => {
|
||||
// 保存表单数据
|
||||
Mock.mock(new RegExp('/api/groupForm'), () => {
|
||||
return true;
|
||||
});
|
||||
},
|
||||
});
|
||||
@ -1,23 +0,0 @@
|
||||
.container {
|
||||
overflow: hidden;
|
||||
|
||||
:global(.arco-card-body) {
|
||||
padding: 20px 20px 10px;
|
||||
}
|
||||
|
||||
:global(.arco-card) {
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
}
|
||||
|
||||
.actions {
|
||||
padding: 12px 40px;
|
||||
background-color: var(--color-bg-2);
|
||||
display: flex;
|
||||
flex-direction: row-reverse;
|
||||
position: fixed;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
box-shadow: 0 -3px 12px rgb(0 0 0 / 10%);
|
||||
}
|
||||
@ -1,257 +0,0 @@
|
||||
import React, { useState } from 'react';
|
||||
import {
|
||||
Steps,
|
||||
Form,
|
||||
Input,
|
||||
Select,
|
||||
DatePicker,
|
||||
InputTag,
|
||||
Button,
|
||||
Typography,
|
||||
Space,
|
||||
Card,
|
||||
Switch,
|
||||
Result,
|
||||
} from '@arco-design/web-react';
|
||||
import useLocale from '@/utils/useLocale';
|
||||
import locale from './locale';
|
||||
import styles from './style/index.module.less';
|
||||
|
||||
const { Title, Paragraph } = Typography;
|
||||
function StepForm() {
|
||||
const t = useLocale(locale);
|
||||
const [current, setCurrent] = useState(1);
|
||||
|
||||
const [form] = Form.useForm();
|
||||
|
||||
const viewForm = () => {
|
||||
const values = form.getFields();
|
||||
form.setFields(values);
|
||||
setCurrent(1);
|
||||
};
|
||||
|
||||
const reCreateForm = () => {
|
||||
form.resetFields();
|
||||
setCurrent(1);
|
||||
};
|
||||
|
||||
const toNext = async () => {
|
||||
try {
|
||||
await form.validate();
|
||||
setCurrent(current + 1);
|
||||
} catch (_) {}
|
||||
};
|
||||
return (
|
||||
<div className={styles.container}>
|
||||
<Card>
|
||||
<Title heading={5}>{t['stepForm.desc.basicInfo']}</Title>
|
||||
<div className={styles.wrapper}>
|
||||
<Steps current={current} lineless>
|
||||
<Steps.Step
|
||||
title={t['stepForm.title.basicInfo']}
|
||||
description={t['stepForm.desc.basicInfo']}
|
||||
/>
|
||||
<Steps.Step
|
||||
title={t['stepForm.title.channel']}
|
||||
description={t['stepForm.desc.channel']}
|
||||
/>
|
||||
<Steps.Step
|
||||
title={t['stepForm.title.created']}
|
||||
description={t['stepForm.desc.created']}
|
||||
/>
|
||||
</Steps>
|
||||
<Form form={form} className={styles.form}>
|
||||
{current === 1 && (
|
||||
<Form.Item noStyle>
|
||||
<Form.Item
|
||||
label={t['stepForm.basicInfo.name']}
|
||||
required
|
||||
field="basic.name"
|
||||
rules={[
|
||||
{
|
||||
required: true,
|
||||
message: t['stepForm.basicInfo.name.required'],
|
||||
},
|
||||
{
|
||||
validator: (value: string, callback) => {
|
||||
if (!/^[\u4e00-\u9fa5a-zA-Z0-9]{1,20}$/g.test(value)) {
|
||||
callback(t['stepForm.basicInfo.name.placeholder']);
|
||||
}
|
||||
},
|
||||
},
|
||||
]}
|
||||
>
|
||||
<Input
|
||||
placeholder={t['stepForm.basicInfo.name.placeholder']}
|
||||
/>
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label={t['stepForm.basicInfo.channelType']}
|
||||
required
|
||||
initialValue="app"
|
||||
field="basic.channelType"
|
||||
rules={[
|
||||
{
|
||||
required: true,
|
||||
message: t['stepForm.basicInfo.channelType.required'],
|
||||
},
|
||||
]}
|
||||
>
|
||||
<Select>
|
||||
<Select.Option value="app">APP通用渠道</Select.Option>
|
||||
<Select.Option value="site">网页通用渠道</Select.Option>
|
||||
<Select.Option value="game">游戏通用渠道</Select.Option>
|
||||
</Select>
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label={t['stepForm.basicInfo.time']}
|
||||
required
|
||||
field="basic.time"
|
||||
rules={[
|
||||
{
|
||||
required: true,
|
||||
message: t['stepForm.basicInfo.time.required'],
|
||||
},
|
||||
]}
|
||||
>
|
||||
<DatePicker.RangePicker style={{ width: '100%' }} />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label={t['stepForm.basicInfo.link']}
|
||||
required
|
||||
extra={t['stepForm.basicInfo.link.tips']}
|
||||
field="basic.link"
|
||||
initialValue={'https://arco.design'}
|
||||
rules={[{ required: true }]}
|
||||
>
|
||||
<Input
|
||||
placeholder={t['stepForm.basicInfo.link.placeholder']}
|
||||
/>
|
||||
</Form.Item>
|
||||
</Form.Item>
|
||||
)}
|
||||
{current === 2 && (
|
||||
<Form.Item noStyle>
|
||||
<Form.Item
|
||||
label={t['stepForm.channel.source']}
|
||||
required
|
||||
field="channel.source"
|
||||
rules={[
|
||||
{
|
||||
required: true,
|
||||
message: t['stepForm.channel.source.required'],
|
||||
},
|
||||
]}
|
||||
>
|
||||
<Input
|
||||
placeholder={t['stepForm.channel.source.placeholder']}
|
||||
/>
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label={t['stepForm.channel.media']}
|
||||
required
|
||||
field="channel.media"
|
||||
rules={[
|
||||
{
|
||||
required: true,
|
||||
message: t['stepForm.channel.media.required'],
|
||||
},
|
||||
]}
|
||||
>
|
||||
<Input
|
||||
placeholder={t['stepForm.channel.media.placeholder']}
|
||||
/>
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label={t['stepForm.channel.keywords']}
|
||||
required
|
||||
field="channel.keywords"
|
||||
initialValue={['今日头条', '火山']}
|
||||
rules={[{ required: true }]}
|
||||
>
|
||||
<InputTag />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label={t['stepForm.channel.remind']}
|
||||
required
|
||||
initialValue={true}
|
||||
field="channel.remind"
|
||||
triggerPropName="checked"
|
||||
rules={[{ required: true }]}
|
||||
>
|
||||
<Switch />
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item
|
||||
label={t['stepForm.channel.content']}
|
||||
required
|
||||
field="channel.content"
|
||||
rules={[
|
||||
{
|
||||
required: true,
|
||||
message: t['stepForm.channel.content.required'],
|
||||
},
|
||||
]}
|
||||
>
|
||||
<Input.TextArea
|
||||
placeholder={t['stepForm.channel.content.placeholder']}
|
||||
/>
|
||||
</Form.Item>
|
||||
</Form.Item>
|
||||
)}
|
||||
{current !== 3 ? (
|
||||
<Form.Item label=" ">
|
||||
<Space>
|
||||
{current === 2 && (
|
||||
<Button
|
||||
size="large"
|
||||
onClick={() => setCurrent(current - 1)}
|
||||
>
|
||||
{t['stepForm.prev']}
|
||||
</Button>
|
||||
)}
|
||||
{current !== 3 && (
|
||||
<Button type="primary" size="large" onClick={toNext}>
|
||||
{t['stepForm.next']}
|
||||
</Button>
|
||||
)}
|
||||
</Space>
|
||||
</Form.Item>
|
||||
) : (
|
||||
<Form.Item noStyle>
|
||||
<Result
|
||||
status="success"
|
||||
title={t['stepForm.created.success.title']}
|
||||
subTitle={t['stepForm.created.success.desc']}
|
||||
extra={[
|
||||
<Button
|
||||
key="reset"
|
||||
style={{ marginRight: 16 }}
|
||||
onClick={viewForm}
|
||||
>
|
||||
{t['stepForm.created.success.view']}
|
||||
</Button>,
|
||||
<Button key="again" type="primary" onClick={reCreateForm}>
|
||||
{t['stepForm.created.success.again']}
|
||||
</Button>,
|
||||
]}
|
||||
/>
|
||||
</Form.Item>
|
||||
)}
|
||||
</Form>
|
||||
</div>
|
||||
{current === 3 && (
|
||||
<div className={styles['form-extra']}>
|
||||
<Title heading={6}>{t['stepForm.created.extra.title']}</Title>
|
||||
<Paragraph type="secondary">
|
||||
{t['stepForm.created.extra.desc']}
|
||||
<Button type="text">{t['stepForm.created.extra.detail']}</Button>
|
||||
</Paragraph>
|
||||
</div>
|
||||
)}
|
||||
</Card>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default StepForm;
|
||||
@ -1,11 +0,0 @@
|
||||
import Mock from 'mockjs';
|
||||
import setupMock from '@/utils/setupMock';
|
||||
|
||||
setupMock({
|
||||
setup: () => {
|
||||
// 保存表单数据
|
||||
Mock.mock(new RegExp('/api/groupForm'), () => {
|
||||
return true;
|
||||
});
|
||||
},
|
||||
});
|
||||
@ -1,39 +0,0 @@
|
||||
.container {
|
||||
:global(.arco-card-body) {
|
||||
> h5 {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
padding: 20px;
|
||||
}
|
||||
}
|
||||
|
||||
.wrapper {
|
||||
width: 624px;
|
||||
margin: 0 auto;
|
||||
padding-top: 56px;
|
||||
padding-bottom: 70px;
|
||||
}
|
||||
|
||||
.form {
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
margin-top: 76px;
|
||||
padding-right: 76px;
|
||||
}
|
||||
|
||||
.form-extra {
|
||||
width: 895px;
|
||||
margin: 54px auto;
|
||||
background-color: var(--color-fill-1);
|
||||
padding: 20px;
|
||||
margin-bottom: 120px;
|
||||
|
||||
> h6 {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
> div {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
@ -1,28 +0,0 @@
|
||||
import React from 'react';
|
||||
import { Card } from '@arco-design/web-react';
|
||||
import cs from 'classnames';
|
||||
import { IconPlus } from '@arco-design/web-react/icon';
|
||||
import styles from './style/index.module.less';
|
||||
|
||||
interface AddCardProps {
|
||||
description?: string;
|
||||
}
|
||||
function AddCard(props: AddCardProps) {
|
||||
return (
|
||||
<Card
|
||||
className={cs(styles['card-block'], styles['add-card'])}
|
||||
title={null}
|
||||
bordered={true}
|
||||
size="small"
|
||||
>
|
||||
<div className={styles.content}>
|
||||
<div className={styles['add-icon']}>
|
||||
<IconPlus />
|
||||
</div>
|
||||
<div className={styles.description}>{props.description}</div>
|
||||
</div>
|
||||
</Card>
|
||||
);
|
||||
}
|
||||
|
||||
export default AddCard;
|
||||
@ -1,255 +0,0 @@
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import cs from 'classnames';
|
||||
import {
|
||||
Button,
|
||||
Switch,
|
||||
Tag,
|
||||
Card,
|
||||
Descriptions,
|
||||
Typography,
|
||||
Dropdown,
|
||||
Menu,
|
||||
Skeleton,
|
||||
} from '@arco-design/web-react';
|
||||
import {
|
||||
IconStarFill,
|
||||
IconThumbUpFill,
|
||||
IconSunFill,
|
||||
IconFaceSmileFill,
|
||||
IconPenFill,
|
||||
IconCheckCircleFill,
|
||||
IconCloseCircleFill,
|
||||
IconMore,
|
||||
} from '@arco-design/web-react/icon';
|
||||
import PermissionWrapper from '@/components/PermissionWrapper';
|
||||
import useLocale from '@/utils/useLocale';
|
||||
import locale from './locale';
|
||||
import { QualityInspection, BasicCard } from './interface';
|
||||
import styles from './style/index.module.less';
|
||||
|
||||
interface CardBlockType {
|
||||
type: 'quality' | 'service' | 'rules';
|
||||
card: QualityInspection & BasicCard;
|
||||
loading?: boolean;
|
||||
}
|
||||
|
||||
const IconList = [
|
||||
IconStarFill,
|
||||
IconThumbUpFill,
|
||||
IconSunFill,
|
||||
IconFaceSmileFill,
|
||||
IconPenFill,
|
||||
].map((Tag, index) => <Tag key={index} />);
|
||||
|
||||
const { Paragraph } = Typography;
|
||||
|
||||
function CardBlock(props: CardBlockType) {
|
||||
const { type, card = {} } = props;
|
||||
const [visible, setVisible] = useState(false);
|
||||
const [status, setStatus] = useState(card.status);
|
||||
const [loading, setLoading] = useState(props.loading);
|
||||
|
||||
const t = useLocale(locale);
|
||||
const changeStatus = async () => {
|
||||
setLoading(true);
|
||||
await new Promise((resolve) =>
|
||||
setTimeout(() => {
|
||||
setStatus(status !== 1 ? 1 : 0);
|
||||
resolve(null);
|
||||
}, 1000)
|
||||
).finally(() => setLoading(false));
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
setLoading(props.loading);
|
||||
}, [props.loading]);
|
||||
|
||||
useEffect(() => {
|
||||
if (card.status !== status) {
|
||||
setStatus(card.status);
|
||||
}
|
||||
}, [card.status]);
|
||||
|
||||
const getTitleIcon = () => {
|
||||
if (type === 'service' && typeof card.icon === 'number') {
|
||||
return (
|
||||
<div className={styles.icon}>
|
||||
{IconList[card.icon % IconList.length]}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
const getButtonGroup = () => {
|
||||
if (type === 'quality') {
|
||||
return (
|
||||
<>
|
||||
<PermissionWrapper
|
||||
requiredPermissions={[
|
||||
{ resource: /^menu.list.*/, actions: ['read'] },
|
||||
]}
|
||||
>
|
||||
<Button
|
||||
type="primary"
|
||||
style={{ marginLeft: '12px' }}
|
||||
loading={loading}
|
||||
>
|
||||
{t['cardList.options.qualityInspection']}
|
||||
</Button>
|
||||
</PermissionWrapper>
|
||||
|
||||
<PermissionWrapper
|
||||
requiredPermissions={[
|
||||
{ resource: /^menu.list.*/, actions: ['write'] },
|
||||
]}
|
||||
>
|
||||
<Button loading={loading}>{t['cardList.options.remove']}</Button>
|
||||
</PermissionWrapper>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
if (type === 'service') {
|
||||
return (
|
||||
<>
|
||||
{status === 1 ? (
|
||||
<Button loading={loading} onClick={changeStatus}>
|
||||
{t['cardList.options.cancel']}
|
||||
</Button>
|
||||
) : (
|
||||
<Button type="outline" loading={loading} onClick={changeStatus}>
|
||||
{status === 0
|
||||
? t['cardList.options.subscribe']
|
||||
: t['cardList.options.renewal']}
|
||||
</Button>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<Switch checked={!!status} loading={loading} onChange={changeStatus} />
|
||||
);
|
||||
};
|
||||
|
||||
const getStatus = () => {
|
||||
if (type === 'rules' && status) {
|
||||
return (
|
||||
<Tag
|
||||
color="green"
|
||||
icon={<IconCheckCircleFill />}
|
||||
className={styles.status}
|
||||
size="small"
|
||||
>
|
||||
{t['cardList.tag.activated']}
|
||||
</Tag>
|
||||
);
|
||||
}
|
||||
switch (status) {
|
||||
case 1:
|
||||
return (
|
||||
<Tag
|
||||
color="green"
|
||||
icon={<IconCheckCircleFill />}
|
||||
className={styles.status}
|
||||
size="small"
|
||||
>
|
||||
{t['cardList.tag.opened']}
|
||||
</Tag>
|
||||
);
|
||||
case 2:
|
||||
return (
|
||||
<Tag
|
||||
color="red"
|
||||
icon={<IconCloseCircleFill />}
|
||||
className={styles.status}
|
||||
size="small"
|
||||
>
|
||||
{t['cardList.tag.expired']}
|
||||
</Tag>
|
||||
);
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
const getContent = () => {
|
||||
if (loading) {
|
||||
return (
|
||||
<Skeleton
|
||||
text={{ rows: type !== 'quality' ? 3 : 2 }}
|
||||
animation
|
||||
className={styles['card-block-skeleton']}
|
||||
/>
|
||||
);
|
||||
}
|
||||
if (type !== 'quality') {
|
||||
return <Paragraph>{card.description}</Paragraph>;
|
||||
}
|
||||
return (
|
||||
<Descriptions
|
||||
column={2}
|
||||
data={[
|
||||
{ label: '待质检数', value: card.qualityCount },
|
||||
{ label: '积压时长', value: `${card.duration}s` },
|
||||
{ label: '待抽检数', value: card.randomCount },
|
||||
]}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
const className = cs(styles['card-block'], styles[`${type}-card`]);
|
||||
|
||||
return (
|
||||
<Card
|
||||
bordered={true}
|
||||
className={className}
|
||||
size="small"
|
||||
title={
|
||||
loading ? (
|
||||
<Skeleton
|
||||
animation
|
||||
text={{ rows: 1, width: ['100%'] }}
|
||||
style={{ width: '120px', height: '24px' }}
|
||||
className={styles['card-block-skeleton']}
|
||||
/>
|
||||
) : (
|
||||
<>
|
||||
<div
|
||||
className={cs(styles.title, {
|
||||
[styles['title-more']]: visible,
|
||||
})}
|
||||
>
|
||||
{getTitleIcon()}
|
||||
{card.title}
|
||||
{getStatus()}
|
||||
<Dropdown
|
||||
droplist={
|
||||
<Menu>
|
||||
{['操作1', '操作2'].map((item, key) => (
|
||||
<Menu.Item key={key.toString()}>{item}</Menu.Item>
|
||||
))}
|
||||
</Menu>
|
||||
}
|
||||
trigger="click"
|
||||
onVisibleChange={setVisible}
|
||||
popupVisible={visible}
|
||||
>
|
||||
<div className={styles.more}>
|
||||
<IconMore />
|
||||
</div>
|
||||
</Dropdown>
|
||||
</div>
|
||||
<div className={styles.time}>{card.time}</div>
|
||||
</>
|
||||
)
|
||||
}
|
||||
>
|
||||
<div className={styles.content}>{getContent()}</div>
|
||||
<div className={styles.extra}>{getButtonGroup()}</div>
|
||||
</Card>
|
||||
);
|
||||
}
|
||||
|
||||
export default CardBlock;
|
||||
@ -1,95 +0,0 @@
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import axios from 'axios';
|
||||
import { Tabs, Card, Input, Typography, Grid } from '@arco-design/web-react';
|
||||
import useLocale from '@/utils/useLocale';
|
||||
import locale from './locale';
|
||||
import styles from './style/index.module.less';
|
||||
import CardBlock from './card-block';
|
||||
import AddCard from './card-add';
|
||||
import { QualityInspection, BasicCard } from './interface';
|
||||
import './mock';
|
||||
|
||||
const { Title } = Typography;
|
||||
const { Row, Col } = Grid;
|
||||
|
||||
const defaultList = new Array(10).fill({});
|
||||
export default function ListCard() {
|
||||
const t = useLocale(locale);
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [data, setData] = useState({
|
||||
quality: defaultList,
|
||||
service: defaultList,
|
||||
rules: defaultList,
|
||||
});
|
||||
|
||||
const [activeKey, setActiveKey] = useState('all');
|
||||
|
||||
const getData = () => {
|
||||
axios
|
||||
.get('/api/cardList')
|
||||
.then((res) => {
|
||||
setData(res.data);
|
||||
})
|
||||
.finally(() => setLoading(false));
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
getData();
|
||||
}, []);
|
||||
7;
|
||||
const getCardList = (
|
||||
list: Array<BasicCard & QualityInspection>,
|
||||
type: keyof typeof data
|
||||
) => {
|
||||
return (
|
||||
<Row gutter={24} className={styles['card-content']}>
|
||||
{type === 'quality' && (
|
||||
<Col xs={24} sm={12} md={8} lg={6} xl={6} xxl={6}>
|
||||
<AddCard description={t['cardList.add.quality']} />
|
||||
</Col>
|
||||
)}
|
||||
{list.map((item, index) => (
|
||||
<Col xs={24} sm={12} md={8} lg={6} xl={6} xxl={6} key={index}>
|
||||
<CardBlock card={item} type={type} loading={loading} />
|
||||
</Col>
|
||||
))}
|
||||
</Row>
|
||||
);
|
||||
};
|
||||
|
||||
return (
|
||||
<Card>
|
||||
<Title heading={6}>{t['menu.list.card']}</Title>
|
||||
<Tabs
|
||||
activeTab={activeKey}
|
||||
type="rounded"
|
||||
onChange={setActiveKey}
|
||||
extra={
|
||||
<Input.Search
|
||||
style={{ width: '240px' }}
|
||||
placeholder={t[`cardList.tab.${activeKey}.placeholder`]}
|
||||
/>
|
||||
}
|
||||
>
|
||||
<Tabs.TabPane key="all" title={t['cardList.tab.title.all']} />
|
||||
<Tabs.TabPane key="quality" title={t['cardList.tab.title.quality']} />
|
||||
<Tabs.TabPane key="service" title={t['cardList.tab.title.service']} />
|
||||
<Tabs.TabPane key="rules" title={t['cardList.tab.title.rules']} />
|
||||
</Tabs>
|
||||
<div className={styles.container}>
|
||||
{activeKey === 'all' ? (
|
||||
Object.entries(data).map(([key, list]) => (
|
||||
<div key={key}>
|
||||
<Title heading={6}>{t[`cardList.tab.title.${key}`]}</Title>
|
||||
{getCardList(list, key as keyof typeof data)}
|
||||
</div>
|
||||
))
|
||||
) : (
|
||||
<div className={styles['single-content']}>
|
||||
{getCardList(data[activeKey], activeKey as keyof typeof data)}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</Card>
|
||||
);
|
||||
}
|
||||
@ -1,13 +0,0 @@
|
||||
export interface QualityInspection {
|
||||
title?: string;
|
||||
time?: string;
|
||||
qualityCount?: number;
|
||||
randomCount?: number;
|
||||
duration?: number;
|
||||
}
|
||||
|
||||
export interface BasicCard {
|
||||
icon?: number;
|
||||
status?: 0 | 1 | 2;
|
||||
description?: string;
|
||||
}
|
||||
@ -1,66 +0,0 @@
|
||||
const i18n = {
|
||||
'en-US': {
|
||||
'menu.list': 'List',
|
||||
'menu.list.card': 'Card List',
|
||||
'cardList.tab.title.all': 'All',
|
||||
'cardList.tab.title.quality': 'Content quality',
|
||||
'cardList.tab.title.service': 'Service opening',
|
||||
'cardList.tab.title.rules': 'Rule presets',
|
||||
'cardList.tab.all.placeholder': 'Search',
|
||||
'cardList.tab.quality.placeholder': 'Search queue',
|
||||
'cardList.tab.service.placeholder': 'Search service',
|
||||
'cardList.tab.rules.placeholder': 'Search rule',
|
||||
'cardList.searchInput.placeholder': 'Search service',
|
||||
'cardList.add.quality': 'Create quality inspection queue',
|
||||
'cardList.enable': 'Enable',
|
||||
'cardList.disable': 'Disable',
|
||||
'cardList.action': 'action',
|
||||
'cardList.detail': 'Detail',
|
||||
'cardList.tab.title.announcement': 'Recent Announcement',
|
||||
'cardList.announcement.noData': 'No announcement',
|
||||
'cardList.statistic.enable': 'Enable',
|
||||
'cardList.statistic.disable': 'Disable',
|
||||
'cardList.statistic.applicationNum': 'Applications',
|
||||
'cardList.options.qualityInspection': 'Quality inspection',
|
||||
'cardList.options.remove': 'Remove',
|
||||
'cardList.options.cancel': 'Cancel',
|
||||
'cardList.options.subscribe': 'Subscribe',
|
||||
'cardList.options.renewal': 'Renewal',
|
||||
'cardList.tag.activated': 'Activated',
|
||||
'cardList.tag.opened': 'Already Opened',
|
||||
'cardList.tag.expired': 'Expired',
|
||||
},
|
||||
'zh-CN': {
|
||||
'menu.list': '列表页',
|
||||
'menu.list.card': '卡片列表',
|
||||
'cardList.tab.title.all': '全部',
|
||||
'cardList.tab.title.quality': '内容质检',
|
||||
'cardList.tab.title.service': '服务开通',
|
||||
'cardList.tab.title.rules': '规则预置',
|
||||
'cardList.tab.all.placeholder': '搜索',
|
||||
'cardList.tab.quality.placeholder': '搜索队列',
|
||||
'cardList.tab.service.placeholder': '搜索服务',
|
||||
'cardList.tab.rules.placeholder': '搜索规则',
|
||||
'cardList.searchInput.placeholder': '搜索服务',
|
||||
'cardList.add.quality': '点击创建质检内容队列',
|
||||
'cardList.enable': '启用',
|
||||
'cardList.disable': '禁用',
|
||||
'cardList.action': '操作',
|
||||
'cardList.detail': '详细信息',
|
||||
'cardList.tab.title.announcement': '最近公告',
|
||||
'cardList.announcement.noData': '暂无公告',
|
||||
'cardList.statistic.enable': '已启用',
|
||||
'cardList.statistic.disable': '未启用',
|
||||
'cardList.statistic.applicationNum': '应用数',
|
||||
'cardList.options.qualityInspection': '质检',
|
||||
'cardList.options.remove': '删除',
|
||||
'cardList.options.cancel': '取消开通',
|
||||
'cardList.options.subscribe': '开通服务',
|
||||
'cardList.options.renewal': '续约服务',
|
||||
'cardList.tag.activated': '已启用',
|
||||
'cardList.tag.opened': '已开通',
|
||||
'cardList.tag.expired': '已过期',
|
||||
},
|
||||
};
|
||||
|
||||
export default i18n;
|
||||
@ -1,156 +0,0 @@
|
||||
.container {
|
||||
:global(.arco-list-content) {
|
||||
overflow-x: hidden;
|
||||
}
|
||||
|
||||
:global(.arco-card-meta-title) {
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
h6 {
|
||||
font-size: 14px;
|
||||
margin-top: 16px;
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
.card-content {
|
||||
min-height: 180px;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.single-content {
|
||||
margin-top: 30px;
|
||||
}
|
||||
}
|
||||
|
||||
.card-block {
|
||||
margin-bottom: 16px;
|
||||
|
||||
:global(.arco-card-header) {
|
||||
border-bottom: none;
|
||||
height: auto;
|
||||
padding: 16px;
|
||||
padding-bottom: 0;
|
||||
}
|
||||
|
||||
.title {
|
||||
display: flex;
|
||||
line-height: 24px;
|
||||
align-items: center;
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
|
||||
.icon {
|
||||
height: 24px;
|
||||
width: 24px;
|
||||
color: var(--color-white);
|
||||
background: #626aea;
|
||||
text-align: center;
|
||||
line-height: 24px;
|
||||
border-radius: 50%;
|
||||
margin-right: 8px;
|
||||
}
|
||||
|
||||
.status {
|
||||
margin-left: 12px;
|
||||
}
|
||||
|
||||
.more {
|
||||
color: var(--color-text-4);
|
||||
font-size: 16px;
|
||||
position: absolute;
|
||||
right: 16px;
|
||||
cursor: pointer;
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.title-more {
|
||||
.more {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
.time,
|
||||
.content > :global(.arco-typography),
|
||||
:global(.arco-descriptions-item-label),
|
||||
:global(.arco-descriptions-item-value) {
|
||||
font-size: 12px;
|
||||
font-weight: 400;
|
||||
color: var(--color-text-3);
|
||||
padding: 0;
|
||||
line-height: 20px;
|
||||
}
|
||||
|
||||
:global(.arco-descriptions-item-value) {
|
||||
color: var(--color-text-2);
|
||||
padding-left: 6px;
|
||||
}
|
||||
|
||||
.content {
|
||||
height: 48px;
|
||||
}
|
||||
|
||||
.extra {
|
||||
display: flex;
|
||||
flex-direction: row-reverse;
|
||||
}
|
||||
|
||||
&-skeleton {
|
||||
:global(.arco-skeleton-content .arco-skeleton-text-row:not(:last-child)) {
|
||||
height: 14px;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.card-block:hover {
|
||||
box-shadow: 4px 4px 10px rgba(0, 0, 0, 10%);
|
||||
|
||||
.title {
|
||||
.more {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.add-card {
|
||||
text-align: center;
|
||||
cursor: pointer;
|
||||
|
||||
.add-icon {
|
||||
font-size: 22px;
|
||||
}
|
||||
|
||||
.description {
|
||||
margin-top: 16px;
|
||||
color: var(--color-text-3);
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
:global(.arco-card-body) {
|
||||
padding-top: 52px;
|
||||
padding-bottom: 64px;
|
||||
}
|
||||
}
|
||||
|
||||
.service-card {
|
||||
:global(.arco-card-body) {
|
||||
padding: 12px 16px 16px 48px;
|
||||
}
|
||||
|
||||
.content {
|
||||
margin-bottom: 10px;
|
||||
height: 60px;
|
||||
}
|
||||
}
|
||||
|
||||
.rules-card {
|
||||
:global(.arco-card-body) {
|
||||
padding: 12px 16px 16px;
|
||||
}
|
||||
|
||||
.content {
|
||||
margin-bottom: 14px;
|
||||
}
|
||||
}
|
||||
@ -1,21 +0,0 @@
|
||||
import axios from 'axios';
|
||||
import { useEffect, useState } from 'react';
|
||||
|
||||
export default <T>(url: string, defaultValue: T[]): [boolean, T[]] => {
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [data, setData] = useState<T[]>(defaultValue);
|
||||
|
||||
useEffect(() => {
|
||||
setLoading(true);
|
||||
axios
|
||||
.get(url)
|
||||
.then((res) => {
|
||||
setData(res.data);
|
||||
})
|
||||
.finally(() => {
|
||||
setLoading(false);
|
||||
});
|
||||
}, [url]);
|
||||
|
||||
return [loading, data];
|
||||
};
|
||||
@ -1,91 +0,0 @@
|
||||
import React from 'react';
|
||||
import { Button, Typography, Badge } from '@arco-design/web-react';
|
||||
import IconText from './icons/text.svg';
|
||||
import IconHorizontalVideo from './icons/horizontal.svg';
|
||||
import IconVerticalVideo from './icons/vertical.svg';
|
||||
import dayjs from 'dayjs';
|
||||
import styles from './style/index.module.less';
|
||||
|
||||
const { Text } = Typography;
|
||||
|
||||
export const ContentType = ['图文', '横版短视频', '竖版短视频'];
|
||||
export const FilterType = ['规则筛选', '人工'];
|
||||
export const Status = ['未上线', '已上线'];
|
||||
|
||||
const ContentIcon = [
|
||||
<IconText key={0} />,
|
||||
<IconHorizontalVideo key={1} />,
|
||||
<IconVerticalVideo key={2} />,
|
||||
];
|
||||
|
||||
export function getColumns(
|
||||
t: any,
|
||||
callback: (record: Record<string, any>, type: string) => Promise<void>
|
||||
) {
|
||||
return [
|
||||
{
|
||||
title: t['searchTable.columns.id'],
|
||||
dataIndex: 'id',
|
||||
render: (value) => <Text copyable>{value}</Text>,
|
||||
},
|
||||
{
|
||||
title: t['searchTable.columns.name'],
|
||||
dataIndex: 'name',
|
||||
},
|
||||
{
|
||||
title: t['searchTable.columns.contentType'],
|
||||
dataIndex: 'contentType',
|
||||
render: (value) => (
|
||||
<div className={styles['content-type']}>
|
||||
{ContentIcon[value]}
|
||||
{ContentType[value]}
|
||||
</div>
|
||||
),
|
||||
},
|
||||
{
|
||||
title: t['searchTable.columns.filterType'],
|
||||
dataIndex: 'filterType',
|
||||
render: (value) => FilterType[value],
|
||||
},
|
||||
{
|
||||
title: t['searchTable.columns.contentNum'],
|
||||
dataIndex: 'count',
|
||||
sorter: (a, b) => a.count - b.count,
|
||||
render(x) {
|
||||
return Number(x).toLocaleString();
|
||||
},
|
||||
},
|
||||
{
|
||||
title: t['searchTable.columns.createdTime'],
|
||||
dataIndex: 'createdTime',
|
||||
render: (x) => dayjs().subtract(x, 'days').format('YYYY-MM-DD HH:mm:ss'),
|
||||
sorter: (a, b) => b.createdTime - a.createdTime,
|
||||
},
|
||||
{
|
||||
title: t['searchTable.columns.status'],
|
||||
dataIndex: 'status',
|
||||
render: (x) => {
|
||||
if (x === 0) {
|
||||
return <Badge status="error" text={Status[x]}></Badge>;
|
||||
}
|
||||
return <Badge status="success" text={Status[x]}></Badge>;
|
||||
},
|
||||
},
|
||||
{
|
||||
title: t['searchTable.columns.operations'],
|
||||
dataIndex: 'operations',
|
||||
headerCellStyle: { paddingLeft: '15px' },
|
||||
render: (_, record) => (
|
||||
<Button
|
||||
type="text"
|
||||
size="small"
|
||||
onClick={() => callback(record, 'view')}
|
||||
>
|
||||
{t['searchTable.columns.operations.view']}
|
||||
</Button>
|
||||
),
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
export default () => ContentIcon;
|
||||
@ -1,135 +0,0 @@
|
||||
import React, { useContext } from 'react';
|
||||
import dayjs from 'dayjs';
|
||||
import {
|
||||
Form,
|
||||
Input,
|
||||
Select,
|
||||
DatePicker,
|
||||
Button,
|
||||
Grid,
|
||||
} from '@arco-design/web-react';
|
||||
import { GlobalContext } from '@/context';
|
||||
import locale from './locale';
|
||||
import useLocale from '@/utils/useLocale';
|
||||
import { IconRefresh, IconSearch } from '@arco-design/web-react/icon';
|
||||
import { ContentType, FilterType, Status } from './constants';
|
||||
import styles from './style/index.module.less';
|
||||
|
||||
const { Row, Col } = Grid;
|
||||
const { useForm } = Form;
|
||||
|
||||
function SearchForm(props: {
|
||||
onSearch: (values: Record<string, any>) => void;
|
||||
}) {
|
||||
const { lang } = useContext(GlobalContext);
|
||||
|
||||
const t = useLocale(locale);
|
||||
const [form] = useForm();
|
||||
|
||||
const handleSubmit = () => {
|
||||
const values = form.getFieldsValue();
|
||||
props.onSearch(values);
|
||||
};
|
||||
|
||||
const handleReset = () => {
|
||||
form.resetFields();
|
||||
props.onSearch({});
|
||||
};
|
||||
|
||||
const colSpan = lang === 'zh-CN' ? 8 : 12;
|
||||
|
||||
return (
|
||||
<div className={styles['search-form-wrapper']}>
|
||||
<Form
|
||||
form={form}
|
||||
className={styles['search-form']}
|
||||
labelAlign="left"
|
||||
labelCol={{ span: 5 }}
|
||||
wrapperCol={{ span: 19 }}
|
||||
>
|
||||
<Row gutter={24}>
|
||||
<Col span={colSpan}>
|
||||
<Form.Item label={t['searchTable.columns.id']} field="id">
|
||||
<Input placeholder={t['searchForm.id.placeholder']} allowClear />
|
||||
</Form.Item>
|
||||
</Col>
|
||||
<Col span={colSpan}>
|
||||
<Form.Item label={t['searchTable.columns.name']} field="name">
|
||||
<Input
|
||||
allowClear
|
||||
placeholder={t['searchForm.name.placeholder']}
|
||||
/>
|
||||
</Form.Item>
|
||||
</Col>
|
||||
<Col span={colSpan}>
|
||||
<Form.Item
|
||||
label={t['searchTable.columns.contentType']}
|
||||
field="contentType"
|
||||
>
|
||||
<Select
|
||||
placeholder={t['searchForm.all.placeholder']}
|
||||
options={ContentType.map((item, index) => ({
|
||||
label: item,
|
||||
value: index,
|
||||
}))}
|
||||
mode="multiple"
|
||||
allowClear
|
||||
/>
|
||||
</Form.Item>
|
||||
</Col>
|
||||
<Col span={colSpan}>
|
||||
<Form.Item
|
||||
label={t['searchTable.columns.filterType']}
|
||||
field="filterType"
|
||||
>
|
||||
<Select
|
||||
placeholder={t['searchForm.all.placeholder']}
|
||||
options={FilterType.map((item, index) => ({
|
||||
label: item,
|
||||
value: index,
|
||||
}))}
|
||||
mode="multiple"
|
||||
allowClear
|
||||
/>
|
||||
</Form.Item>
|
||||
</Col>
|
||||
<Col span={colSpan}>
|
||||
<Form.Item
|
||||
label={t['searchTable.columns.createdTime']}
|
||||
field="createdTime"
|
||||
>
|
||||
<DatePicker.RangePicker
|
||||
allowClear
|
||||
style={{ width: '100%' }}
|
||||
disabledDate={(date) => dayjs(date).isAfter(dayjs())}
|
||||
/>
|
||||
</Form.Item>
|
||||
</Col>
|
||||
<Col span={colSpan}>
|
||||
<Form.Item label={t['searchTable.columns.status']} field="status">
|
||||
<Select
|
||||
placeholder={t['searchForm.all.placeholder']}
|
||||
options={Status.map((item, index) => ({
|
||||
label: item,
|
||||
value: index,
|
||||
}))}
|
||||
mode="multiple"
|
||||
allowClear
|
||||
/>
|
||||
</Form.Item>
|
||||
</Col>
|
||||
</Row>
|
||||
</Form>
|
||||
<div className={styles['right-button']}>
|
||||
<Button type="primary" icon={<IconSearch />} onClick={handleSubmit}>
|
||||
{t['searchTable.form.search']}
|
||||
</Button>
|
||||
<Button icon={<IconRefresh />} onClick={handleReset}>
|
||||
{t['searchTable.form.reset']}
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default SearchForm;
|
||||
@ -1,20 +0,0 @@
|
||||
<svg width="15" height="15" viewBox="0 0 15 15" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<rect y="1" width="14" height="14" rx="1.67" fill="#FFDDE0"/>
|
||||
<path d="M0.0708579 2.61134C0.0786468 1.68906 0.832619 0.94772 1.7549 0.955509L12.414 1.04553C13.3363 1.05332 14.0776 1.80729 14.0699 2.72957L13.999 11.1181L1.49778e-05 10.9999L0.0708579 2.61134Z" fill="#FF8B96"/>
|
||||
<g opacity="0.9" filter="url(#filter0_d_422_41703)">
|
||||
<path d="M5.32269 7.78472V4.65415C5.32269 4.18777 5.83148 3.8997 6.23139 4.13965L8.8402 5.70494C9.2286 5.93798 9.2286 6.50089 8.8402 6.73393L6.23139 8.29922C5.83148 8.53917 5.32269 8.2511 5.32269 7.78472Z" fill="#FFEDEF"/>
|
||||
</g>
|
||||
<rect opacity="0.6" width="10" height="1" rx="0.4" transform="matrix(1 0 0 -1 2.04199 13.5156)" fill="#FF727F"/>
|
||||
<defs>
|
||||
<filter id="filter0_d_422_41703" x="3.6636" y="2.39413" width="7.12699" height="7.65071" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
||||
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
||||
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
|
||||
<feOffset/>
|
||||
<feGaussianBlur stdDeviation="0.829547"/>
|
||||
<feComposite in2="hardAlpha" operator="out"/>
|
||||
<feColorMatrix type="matrix" values="0 0 0 0 0.8625 0 0 0 0 0.280312 0 0 0 0 0.33552 0 0 0 0.8 0"/>
|
||||
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_422_41703"/>
|
||||
<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow_422_41703" result="shape"/>
|
||||
</filter>
|
||||
</defs>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 1.5 KiB |
@ -1,41 +0,0 @@
|
||||
<svg width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M0 2C0 0.89543 0.895431 0 2 0H12C13.1046 0 14 0.895431 14 2V12C14 13.1046 13.1046 14 12 14H2C0.895431 14 0 13.1046 0 12V2Z" fill="url(#paint0_linear_422_41656)"/>
|
||||
<g opacity="0.9" filter="url(#filter0_d_422_41656)">
|
||||
<path d="M4.48218 3.23096C4.81406 3.23101 5.13232 3.36289 5.36695 3.59758C5.60159 3.83228 5.73337 4.15056 5.73332 4.48241C5.73326 4.81426 5.60137 5.13249 5.36666 5.36711C5.13195 5.60172 4.81364 5.73349 4.48176 5.73344C4.14989 5.73333 3.83165 5.6014 3.59705 5.36666C3.36246 5.13193 3.23072 4.81363 3.23084 4.48178C3.23095 4.14993 3.36289 3.83172 3.59764 3.59714C3.83239 3.36257 4.15072 3.23085 4.4826 3.23096H4.48218Z" fill="white"/>
|
||||
</g>
|
||||
<g clip-path="url(#clip0_422_41656)">
|
||||
<g opacity="0.9" filter="url(#filter1_d_422_41656)">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M8.92035 17.5178C10.868 17.5178 12.447 15.0428 12.447 11.9896C12.447 8.93649 10.868 6.46143 8.92035 6.46143C7.69985 6.46143 6.62416 7.43332 5.99105 8.91033C5.58344 8.38402 5.03884 8.06253 4.44061 8.06253C3.17724 8.06253 2.15308 9.49636 2.15308 11.2651C2.15308 13.0338 3.17724 14.4676 4.44061 14.4676C4.87779 14.4676 5.28633 14.2959 5.6337 13.9981C6.14641 16.0582 7.42464 17.5178 8.92035 17.5178Z" fill="white"/>
|
||||
</g>
|
||||
</g>
|
||||
<defs>
|
||||
<filter id="filter0_d_422_41656" x="0.308552" y="2.25686" width="8.34704" height="8.34701" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
||||
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
||||
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
|
||||
<feOffset dy="1.94819"/>
|
||||
<feGaussianBlur stdDeviation="1.46114"/>
|
||||
<feComposite in2="hardAlpha" operator="out"/>
|
||||
<feColorMatrix type="matrix" values="0 0 0 0 0.207843 0 0 0 0 0.701961 0 0 0 0 0.94902 0 0 0 1 0"/>
|
||||
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_422_41656"/>
|
||||
<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow_422_41656" result="shape"/>
|
||||
</filter>
|
||||
<filter id="filter1_d_422_41656" x="-0.5182" y="5.571" width="15.6364" height="16.3989" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
||||
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
||||
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
|
||||
<feOffset dy="1.78085"/>
|
||||
<feGaussianBlur stdDeviation="1.33564"/>
|
||||
<feComposite in2="hardAlpha" operator="out"/>
|
||||
<feColorMatrix type="matrix" values="0 0 0 0 0.207843 0 0 0 0 0.701961 0 0 0 0 0.94902 0 0 0 1 0"/>
|
||||
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_422_41656"/>
|
||||
<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow_422_41656" result="shape"/>
|
||||
</filter>
|
||||
<linearGradient id="paint0_linear_422_41656" x1="0" y1="0" x2="9.36513" y2="14.6703" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#1B9FFF"/>
|
||||
<stop offset="0.0001" stop-color="#479AFB"/>
|
||||
<stop offset="1" stop-color="#77C6FF"/>
|
||||
</linearGradient>
|
||||
<clipPath id="clip0_422_41656">
|
||||
<rect x="2.15375" y="6.46143" width="10.2939" height="4.95632" rx="2" fill="white"/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 3.1 KiB |
@ -1,24 +0,0 @@
|
||||
<svg width="13" height="16" viewBox="0 0 13 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<rect opacity="0.9" width="13" height="16" rx="1.67" fill="url(#paint0_linear_422_41748)"/>
|
||||
<g opacity="0.9" filter="url(#filter0_d_422_41748)">
|
||||
<path d="M5 7.91745V5.08255C5 4.61129 5.51837 4.32398 5.918 4.57375L8.18592 5.9912C8.56192 6.2262 8.56192 6.7738 8.18592 7.0088L5.918 8.42625C5.51837 8.67602 5 8.38871 5 7.91745Z" fill="white"/>
|
||||
</g>
|
||||
<rect opacity="0.8" width="9" height="1" rx="0.315789" transform="matrix(1 0 0 -1 2 12)" fill="#FFF5E8"/>
|
||||
<rect opacity="0.8" width="6" height="1" rx="0.315789" transform="matrix(1 0 0 -1 2 14)" fill="#FFF5E8"/>
|
||||
<defs>
|
||||
<filter id="filter0_d_422_41748" x="3.73684" y="3.21853" width="5.99424" height="6.56294" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
||||
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
||||
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
|
||||
<feOffset/>
|
||||
<feGaussianBlur stdDeviation="0.631579"/>
|
||||
<feComposite in2="hardAlpha" operator="out"/>
|
||||
<feColorMatrix type="matrix" values="0 0 0 0 0.870833 0 0 0 0 0.554311 0 0 0 0 0.148767 0 0 0 0.8 0"/>
|
||||
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_422_41748"/>
|
||||
<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow_422_41748" result="shape"/>
|
||||
</filter>
|
||||
<linearGradient id="paint0_linear_422_41748" x1="0.5" y1="0.5" x2="12.5" y2="15.5" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#FF8A00"/>
|
||||
<stop offset="1" stop-color="#FFC581"/>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 1.6 KiB |
@ -1,120 +0,0 @@
|
||||
import React, { useState, useEffect, useMemo } from 'react';
|
||||
import {
|
||||
Table,
|
||||
Card,
|
||||
PaginationProps,
|
||||
Button,
|
||||
Space,
|
||||
Typography,
|
||||
} from '@arco-design/web-react';
|
||||
import PermissionWrapper from '@/components/PermissionWrapper';
|
||||
import { IconDownload, IconPlus } from '@arco-design/web-react/icon';
|
||||
import axios from 'axios';
|
||||
import useLocale from '@/utils/useLocale';
|
||||
import SearchForm from './form';
|
||||
import locale from './locale';
|
||||
import styles from './style/index.module.less';
|
||||
import './mock';
|
||||
import { getColumns } from './constants';
|
||||
|
||||
const { Title } = Typography;
|
||||
export const ContentType = ['图文', '横版短视频', '竖版短视频'];
|
||||
export const FilterType = ['规则筛选', '人工'];
|
||||
export const Status = ['已上线', '未上线'];
|
||||
|
||||
function SearchTable() {
|
||||
const t = useLocale(locale);
|
||||
|
||||
const tableCallback = async (record, type) => {
|
||||
console.log(record, type);
|
||||
};
|
||||
|
||||
const columns = useMemo(() => getColumns(t, tableCallback), [t]);
|
||||
|
||||
const [data, setData] = useState([]);
|
||||
const [pagination, setPatination] = useState<PaginationProps>({
|
||||
sizeCanChange: true,
|
||||
showTotal: true,
|
||||
pageSize: 10,
|
||||
current: 1,
|
||||
pageSizeChangeResetCurrent: true,
|
||||
});
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [formParams, setFormParams] = useState({});
|
||||
|
||||
useEffect(() => {
|
||||
fetchData();
|
||||
}, [pagination.current, pagination.pageSize, JSON.stringify(formParams)]);
|
||||
|
||||
function fetchData() {
|
||||
const { current, pageSize } = pagination;
|
||||
setLoading(true);
|
||||
axios
|
||||
.get('/api/list', {
|
||||
params: {
|
||||
page: current,
|
||||
pageSize,
|
||||
...formParams,
|
||||
},
|
||||
})
|
||||
.then((res) => {
|
||||
setData(res.data.list);
|
||||
setPatination({
|
||||
...pagination,
|
||||
current,
|
||||
pageSize,
|
||||
total: res.data.total,
|
||||
});
|
||||
setLoading(false);
|
||||
});
|
||||
}
|
||||
|
||||
function onChangeTable({ current, pageSize }) {
|
||||
setPatination({
|
||||
...pagination,
|
||||
current,
|
||||
pageSize,
|
||||
});
|
||||
}
|
||||
|
||||
function handleSearch(params) {
|
||||
setPatination({ ...pagination, current: 1 });
|
||||
setFormParams(params);
|
||||
}
|
||||
|
||||
return (
|
||||
<Card>
|
||||
<Title heading={6}>{t['menu.list.searchTable']}</Title>
|
||||
<SearchForm onSearch={handleSearch} />
|
||||
<PermissionWrapper
|
||||
requiredPermissions={[
|
||||
{ resource: 'menu.list.searchTable', actions: ['write'] },
|
||||
]}
|
||||
>
|
||||
<div className={styles['button-group']}>
|
||||
<Space>
|
||||
<Button type="primary" icon={<IconPlus />}>
|
||||
{t['searchTable.operations.add']}
|
||||
</Button>
|
||||
<Button>{t['searchTable.operations.upload']}</Button>
|
||||
</Space>
|
||||
<Space>
|
||||
<Button icon={<IconDownload />}>
|
||||
{t['searchTable.operation.download']}
|
||||
</Button>
|
||||
</Space>
|
||||
</div>
|
||||
</PermissionWrapper>
|
||||
<Table
|
||||
rowKey="id"
|
||||
loading={loading}
|
||||
onChange={onChangeTable}
|
||||
pagination={pagination}
|
||||
columns={columns}
|
||||
data={data}
|
||||
/>
|
||||
</Card>
|
||||
);
|
||||
}
|
||||
|
||||
export default SearchTable;
|
||||
@ -1,52 +0,0 @@
|
||||
const i18n = {
|
||||
'en-US': {
|
||||
'menu.list': 'List',
|
||||
'menu.list.searchTable': 'Search Table',
|
||||
'searchTable.form.search': 'Search',
|
||||
'searchTable.form.reset': 'Reset',
|
||||
'searchTable.columns.id': 'Collection ID',
|
||||
'searchTable.columns.name': 'Collection Name',
|
||||
'searchTable.columns.contentType': 'Content genre',
|
||||
'searchTable.columns.filterType': 'Filter method',
|
||||
'searchTable.columns.createdTime': 'Creation time',
|
||||
'searchTable.columns.status': 'Status',
|
||||
'searchTable.columns.contentNum': 'Content quantity',
|
||||
'searchTable.columns.operations': 'Operation',
|
||||
'searchTable.columns.operations.view': 'View',
|
||||
'searchTable.columns.operations.update': 'Edit',
|
||||
'searchTable.columns.operations.offline': 'Offline',
|
||||
'searchTable.columns.operations.online': 'Online',
|
||||
'searchTable.operations.add': 'New',
|
||||
'searchTable.operations.upload': 'Bulk upload',
|
||||
'searchTable.operation.download': 'Download',
|
||||
'searchForm.id.placeholder': 'Please enter the collection ID',
|
||||
'searchForm.name.placeholder': 'Please enter the collection name',
|
||||
'searchForm.all.placeholder': 'all',
|
||||
},
|
||||
'zh-CN': {
|
||||
'menu.list': '列表页',
|
||||
'menu.list.searchTable': '查询表格',
|
||||
'searchTable.form.search': '查询',
|
||||
'searchTable.form.reset': '重置',
|
||||
'searchTable.columns.id': '集合编号',
|
||||
'searchTable.columns.name': '集合名称',
|
||||
'searchTable.columns.contentType': '内容体裁',
|
||||
'searchTable.columns.filterType': '筛选方式',
|
||||
'searchTable.columns.createdTime': '创建时间',
|
||||
'searchTable.columns.status': '状态',
|
||||
'searchTable.columns.contentNum': '内容量',
|
||||
'searchTable.columns.operations': '操作',
|
||||
'searchTable.columns.operations.view': '查看',
|
||||
'searchTable.columns.operations.update': '修改',
|
||||
'searchTable.columns.operations.online': '上线',
|
||||
'searchTable.columns.operations.offline': '下线',
|
||||
'searchTable.operations.add': '新建',
|
||||
'searchTable.operations.upload': '批量导入',
|
||||
'searchTable.operation.download': '下载',
|
||||
'searchForm.id.placeholder': '请输入集合编号',
|
||||
'searchForm.name.placeholder': '请输入集合名称',
|
||||
'searchForm.all.placeholder': '全部',
|
||||
},
|
||||
};
|
||||
|
||||
export default i18n;
|
||||
@ -1,99 +0,0 @@
|
||||
import Mock from 'mockjs';
|
||||
import qs from 'query-string';
|
||||
import dayjs from 'dayjs';
|
||||
import setupMock from '@/utils/setupMock';
|
||||
|
||||
const { list } = Mock.mock({
|
||||
'list|100': [
|
||||
{
|
||||
id: /[0-9]{8}[-][0-9]{4}/,
|
||||
name: () =>
|
||||
Mock.Random.pick([
|
||||
'每日推荐视频集',
|
||||
'抖音短视频候选集',
|
||||
'国际新闻集合',
|
||||
]),
|
||||
'contentType|0-2': 0,
|
||||
'filterType|0-1': 0,
|
||||
'count|0-2000': 0,
|
||||
'createdTime|1-60': 0,
|
||||
'status|0-1': 0,
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
const filterData = (
|
||||
rest: {
|
||||
id?: string;
|
||||
name?: string;
|
||||
'contentType[]'?: string[];
|
||||
'filterType[]'?: string[];
|
||||
'createdTime[]'?: string[];
|
||||
'status[]'?: string;
|
||||
} = {}
|
||||
) => {
|
||||
const {
|
||||
id,
|
||||
name,
|
||||
'contentType[]': contentType,
|
||||
'filterType[]': filterType,
|
||||
'createdTime[]': createdTime,
|
||||
'status[]': status,
|
||||
} = rest;
|
||||
if (id) {
|
||||
return list.filter((item) => item.id === id);
|
||||
}
|
||||
let result = [...list];
|
||||
if (name) {
|
||||
result = result.filter((item) => {
|
||||
return (item.name as string).toLowerCase().includes(name.toLowerCase());
|
||||
});
|
||||
}
|
||||
if (contentType) {
|
||||
result = result.filter((item) =>
|
||||
contentType.includes(item.contentType.toString())
|
||||
);
|
||||
}
|
||||
if (filterType) {
|
||||
result = result.filter((item) =>
|
||||
filterType.includes(item.filterType.toString())
|
||||
);
|
||||
}
|
||||
if (createdTime && createdTime.length === 2) {
|
||||
const [begin, end] = createdTime;
|
||||
result = result.filter((item) => {
|
||||
const time = dayjs()
|
||||
.subtract(item.createdTime, 'days')
|
||||
.format('YYYY-MM-DD HH:mm:ss');
|
||||
return (
|
||||
!dayjs(time).isBefore(dayjs(begin)) && !dayjs(time).isAfter(dayjs(end))
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
if (status && status.length) {
|
||||
result = result.filter((item) => status.includes(item.status.toString()));
|
||||
}
|
||||
|
||||
return result;
|
||||
};
|
||||
|
||||
setupMock({
|
||||
setup: () => {
|
||||
Mock.mock(new RegExp('/api/list'), (params) => {
|
||||
const {
|
||||
page = 1,
|
||||
pageSize = 10,
|
||||
...rest
|
||||
} = qs.parseUrl(params.url).query;
|
||||
const p = page as number;
|
||||
const ps = pageSize as number;
|
||||
|
||||
const result = filterData(rest);
|
||||
return {
|
||||
list: result.slice((p - 1) * ps, p * ps),
|
||||
total: result.length,
|
||||
};
|
||||
});
|
||||
},
|
||||
});
|
||||
@ -1,50 +0,0 @@
|
||||
.toolbar {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
|
||||
.operations {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.content-type {
|
||||
display: flex;
|
||||
|
||||
> svg {
|
||||
margin-right: 8px;
|
||||
margin-top: 3px;
|
||||
}
|
||||
}
|
||||
|
||||
.search-form-wrapper {
|
||||
display: flex;
|
||||
border-bottom: 1px solid var(--color-border-1);
|
||||
margin-bottom: 20px;
|
||||
|
||||
.right-button {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
padding-left: 20px;
|
||||
margin-bottom: 20px;
|
||||
border-left: 1px solid var(--color-border-2);
|
||||
box-sizing: border-box;
|
||||
}
|
||||
}
|
||||
|
||||
.button-group {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.search-form {
|
||||
padding-right: 20px;
|
||||
|
||||
:global(.arco-form-label-item-left) {
|
||||
> label {
|
||||
white-space: nowrap;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,164 +0,0 @@
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import {
|
||||
Card,
|
||||
Steps,
|
||||
Typography,
|
||||
Grid,
|
||||
Space,
|
||||
Button,
|
||||
Table,
|
||||
Badge,
|
||||
} from '@arco-design/web-react';
|
||||
import axios from 'axios';
|
||||
import useLocale from '@/utils/useLocale';
|
||||
import locale from './locale';
|
||||
import ProfileItem from './item';
|
||||
import styles from './style/index.module.less';
|
||||
import './mock';
|
||||
|
||||
function BasicProfile() {
|
||||
const t = useLocale(locale);
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [data, setData] = useState({ status: 1 });
|
||||
const [preLoading, setPreLoading] = useState(false);
|
||||
const [preData, setPreData] = useState({});
|
||||
const [tableLoading, setTableLoading] = useState(false);
|
||||
const [tableData, setTableData] = useState([]);
|
||||
|
||||
function fetchData() {
|
||||
setLoading(true);
|
||||
axios
|
||||
.get('/api/basicProfile')
|
||||
.then((res) => {
|
||||
setData(res.data || {});
|
||||
})
|
||||
.finally(() => {
|
||||
setLoading(false);
|
||||
});
|
||||
}
|
||||
|
||||
function fetchPreData() {
|
||||
setPreLoading(true);
|
||||
axios
|
||||
.get('/api/basicProfile')
|
||||
.then((res) => {
|
||||
setPreData(res.data || {});
|
||||
})
|
||||
.finally(() => {
|
||||
setPreLoading(false);
|
||||
});
|
||||
}
|
||||
|
||||
function fetchTableData() {
|
||||
setTableLoading(true);
|
||||
axios
|
||||
.get('/api/adjustment')
|
||||
.then((res) => {
|
||||
setTableData(res.data);
|
||||
})
|
||||
.finally(() => {
|
||||
setTableLoading(false);
|
||||
});
|
||||
}
|
||||
useEffect(() => {
|
||||
fetchData();
|
||||
fetchPreData();
|
||||
fetchTableData();
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<div className={styles.container}>
|
||||
<Card>
|
||||
<Grid.Row justify="space-between" align="center">
|
||||
<Grid.Col span={16}>
|
||||
<Typography.Title heading={6}>
|
||||
{t['basicProfile.title.form']}
|
||||
</Typography.Title>
|
||||
</Grid.Col>
|
||||
<Grid.Col span={8} style={{ textAlign: 'right' }}>
|
||||
<Space>
|
||||
<Button>{t['basicProfile.cancel']}</Button>
|
||||
<Button type="primary">{t['basicProfile.goBack']}</Button>
|
||||
</Space>
|
||||
</Grid.Col>
|
||||
</Grid.Row>
|
||||
|
||||
<Steps current={data.status} lineless className={styles.steps}>
|
||||
<Steps.Step title={t['basicProfile.steps.commit']} />
|
||||
<Steps.Step title={t['basicProfile.steps.approval']} />
|
||||
<Steps.Step title={t['basicProfile.steps.finish']} />
|
||||
</Steps>
|
||||
</Card>
|
||||
|
||||
<ProfileItem
|
||||
title={t['basicProfile.title.currentParams']}
|
||||
data={data}
|
||||
type="current"
|
||||
loading={loading}
|
||||
/>
|
||||
<ProfileItem
|
||||
title={t['basicProfile.title.originParams']}
|
||||
data={preData}
|
||||
type="origin"
|
||||
loading={preLoading}
|
||||
/>
|
||||
<Card>
|
||||
<Typography.Title heading={6}>
|
||||
{t['basicProfile.adjustment.record']}
|
||||
</Typography.Title>
|
||||
<Table
|
||||
loading={tableLoading}
|
||||
data={tableData}
|
||||
columns={[
|
||||
{
|
||||
dataIndex: 'contentId',
|
||||
title: t['basicProfile.adjustment.contentId'],
|
||||
},
|
||||
{
|
||||
dataIndex: 'content',
|
||||
title: t['basicProfile.adjustment.content'],
|
||||
},
|
||||
{
|
||||
dataIndex: 'status',
|
||||
title: t['basicProfile.adjustment.status'],
|
||||
render: (status) => {
|
||||
if (status) {
|
||||
return (
|
||||
<Badge
|
||||
status="success"
|
||||
text={t['basicProfile.adjustment.success']}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<Badge
|
||||
status="processing"
|
||||
text={t['basicProfile.adjustment.waiting']}
|
||||
/>
|
||||
);
|
||||
},
|
||||
},
|
||||
{
|
||||
dataIndex: 'updatedTime',
|
||||
title: t['basicProfile.adjustment.updatedTime'],
|
||||
},
|
||||
{
|
||||
title: t['basicProfile.adjustment.operation'],
|
||||
headerCellStyle: { paddingLeft: '15px' },
|
||||
render() {
|
||||
return (
|
||||
<Button type="text">
|
||||
{t['basicProfile.adjustment.operation.view']}
|
||||
</Button>
|
||||
);
|
||||
},
|
||||
},
|
||||
]}
|
||||
/>
|
||||
</Card>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default BasicProfile;
|
||||
@ -1,128 +0,0 @@
|
||||
import React, { CSSProperties } from 'react';
|
||||
import useLocale from '@/utils/useLocale';
|
||||
import { Descriptions, Card, Skeleton } from '@arco-design/web-react';
|
||||
import locale from './locale';
|
||||
|
||||
interface ProfileItemProps {
|
||||
title: string;
|
||||
data: any;
|
||||
style?: CSSProperties;
|
||||
type: 'origin' | 'current';
|
||||
loading?: boolean;
|
||||
}
|
||||
|
||||
function ProfileItem(props: ProfileItemProps) {
|
||||
const t = useLocale(locale);
|
||||
const { title, data, type, loading } = props;
|
||||
const blockDataList: {
|
||||
title: string;
|
||||
data: {
|
||||
label: string;
|
||||
value: string;
|
||||
}[];
|
||||
}[] = [];
|
||||
|
||||
blockDataList.push({
|
||||
title: t[`basicProfile.title.${type}Video`],
|
||||
data: [
|
||||
{
|
||||
label: t['basicProfile.label.video.mode'],
|
||||
value: data?.video?.mode || '-',
|
||||
},
|
||||
{
|
||||
label: t['basicProfile.label.video.acquisition.resolution'],
|
||||
value: data?.video?.acquisition.resolution || '-',
|
||||
},
|
||||
{
|
||||
label: t['basicProfile.label.video.acquisition.frameRate'],
|
||||
value: `${data?.video?.acquisition.frameRate || '-'} fps`,
|
||||
},
|
||||
{
|
||||
label: t['basicProfile.label.video.encoding.resolution'],
|
||||
value: data?.video?.encoding.resolution || '-',
|
||||
},
|
||||
{
|
||||
label: t['basicProfile.label.video.encoding.rate.min'],
|
||||
value: `${data?.video?.encoding.rate.min || '-'} bps`,
|
||||
},
|
||||
{
|
||||
label: t['basicProfile.label.video.encoding.rate.max'],
|
||||
value: `${data?.video?.encoding.rate.max || '-'} bps`,
|
||||
},
|
||||
{
|
||||
label: t['basicProfile.label.video.encoding.rate.default'],
|
||||
value: `${data?.video?.encoding.rate.default || '-'} bps`,
|
||||
},
|
||||
{
|
||||
label: t['basicProfile.label.video.encoding.frameRate'],
|
||||
value: `${data?.video?.encoding.frameRate || '-'} fpx`,
|
||||
},
|
||||
{
|
||||
label: t['basicProfile.label.video.encoding.profile'],
|
||||
value: data?.video?.encoding.profile || '-',
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
blockDataList.push({
|
||||
title: t[`basicProfile.title.${type}Audio`],
|
||||
data: [
|
||||
{
|
||||
label: t['basicProfile.label.audio.mode'],
|
||||
value: data?.audio?.mode || '-',
|
||||
},
|
||||
{
|
||||
label: t['basicProfile.label.audio.acquisition.channels'],
|
||||
value: `${data?.audio?.acquisition.channels || '-'} ${
|
||||
t['basicProfile.unit.audio.channels']
|
||||
}`,
|
||||
},
|
||||
{
|
||||
label: t['basicProfile.label.audio.encoding.channels'],
|
||||
value: `${data?.audio?.encoding.channels || '-'} ${
|
||||
t['basicProfile.unit.audio.channels']
|
||||
}`,
|
||||
},
|
||||
{
|
||||
label: t['basicProfile.label.audio.encoding.rate'],
|
||||
value: `${data?.audio?.encoding.rate || '-'} kbps`,
|
||||
},
|
||||
{
|
||||
label: t['basicProfile.label.audio.encoding.profile'],
|
||||
value: data?.audio?.encoding.profile || '-',
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
return (
|
||||
<Card>
|
||||
<div>
|
||||
{blockDataList.map(({ title: blockTitle, data: blockData }, index) => (
|
||||
<Descriptions
|
||||
key={`${index}`}
|
||||
colon=":"
|
||||
labelStyle={{ textAlign: 'right', width: 200, paddingRight: 10 }}
|
||||
valueStyle={{ width: 400 }}
|
||||
title={blockTitle}
|
||||
data={
|
||||
loading
|
||||
? blockData.map((item) => ({
|
||||
...item,
|
||||
value: (
|
||||
<Skeleton
|
||||
text={{ rows: 1, style: { width: '200px' } }}
|
||||
animation
|
||||
/>
|
||||
),
|
||||
}))
|
||||
: blockData
|
||||
}
|
||||
style={index > 0 ? { marginTop: '20px' } : {}}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
</Card>
|
||||
);
|
||||
}
|
||||
|
||||
export default ProfileItem;
|
||||
@ -1,82 +0,0 @@
|
||||
const i18n = {
|
||||
'en-US': {
|
||||
'menu.profile': 'Profile',
|
||||
'menu.profile.basic': 'Basic Profile',
|
||||
'basicProfile.title.form': 'Parameter Approval Process Table',
|
||||
'basicProfile.steps.commit': 'Commit',
|
||||
'basicProfile.steps.approval': 'Approval',
|
||||
'basicProfile.steps.finish': 'Finish',
|
||||
'basicProfile.title.currentVideo': 'Current Video Parameters',
|
||||
'basicProfile.title.currentAudio': 'Current Audio Parameters',
|
||||
'basicProfile.title.originVideo': 'Origin Video Parameters',
|
||||
'basicProfile.title.originAudio': 'Origin Audio Parameters',
|
||||
'basicProfile.label.video.mode': 'Config Mode',
|
||||
'basicProfile.label.video.acquisition.resolution': 'Acquisition Resolution',
|
||||
'basicProfile.label.video.acquisition.frameRate': 'Acquisition Frame Rate',
|
||||
'basicProfile.label.video.encoding.resolution': 'Encoding Resolution',
|
||||
'basicProfile.label.video.encoding.rate.min': 'Encoding Min Rate',
|
||||
'basicProfile.label.video.encoding.rate.max': 'Encoding Max Rate',
|
||||
'basicProfile.label.video.encoding.rate.default': 'Encoding Default Rate',
|
||||
'basicProfile.label.video.encoding.frameRate': 'Encoding Frame Rate',
|
||||
'basicProfile.label.video.encoding.profile': 'Encoding Profile',
|
||||
'basicProfile.label.audio.mode': 'Config Mode',
|
||||
'basicProfile.label.audio.acquisition.channels': 'Acquisition Channels',
|
||||
'basicProfile.label.audio.encoding.channels': 'Encoding Channels',
|
||||
'basicProfile.label.audio.encoding.rate': 'Encoding Rate',
|
||||
'basicProfile.label.audio.encoding.profile': 'Encoding Profile',
|
||||
'basicProfile.unit.audio.channels': 'channels',
|
||||
'basicProfile.goBack': 'GoBack',
|
||||
'basicProfile.cancel': 'Cancel Process',
|
||||
|
||||
'basicProfile.adjustment.record': 'Parameter adjustment record',
|
||||
'basicProfile.adjustment.contentId': 'Content number',
|
||||
'basicProfile.adjustment.content': 'Adjust content',
|
||||
'basicProfile.adjustment.status': 'Current state',
|
||||
'basicProfile.adjustment.updatedTime': 'Change the time',
|
||||
'basicProfile.adjustment.operation': 'Operation',
|
||||
'basicProfile.adjustment.success': 'passed',
|
||||
'basicProfile.adjustment.waiting': 'under review',
|
||||
'basicProfile.adjustment.operation.view': 'view',
|
||||
},
|
||||
'zh-CN': {
|
||||
'menu.profile': '详情页',
|
||||
'menu.profile.basic': '基础详情页',
|
||||
'basicProfile.title.form': '参数审批流程表',
|
||||
'basicProfile.steps.commit': '提交修改',
|
||||
'basicProfile.steps.approval': '审批中',
|
||||
'basicProfile.steps.finish': '修改完成',
|
||||
'basicProfile.title.currentVideo': '现视频参数',
|
||||
'basicProfile.title.currentAudio': '现音频参数',
|
||||
'basicProfile.title.originVideo': '原视频参数',
|
||||
'basicProfile.title.originAudio': '原音频参数',
|
||||
'basicProfile.label.video.mode': '配置模式',
|
||||
'basicProfile.label.video.acquisition.resolution': '采集分辨率',
|
||||
'basicProfile.label.video.acquisition.frameRate': '采集帧率',
|
||||
'basicProfile.label.video.encoding.resolution': '编码分辨率',
|
||||
'basicProfile.label.video.encoding.rate.min': '编码码率最小值',
|
||||
'basicProfile.label.video.encoding.rate.max': '编码码率最大值',
|
||||
'basicProfile.label.video.encoding.rate.default': '编码码率默认值',
|
||||
'basicProfile.label.video.encoding.frameRate': '编码帧率',
|
||||
'basicProfile.label.video.encoding.profile': '编码profile',
|
||||
'basicProfile.label.audio.mode': '配置模式',
|
||||
'basicProfile.label.audio.acquisition.channels': '采集声道数',
|
||||
'basicProfile.label.audio.encoding.channels': '编码声道数',
|
||||
'basicProfile.label.audio.encoding.rate': '编码码率',
|
||||
'basicProfile.label.audio.encoding.profile': '编码 profile',
|
||||
'basicProfile.unit.audio.channels': '声道',
|
||||
'basicProfile.goBack': '返回',
|
||||
'basicProfile.cancel': '取消流程',
|
||||
|
||||
'basicProfile.adjustment.record': '参数调整记录',
|
||||
'basicProfile.adjustment.contentId': '内容编号',
|
||||
'basicProfile.adjustment.content': '调整内容',
|
||||
'basicProfile.adjustment.status': '当前状态',
|
||||
'basicProfile.adjustment.updatedTime': '修改时间',
|
||||
'basicProfile.adjustment.operation': '操作',
|
||||
'basicProfile.adjustment.success': '已通过',
|
||||
'basicProfile.adjustment.waiting': '审核中',
|
||||
'basicProfile.adjustment.operation.view': '查看',
|
||||
},
|
||||
};
|
||||
|
||||
export default i18n;
|
||||
@ -1,52 +0,0 @@
|
||||
import Mock from 'mockjs';
|
||||
import setupMock from '@/utils/setupMock';
|
||||
|
||||
setupMock({
|
||||
setup: () => {
|
||||
Mock.mock(new RegExp('/api/basicProfile'), () => {
|
||||
return {
|
||||
status: 2,
|
||||
video: {
|
||||
mode: '自定义',
|
||||
acquisition: {
|
||||
resolution: '720*1280',
|
||||
frameRate: 15,
|
||||
},
|
||||
encoding: {
|
||||
resolution: '720*1280',
|
||||
rate: {
|
||||
min: 300,
|
||||
max: 800,
|
||||
default: 1500,
|
||||
},
|
||||
frameRate: 15,
|
||||
profile: 'high',
|
||||
},
|
||||
},
|
||||
audio: {
|
||||
mode: '自定义',
|
||||
acquisition: {
|
||||
channels: 8,
|
||||
},
|
||||
encoding: {
|
||||
channels: 8,
|
||||
rate: 128,
|
||||
profile: 'ACC-LC',
|
||||
},
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
Mock.mock(new RegExp('/api/adjustment'), () => {
|
||||
return new Array(2).fill('0').map(() => ({
|
||||
contentId: `${Mock.Random.pick([
|
||||
'视频类',
|
||||
'音频类',
|
||||
])}${Mock.Random.natural(1000, 9999)}`,
|
||||
content: '视频参数变更,音频参数变更',
|
||||
status: Mock.Random.natural(0, 1),
|
||||
updatedTime: Mock.Random.datetime('yyyy-MM-dd HH:mm:ss'),
|
||||
}));
|
||||
});
|
||||
},
|
||||
});
|
||||
@ -1,12 +0,0 @@
|
||||
.container {
|
||||
:global(.arco-card) {
|
||||
margin-top: 16px;
|
||||
}
|
||||
}
|
||||
|
||||
.steps {
|
||||
max-width: 548px;
|
||||
margin: 0 auto;
|
||||
margin-top: 8px;
|
||||
margin-bottom: 30px;
|
||||
}
|
||||
@ -1,53 +0,0 @@
|
||||
import React from 'react';
|
||||
import { Typography, Result, Button, Link } from '@arco-design/web-react';
|
||||
import { IconLink } from '@arco-design/web-react/icon';
|
||||
import useLocale from '@/utils/useLocale';
|
||||
import locale from './locale';
|
||||
import styles from './style/index.module.less';
|
||||
|
||||
function Success() {
|
||||
const t = useLocale(locale);
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div className={styles.wrapper}>
|
||||
<Result
|
||||
className={styles.result}
|
||||
status="error"
|
||||
title={t['error.result.title']}
|
||||
subTitle={t['error.result.subTitle']}
|
||||
extra={[
|
||||
<Button key="again" type="secondary" style={{ marginRight: 16 }}>
|
||||
{t['error.result.goBack']}
|
||||
</Button>,
|
||||
<Button key="back" type="primary">
|
||||
{t['error.result.retry']}
|
||||
</Button>,
|
||||
]}
|
||||
/>
|
||||
<div className={styles['details-wrapper']}>
|
||||
<Typography.Title heading={6} style={{ marginTop: 0 }}>
|
||||
{t['error.detailTitle']}
|
||||
</Typography.Title>
|
||||
<Typography.Paragraph style={{ marginBottom: 0 }}>
|
||||
<ol>
|
||||
<li>
|
||||
{t['error.detailLine.record']}
|
||||
<Link suppressHydrationWarning>
|
||||
<IconLink />
|
||||
{t['error.detailLine.record.link']}
|
||||
</Link>
|
||||
</li>
|
||||
<li>
|
||||
{t['error.detailLine.auth']}
|
||||
<Link suppressHydrationWarning>{t['error.detailLine.auth.link']}</Link>
|
||||
</li>
|
||||
</ol>
|
||||
</Typography.Paragraph>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default Success;
|
||||
@ -1,33 +0,0 @@
|
||||
const i18n = {
|
||||
'en-US': {
|
||||
'menu.result': 'Result',
|
||||
'menu.result.error': 'Error',
|
||||
'error.result.title': 'Submit Error',
|
||||
'error.result.subTitle':
|
||||
'Please check the modified information and try again',
|
||||
'error.result.goBack': 'GoBack',
|
||||
'error.result.retry': 'Retry',
|
||||
'error.detailTitle': 'Details of Error',
|
||||
'error.detailLine.record':
|
||||
'The current domain name has not been registered, please check the registration process: ',
|
||||
'error.detailLine.record.link': 'Registration Process',
|
||||
'error.detailLine.auth':
|
||||
'Your user group does not have the authority to perform this operation;',
|
||||
'error.detailLine.auth.link': 'Request for access',
|
||||
},
|
||||
'zh-CN': {
|
||||
'menu.result': '结果页',
|
||||
'menu.result.error': '失败页',
|
||||
'error.result.title': '提交失败',
|
||||
'error.result.subTitle': '请核对修改信息后,再重试',
|
||||
'error.result.goBack': '回到首页',
|
||||
'error.result.retry': '返回修改',
|
||||
'error.detailTitle': '错误详情',
|
||||
'error.detailLine.record': '当前域名未备案,备案流程请查看:',
|
||||
'error.detailLine.record.link': '备案流程',
|
||||
'error.detailLine.auth': '你的用户组不具有进行此操作的权限;',
|
||||
'error.detailLine.auth.link': '申请权限',
|
||||
},
|
||||
};
|
||||
|
||||
export default i18n;
|
||||
@ -1,18 +0,0 @@
|
||||
.wrapper {
|
||||
padding: 24px 150px;
|
||||
background-color: var(--color-bg-2);
|
||||
box-sizing: border-box;
|
||||
min-height: calc(100vh - 168px);
|
||||
}
|
||||
|
||||
.result {
|
||||
margin: 150px 0 36px;
|
||||
}
|
||||
|
||||
.details-wrapper {
|
||||
width: 100%;
|
||||
padding: 20px;
|
||||
background-color: var(--color-fill-2);
|
||||
box-sizing: border-box;
|
||||
margin-bottom: 150px;
|
||||
}
|
||||
@ -1,61 +0,0 @@
|
||||
import React from 'react';
|
||||
import { Typography, Result, Button, Steps } from '@arco-design/web-react';
|
||||
import useLocale from '@/utils/useLocale';
|
||||
import locale from './locale';
|
||||
import styles from './style/index.module.less';
|
||||
|
||||
const Step = Steps.Step;
|
||||
|
||||
function Success() {
|
||||
const t = useLocale(locale);
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div className={styles.wrapper}>
|
||||
<Result
|
||||
className={styles.result}
|
||||
status="success"
|
||||
title={t['success.result.title']}
|
||||
subTitle={t['success.result.subTitle']}
|
||||
extra={[
|
||||
<Button key="again" type="secondary" style={{ marginRight: 16 }}>
|
||||
{t['success.result.printResult']}
|
||||
</Button>,
|
||||
<Button key="back" type="primary">
|
||||
{t['success.result.projectList']}
|
||||
</Button>,
|
||||
]}
|
||||
/>
|
||||
<div className={styles['steps-wrapper']}>
|
||||
<Typography.Paragraph bold>
|
||||
{t['success.result.progress']}
|
||||
</Typography.Paragraph>
|
||||
<Steps type="dot" current={2}>
|
||||
<Step
|
||||
title={t['success.submitApplication']}
|
||||
description="2020/10/10 14:00:39"
|
||||
/>
|
||||
<Step
|
||||
title={t['success.leaderReview']}
|
||||
description={t['success.processing']}
|
||||
/>
|
||||
<Step
|
||||
title={t['success.purchaseCertificate']}
|
||||
description={t['success.waiting']}
|
||||
/>
|
||||
<Step
|
||||
title={t['success.safetyTest']}
|
||||
description={t['success.waiting']}
|
||||
/>
|
||||
<Step
|
||||
title={t['success.launched']}
|
||||
description={t['success.waiting']}
|
||||
/>
|
||||
</Steps>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default Success;
|
||||
@ -1,36 +0,0 @@
|
||||
const i18n = {
|
||||
'en-US': {
|
||||
'menu.result': 'Result',
|
||||
'menu.result.success': 'Success',
|
||||
'success.result.title': 'Submit Success',
|
||||
'success.result.subTitle': 'Submit form success!',
|
||||
'success.result.printResult': 'Print result',
|
||||
'success.result.projectList': 'Project List',
|
||||
'success.result.progress': 'Progress',
|
||||
'success.submitApplication': 'Submit Application',
|
||||
'success.leaderReview': 'Leader Review',
|
||||
'success.purchaseCertificate': 'Purchase Certificate',
|
||||
'success.safetyTest': 'Safety Test',
|
||||
'success.launched': 'Officially launched',
|
||||
'success.waiting': 'Waiting',
|
||||
'success.processing': 'Processing',
|
||||
},
|
||||
'zh-CN': {
|
||||
'menu.result': '结果页',
|
||||
'menu.result.success': '成功页',
|
||||
'success.result.title': '提交成功',
|
||||
'success.result.subTitle': '表单提交成功!',
|
||||
'success.result.printResult': '打印结果',
|
||||
'success.result.projectList': '返回项目列表',
|
||||
'success.result.progress': '当前进度',
|
||||
'success.submitApplication': '提交申请',
|
||||
'success.leaderReview': '直属领导审核',
|
||||
'success.purchaseCertificate': '购买证书',
|
||||
'success.safetyTest': '安全测试',
|
||||
'success.launched': '正式上线',
|
||||
'success.waiting': '未开始',
|
||||
'success.processing': '进行中',
|
||||
},
|
||||
};
|
||||
|
||||
export default i18n;
|
||||
@ -1,19 +0,0 @@
|
||||
.wrapper {
|
||||
padding: 24px 150px;
|
||||
background-color: var(--color-bg-2);
|
||||
box-sizing: border-box;
|
||||
min-height: calc(100vh - 168px);
|
||||
}
|
||||
|
||||
.result {
|
||||
margin: 150px 0 36px;
|
||||
}
|
||||
|
||||
.steps-wrapper {
|
||||
width: 100%;
|
||||
min-width: fit-content;
|
||||
padding: 20px;
|
||||
background-color: var(--color-fill-2);
|
||||
box-sizing: border-box;
|
||||
margin-bottom: 150px;
|
||||
}
|
||||
Loading…
Reference in New Issue