提交 9ec935b8 authored 作者: 王鹏飞's avatar 王鹏飞

refactor(admin): unify list filters in AppList

上级 761e2bd5
......@@ -3,8 +3,6 @@ import {
Table,
Input,
Button,
Row,
Col,
Space,
DatePicker,
Radio,
......@@ -21,9 +19,6 @@ import { getList, addVersion, editVersion, infoVersion, delVersion } from "../ap
const { TextArea } = Input;
import dayjs from "dayjs";
import Add from "@/assets/images/icon/add.png";
import reload from "@/assets/images/icon/reload.png";
import reset from "@/assets/images/icon/reset.png";
import filter from "@/assets/images/icon/filter.png";
import { useSelector } from "react-redux";
import AliOSS from "ali-oss";
import { getAliOSSSTSToken } from "@/pages/setting/help/addedit/requet";
......@@ -36,7 +31,6 @@ const AppVersion = () => {
const [isEdit, setIsEdit] = useState(false);
const [delMoadal, setDelModal] = useState(false);
const [isadd, setisadd] = useState(true);
const [dateVal, setDateVal] = useState("");
const [form] = Form.useForm();
// 获取操作权限
const { operationPermissionsList } = useSelector((state) => state.user);
......@@ -49,8 +43,7 @@ const AppVersion = () => {
const [delid, setdelid] = useState(0);
const [filterObj, setfilterObj] = useState({
version: "",
start_time: "",
end_time: "",
dateRange: [],
});
const [ossClient, setOssClient] = useState(null); // oss 操作
......@@ -140,11 +133,6 @@ const AppVersion = () => {
},
};
const handleReset = () => {
setfilterObj({ version: "" });
setDateVal("");
init();
};
const handleEdit = async (id) => {
const data = await infoVersion({ id });
setisadd(false);
......@@ -189,37 +177,28 @@ const AppVersion = () => {
form.setFieldsValue(initialValues);
}
}, [isEdit]);
// 过滤
const handleFilter = (flag, val) => {
if (flag == "startandend") {
let val2 = val || [];
filterObj["start_time"] = parseInt(
new Date(dayjs(val2[0]).format("YYYY-MM-DD") + " 00:00:00").getTime() / 1000,
const getQuery = ({ version, dateRange }) => {
const query = version ? { version } : {};
if (dateRange?.length === 2) {
query.start_time = parseInt(
new Date(dayjs(dateRange[0]).format("YYYY-MM-DD") + " 00:00:00").getTime() / 1000,
);
const endDate = new Date(dayjs(val2[1])).getDate();
const endTime = parseInt(
new Date(dayjs(val2[1]).format("YYYY-MM-") + endDate + " 23:59:59").getTime() / 1000,
const endDate = new Date(dayjs(dateRange[1])).getDate();
query.end_time = parseInt(
new Date(dayjs(dateRange[1]).format("YYYY-MM-") + endDate + " 23:59:59").getTime() / 1000,
);
filterObj["end_time"] = endTime;
setDateVal(val);
if (!val2.length) {
delete filterObj["start_time"];
delete filterObj["end_time"];
}
} else {
filterObj[flag] = val;
}
for (const key in filterObj) {
if (!filterObj[key]) {
delete filterObj[key];
}
}
setfilterObj({ ...filterObj });
if (!val) init(filterObj);
return query;
};
const init = async (obj = {}) => {
const init = async (obj = filterObj, nextPage = page, nextPageSize = page_size) => {
setLoading(true);
const { total, list } = await getList({ page, page_size, ...obj });
const { total, list } = await getList({
page: nextPage,
page_size: nextPageSize,
...getQuery(obj),
});
setTotal(total);
setData(list);
setLoading(false);
......@@ -227,7 +206,7 @@ const AppVersion = () => {
// 删除
const handleDel = async () => {
const bool = await delVersion({ id: delid });
bool && init();
bool && init(filterObj);
setDelModal(false);
};
......@@ -301,123 +280,86 @@ const AppVersion = () => {
];
return (
<div className="classify">
<Row justify={"space-between"}>
<Col className="form-devices-inline">
<Form layout="inline">
<Form.Item label="版本号">
<Input
autoComplete="off"
allowClear
value={filterObj.version}
placeholder="请输入版本号"
id="name"
onChange={(ev) => handleFilter("version", ev.target.value)}
></Input>
</Form.Item>
<Form.Item label="发布时间">
<RangePicker
value={dateVal}
id="createTime"
onChange={(ev) => handleFilter("startandend", ev)}
></RangePicker>
</Form.Item>
<Space>
<Button
type="primary"
ghost
icon={
<span
style={{
display: "inline-block",
width: "11px",
height: "10px",
pointerEvents: "none",
}}
>
<Image src={reset} />
</span>
}
onClick={handleReset}
>
重置
</Button>
<Button
type="primary"
ghost
icon={
<span
style={{
display: "inline-block",
width: "13px",
height: "12px",
pointerEvents: "none",
}}
>
<Image src={filter} />
</span>
}
onClick={() => {
setPage(1);
Object.values(filterObj).some((item) => item) ? init(filterObj) : init();
}}
>
搜索
</Button>
<Button
type="primary"
ghost
icon={
<span
style={{
display: "inline-block",
width: "10px",
height: "12px",
pointerEvents: "none",
}}
>
<Image src={reload} />
</span>
}
onClick={() =>
Object.values(filterObj).some((item) => item) ? init(filterObj) : init()
}
>
刷新
</Button>
</Space>
</Form>
</Col>
<Col>
<Space>
{operationPermissionsList.includes("/setting/applied/add") && (
<Button
type="primary"
ghost
icon={
<span
style={{
display: "inline-block",
width: "13px",
height: "12px",
pointerEvents: "none",
}}
>
<Image src={Add} />
</span>
}
onClick={() => {
setisadd(true);
setIsEdit(true);
}}
>
添加
</Button>
)}
</Space>
</Col>
</Row>
<br />
<AppList rowKey="id" columns={columns} data={{ rows: data, total, loading }} pagination={{ page, pageSize: page_size, pageSizeOptions: [10, 20, 30, 40], onChange: setPage, onPageSizeChange: setpage_size }} />
<AppList
rowKey="id"
columns={columns}
data={{ rows: data, total, loading }}
filters={{
value: filterObj,
items: [
{
name: "version",
label: "版本号",
render: (field) => (
<Input
autoComplete="off"
allowClear
value={field.value}
placeholder="请输入版本号"
onChange={(event) => field.onChange(event.target.value)}
/>
),
},
{
name: "dateRange",
label: "发布时间",
render: (field) => <RangePicker value={field.value} onChange={field.onChange} />,
},
],
onChange: setfilterObj,
onSearch: () => {
setPage(1);
init(filterObj, 1);
},
onReset: () => {
const nextFilters = { version: "", dateRange: [] };
setfilterObj(nextFilters);
setPage(1);
init(nextFilters, 1);
},
onRefresh: () => init(filterObj),
}}
pagination={{
page,
pageSize: page_size,
pageSizeOptions: [10, 20, 30, 40],
onChange: (nextPage) => {
setPage(nextPage);
init(filterObj, nextPage);
},
onPageSizeChange: (nextPageSize) => {
setpage_size(nextPageSize);
setPage(1);
init(filterObj, 1, nextPageSize);
},
}}
toolbar={
operationPermissionsList.includes("/setting/applied/add") ? (
<Button
type="primary"
ghost
icon={
<span
style={{
display: "inline-block",
width: "13px",
height: "12px",
pointerEvents: "none",
}}
>
<Image src={Add} />
</span>
}
onClick={() => {
setisadd(true);
setIsEdit(true);
}}
>
添加
</Button>
) : null
}
/>
<Modal
mask={false}
centered
......
......@@ -3,7 +3,6 @@ import {
Input,
Button,
Row,
Col,
Space,
DatePicker,
Drawer,
......@@ -20,9 +19,6 @@ import { AppList } from "@/shared/components/AppList";
import { getAppList, addApp, editApp, delApp, changeStatus, getAppInfo } from "../api";
import { MinusOutlined, PlusOutlined } from "@ant-design/icons";
import Add from "@/assets/images/icon/add.png";
import reload from "@/assets/images/icon/reload.png";
import reset from "@/assets/images/icon/reset.png";
import filter from "@/assets/images/icon/filter.png";
import dayjs from "dayjs";
import { useSelector } from "react-redux";
// import './index.less'
......@@ -48,7 +44,7 @@ const Applied = () => {
app_name: "",
validity: "",
});
const [dateVal, setDateVal] = useState("");
const [dateVal, setDateVal] = useState();
const [id, setid] = useState(0);
const [delid, setdelid] = useState(0);
// 获取操作权限
......@@ -58,36 +54,16 @@ const Applied = () => {
start_time: "",
end_time: "",
});
// 过滤
const handleFilter = (flag, val) => {
if (flag == "startandend") {
let val2 = val || [];
filterObj["start_time"] = parseInt(
new Date(dayjs(val2[0]).format("YYYY-MM-DD") + " 00:00:00").getTime() / 1000,
);
const endDate = new Date(dayjs(val2[1])).getDate();
const endTime = parseInt(
new Date(dayjs(val2[1]).format("YYYY-MM-") + endDate + " 23:59:59").getTime() / 1000,
);
filterObj["end_time"] = endTime;
setDateVal(val);
if (!val2.length) {
delete filterObj["start_time"];
delete filterObj["end_time"];
}
} else {
filterObj[flag] = val;
}
for (const key in filterObj) {
if (!filterObj[key]) {
delete filterObj[key];
}
const handleFiltersChange = ({ app_name, startandend }) => {
const nextFilters = app_name ? { app_name } : {};
if (startandend?.length === 2) {
nextFilters.start_time = dayjs(startandend[0]).startOf("day").unix();
nextFilters.end_time = dayjs(startandend[1]).endOf("day").unix();
}
console.log("start_time", filterObj["start_time"]);
console.log("end_time", filterObj["end_time"]);
setfilterObj({ ...filterObj });
if (!val) init(filterObj);
setfilterObj(nextFilters);
setDateVal(startandend);
};
const handleEdit = async (id) => {
setisadd(false);
......@@ -139,9 +115,9 @@ const Applied = () => {
bool && init();
};
// 获取数据
const init = async (obj = {}) => {
const init = async (obj = {}, targetPage = page) => {
setLoading(true);
const { total, list } = await getAppList({ page, page_size, ...obj });
const { total, list } = await getAppList({ page: targetPage, page_size, ...obj });
setTotal(total);
setData(list);
setLoading(false);
......@@ -241,128 +217,43 @@ const Applied = () => {
},
];
const handleReset = () => {
setfilterObj({ app_name: "" });
setDateVal("");
init();
setfilterObj({});
setDateVal();
setPage(1);
init({}, 1);
};
const handleSearch = () => {
setPage(1);
init(filterObj, 1);
};
const toolbar = operationPermissionsList.includes("/setting/applied/add") ? (
<Button
type="primary"
ghost
onClick={() => {
setisadd(true);
setIsEdit(true);
}}
icon={
<span
style={{
display: "inline-block",
width: "13px",
height: "12px",
pointerEvents: "none",
}}
>
<Image src={Add} />
</span>
}
>
添加
</Button>
) : null;
return (
<div>
<Row justify={"space-between"}>
<Col className="form-devices-inline">
<Form layout="inline">
<Form.Item label="应用名称">
<Input
autoComplete="off"
value={filterObj.app_name}
allowClear
placeholder="请输入应用名称"
id="name"
onChange={(ev) => handleFilter("app_name", ev.target.value)}
></Input>
</Form.Item>
<Form.Item label="有效期">
<RangePicker
value={dateVal}
id="createTime"
onChange={(ev) => handleFilter("startandend", ev)}
></RangePicker>
</Form.Item>
<Space>
<Button
type="primary"
ghost
icon={
<span
style={{
display: "inline-block",
width: "11px",
height: "10px",
pointerEvents: "none",
}}
>
<Image src={reset} />
</span>
}
onClick={handleReset}
>
重置
</Button>
<Button
type="primary"
ghost
icon={
<span
style={{
display: "inline-block",
width: "13px",
height: "12px",
pointerEvents: "none",
}}
>
<Image src={filter} />
</span>
}
onClick={() => {
setPage(1);
Object.values(filterObj).some((item) => item) ? init(filterObj) : init();
}}
>
搜索
</Button>
<Button
type="primary"
ghost
icon={
<span
style={{
display: "inline-block",
width: "10px",
height: "12px",
pointerEvents: "none",
}}
>
<Image src={reload} />
</span>
}
onClick={() =>
Object.values(filterObj).some((item) => item) ? init(filterObj) : init()
}
>
刷新
</Button>
</Space>
</Form>
</Col>
<Col>
<Space>
{operationPermissionsList.includes("/setting/applied/add") && (
<Button
type="primary"
ghost
onClick={() => {
setisadd(true);
setIsEdit(true);
}}
icon={
<span
style={{
display: "inline-block",
width: "13px",
height: "12px",
pointerEvents: "none",
}}
>
<Image src={Add} />
</span>
}
>
添加
</Button>
)}
</Space>
</Col>
</Row>
<br />
<Modal
mask={false}
centered
......@@ -389,6 +280,36 @@ const Applied = () => {
rowKey="id"
columns={columns}
data={{ rows: data, total, loading }}
filters={{
value: { app_name: filterObj.app_name || "", startandend: dateVal },
items: [
{
name: "app_name",
label: "应用名称",
render: ({ value, onChange }) => (
<Input
autoComplete="off"
allowClear
placeholder="请输入应用名称"
value={value}
onChange={(event) => onChange(event.target.value)}
/>
),
},
{
name: "startandend",
label: "有效期",
render: ({ value, onChange }) => (
<RangePicker value={value} onChange={onChange} />
),
},
],
onChange: handleFiltersChange,
onSearch: handleSearch,
onReset: handleReset,
onRefresh: () => init(filterObj),
}}
toolbar={toolbar}
pagination={{
page,
pageSize: page_size,
......
......@@ -3,21 +3,16 @@ import {
Input,
Button,
Row,
Col,
Space,
DatePicker,
Popover,
Modal,
Form,
Image,
} from "antd";
const { RangePicker } = DatePicker;
import { delHelp } from "../api";
import { useNavigate } from "react-router";
import Add from "@/assets/images/icon/add.png";
import reload from "@/assets/images/icon/reload.png";
import reset from "@/assets/images/icon/reset.png";
import filter from "@/assets/images/icon/filter.png";
import dayjs from "dayjs";
import { useSelector } from "react-redux";
import { AppList } from "@/shared/components/AppList";
......@@ -34,7 +29,7 @@ const HelpTable = () => {
start_time: "",
end_time: "",
});
const [dateVal, setDateVal] = useState("");
const [dateVal, setDateVal] = useState(null);
const handleReset = () => {
setFilterObj({
......@@ -43,7 +38,7 @@ const HelpTable = () => {
end_time: "",
});
setDateVal("");
setDateVal(null);
init({});
};
......@@ -52,33 +47,19 @@ const HelpTable = () => {
// init();
// }, []);
// 过滤
const handleFilter = (flag, val) => {
if (flag == "startandend") {
let val2 = val || [];
filterObj["start_time"] = parseInt(
new Date(dayjs(val2[0]).format("YYYY-MM-DD") + " 00:00:00").getTime() / 1000,
);
const endDate = new Date(dayjs(val2[1])).getDate();
const endTime = parseInt(
new Date(dayjs(val2[1]).format("YYYY-MM-") + endDate + " 23:59:59").getTime() / 1000,
);
filterObj["end_time"] = endTime;
setDateVal(val);
if (!val2.length) {
delete filterObj["start_time"];
delete filterObj["end_time"];
}
} else {
filterObj[flag] = val;
const handleFiltersChange = (nextFilters) => {
const nextFilterObj = {};
if (nextFilters.help_title) {
nextFilterObj.help_title = nextFilters.help_title;
}
for (const key in filterObj) {
if (!filterObj[key]) {
delete filterObj[key];
}
if (nextFilters.dateRange?.length === 2) {
nextFilterObj.start_time = dayjs(nextFilters.dateRange[0]).startOf("day").unix();
nextFilterObj.end_time = dayjs(nextFilters.dateRange[1]).endOf("day").unix();
}
setFilterObj({ ...filterObj });
if (!val) init(filterObj);
setDateVal(nextFilters.dateRange || null);
setFilterObj(nextFilterObj);
};
// 删除
......@@ -159,120 +140,6 @@ const HelpTable = () => {
];
return (
<div>
<Row justify={"space-between"}>
<Col className="form-devices-inline">
<Form layout="inline">
<Form.Item label="问题名称">
<Input
autoComplete="off"
allowClear
placeholder="请输入问题名称"
id="name"
value={filterObj.help_title}
onChange={(ev) => handleFilter("help_title", ev.target.value)}
></Input>
</Form.Item>
<Form.Item label="创建时间">
<RangePicker
id="createTime"
value={dateVal}
onChange={(ev) => handleFilter("startandend", ev)}
></RangePicker>
</Form.Item>
<Space>
<Button
type="primary"
ghost
icon={
<span
style={{
display: "inline-block",
width: "11px",
height: "10px",
pointerEvents: "none",
}}
>
<Image src={reset} />
</span>
}
onClick={handleReset}
>
重置
</Button>
<Button
type="primary"
icon={
<span
style={{
display: "inline-block",
width: "13px",
height: "12px",
pointerEvents: "none",
}}
>
<Image src={filter} />
</span>
}
ghost
onClick={() => {
Object.values(filterObj).some((item) => item) ? init(filterObj, 1) : init({}, 1);
}}
>
搜索
</Button>
<Button
type="primary"
ghost
icon={
<span
style={{
display: "inline-block",
width: "10px",
height: "12px",
pointerEvents: "none",
}}
>
<Image src={reload} />
</span>
}
onClick={() =>
Object.values(filterObj).some((item) => item) ? init(filterObj) : init({})
}
>
刷新
</Button>
</Space>
</Form>
</Col>
<Col>
<Space>
{operationPermissionsList.includes("/setting/help/add") && (
<Button
type="primary"
ghost
onClick={() => {
navigate("/setting/help/addedit");
}}
icon={
<span
style={{
display: "inline-block",
width: "13px",
height: "12px",
pointerEvents: "none",
}}
>
<Image src={Add} />
</span>
}
>
添加
</Button>
)}
</Space>
</Col>
</Row>
<br />
<Modal
mask={false}
centered
......@@ -299,6 +166,49 @@ const HelpTable = () => {
rowKey="id"
columns={columns}
data={{ rows, total, loading, error }}
filters={{
value: { help_title: filterObj.help_title || "", dateRange: dateVal },
items: [
{
name: "help_title",
label: "问题名称",
render: ({ value, onChange }) => (
<Input
autoComplete="off"
allowClear
placeholder="请输入问题名称"
value={value}
onChange={(event) => onChange(event.target.value)}
/>
),
},
{
name: "dateRange",
label: "创建时间",
render: ({ value, onChange }) => <RangePicker value={value} onChange={onChange} />,
},
],
onChange: handleFiltersChange,
onSearch: () => init(filterObj, 1),
onReset: handleReset,
onRefresh: () => init(filterObj),
}}
toolbar={
operationPermissionsList.includes("/setting/help/add") ? (
<Button
type="primary"
ghost
onClick={() => navigate("/setting/help/addedit")}
icon={
<span style={{ display: "inline-block", width: "13px", height: "12px", pointerEvents: "none" }}>
<Image src={Add} />
</span>
}
>
添加
</Button>
) : null
}
pagination={{
page,
pageSize,
......
......@@ -20,9 +20,6 @@ import { useSelector } from 'react-redux'
import { AppList } from '@/shared/components/AppList'
import { getAllList } from '@/pages/jurisdiction/role/request.js'
import add from '@/assets/images/icon/add.png'
import filter from '@/assets/images/icon/filter.png'
import reload from '@/assets/images/icon/reload.png'
import reset from '@/assets/images/icon/reset.png'
import {
addTeacher,
......@@ -58,7 +55,7 @@ export default function TeacherListView() {
const [isEditValidity, setIsEditValidity] = useState(false)
const [id, setId] = useState(0)
const [roleList, setRoleList] = useState([])
const [dateVal, setDateVal] = useState('')
const [dateVal, setDateVal] = useState([])
const [filters, setFilters] = useState({ real_name: '', tel: '', start_time: '', end_time: '' })
const [form] = Form.useForm()
const [passwordForm] = Form.useForm()
......@@ -85,31 +82,21 @@ export default function TeacherListView() {
if (has('/teacher/list/getSystem')) void getInfo()
}, [operationPermissionsList])
const handleFilter = (name, value) => {
const next = { ...filters }
if (name === 'startandend') {
const range = value || []
if (range.length) {
next.start_time = dayjs(dayjs(range[0]).format('YYYY-MM-DD') + ' 00:00:00').unix()
next.end_time = dayjs(dayjs(range[1]).format('YYYY-MM-DD') + ' 23:59:59').unix()
} else {
delete next.start_time
delete next.end_time
}
setDateVal(value)
} else {
next[name] = value
const updateListFilters = (next) => {
const { dateRange, ...fields } = next
const query = Object.fromEntries(Object.entries(fields).filter(([, value]) => value))
if (dateRange?.length) {
query.start_time = dayjs(`${dayjs(dateRange[0]).format('YYYY-MM-DD')} 00:00:00`).unix()
query.end_time = dayjs(`${dayjs(dateRange[1]).format('YYYY-MM-DD')} 23:59:59`).unix()
}
Object.keys(next).forEach((key) => !next[key] && delete next[key])
setFilters(next)
if (!value) void init(next)
setDateVal(dateRange || [])
setFilters(query)
}
const resetFilters = () => {
const next = { real_name: '', tel: '' }
setFilters(next)
setDateVal('')
void init(next)
const listFilterValue = {
real_name: filters.real_name || '',
tel: filters.tel || '',
dateRange: dateVal,
}
const submitTeacher = async (values) => {
......@@ -177,26 +164,21 @@ export default function TeacherListView() {
const icon = (source, width, height) => <span style={{ display: 'inline-block', width, height, pointerEvents: 'none' }}><Image src={source} /></span>
return <div>
<Row justify="space-between">
<Col className="form-devices-inline">
<Form layout="inline">
<Form.Item label="老师名称"><Input autoComplete="off" allowClear value={filters.real_name} onChange={(event) => handleFilter('real_name', event.target.value)} placeholder="请输入老师名称" id="name" /></Form.Item>
<Form.Item label="手机号"><Input autoComplete="off" allowClear value={filters.tel} onChange={(event) => handleFilter('tel', event.target.value)} placeholder="请输入手机号" id="phone" /></Form.Item>
<Form.Item label="创建时间"><RangePicker value={dateVal} onChange={(value) => handleFilter('startandend', value)} id="createTime" /></Form.Item>
<Space>
<Button type="primary" ghost icon={icon(reset, '11px', '10px')} onClick={resetFilters}>重置</Button>
<Button type="primary" ghost icon={icon(filter, '13px', '12px')} onClick={() => { void init(filters, 1); }}>搜索</Button>
<Button type="primary" ghost icon={icon(reload, '10px', '12px')} onClick={() => { void reloadList(); }}>刷新</Button>
</Space>
</Form>
</Col>
<Col><Space>
<AppList rowKey="id" columns={columns} data={{ rows, total, loading, error }} filters={{
value: listFilterValue,
items: [
{ name: 'real_name', label: '老师名称', render: ({ value, onChange }) => <Input autoComplete="off" allowClear value={value} onChange={(event) => onChange(event.target.value)} placeholder="请输入老师名称" id="name" /> },
{ name: 'tel', label: '手机号', render: ({ value, onChange }) => <Input autoComplete="off" allowClear value={value} onChange={(event) => onChange(event.target.value)} placeholder="请输入手机号" id="phone" /> },
{ name: 'dateRange', label: '创建时间', render: ({ value, onChange }) => <RangePicker value={value} onChange={onChange} id="createTime" /> },
],
onChange: updateListFilters,
onSearch: () => { void init(filters, 1) },
onReset: () => { setFilters({}); setDateVal([]); void init({}, 1) },
onRefresh: () => { void reloadList() },
}} toolbar={<Space>
{has('/teacher/list/add') && <Button type="primary" ghost icon={icon(add, '13px', '12px')} onClick={() => { setIsAdd(true); setShowModal(true) }}>添加</Button>}
{has('/teacher/list/getSystem') && <Button type="primary" ghost onClick={() => { setIsAdd(true); setIsEditValidity(true) }}>分成设置</Button>}
</Space></Col>
</Row>
<br />
<AppList rowKey="id" columns={columns} data={{ rows, total, loading, error }} pagination={{ page, pageSize, pageSizeOptions: [10, 20, 30, 40], onChange: (nextPage) => changePage(nextPage, filters), onPageSizeChange: (nextPageSize) => changePageSize(nextPageSize, filters) }} onRetry={() => reloadList()} />
</Space>} pagination={{ page, pageSize, pageSizeOptions: [10, 20, 30, 40], onChange: (nextPage) => changePage(nextPage, filters), onPageSizeChange: (nextPageSize) => changePageSize(nextPageSize, filters) }} onRetry={() => reloadList()} />
<Modal mask={false} centered open={deleteModal} onOk={() => void submitDelete()} onCancel={() => setDeleteModal(false)} footer={(_, { OkBtn, CancelBtn }) => <Row justify="center" className="delModal" style={{ marginBottom: '30px' }}><Space size={20}><CancelBtn /><OkBtn /></Space></Row>} okText="提交"><p style={{ textAlign: 'center', padding: '30px 0 18px', fontSize: 16 }}>老师将永久删除,是否继续?</p></Modal>
<Drawer mask={false} open={passwordModal} onClose={() => setPasswordModal(false)} footer={null} width={700}>
<Form labelCol={{ span: 6 }} form={passwordForm} wrapperCol={{ span: 12 }} onFinish={submitPassword}>
......
import { useEffect, useState, useRef } from "react";
import { Input, Button, Space, Popover, Switch, Image, App } from "antd";
import { getCoupon, setCoupon } from "./request";
import Add from "@/assets/images/icon/add.png";
import coupon from "@/assets/images/icon/coupon.png";
import coupon2 from "@/assets/images/icon/coupon2.png";
import { useSelector } from "react-redux";
import AppList from "@/components/list";
import FormDrawer from "./components/FormDrawer";
import SendCouponDrawer from "./components/SendCouponDrawer";
import * as api from "./api";
const Coupon = () => {
const { modal } = App.useApp();
const appListRef = useRef(null);
const reload = async () => {
await appListRef.current.handleReload(true);
};
const [drawerOpen, setDrawerOpen] = useState(false);
// 获取操作权限
const { operationPermissionsList } = useSelector((state) => state.user);
// 操作某一项的id
const [id, setId] = useState("");
const [switchFlag, setSwitchFlag] = useState(false);
const [couponList, setCouponList] = useState([]);
const [sendCouponDrawerOpen, setSendCouponDrawerOpen] = useState(false);
// 添加
const handleAdd = () => {
setId("");
setDrawerOpen(true);
};
// 编辑
const handleEdit = async (id) => {
setId(id);
setDrawerOpen(true);
};
const onClose = () => {
setDrawerOpen(false);
};
// 删除
const handleDelete = async (id) => {
modal.confirm({
title: "提示",
content: "优惠券将永久删除,是否继续?",
onOk: async () => {
await api.delCoupon({ id });
reload();
},
});
};
// 获取优惠券开关状态
const handleCoupon = async () => {
const { coupon_switch } = await getCoupon();
coupon_switch == "1" ? setSwitchFlag(true) : setSwitchFlag(false);
};
const [swithcLoad, setSwitchLoad] = useState(false);
// 改变优惠券开关
const changeCoupon = async (val) => {
setSwitchLoad(true);
let coupon_switch = val ? "1" : "0";
const bool = await setCoupon({ coupon_switch });
setTimeout(() => {
setSwitchLoad(false);
}, 500);
handleCoupon();
};
useEffect(() => {
handleCoupon();
}, []);
const remote = {
request: api.getList,
afterRequest(data) {
setCouponList(data.list);
return data;
},
};
const filters = [
{
label: "优惠券名称",
name: "name",
element: <Input placeholder="请输入优惠券名称" allowClear />,
},
];
const columns = [
{
title: "ID",
key: "id",
align: "center",
dataIndex: "id",
},
{
title: "优惠券名称",
key: "name",
align: "center",
dataIndex: "name",
width: 200,
render: (text) => (
<Popover content={text} overlayStyle={{ maxWidth: "400px" }}>
<div
style={{
display: "-webkit-box",
WebkitLineClamp: "2",
WebkitBoxOrient: "vertical",
overflow: "hidden",
textOverflow: "ellipsis",
textAlign: "center",
}}
>
{text}
</div>
</Popover>
),
},
{
title: "达标金额",
key: "norm_price",
align: "center",
dataIndex: "norm_price",
},
{
title: "满减金额",
key: "reduced_price",
align: "center",
dataIndex: "reduced_price",
},
{
title: "有效期开始时间",
key: "start_time",
align: "center",
dataIndex: "start_time",
},
{
title: "有效期结束时间",
key: "end_time",
align: "center",
dataIndex: "end_time",
},
{
title: "领取人数",
key: "receive_num",
align: "center",
dataIndex: "receive_num",
},
{
title: "使用人数",
key: "use_num",
align: "center",
dataIndex: "use_num",
},
{
title: "操作",
key: "handle",
align: "center",
dataIndex: "handle",
render: (_, { id }) => {
return (
<Space>
{operationPermissionsList.includes("/setting/coupon/getInfoById") && (
<Button onClick={() => handleEdit(id)}>编辑</Button>
)}
{operationPermissionsList.includes("/setting/coupon/del") && (
<Button onClick={() => handleDelete(id)}>删除</Button>
)}
</Space>
);
},
},
];
const filterAside = (
<Space>
<label htmlFor="coupon">优惠券开关</label>
<Switch
checked={switchFlag}
loading={swithcLoad}
onChange={changeCoupon}
disabled={!operationPermissionsList.includes("/setting/coupon/getCoupon")}
></Switch>
{operationPermissionsList.includes("/setting/coupon/add") && (
<Button
type="primary"
disabled={!switchFlag}
ghost
icon={
<img
style={{
background: !switchFlag,
display: "inline-block",
width: "13px",
height: "11px",
pointerEvents: "none",
}}
src={!switchFlag ? coupon2 : coupon}
/>
}
onClick={() => setSendCouponDrawerOpen(true)}
>
优惠券发放
</Button>
)}
{operationPermissionsList.includes("/setting/coupon/give") && (
<Button
type="primary"
ghost
icon={
<span
style={{
display: "inline-block",
width: "13px",
height: "12px",
pointerEvents: "none",
}}
>
<Image src={Add} />
</span>
}
onClick={handleAdd}
>
添加
</Button>
)}
</Space>
);
return (
<div className="classify">
<AppList {...{ remote, filters, columns, filterAside }} ref={appListRef}></AppList>
{/* 添加编辑 */}
<FormDrawer open={drawerOpen} id={id} onClose={onClose} onComplete={reload}></FormDrawer>
{/* 优惠券发送 */}
<SendCouponDrawer
open={sendCouponDrawerOpen}
couponList={couponList}
onClose={() => setSendCouponDrawerOpen(false)}
></SendCouponDrawer>
</div>
);
};
export default Coupon;
export { default } from "@/modules/settings/coupon/views/CouponListView";
......@@ -104,7 +104,7 @@ describe("AppList", () => {
expect(input).toHaveValue("原值");
});
it("reports search, reset, and refresh without doing work itself", async () => {
it("reports search and reset without doing work itself", async () => {
const user = userEvent.setup();
const onSearch = vi.fn();
const onReset = vi.fn();
......@@ -123,11 +123,10 @@ describe("AppList", () => {
await user.click(screen.getByRole("button", { name: /搜\s*索/ }));
await user.click(screen.getByRole("button", { name: /重\s*置/ }));
await user.click(screen.getByRole("button", { name: /刷\s*新/ }));
expect(onSearch).toHaveBeenCalledTimes(1);
expect(onReset).toHaveBeenCalledTimes(1);
expect(onRefresh).toHaveBeenCalledTimes(1);
expect(onRefresh).not.toHaveBeenCalled();
expect(screen.queryByRole("button", { name: /刷\s*新/ })).not.toBeInTheDocument();
});
it("uses controlled page, pageSize, and total and reports pagination changes", async () => {
......
import { Alert, Button, Empty, Space, Table } from "antd";
import type { TablePaginationConfig } from "antd/es/table";
import { ReloadOutlined, SearchOutlined } from "@ant-design/icons";
import type { AppListFilterItem, AppListProps } from "./types";
......@@ -64,11 +65,12 @@ export function AppList<Row extends object, Filters extends object = Record<stri
))}
</div>
<Space wrap>
<Button type="primary" onClick={filters.onSearch}>
<Button type="primary" icon={<SearchOutlined />} onClick={filters.onSearch}>
搜索
</Button>
<Button onClick={filters.onReset}>重置</Button>
<Button onClick={filters.onRefresh}>刷新</Button>
<Button icon={<ReloadOutlined />} onClick={filters.onReset}>
重置
</Button>
</Space>
</section>
) : null}
......
Markdown 格式
0% 或
您添加了 0 人 到此讨论。请谨慎行事。
请先完成此评论的编辑!
请 注册 或者 后发表评论