6 changed files with 893 additions and 18 deletions
-
8src/config/character.config.js
-
4src/pages/MerchantMgm/InvoiceConf/loadable.jsx
-
56src/pages/OperationCenter/OperationSales/YardDiscount/DebounceSelect.jsx
-
291src/pages/OperationCenter/OperationSales/YardDiscount/index.scss
-
502src/pages/OperationCenter/OperationSales/YardDiscount/loadable.jsx
-
40src/services/OperationCenter/OperationSales/index.js
@ -0,0 +1,56 @@ |
|||||
|
import { Select, Spin } from 'antd'; |
||||
|
import _ from 'lodash'; |
||||
|
import React, { useEffect, useMemo, useRef, useState } from 'react'; |
||||
|
|
||||
|
/** |
||||
|
* |
||||
|
* @param {type} 1车牌号,2路段/停车场名称,3收费员,4活动名称 |
||||
|
* @returns |
||||
|
*/ |
||||
|
const DebounceSelect = ({ |
||||
|
fetchOptions, |
||||
|
ajaxType, |
||||
|
debounceTimeout = 800, |
||||
|
...props |
||||
|
}) => { |
||||
|
const [fetching, setFetching] = useState(false); |
||||
|
const [options, setOptions] = useState([]); |
||||
|
const fetchRef = useRef(0); |
||||
|
const debounceFetcher = useMemo(() => { |
||||
|
const $loadOptions = (value) => { |
||||
|
fetchRef.current += 1; |
||||
|
const fetchId = fetchRef.current; |
||||
|
setOptions([]); |
||||
|
setFetching(true); |
||||
|
fetchOptions({value, type: ajaxType}).then((newOptions) => { |
||||
|
if (fetchId !== fetchRef.current) { |
||||
|
// for fetch callback order |
||||
|
return; |
||||
|
} |
||||
|
setOptions(newOptions); |
||||
|
setFetching(false); |
||||
|
}); |
||||
|
}; |
||||
|
if(props?.value?.length) { |
||||
|
return _.debounce($loadOptions, 0) |
||||
|
}; |
||||
|
return _.debounce($loadOptions, debounceTimeout); |
||||
|
}, [fetchOptions, debounceTimeout]); |
||||
|
|
||||
|
useEffect(() => { |
||||
|
if(props?.value?.length) debounceFetcher(); |
||||
|
}, []); |
||||
|
return ( |
||||
|
<Select |
||||
|
// labelInValue |
||||
|
filterOption={false} |
||||
|
onSearch={debounceFetcher} |
||||
|
showSearch={true} |
||||
|
notFoundContent={fetching ? <Spin size="small" /> : null} |
||||
|
{...props} |
||||
|
options={options} |
||||
|
/> |
||||
|
); |
||||
|
}; |
||||
|
|
||||
|
export default DebounceSelect; |
@ -1,15 +1,495 @@ |
|||||
|
|
||||
|
|
||||
import React, { useState, useRef, useEffect } from "react"; |
import React, { useState, useRef, useEffect } from "react"; |
||||
// import { message, Pagination, Table, Space, Modal, } from "antd"; |
|
||||
// import { dictionary, utils } from "@/config/common"; |
|
||||
// import moment from 'moment' |
|
||||
// import { useSessionStorageState, useUpdateEffect, useSize, useUpdate } from 'ahooks'; |
|
||||
// import ajax from "@/services" |
|
||||
// import { FormInput, FormSelect, OptionPanel, ResultPanel, FormSliderPicker, AreaCascader, ImgResize, ImgZoom, } from "@/components" |
|
||||
// import "./index.scss"; |
|
||||
// import errorImg from "@/assets/images/layout/error.png" |
|
||||
// import { useLocation } from "react-router-dom"; |
|
||||
function YardDiscount() { |
|
||||
return <div>YardDiscount</div> |
|
||||
|
import { message, Pagination, Table, Select, Popconfirm, Input, DatePicker, Button, Popover, Modal } from "antd"; |
||||
|
import { dictionary, utils } from "@/config/common"; |
||||
|
import moment from "moment"; |
||||
|
import { useSessionStorageState } from "ahooks"; |
||||
|
import ajax from "@/services"; |
||||
|
import { QuickMenu, ParkingRecordModal } from "@/components"; |
||||
|
import DebounceSelect from "./DebounceSelect"; |
||||
|
import "./index.scss"; |
||||
|
import { use } from "echarts"; |
||||
|
const { RangePicker } = DatePicker; |
||||
|
const YardDiscount = () => { |
||||
|
// 默认数据 |
||||
|
const defaultData = { |
||||
|
activity: [], // 活动名称 |
||||
|
road: [], // 停车场名称 |
||||
|
status: "0", // 状态 |
||||
|
pn: 1, |
||||
|
page_size: dictionary?.pageSizeOptions1[0] |
||||
|
}; |
||||
|
|
||||
|
// 默认模态框数据 |
||||
|
const defaultModal = { |
||||
|
activity: [], // 活动名称 |
||||
|
road: [], // 停车场名称 |
||||
|
discount: "", // 折扣 |
||||
|
start_time: null, // 开始时间 |
||||
|
end_time: null,// 结束时间 |
||||
|
} |
||||
|
|
||||
|
//列表 |
||||
|
const tableColumns = [ |
||||
|
{ |
||||
|
title: "活动名称", |
||||
|
dataIndex: "activity", |
||||
|
key: "activity", |
||||
|
align: "center", |
||||
|
}, |
||||
|
{ |
||||
|
title: "停车场名称", |
||||
|
dataIndex: "road", |
||||
|
key: "road", |
||||
|
align: "center", |
||||
|
}, |
||||
|
{ |
||||
|
title: "折扣", |
||||
|
dataIndex: "discount", |
||||
|
key: "discount", |
||||
|
align: "center", |
||||
|
render: (text, record, index) => { |
||||
|
return <>{record.discount || "--"}%</> |
||||
|
}, |
||||
|
}, |
||||
|
{ |
||||
|
title: "活动时间", |
||||
|
dataIndex: "start_time", |
||||
|
key: "start_time", |
||||
|
align: "center", |
||||
|
render: (text, record, index) => { |
||||
|
return <> |
||||
|
<span>{record?.start_time || "--"} 至 {record?.end_time}</span> |
||||
|
</> |
||||
|
}, |
||||
|
}, |
||||
|
{ |
||||
|
title: "状态", |
||||
|
dataIndex: "status", |
||||
|
key: "status", |
||||
|
align: "center", |
||||
|
width: 150, |
||||
|
render: (text, record, index) => { |
||||
|
let content = '--' |
||||
|
switch (text) { |
||||
|
case "0": |
||||
|
content = "全部" |
||||
|
break; |
||||
|
case "1": |
||||
|
content = "进行中" |
||||
|
break; |
||||
|
case "2": |
||||
|
content = "未开始" |
||||
|
break; |
||||
|
case "3": |
||||
|
content = "已下架" |
||||
|
break; |
||||
|
case "4": |
||||
|
content = "已结束" |
||||
|
break; |
||||
|
default: |
||||
|
break; |
||||
|
} |
||||
|
return <>{content}</> |
||||
|
}, |
||||
|
}, |
||||
|
{ |
||||
|
title: "更新时间", |
||||
|
dataIndex: "update_time", |
||||
|
key: "update_time", |
||||
|
align: "center", |
||||
|
}, |
||||
|
|
||||
|
{ |
||||
|
title: '操作', |
||||
|
key: 'operation', |
||||
|
dataIndex: 'operation', |
||||
|
align: "center", |
||||
|
fixed: 'right', |
||||
|
width: 100, |
||||
|
render: (text, record, index) => { |
||||
|
return <> |
||||
|
<Popover |
||||
|
overlayClassName="start-exception-deal-operate" |
||||
|
content={ |
||||
|
<div className="operateBtn operate-btn" style={{ cursor: "pointer" }} trigger="hover"> |
||||
|
<div |
||||
|
className="hover" |
||||
|
onClick={() => { |
||||
|
setModalData({ |
||||
|
activity: record?.activity_id?.split() || [], |
||||
|
road: record?.road_id?.split() || [], |
||||
|
discount: record?.discount || "", |
||||
|
start_time: record?.start_time || null, |
||||
|
end_time: record?.end_time || null |
||||
|
}); |
||||
|
setModalVisible({ |
||||
|
open: true, |
||||
|
title: "查看", |
||||
|
}); |
||||
|
}} |
||||
|
> |
||||
|
查看 |
||||
|
</div> |
||||
|
{record?.status == 1 ? |
||||
|
<Popconfirm placement="left" title="您确定要下架该活动吗?" onConfirm={() => { $deleteConfirm(record?.id, "下架") }} okText="确认" cancelText="取消"> |
||||
|
<div className="hover">下架</div> |
||||
|
</Popconfirm> : |
||||
|
record?.status == 2 ? |
||||
|
<> |
||||
|
<div |
||||
|
className="hover" |
||||
|
onClick={() => { |
||||
|
setModalData({ |
||||
|
activity: record?.activity_id?.split() || [], |
||||
|
road: record?.road_id?.split() || [], |
||||
|
discount: record?.discount || "", |
||||
|
start_time: record?.start_time || null, |
||||
|
end_time: record?.end_time || null |
||||
|
}); |
||||
|
setModalVisible({ |
||||
|
open: true, |
||||
|
title: "编辑", |
||||
|
}); |
||||
|
}} |
||||
|
> |
||||
|
编辑 |
||||
|
</div> |
||||
|
<Popconfirm placement="left" title="您确定要删除该活动吗?" onConfirm={() => { $deleteConfirm(record?.id, "删除") }} okText="确认" cancelText="取消"> |
||||
|
<div className="hover">删除</div> |
||||
|
</Popconfirm> |
||||
|
</> : |
||||
|
"" |
||||
|
} |
||||
|
</div> |
||||
|
} |
||||
|
> |
||||
|
<Button type="primary">操作</Button> |
||||
|
</Popover> |
||||
|
</> |
||||
|
}, |
||||
|
}, |
||||
|
]; |
||||
|
|
||||
|
const [formData, setFormData] = useState(defaultData); // 表单数据 |
||||
|
const [sessionData, setSessionData] = useSessionStorageState("yardDiscount", { value: {} }); // session缓存 |
||||
|
const [loading, setLoading] = useState(false); // 检索按钮加载状态 |
||||
|
const [modalVisible, setModalVisible] = useState({open: false, title: ""}); // 模态框开关 |
||||
|
const [modalData, setModalData] = useState(defaultModal); // 模态框数据 |
||||
|
// 表格返回数据 |
||||
|
const [resultData, setResultData] = useState({ |
||||
|
total: 0, |
||||
|
list: [], |
||||
|
}); |
||||
|
|
||||
|
|
||||
|
|
||||
|
// 活动名称模糊搜索数据 |
||||
|
const $fetchActivityList = (value) => { |
||||
|
return ajax.fetchActivityData({ ...value }).then((res) => { |
||||
|
if (res.status === 20000 || res.status == 0) { |
||||
|
if (res?.data?.length) return res.data; |
||||
|
} else { |
||||
|
message.error(res.message); |
||||
|
} |
||||
|
}).catch((error) => { |
||||
|
message.error(error.message); |
||||
|
}); |
||||
|
}; |
||||
|
|
||||
|
// 分页 |
||||
|
const $changePn = (pn, page_size) => { |
||||
|
let temFormData = {}; |
||||
|
if (formData.page_size == page_size) { |
||||
|
temFormData = { |
||||
|
...formData, |
||||
|
pn |
||||
|
}; |
||||
|
} else { |
||||
|
temFormData = { |
||||
|
...formData, |
||||
|
pn: 1, |
||||
|
page_size, |
||||
|
}; |
||||
|
}; |
||||
|
setFormData(temFormData); |
||||
|
$getTableList(temFormData); |
||||
|
}; |
||||
|
|
||||
|
// 删除及下架 |
||||
|
const $deleteConfirm = (id, type) => { |
||||
|
let url = type == "下架" ? ajax.yardDiscountDown : ajax.yardDiscountDelete; |
||||
|
url({ id }).then((res) => { |
||||
|
if (res.status === 20000 || res.status == 0) { |
||||
|
message.success(res.message || `${type}成功`); |
||||
|
$getTableList(); |
||||
|
} else { |
||||
|
message.error(res.message); |
||||
|
} |
||||
|
}).catch((error) => { |
||||
|
message.error(error.message); |
||||
|
}); |
||||
|
}; |
||||
|
|
||||
|
// 获取表格数据 |
||||
|
const $getTableList = (value = {}) => { |
||||
|
let _data = { |
||||
|
...formData, |
||||
|
...value, |
||||
|
activity: value?.activity?.length ? value?.activity.join() : formData?.activity?.length ? formData?.activity.join() : "", |
||||
|
road: value?.road?.length ? value?.road.join() : formData?.road?.length ? formData?.road.join() : "", |
||||
|
}; |
||||
|
setLoading(true); |
||||
|
ajax.yardDiscountTableData(_data).then((res) => { |
||||
|
setLoading(false); |
||||
|
if (res.status === 20000 || res.status == 0) { |
||||
|
setResultData(res?.data || { total: 0, list: [] }); |
||||
|
} else { |
||||
|
message.error(res.message); |
||||
|
} |
||||
|
}).catch((error) => { |
||||
|
message.error(error.message); |
||||
|
}); |
||||
|
}; |
||||
|
const $disabledDate = (current) => { |
||||
|
// Can not select days before today and today |
||||
|
return current && current <= moment().subtract(1, 'day'); |
||||
|
}; |
||||
|
|
||||
|
useEffect(() => { |
||||
|
let _data = {}; |
||||
|
if (sessionData && Object.values(sessionData).length > 0) { |
||||
|
_data = { |
||||
|
activity: sessionData?.activity || [], // 活动名称 |
||||
|
road: sessionData?.road || [], // 活动名称 |
||||
|
pn: 1, |
||||
|
page_size: dictionary?.pageSizeOptions1[0], |
||||
|
}; |
||||
|
setFormData({ ..._data }); |
||||
|
}; |
||||
|
$getTableList(_data); |
||||
|
}, []); |
||||
|
|
||||
|
useEffect(() => { |
||||
|
// setSessionData(formData); |
||||
|
}, [formData]); |
||||
|
|
||||
|
return ( |
||||
|
<div className="yard-discount"> |
||||
|
<div className="paid-search"> |
||||
|
<div className="title">查询条件</div> |
||||
|
<div className="form-Wrap"> |
||||
|
<div className="yisa-search debounce-select"> |
||||
|
<label>活动名称</label> |
||||
|
<DebounceSelect |
||||
|
className="form-con" |
||||
|
popupClassName="yard-discount-sel-modal" |
||||
|
placeholder="请输入活动名称" |
||||
|
ajaxType="2" |
||||
|
mode="multiple" |
||||
|
allowClear |
||||
|
value={formData?.activity || []} |
||||
|
fetchOptions={$fetchActivityList} |
||||
|
onChange={(newValue) => { |
||||
|
let value = newValue.slice(-1); |
||||
|
setFormData({ |
||||
|
...formData, |
||||
|
activity: value |
||||
|
}); |
||||
|
}} |
||||
|
/> |
||||
|
</div> |
||||
|
<div className="yisa-search debounce-select"> |
||||
|
<label>停车场名称</label> |
||||
|
<DebounceSelect |
||||
|
className="form-con" |
||||
|
popupClassName="yard-discount-sel-modal" |
||||
|
placeholder="请输入停车场名称" |
||||
|
allowClear |
||||
|
ajaxType="4" |
||||
|
mode="multiple" |
||||
|
value={formData?.road || []} |
||||
|
fetchOptions={$fetchActivityList} |
||||
|
onChange={(newValue) => { |
||||
|
let value = newValue.slice(-1); |
||||
|
setFormData({ |
||||
|
...formData, |
||||
|
road: value |
||||
|
}); |
||||
|
}} |
||||
|
/> |
||||
|
</div> |
||||
|
<div className="yisa-search"> |
||||
|
<label>商户名称</label> |
||||
|
<Select |
||||
|
className="form-con" |
||||
|
placeholder="请选择" |
||||
|
options={dictionary.YardDiscountType} |
||||
|
allowClear |
||||
|
value={formData.status} |
||||
|
onChange={(v) => setFormData({ ...formData, status: v || "0" })} |
||||
|
/> |
||||
|
</div> |
||||
|
<div className="form-btn"> |
||||
|
<Button |
||||
|
className="submit" |
||||
|
type="primary" |
||||
|
loading={loading} |
||||
|
onClick={() => { |
||||
|
let _data = { |
||||
|
...formData, |
||||
|
pn: 1, |
||||
|
page_size: dictionary?.pageSizeOptions1[0] |
||||
|
} |
||||
|
setFormData(_data) |
||||
|
$getTableList(_data) |
||||
|
}} |
||||
|
> |
||||
|
查询 |
||||
|
</Button> |
||||
|
<Button |
||||
|
className="add" |
||||
|
type="primary" |
||||
|
onClick={() => setModalVisible({open: true, title: "添加"})} |
||||
|
> |
||||
|
添加 |
||||
|
</Button> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
<div className="paid-result"> |
||||
|
<div className="result"> |
||||
|
<div className="result-data"> |
||||
|
<Table |
||||
|
rowKey={(row) => row.park_id} |
||||
|
className="table" |
||||
|
dataSource={resultData?.list || []} |
||||
|
columns={tableColumns} |
||||
|
pagination={false} |
||||
|
loading={loading} |
||||
|
scroll={{ y: "calc(100vh - 265px)" }} |
||||
|
/> |
||||
|
<Pagination |
||||
|
className="pagination-common" |
||||
|
showSizeChanger={true} |
||||
|
showQuickJumper={true} |
||||
|
showTotal={() => `共 ${resultData.total || 0} 条`} |
||||
|
total={resultData.total} |
||||
|
current={formData.pn} |
||||
|
pageSize={formData.page_size} |
||||
|
pageSizeOptions={dictionary?.pageSizeOptions1} |
||||
|
onChange={$changePn} |
||||
|
/> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
<Modal |
||||
|
className="yard-discount-modal" |
||||
|
title={modalVisible.title} |
||||
|
open={modalVisible.open} |
||||
|
onCancel={() => { |
||||
|
setModalVisible({open: false, title: ""}); |
||||
|
setModalData(defaultModal); |
||||
|
}} |
||||
|
destroyOnClose={true} |
||||
|
footer={[ |
||||
|
modalVisible.title != "查看" ? |
||||
|
<Button key="提交" type="primary" onClick={() => {console.log(modalData, "这是确定");}}>提交</Button> |
||||
|
: "", |
||||
|
<Button key="取消" onClick={() => { |
||||
|
setModalVisible({open: false, title: ""}); |
||||
|
setModalData(defaultModal); |
||||
|
}}> |
||||
|
取消 |
||||
|
</Button>, |
||||
|
]} |
||||
|
> |
||||
|
<div className="form-Wrap"> |
||||
|
<div className="yisa-search debounce-select"> |
||||
|
<label><em>*</em> 活动名称</label> |
||||
|
<DebounceSelect |
||||
|
className="form-con" |
||||
|
popupClassName="yard-discount-sel-modal" |
||||
|
placeholder="请输入活动名称" |
||||
|
disabled={modalVisible.title == "查看" ? true : false} |
||||
|
ajaxType="2" |
||||
|
mode="multiple" |
||||
|
allowClear |
||||
|
value={modalData?.activity || []} |
||||
|
fetchOptions={$fetchActivityList} |
||||
|
onChange={(newValue) => { |
||||
|
let value = newValue.slice(-1); |
||||
|
setModalData({ |
||||
|
...modalData, |
||||
|
activity: value |
||||
|
}); |
||||
|
}} |
||||
|
/> |
||||
|
</div> |
||||
|
<div className="yisa-search debounce-select"> |
||||
|
<label><em>*</em> 停车场名称</label> |
||||
|
<DebounceSelect |
||||
|
className="form-con" |
||||
|
popupClassName="yard-discount-sel-modal" |
||||
|
placeholder="请输入停车场名称" |
||||
|
ajaxType="4" |
||||
|
allowClear |
||||
|
mode="multiple" |
||||
|
disabled={modalVisible.title == "查看" ? true : false} |
||||
|
value={modalData?.road || []} |
||||
|
fetchOptions={$fetchActivityList} |
||||
|
onChange={(newValue) => { |
||||
|
let value = newValue.slice(-1); |
||||
|
setModalData({ |
||||
|
...modalData, |
||||
|
road: value |
||||
|
}); |
||||
|
}} |
||||
|
/> |
||||
|
</div> |
||||
|
<div className="yisa-search"> |
||||
|
<label><em>*</em> 折扣</label> |
||||
|
<Input |
||||
|
className="form-con" |
||||
|
placeholder="请输入折扣" |
||||
|
value={modalData?.discount} |
||||
|
disabled={modalVisible.title == "查看" ? true : false} |
||||
|
suffix="%" |
||||
|
onChange={(e) =>{ |
||||
|
let onlyNumber = /^[1-9]\d*$/; |
||||
|
if(onlyNumber.test(e.target.value) || e.target.value.length > 2 ? true : false) { |
||||
|
return message.error("折扣必须填1-99的整数"); |
||||
|
} |
||||
|
setFormData({ |
||||
|
...modalData, |
||||
|
discount: e.target.value || "" |
||||
|
}) |
||||
|
}} |
||||
|
/> |
||||
|
</div> |
||||
|
<div className="yisa-search"> |
||||
|
<label><em>*</em> 活动时间</label> |
||||
|
<RangePicker |
||||
|
disabledDate={$disabledDate} |
||||
|
disabled={modalVisible.title == "查看" ? true : false} |
||||
|
value={[ |
||||
|
modalData?.start_time ? moment(modalData.start_time) : null, |
||||
|
modalData?.end_time ? moment(modalData.end_time) : null, |
||||
|
]} |
||||
|
onChange={(date, time) => { |
||||
|
setModalData({ |
||||
|
...modalData, |
||||
|
start_time: time[0], |
||||
|
end_time: time[1] |
||||
|
}) |
||||
|
}} |
||||
|
/> |
||||
|
</div> |
||||
|
</div> |
||||
|
</Modal> |
||||
|
</div> |
||||
|
); |
||||
} |
} |
||||
|
|
||||
export default YardDiscount; |
export default YardDiscount; |
Write
Preview
Loading…
Cancel
Save
Reference in new issue