🎨 chore(web): apply ESLint and Prettier auto-fixes (baseline)
- Ran: bun run eslint:fix && bun run lint:fix - Inserted AGPL license header via eslint-plugin-header - Enforced no-multiple-empty-lines and other lint rules - Formatted code using Prettier v3 (@so1ve/prettier-config) - No functional changes; formatting-only baseline across JS/JSX files
This commit is contained in:
@@ -26,9 +26,8 @@ const RedemptionsActions = ({
|
||||
setShowEdit,
|
||||
batchCopyRedemptions,
|
||||
batchDeleteRedemptions,
|
||||
t
|
||||
t,
|
||||
}) => {
|
||||
|
||||
// Add new redemption code
|
||||
const handleAddRedemption = () => {
|
||||
setEditingRedemption({
|
||||
@@ -38,30 +37,30 @@ const RedemptionsActions = ({
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="flex flex-wrap gap-2 w-full md:w-auto order-2 md:order-1">
|
||||
<div className='flex flex-wrap gap-2 w-full md:w-auto order-2 md:order-1'>
|
||||
<Button
|
||||
type="primary"
|
||||
className="flex-1 md:flex-initial"
|
||||
type='primary'
|
||||
className='flex-1 md:flex-initial'
|
||||
onClick={handleAddRedemption}
|
||||
size="small"
|
||||
size='small'
|
||||
>
|
||||
{t('添加兑换码')}
|
||||
</Button>
|
||||
|
||||
<Button
|
||||
type='tertiary'
|
||||
className="flex-1 md:flex-initial"
|
||||
className='flex-1 md:flex-initial'
|
||||
onClick={batchCopyRedemptions}
|
||||
size="small"
|
||||
size='small'
|
||||
>
|
||||
{t('复制所选兑换码到剪贴板')}
|
||||
</Button>
|
||||
|
||||
<Button
|
||||
type='danger'
|
||||
className="w-full md:w-auto"
|
||||
className='w-full md:w-auto'
|
||||
onClick={batchDeleteRedemptions}
|
||||
size="small"
|
||||
size='small'
|
||||
>
|
||||
{t('清除失效兑换码')}
|
||||
</Button>
|
||||
@@ -69,4 +68,4 @@ const RedemptionsActions = ({
|
||||
);
|
||||
};
|
||||
|
||||
export default RedemptionsActions;
|
||||
export default RedemptionsActions;
|
||||
|
||||
@@ -21,15 +21,21 @@ import React from 'react';
|
||||
import { Tag, Button, Space, Popover, Dropdown } from '@douyinfe/semi-ui';
|
||||
import { IconMore } from '@douyinfe/semi-icons';
|
||||
import { renderQuota, timestamp2string } from '../../../helpers';
|
||||
import { REDEMPTION_STATUS, REDEMPTION_STATUS_MAP, REDEMPTION_ACTIONS } from '../../../constants/redemption.constants';
|
||||
import {
|
||||
REDEMPTION_STATUS,
|
||||
REDEMPTION_STATUS_MAP,
|
||||
REDEMPTION_ACTIONS,
|
||||
} from '../../../constants/redemption.constants';
|
||||
|
||||
/**
|
||||
* Check if redemption code is expired
|
||||
*/
|
||||
export const isExpired = (record) => {
|
||||
return record.status === REDEMPTION_STATUS.UNUSED &&
|
||||
return (
|
||||
record.status === REDEMPTION_STATUS.UNUSED &&
|
||||
record.expired_time !== 0 &&
|
||||
record.expired_time < Math.floor(Date.now() / 1000);
|
||||
record.expired_time < Math.floor(Date.now() / 1000)
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -45,7 +51,9 @@ const renderTimestamp = (timestamp) => {
|
||||
const renderStatus = (status, record, t) => {
|
||||
if (isExpired(record)) {
|
||||
return (
|
||||
<Tag color='orange' shape='circle'>{t('已过期')}</Tag>
|
||||
<Tag color='orange' shape='circle'>
|
||||
{t('已过期')}
|
||||
</Tag>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -77,7 +85,7 @@ export const getRedemptionsColumns = ({
|
||||
refresh,
|
||||
redemptions,
|
||||
activePage,
|
||||
showDeleteRedemptionModal
|
||||
showDeleteRedemptionModal,
|
||||
}) => {
|
||||
return [
|
||||
{
|
||||
@@ -145,7 +153,7 @@ export const getRedemptionsColumns = ({
|
||||
onClick: () => {
|
||||
showDeleteRedemptionModal(record);
|
||||
},
|
||||
}
|
||||
},
|
||||
];
|
||||
|
||||
if (record.status === REDEMPTION_STATUS.UNUSED && !isExpired(record)) {
|
||||
@@ -171,16 +179,17 @@ export const getRedemptionsColumns = ({
|
||||
|
||||
return (
|
||||
<Space>
|
||||
<Popover content={record.key} style={{ padding: 20 }} position='top'>
|
||||
<Button
|
||||
type='tertiary'
|
||||
size="small"
|
||||
>
|
||||
<Popover
|
||||
content={record.key}
|
||||
style={{ padding: 20 }}
|
||||
position='top'
|
||||
>
|
||||
<Button type='tertiary' size='small'>
|
||||
{t('查看')}
|
||||
</Button>
|
||||
</Popover>
|
||||
<Button
|
||||
size="small"
|
||||
size='small'
|
||||
onClick={async () => {
|
||||
await copyText(record.key);
|
||||
}}
|
||||
@@ -189,7 +198,7 @@ export const getRedemptionsColumns = ({
|
||||
</Button>
|
||||
<Button
|
||||
type='tertiary'
|
||||
size="small"
|
||||
size='small'
|
||||
onClick={() => {
|
||||
setEditingRedemption(record);
|
||||
setShowEdit(true);
|
||||
@@ -203,15 +212,11 @@ export const getRedemptionsColumns = ({
|
||||
position='bottomRight'
|
||||
menu={moreMenuItems}
|
||||
>
|
||||
<Button
|
||||
type='tertiary'
|
||||
size="small"
|
||||
icon={<IconMore />}
|
||||
/>
|
||||
<Button type='tertiary' size='small' icon={<IconMore />} />
|
||||
</Dropdown>
|
||||
</Space>
|
||||
);
|
||||
},
|
||||
},
|
||||
];
|
||||
};
|
||||
};
|
||||
|
||||
@@ -26,9 +26,9 @@ const { Text } = Typography;
|
||||
|
||||
const RedemptionsDescription = ({ compactMode, setCompactMode, t }) => {
|
||||
return (
|
||||
<div className="flex flex-col md:flex-row justify-between items-start md:items-center gap-2 w-full">
|
||||
<div className="flex items-center text-orange-500">
|
||||
<Ticket size={16} className="mr-2" />
|
||||
<div className='flex flex-col md:flex-row justify-between items-start md:items-center gap-2 w-full'>
|
||||
<div className='flex items-center text-orange-500'>
|
||||
<Ticket size={16} className='mr-2' />
|
||||
<Text>{t('兑换码管理')}</Text>
|
||||
</div>
|
||||
|
||||
@@ -41,4 +41,4 @@ const RedemptionsDescription = ({ compactMode, setCompactMode, t }) => {
|
||||
);
|
||||
};
|
||||
|
||||
export default RedemptionsDescription;
|
||||
export default RedemptionsDescription;
|
||||
|
||||
@@ -27,9 +27,8 @@ const RedemptionsFilters = ({
|
||||
searchRedemptions,
|
||||
loading,
|
||||
searching,
|
||||
t
|
||||
t,
|
||||
}) => {
|
||||
|
||||
// Handle form reset and immediate search
|
||||
const formApiRef = useRef(null);
|
||||
|
||||
@@ -50,38 +49,38 @@ const RedemptionsFilters = ({
|
||||
}}
|
||||
onSubmit={searchRedemptions}
|
||||
allowEmpty={true}
|
||||
autoComplete="off"
|
||||
layout="horizontal"
|
||||
trigger="change"
|
||||
autoComplete='off'
|
||||
layout='horizontal'
|
||||
trigger='change'
|
||||
stopValidateWithError={false}
|
||||
className="w-full md:w-auto order-1 md:order-2"
|
||||
className='w-full md:w-auto order-1 md:order-2'
|
||||
>
|
||||
<div className="flex flex-col md:flex-row items-center gap-2 w-full md:w-auto">
|
||||
<div className="relative w-full md:w-64">
|
||||
<div className='flex flex-col md:flex-row items-center gap-2 w-full md:w-auto'>
|
||||
<div className='relative w-full md:w-64'>
|
||||
<Form.Input
|
||||
field="searchKeyword"
|
||||
field='searchKeyword'
|
||||
prefix={<IconSearch />}
|
||||
placeholder={t('关键字(id或者名称)')}
|
||||
showClear
|
||||
pure
|
||||
size="small"
|
||||
size='small'
|
||||
/>
|
||||
</div>
|
||||
<div className="flex gap-2 w-full md:w-auto">
|
||||
<div className='flex gap-2 w-full md:w-auto'>
|
||||
<Button
|
||||
type="tertiary"
|
||||
htmlType="submit"
|
||||
type='tertiary'
|
||||
htmlType='submit'
|
||||
loading={loading || searching}
|
||||
className="flex-1 md:flex-initial md:w-auto"
|
||||
size="small"
|
||||
className='flex-1 md:flex-initial md:w-auto'
|
||||
size='small'
|
||||
>
|
||||
{t('查询')}
|
||||
</Button>
|
||||
<Button
|
||||
type="tertiary"
|
||||
type='tertiary'
|
||||
onClick={handleReset}
|
||||
className="flex-1 md:flex-initial md:w-auto"
|
||||
size="small"
|
||||
className='flex-1 md:flex-initial md:w-auto'
|
||||
size='small'
|
||||
>
|
||||
{t('重置')}
|
||||
</Button>
|
||||
@@ -91,4 +90,4 @@ const RedemptionsFilters = ({
|
||||
);
|
||||
};
|
||||
|
||||
export default RedemptionsFilters;
|
||||
export default RedemptionsFilters;
|
||||
|
||||
@@ -22,7 +22,7 @@ import { Empty } from '@douyinfe/semi-ui';
|
||||
import CardTable from '../../common/ui/CardTable';
|
||||
import {
|
||||
IllustrationNoResult,
|
||||
IllustrationNoResultDark
|
||||
IllustrationNoResultDark,
|
||||
} from '@douyinfe/semi-illustrations';
|
||||
import { getRedemptionsColumns, isExpired } from './RedemptionsColumnDefs';
|
||||
import DeleteRedemptionModal from './modals/DeleteRedemptionModal';
|
||||
@@ -67,7 +67,7 @@ const RedemptionsTable = (redemptionsData) => {
|
||||
refresh,
|
||||
redemptions,
|
||||
activePage,
|
||||
showDeleteRedemptionModal
|
||||
showDeleteRedemptionModal,
|
||||
});
|
||||
}, [
|
||||
t,
|
||||
@@ -83,13 +83,15 @@ const RedemptionsTable = (redemptionsData) => {
|
||||
|
||||
// Handle compact mode by removing fixed positioning
|
||||
const tableColumns = useMemo(() => {
|
||||
return compactMode ? columns.map(col => {
|
||||
if (col.dataIndex === 'operate') {
|
||||
const { fixed, ...rest } = col;
|
||||
return rest;
|
||||
}
|
||||
return col;
|
||||
}) : columns;
|
||||
return compactMode
|
||||
? columns.map((col) => {
|
||||
if (col.dataIndex === 'operate') {
|
||||
const { fixed, ...rest } = col;
|
||||
return rest;
|
||||
}
|
||||
return col;
|
||||
})
|
||||
: columns;
|
||||
}, [compactMode, columns]);
|
||||
|
||||
return (
|
||||
@@ -114,13 +116,15 @@ const RedemptionsTable = (redemptionsData) => {
|
||||
empty={
|
||||
<Empty
|
||||
image={<IllustrationNoResult style={{ width: 150, height: 150 }} />}
|
||||
darkModeImage={<IllustrationNoResultDark style={{ width: 150, height: 150 }} />}
|
||||
darkModeImage={
|
||||
<IllustrationNoResultDark style={{ width: 150, height: 150 }} />
|
||||
}
|
||||
description={t('搜索无结果')}
|
||||
style={{ padding: 30 }}
|
||||
/>
|
||||
}
|
||||
className="rounded-xl overflow-hidden"
|
||||
size="middle"
|
||||
className='rounded-xl overflow-hidden'
|
||||
size='middle'
|
||||
/>
|
||||
|
||||
<DeleteRedemptionModal
|
||||
@@ -137,4 +141,4 @@ const RedemptionsTable = (redemptionsData) => {
|
||||
);
|
||||
};
|
||||
|
||||
export default RedemptionsTable;
|
||||
export default RedemptionsTable;
|
||||
|
||||
@@ -71,7 +71,7 @@ const RedemptionsPage = () => {
|
||||
/>
|
||||
|
||||
<CardPro
|
||||
type="type1"
|
||||
type='type1'
|
||||
descriptionArea={
|
||||
<RedemptionsDescription
|
||||
compactMode={compactMode}
|
||||
@@ -80,7 +80,7 @@ const RedemptionsPage = () => {
|
||||
/>
|
||||
}
|
||||
actionsArea={
|
||||
<div className="flex flex-col md:flex-row justify-between items-center gap-2 w-full">
|
||||
<div className='flex flex-col md:flex-row justify-between items-center gap-2 w-full'>
|
||||
<RedemptionsActions
|
||||
selectedKeys={selectedKeys}
|
||||
setEditingRedemption={setEditingRedemption}
|
||||
@@ -90,7 +90,7 @@ const RedemptionsPage = () => {
|
||||
t={t}
|
||||
/>
|
||||
|
||||
<div className="w-full md:w-full lg:w-auto order-1 md:order-2">
|
||||
<div className='w-full md:w-full lg:w-auto order-1 md:order-2'>
|
||||
<RedemptionsFilters
|
||||
formInitValues={formInitValues}
|
||||
setFormApi={setFormApi}
|
||||
@@ -119,4 +119,4 @@ const RedemptionsPage = () => {
|
||||
);
|
||||
};
|
||||
|
||||
export default RedemptionsPage;
|
||||
export default RedemptionsPage;
|
||||
|
||||
@@ -21,15 +21,15 @@ import React from 'react';
|
||||
import { Modal } from '@douyinfe/semi-ui';
|
||||
import { REDEMPTION_ACTIONS } from '../../../../constants/redemption.constants';
|
||||
|
||||
const DeleteRedemptionModal = ({
|
||||
visible,
|
||||
onCancel,
|
||||
record,
|
||||
manageRedemption,
|
||||
const DeleteRedemptionModal = ({
|
||||
visible,
|
||||
onCancel,
|
||||
record,
|
||||
manageRedemption,
|
||||
refresh,
|
||||
redemptions,
|
||||
activePage,
|
||||
t
|
||||
t,
|
||||
}) => {
|
||||
const handleConfirm = async () => {
|
||||
await manageRedemption(record.id, REDEMPTION_ACTIONS.DELETE, record);
|
||||
@@ -48,11 +48,11 @@ const DeleteRedemptionModal = ({
|
||||
visible={visible}
|
||||
onCancel={onCancel}
|
||||
onOk={handleConfirm}
|
||||
type="warning"
|
||||
type='warning'
|
||||
>
|
||||
{t('此修改将不可逆')}
|
||||
</Modal>
|
||||
);
|
||||
};
|
||||
|
||||
export default DeleteRedemptionModal;
|
||||
export default DeleteRedemptionModal;
|
||||
|
||||
@@ -109,7 +109,9 @@ const EditRedemptionModal = (props) => {
|
||||
if (!localInputs.expired_time) {
|
||||
localInputs.expired_time = 0;
|
||||
} else {
|
||||
localInputs.expired_time = Math.floor(localInputs.expired_time.getTime() / 1000);
|
||||
localInputs.expired_time = Math.floor(
|
||||
localInputs.expired_time.getTime() / 1000,
|
||||
);
|
||||
}
|
||||
let res;
|
||||
if (isEdit) {
|
||||
@@ -164,11 +166,16 @@ const EditRedemptionModal = (props) => {
|
||||
placement={isEdit ? 'right' : 'left'}
|
||||
title={
|
||||
<Space>
|
||||
{isEdit ?
|
||||
<Tag color="blue" shape="circle">{t('更新')}</Tag> :
|
||||
<Tag color="green" shape="circle">{t('新建')}</Tag>
|
||||
}
|
||||
<Title heading={4} className="m-0">
|
||||
{isEdit ? (
|
||||
<Tag color='blue' shape='circle'>
|
||||
{t('更新')}
|
||||
</Tag>
|
||||
) : (
|
||||
<Tag color='green' shape='circle'>
|
||||
{t('新建')}
|
||||
</Tag>
|
||||
)}
|
||||
<Title heading={4} className='m-0'>
|
||||
{isEdit ? t('更新兑换码信息') : t('创建新的兑换码')}
|
||||
</Title>
|
||||
</Space>
|
||||
@@ -177,10 +184,10 @@ const EditRedemptionModal = (props) => {
|
||||
visible={props.visiable}
|
||||
width={isMobile ? '100%' : 600}
|
||||
footer={
|
||||
<div className="flex justify-end bg-white">
|
||||
<div className='flex justify-end bg-white'>
|
||||
<Space>
|
||||
<Button
|
||||
theme="solid"
|
||||
theme='solid'
|
||||
onClick={() => formApiRef.current?.submitForm()}
|
||||
icon={<IconSave />}
|
||||
loading={loading}
|
||||
@@ -188,8 +195,8 @@ const EditRedemptionModal = (props) => {
|
||||
{t('提交')}
|
||||
</Button>
|
||||
<Button
|
||||
theme="light"
|
||||
type="primary"
|
||||
theme='light'
|
||||
type='primary'
|
||||
onClick={handleCancel}
|
||||
icon={<IconClose />}
|
||||
>
|
||||
@@ -204,20 +211,28 @@ const EditRedemptionModal = (props) => {
|
||||
<Spin spinning={loading}>
|
||||
<Form
|
||||
initValues={getInitValues()}
|
||||
getFormApi={(api) => formApiRef.current = api}
|
||||
getFormApi={(api) => (formApiRef.current = api)}
|
||||
onSubmit={submit}
|
||||
>
|
||||
{({ values }) => (
|
||||
<div className="p-2">
|
||||
<Card className="!rounded-2xl shadow-sm border-0 mb-6">
|
||||
<div className='p-2'>
|
||||
<Card className='!rounded-2xl shadow-sm border-0 mb-6'>
|
||||
{/* Header: Basic Info */}
|
||||
<div className="flex items-center mb-2">
|
||||
<Avatar size="small" color="blue" className="mr-2 shadow-md">
|
||||
<div className='flex items-center mb-2'>
|
||||
<Avatar
|
||||
size='small'
|
||||
color='blue'
|
||||
className='mr-2 shadow-md'
|
||||
>
|
||||
<IconGift size={16} />
|
||||
</Avatar>
|
||||
<div>
|
||||
<Text className="text-lg font-medium">{t('基本信息')}</Text>
|
||||
<div className="text-xs text-gray-600">{t('设置兑换码的基本信息')}</div>
|
||||
<Text className='text-lg font-medium'>
|
||||
{t('基本信息')}
|
||||
</Text>
|
||||
<div className='text-xs text-gray-600'>
|
||||
{t('设置兑换码的基本信息')}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -228,7 +243,11 @@ const EditRedemptionModal = (props) => {
|
||||
label={t('名称')}
|
||||
placeholder={t('请输入名称')}
|
||||
style={{ width: '100%' }}
|
||||
rules={!isEdit ? [] : [{ required: true, message: t('请输入名称') }]}
|
||||
rules={
|
||||
!isEdit
|
||||
? []
|
||||
: [{ required: true, message: t('请输入名称') }]
|
||||
}
|
||||
showClear
|
||||
/>
|
||||
</Col>
|
||||
@@ -245,15 +264,23 @@ const EditRedemptionModal = (props) => {
|
||||
</Row>
|
||||
</Card>
|
||||
|
||||
<Card className="!rounded-2xl shadow-sm border-0">
|
||||
<Card className='!rounded-2xl shadow-sm border-0'>
|
||||
{/* Header: Quota Settings */}
|
||||
<div className="flex items-center mb-2">
|
||||
<Avatar size="small" color="green" className="mr-2 shadow-md">
|
||||
<div className='flex items-center mb-2'>
|
||||
<Avatar
|
||||
size='small'
|
||||
color='green'
|
||||
className='mr-2 shadow-md'
|
||||
>
|
||||
<IconCreditCard size={16} />
|
||||
</Avatar>
|
||||
<div>
|
||||
<Text className="text-lg font-medium">{t('额度设置')}</Text>
|
||||
<div className="text-xs text-gray-600">{t('设置兑换码的额度和数量')}</div>
|
||||
<Text className='text-lg font-medium'>
|
||||
{t('额度设置')}
|
||||
</Text>
|
||||
<div className='text-xs text-gray-600'>
|
||||
{t('设置兑换码的额度和数量')}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -276,7 +303,9 @@ const EditRedemptionModal = (props) => {
|
||||
},
|
||||
},
|
||||
]}
|
||||
extraText={renderQuotaWithPrompt(Number(values.quota) || 0)}
|
||||
extraText={renderQuotaWithPrompt(
|
||||
Number(values.quota) || 0,
|
||||
)}
|
||||
data={[
|
||||
{ value: 500000, label: '1$' },
|
||||
{ value: 5000000, label: '10$' },
|
||||
@@ -321,4 +350,4 @@ const EditRedemptionModal = (props) => {
|
||||
);
|
||||
};
|
||||
|
||||
export default EditRedemptionModal;
|
||||
export default EditRedemptionModal;
|
||||
|
||||
Reference in New Issue
Block a user