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