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

refactor(admin): unify list filters in AppList

上级 761e2bd5
...@@ -3,8 +3,6 @@ import { ...@@ -3,8 +3,6 @@ import {
Table, Table,
Input, Input,
Button, Button,
Row,
Col,
Space, Space,
DatePicker, DatePicker,
Radio, Radio,
...@@ -21,9 +19,6 @@ import { getList, addVersion, editVersion, infoVersion, delVersion } from "../ap ...@@ -21,9 +19,6 @@ import { getList, addVersion, editVersion, infoVersion, delVersion } from "../ap
const { TextArea } = Input; const { TextArea } = Input;
import dayjs from "dayjs"; import dayjs from "dayjs";
import Add from "@/assets/images/icon/add.png"; 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 { useSelector } from "react-redux";
import AliOSS from "ali-oss"; import AliOSS from "ali-oss";
import { getAliOSSSTSToken } from "@/pages/setting/help/addedit/requet"; import { getAliOSSSTSToken } from "@/pages/setting/help/addedit/requet";
...@@ -36,7 +31,6 @@ const AppVersion = () => { ...@@ -36,7 +31,6 @@ const AppVersion = () => {
const [isEdit, setIsEdit] = useState(false); const [isEdit, setIsEdit] = useState(false);
const [delMoadal, setDelModal] = useState(false); const [delMoadal, setDelModal] = useState(false);
const [isadd, setisadd] = useState(true); const [isadd, setisadd] = useState(true);
const [dateVal, setDateVal] = useState("");
const [form] = Form.useForm(); const [form] = Form.useForm();
// 获取操作权限 // 获取操作权限
const { operationPermissionsList } = useSelector((state) => state.user); const { operationPermissionsList } = useSelector((state) => state.user);
...@@ -49,8 +43,7 @@ const AppVersion = () => { ...@@ -49,8 +43,7 @@ const AppVersion = () => {
const [delid, setdelid] = useState(0); const [delid, setdelid] = useState(0);
const [filterObj, setfilterObj] = useState({ const [filterObj, setfilterObj] = useState({
version: "", version: "",
start_time: "", dateRange: [],
end_time: "",
}); });
const [ossClient, setOssClient] = useState(null); // oss 操作 const [ossClient, setOssClient] = useState(null); // oss 操作
...@@ -140,11 +133,6 @@ const AppVersion = () => { ...@@ -140,11 +133,6 @@ const AppVersion = () => {
}, },
}; };
const handleReset = () => {
setfilterObj({ version: "" });
setDateVal("");
init();
};
const handleEdit = async (id) => { const handleEdit = async (id) => {
const data = await infoVersion({ id }); const data = await infoVersion({ id });
setisadd(false); setisadd(false);
...@@ -189,37 +177,28 @@ const AppVersion = () => { ...@@ -189,37 +177,28 @@ const AppVersion = () => {
form.setFieldsValue(initialValues); form.setFieldsValue(initialValues);
} }
}, [isEdit]); }, [isEdit]);
// 过滤 const getQuery = ({ version, dateRange }) => {
const handleFilter = (flag, val) => { const query = version ? { version } : {};
if (flag == "startandend") {
let val2 = val || []; if (dateRange?.length === 2) {
filterObj["start_time"] = parseInt( query.start_time = parseInt(
new Date(dayjs(val2[0]).format("YYYY-MM-DD") + " 00:00:00").getTime() / 1000, new Date(dayjs(dateRange[0]).format("YYYY-MM-DD") + " 00:00:00").getTime() / 1000,
); );
const endDate = new Date(dayjs(val2[1])).getDate(); const endDate = new Date(dayjs(dateRange[1])).getDate();
const endTime = parseInt( query.end_time = parseInt(
new Date(dayjs(val2[1]).format("YYYY-MM-") + endDate + " 23:59:59").getTime() / 1000, 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 }); return query;
if (!val) init(filterObj);
}; };
const init = async (obj = {}) => { const init = async (obj = filterObj, nextPage = page, nextPageSize = page_size) => {
setLoading(true); 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); setTotal(total);
setData(list); setData(list);
setLoading(false); setLoading(false);
...@@ -227,7 +206,7 @@ const AppVersion = () => { ...@@ -227,7 +206,7 @@ const AppVersion = () => {
// 删除 // 删除
const handleDel = async () => { const handleDel = async () => {
const bool = await delVersion({ id: delid }); const bool = await delVersion({ id: delid });
bool && init(); bool && init(filterObj);
setDelModal(false); setDelModal(false);
}; };
...@@ -301,95 +280,61 @@ const AppVersion = () => { ...@@ -301,95 +280,61 @@ const AppVersion = () => {
]; ];
return ( return (
<div className="classify"> <div className="classify">
<Row justify={"space-between"}> <AppList
<Col className="form-devices-inline"> rowKey="id"
<Form layout="inline"> columns={columns}
<Form.Item label="版本号"> data={{ rows: data, total, loading }}
filters={{
value: filterObj,
items: [
{
name: "version",
label: "版本号",
render: (field) => (
<Input <Input
autoComplete="off" autoComplete="off"
allowClear allowClear
value={filterObj.version} value={field.value}
placeholder="请输入版本号" placeholder="请输入版本号"
id="name" onChange={(event) => field.onChange(event.target.value)}
onChange={(ev) => handleFilter("version", ev.target.value)} />
></Input> ),
</Form.Item> },
<Form.Item label="发布时间"> {
<RangePicker name: "dateRange",
value={dateVal} label: "发布时间",
id="createTime" render: (field) => <RangePicker value={field.value} onChange={field.onChange} />,
onChange={(ev) => handleFilter("startandend", ev)} },
></RangePicker> ],
</Form.Item> onChange: setfilterObj,
<Space> onSearch: () => {
<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); setPage(1);
Object.values(filterObj).some((item) => item) ? init(filterObj) : init(); init(filterObj, 1);
},
onReset: () => {
const nextFilters = { version: "", dateRange: [] };
setfilterObj(nextFilters);
setPage(1);
init(nextFilters, 1);
},
onRefresh: () => init(filterObj),
}} }}
> pagination={{
搜索 page,
</Button> pageSize: page_size,
<Button pageSizeOptions: [10, 20, 30, 40],
type="primary" onChange: (nextPage) => {
ghost setPage(nextPage);
icon={ init(filterObj, nextPage);
<span },
style={{ onPageSizeChange: (nextPageSize) => {
display: "inline-block", setpage_size(nextPageSize);
width: "10px", setPage(1);
height: "12px", init(filterObj, 1, nextPageSize);
pointerEvents: "none", },
}} }}
> toolbar={
<Image src={reload} /> operationPermissionsList.includes("/setting/applied/add") ? (
</span>
}
onClick={() =>
Object.values(filterObj).some((item) => item) ? init(filterObj) : init()
}
>
刷新
</Button>
</Space>
</Form>
</Col>
<Col>
<Space>
{operationPermissionsList.includes("/setting/applied/add") && (
<Button <Button
type="primary" type="primary"
ghost ghost
...@@ -412,12 +357,9 @@ const AppVersion = () => { ...@@ -412,12 +357,9 @@ const AppVersion = () => {
> >
添加 添加
</Button> </Button>
)} ) : null
</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 }} />
<Modal <Modal
mask={false} mask={false}
centered centered
......
...@@ -3,7 +3,6 @@ import { ...@@ -3,7 +3,6 @@ import {
Input, Input,
Button, Button,
Row, Row,
Col,
Space, Space,
DatePicker, DatePicker,
Drawer, Drawer,
...@@ -20,9 +19,6 @@ import { AppList } from "@/shared/components/AppList"; ...@@ -20,9 +19,6 @@ import { AppList } from "@/shared/components/AppList";
import { getAppList, addApp, editApp, delApp, changeStatus, getAppInfo } from "../api"; import { getAppList, addApp, editApp, delApp, changeStatus, getAppInfo } from "../api";
import { MinusOutlined, PlusOutlined } from "@ant-design/icons"; import { MinusOutlined, PlusOutlined } from "@ant-design/icons";
import Add from "@/assets/images/icon/add.png"; 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 dayjs from "dayjs";
import { useSelector } from "react-redux"; import { useSelector } from "react-redux";
// import './index.less' // import './index.less'
...@@ -48,7 +44,7 @@ const Applied = () => { ...@@ -48,7 +44,7 @@ const Applied = () => {
app_name: "", app_name: "",
validity: "", validity: "",
}); });
const [dateVal, setDateVal] = useState(""); const [dateVal, setDateVal] = useState();
const [id, setid] = useState(0); const [id, setid] = useState(0);
const [delid, setdelid] = useState(0); const [delid, setdelid] = useState(0);
// 获取操作权限 // 获取操作权限
...@@ -58,36 +54,16 @@ const Applied = () => { ...@@ -58,36 +54,16 @@ const Applied = () => {
start_time: "", start_time: "",
end_time: "", end_time: "",
}); });
// 过滤 const handleFiltersChange = ({ app_name, startandend }) => {
const handleFilter = (flag, val) => { const nextFilters = app_name ? { app_name } : {};
if (flag == "startandend") {
let val2 = val || []; if (startandend?.length === 2) {
filterObj["start_time"] = parseInt( nextFilters.start_time = dayjs(startandend[0]).startOf("day").unix();
new Date(dayjs(val2[0]).format("YYYY-MM-DD") + " 00:00:00").getTime() / 1000, nextFilters.end_time = dayjs(startandend[1]).endOf("day").unix();
);
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];
}
} }
console.log("start_time", filterObj["start_time"]); setfilterObj(nextFilters);
console.log("end_time", filterObj["end_time"]); setDateVal(startandend);
setfilterObj({ ...filterObj });
if (!val) init(filterObj);
}; };
const handleEdit = async (id) => { const handleEdit = async (id) => {
setisadd(false); setisadd(false);
...@@ -139,9 +115,9 @@ const Applied = () => { ...@@ -139,9 +115,9 @@ const Applied = () => {
bool && init(); bool && init();
}; };
// 获取数据 // 获取数据
const init = async (obj = {}) => { const init = async (obj = {}, targetPage = page) => {
setLoading(true); setLoading(true);
const { total, list } = await getAppList({ page, page_size, ...obj }); const { total, list } = await getAppList({ page: targetPage, page_size, ...obj });
setTotal(total); setTotal(total);
setData(list); setData(list);
setLoading(false); setLoading(false);
...@@ -241,101 +217,18 @@ const Applied = () => { ...@@ -241,101 +217,18 @@ const Applied = () => {
}, },
]; ];
const handleReset = () => { const handleReset = () => {
setfilterObj({ app_name: "" }); setfilterObj({});
setDateVal(""); setDateVal();
init(); setPage(1);
init({}, 1);
}; };
return (
<div> const handleSearch = () => {
<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); setPage(1);
Object.values(filterObj).some((item) => item) ? init(filterObj) : init(); init(filterObj, 1);
}} };
>
搜索 const toolbar = operationPermissionsList.includes("/setting/applied/add") ? (
</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 <Button
type="primary" type="primary"
ghost ghost
...@@ -358,11 +251,9 @@ const Applied = () => { ...@@ -358,11 +251,9 @@ const Applied = () => {
> >
添加 添加
</Button> </Button>
)} ) : null;
</Space> return (
</Col> <div>
</Row>
<br />
<Modal <Modal
mask={false} mask={false}
centered centered
...@@ -389,6 +280,36 @@ const Applied = () => { ...@@ -389,6 +280,36 @@ const Applied = () => {
rowKey="id" rowKey="id"
columns={columns} columns={columns}
data={{ rows: data, total, loading }} 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={{ pagination={{
page, page,
pageSize: page_size, pageSize: page_size,
......
...@@ -3,21 +3,16 @@ import { ...@@ -3,21 +3,16 @@ import {
Input, Input,
Button, Button,
Row, Row,
Col,
Space, Space,
DatePicker, DatePicker,
Popover, Popover,
Modal, Modal,
Form,
Image, Image,
} from "antd"; } from "antd";
const { RangePicker } = DatePicker; const { RangePicker } = DatePicker;
import { delHelp } from "../api"; import { delHelp } from "../api";
import { useNavigate } from "react-router"; import { useNavigate } from "react-router";
import Add from "@/assets/images/icon/add.png"; 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 dayjs from "dayjs";
import { useSelector } from "react-redux"; import { useSelector } from "react-redux";
import { AppList } from "@/shared/components/AppList"; import { AppList } from "@/shared/components/AppList";
...@@ -34,7 +29,7 @@ const HelpTable = () => { ...@@ -34,7 +29,7 @@ const HelpTable = () => {
start_time: "", start_time: "",
end_time: "", end_time: "",
}); });
const [dateVal, setDateVal] = useState(""); const [dateVal, setDateVal] = useState(null);
const handleReset = () => { const handleReset = () => {
setFilterObj({ setFilterObj({
...@@ -43,7 +38,7 @@ const HelpTable = () => { ...@@ -43,7 +38,7 @@ const HelpTable = () => {
end_time: "", end_time: "",
}); });
setDateVal(""); setDateVal(null);
init({}); init({});
}; };
...@@ -52,33 +47,19 @@ const HelpTable = () => { ...@@ -52,33 +47,19 @@ const HelpTable = () => {
// init(); // init();
// }, []); // }, []);
// 过滤 const handleFiltersChange = (nextFilters) => {
const handleFilter = (flag, val) => { const nextFilterObj = {};
if (flag == "startandend") { if (nextFilters.help_title) {
let val2 = val || []; nextFilterObj.help_title = nextFilters.help_title;
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];
} }
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 = () => { ...@@ -159,120 +140,6 @@ const HelpTable = () => {
]; ];
return ( return (
<div> <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 <Modal
mask={false} mask={false}
centered centered
...@@ -299,6 +166,49 @@ const HelpTable = () => { ...@@ -299,6 +166,49 @@ const HelpTable = () => {
rowKey="id" rowKey="id"
columns={columns} columns={columns}
data={{ rows, total, loading, error }} 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={{ pagination={{
page, page,
pageSize, pageSize,
......
...@@ -20,9 +20,6 @@ import { useSelector } from 'react-redux' ...@@ -20,9 +20,6 @@ import { useSelector } from 'react-redux'
import { AppList } from '@/shared/components/AppList' import { AppList } from '@/shared/components/AppList'
import { getAllList } from '@/pages/jurisdiction/role/request.js' import { getAllList } from '@/pages/jurisdiction/role/request.js'
import add from '@/assets/images/icon/add.png' 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 { import {
addTeacher, addTeacher,
...@@ -58,7 +55,7 @@ export default function TeacherListView() { ...@@ -58,7 +55,7 @@ export default function TeacherListView() {
const [isEditValidity, setIsEditValidity] = useState(false) const [isEditValidity, setIsEditValidity] = useState(false)
const [id, setId] = useState(0) const [id, setId] = useState(0)
const [roleList, setRoleList] = useState([]) const [roleList, setRoleList] = useState([])
const [dateVal, setDateVal] = useState('') const [dateVal, setDateVal] = useState([])
const [filters, setFilters] = useState({ real_name: '', tel: '', start_time: '', end_time: '' }) const [filters, setFilters] = useState({ real_name: '', tel: '', start_time: '', end_time: '' })
const [form] = Form.useForm() const [form] = Form.useForm()
const [passwordForm] = Form.useForm() const [passwordForm] = Form.useForm()
...@@ -85,31 +82,21 @@ export default function TeacherListView() { ...@@ -85,31 +82,21 @@ export default function TeacherListView() {
if (has('/teacher/list/getSystem')) void getInfo() if (has('/teacher/list/getSystem')) void getInfo()
}, [operationPermissionsList]) }, [operationPermissionsList])
const handleFilter = (name, value) => { const updateListFilters = (next) => {
const next = { ...filters } const { dateRange, ...fields } = next
if (name === 'startandend') { const query = Object.fromEntries(Object.entries(fields).filter(([, value]) => value))
const range = value || [] if (dateRange?.length) {
if (range.length) { query.start_time = dayjs(`${dayjs(dateRange[0]).format('YYYY-MM-DD')} 00:00:00`).unix()
next.start_time = dayjs(dayjs(range[0]).format('YYYY-MM-DD') + ' 00:00:00').unix() query.end_time = dayjs(`${dayjs(dateRange[1]).format('YYYY-MM-DD')} 23:59:59`).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) setDateVal(dateRange || [])
} else { setFilters(query)
next[name] = value
}
Object.keys(next).forEach((key) => !next[key] && delete next[key])
setFilters(next)
if (!value) void init(next)
} }
const resetFilters = () => { const listFilterValue = {
const next = { real_name: '', tel: '' } real_name: filters.real_name || '',
setFilters(next) tel: filters.tel || '',
setDateVal('') dateRange: dateVal,
void init(next)
} }
const submitTeacher = async (values) => { const submitTeacher = async (values) => {
...@@ -177,26 +164,21 @@ export default function TeacherListView() { ...@@ -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> const icon = (source, width, height) => <span style={{ display: 'inline-block', width, height, pointerEvents: 'none' }}><Image src={source} /></span>
return <div> return <div>
<Row justify="space-between"> <AppList rowKey="id" columns={columns} data={{ rows, total, loading, error }} filters={{
<Col className="form-devices-inline"> value: listFilterValue,
<Form layout="inline"> items: [
<Form.Item label="老师名称"><Input autoComplete="off" allowClear value={filters.real_name} onChange={(event) => handleFilter('real_name', event.target.value)} placeholder="请输入老师名称" id="name" /></Form.Item> { name: 'real_name', label: '老师名称', render: ({ value, onChange }) => <Input autoComplete="off" allowClear value={value} onChange={(event) => onChange(event.target.value)} placeholder="请输入老师名称" id="name" /> },
<Form.Item label="手机号"><Input autoComplete="off" allowClear value={filters.tel} onChange={(event) => handleFilter('tel', event.target.value)} placeholder="请输入手机号" id="phone" /></Form.Item> { name: 'tel', label: '手机号', render: ({ value, onChange }) => <Input autoComplete="off" allowClear value={value} onChange={(event) => onChange(event.target.value)} placeholder="请输入手机号" id="phone" /> },
<Form.Item label="创建时间"><RangePicker value={dateVal} onChange={(value) => handleFilter('startandend', value)} id="createTime" /></Form.Item> { name: 'dateRange', label: '创建时间', render: ({ value, onChange }) => <RangePicker value={value} onChange={onChange} id="createTime" /> },
<Space> ],
<Button type="primary" ghost icon={icon(reset, '11px', '10px')} onClick={resetFilters}>重置</Button> onChange: updateListFilters,
<Button type="primary" ghost icon={icon(filter, '13px', '12px')} onClick={() => { void init(filters, 1); }}>搜索</Button> onSearch: () => { void init(filters, 1) },
<Button type="primary" ghost icon={icon(reload, '10px', '12px')} onClick={() => { void reloadList(); }}>刷新</Button> onReset: () => { setFilters({}); setDateVal([]); void init({}, 1) },
</Space> onRefresh: () => { void reloadList() },
</Form> }} toolbar={<Space>
</Col>
<Col><Space>
{has('/teacher/list/add') && <Button type="primary" ghost icon={icon(add, '13px', '12px')} onClick={() => { setIsAdd(true); setShowModal(true) }}>添加</Button>} {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>} {has('/teacher/list/getSystem') && <Button type="primary" ghost onClick={() => { setIsAdd(true); setIsEditValidity(true) }}>分成设置</Button>}
</Space></Col> </Space>} pagination={{ page, pageSize, pageSizeOptions: [10, 20, 30, 40], onChange: (nextPage) => changePage(nextPage, filters), onPageSizeChange: (nextPageSize) => changePageSize(nextPageSize, filters) }} onRetry={() => reloadList()} />
</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()} />
<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> <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}> <Drawer mask={false} open={passwordModal} onClose={() => setPasswordModal(false)} footer={null} width={700}>
<Form labelCol={{ span: 6 }} form={passwordForm} wrapperCol={{ span: 12 }} onFinish={submitPassword}> <Form labelCol={{ span: 6 }} form={passwordForm} wrapperCol={{ span: 12 }} onFinish={submitPassword}>
......
import { useEffect, useState, useRef } from "react"; export { default } from "@/modules/settings/coupon/views/CouponListView";
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;
...@@ -104,7 +104,7 @@ describe("AppList", () => { ...@@ -104,7 +104,7 @@ describe("AppList", () => {
expect(input).toHaveValue("原值"); 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 user = userEvent.setup();
const onSearch = vi.fn(); const onSearch = vi.fn();
const onReset = vi.fn(); const onReset = vi.fn();
...@@ -123,11 +123,10 @@ describe("AppList", () => { ...@@ -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*置/ })); await user.click(screen.getByRole("button", { name: /重\s*置/ }));
await user.click(screen.getByRole("button", { name: /刷\s*新/ }));
expect(onSearch).toHaveBeenCalledTimes(1); expect(onSearch).toHaveBeenCalledTimes(1);
expect(onReset).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 () => { it("uses controlled page, pageSize, and total and reports pagination changes", async () => {
......
import { Alert, Button, Empty, Space, Table } from "antd"; import { Alert, Button, Empty, Space, Table } from "antd";
import type { TablePaginationConfig } from "antd/es/table"; import type { TablePaginationConfig } from "antd/es/table";
import { ReloadOutlined, SearchOutlined } from "@ant-design/icons";
import type { AppListFilterItem, AppListProps } from "./types"; import type { AppListFilterItem, AppListProps } from "./types";
...@@ -64,11 +65,12 @@ export function AppList<Row extends object, Filters extends object = Record<stri ...@@ -64,11 +65,12 @@ export function AppList<Row extends object, Filters extends object = Record<stri
))} ))}
</div> </div>
<Space wrap> <Space wrap>
<Button type="primary" onClick={filters.onSearch}> <Button type="primary" icon={<SearchOutlined />} onClick={filters.onSearch}>
搜索 搜索
</Button> </Button>
<Button onClick={filters.onReset}>重置</Button> <Button icon={<ReloadOutlined />} onClick={filters.onReset}>
<Button onClick={filters.onRefresh}>刷新</Button> 重置
</Button>
</Space> </Space>
</section> </section>
) : null} ) : null}
......
Markdown 格式
0% 或
您添加了 0 人 到此讨论。请谨慎行事。
请先完成此评论的编辑!
请 注册 或者 后发表评论