24 changed files with 2156 additions and 194 deletions
-
32src/components/TableModule/index.jsx
-
34src/pages/OutRoadMgm/OutBusinessRecord/OutParkingRecordInquiry/Detail/RecordList.jsx
-
10src/pages/OutRoadMgm/OutBusinessRecord/OutParkingRecordInquiry/Detail/RefundList.jsx
-
47src/pages/OutRoadMgm/OutBusinessRecord/OutParkingRecordInquiry/Detail/StopList.jsx
-
10src/pages/OutRoadMgm/OutBusinessRecord/OutParkingRecordInquiry/Detail/index.jsx
-
53src/pages/OutRoadMgm/OutBusinessRecord/OutParkingRecordInquiry/loadable.jsx
-
151src/pages/OutRoadMgm/OutBusinessRecord/OutPayOrders/loadable.jsx
-
293src/pages/OutRoadMgm/OutSegmentMgm/ChargeRulesMgm/AddModal.jsx
-
182src/pages/OutRoadMgm/OutSegmentMgm/ChargeRulesMgm/Detail.jsx
-
193src/pages/OutRoadMgm/OutSegmentMgm/ChargeRulesMgm/EffectiveDate.jsx
-
178src/pages/OutRoadMgm/OutSegmentMgm/ChargeRulesMgm/TimePart.jsx
-
85src/pages/OutRoadMgm/OutSegmentMgm/ChargeRulesMgm/index.scss
-
179src/pages/OutRoadMgm/OutSegmentMgm/ChargeRulesMgm/loadable.jsx
-
254src/pages/OutRoadMgm/OutSegmentMgm/OutSegment/ConfigParking/BillingRules.jsx
-
155src/pages/OutRoadMgm/OutSegmentMgm/OutSegment/ConfigParking/TollCollectorManagement.jsx
-
2src/pages/OutRoadMgm/OutSegmentMgm/OutSegment/ConfigParking/index.jsx
-
207src/pages/OutRoadMgm/OutSegmentMgm/OutSegment/QRModal.jsx
-
12src/pages/OutRoadMgm/OutSegmentMgm/OutSegment/index.scss
-
51src/pages/OutRoadMgm/OutSegmentMgm/OutSegment/loadable.jsx
-
48src/services/OutRoadMgm/ChargeRulesMgm.js
-
25src/services/OutRoadMgm/OutParkingRecordInquiry.js
-
12src/services/OutRoadMgm/OutPayOrders.js
-
131src/services/OutRoadMgm/OutSegment.js
-
6src/services/OutRoadMgm/index.js
@ -1,15 +1,150 @@ |
|||
import React, { useState, useRef, useEffect } from "react"; |
|||
// import { message, Pagination, Table, Space, Modal, } from "antd"; |
|||
import { message, Pagination, Table, Space, Modal, Button } 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"; |
|||
import ajax from "@/services"; |
|||
import { TableModule } from "@/components"; |
|||
import "./index.scss"; |
|||
function OutPayOrders() { |
|||
return <div>OutPayOrders</div> |
|||
const columns = [ |
|||
{ |
|||
title: "订单ID", |
|||
dataIndex: "order_id", |
|||
key: "order_id", |
|||
}, |
|||
{ |
|||
title: "停车场", |
|||
dataIndex: "road", |
|||
key: "road", |
|||
}, |
|||
{ |
|||
title: "车牌号", |
|||
dataIndex: "plate", |
|||
key: "plate", |
|||
}, |
|||
{ |
|||
title: "入场时间", |
|||
dataIndex: "in_time", |
|||
key: "in_time", |
|||
}, |
|||
{ |
|||
title: "出场时间", |
|||
dataIndex: "out_time", |
|||
key: "out_time", |
|||
}, |
|||
{ |
|||
title: "停车时长", |
|||
dataIndex: "parking_duration", |
|||
key: "parking_duration", |
|||
}, |
|||
{ |
|||
title: "应收金额", |
|||
dataIndex: "receivable_amount", |
|||
key: "receivable_amount", |
|||
}, |
|||
{ |
|||
title: "实收金额", |
|||
dataIndex: "actual_amount", |
|||
key: "actual_amount", |
|||
}, |
|||
{ |
|||
title: "支付渠道", |
|||
dataIndex: "payment_channels", |
|||
key: "payment_channels", |
|||
}, |
|||
{ |
|||
title: "支付设备", |
|||
dataIndex: "payment_equipment", |
|||
key: "payment_equipment", |
|||
}, |
|||
{ |
|||
title: "操作人", |
|||
dataIndex: "dealer", |
|||
key: "dealer", |
|||
}, |
|||
{ |
|||
title: "支付时间", |
|||
dataIndex: "pay_time", |
|||
key: "pay_time", |
|||
}, |
|||
{ |
|||
title: "第三方流水ID", |
|||
dataIndex: "third_party_flow_id", |
|||
key: "third_party_flow_id", |
|||
}, |
|||
]; |
|||
const formSearch = [ |
|||
{ |
|||
name: "road", |
|||
type: "Input", |
|||
label: "停车场名称", |
|||
placeholder: "请选择停车场名称", |
|||
}, |
|||
{ |
|||
name: "plate", |
|||
type: "Input", |
|||
label: "车牌号", |
|||
placeholder: "请输入车牌号", |
|||
}, |
|||
{ |
|||
name: "payment_channels", |
|||
type: "Select", |
|||
label: "支付渠道", |
|||
placeholder: "请选择支付渠道", |
|||
}, |
|||
{ |
|||
name: "payment_equipment", |
|||
type: "Select", |
|||
label: "支付设备", |
|||
placeholder: "请选择支付设备", |
|||
}, |
|||
{ |
|||
name: "time", |
|||
type: "RangePicker", |
|||
label: "时间段", |
|||
}, |
|||
]; |
|||
//搜索参数初始化 |
|||
const initFormData = {}; |
|||
|
|||
//搜索的结果 |
|||
const [tableData, setTableData] = useState([]); |
|||
//搜索的总结果数 |
|||
const [total, setTotal] = useState(0); |
|||
const [detailModal, setDetailModal] = useState({ |
|||
id: "", |
|||
visible: false, |
|||
record: {}, |
|||
close: () => setDetailModal({ ...detailModal, visible: false }), |
|||
onOk: () => { |
|||
detailModal.close(); |
|||
}, |
|||
}); |
|||
|
|||
function fetch(params) { |
|||
ajax.getOutPayOrdersList(params).then((res) => { |
|||
if (res.status === 20000) { |
|||
setTableData(res.data.list); |
|||
setTotal(res.data.total); |
|||
} |
|||
}); |
|||
} |
|||
|
|||
return ( |
|||
<> |
|||
<TableModule |
|||
columns={columns} |
|||
tableData={tableData} |
|||
formSearch={formSearch} |
|||
total={total} |
|||
pagename="停车支付订单" |
|||
search={fetch} |
|||
initFormData={initFormData} |
|||
exportUrl="/api/orp/business/get_payment_export" |
|||
/> |
|||
</> |
|||
); |
|||
} |
|||
|
|||
export default OutPayOrders; |
|||
export default OutPayOrders; |
@ -0,0 +1,293 @@ |
|||
import React, { useEffect, useState } from "react"; |
|||
import { |
|||
Modal, |
|||
Form, |
|||
Input, |
|||
Select, |
|||
Button, |
|||
Row, |
|||
Col, |
|||
Divider, |
|||
Checkbox, |
|||
Radio, |
|||
message, |
|||
} from "antd"; |
|||
import ajax from "@/services"; |
|||
import EffectiveDate from "./EffectiveDate"; |
|||
function AddModal(props) { |
|||
const [form] = Form.useForm(); |
|||
const { |
|||
record = {}, |
|||
visible = false, |
|||
close = () => {}, |
|||
status = "add", |
|||
research = () => {}, |
|||
} = props; |
|||
const isEdit = status === "edit"; |
|||
|
|||
const [effectiveDateList, setEffectiveDateList] = useState(() => { |
|||
if (status === "add") { |
|||
return [ |
|||
{ |
|||
key: |
|||
Math.floor(Math.random() * 1000).toString() + |
|||
Date.now().toString().substring(0, 6), |
|||
}, |
|||
]; |
|||
} else { |
|||
return record.property.map((item) => { |
|||
item.key = |
|||
Math.floor(Math.random() * 1000).toString() + |
|||
Date.now().toString().substring(0, 6); |
|||
item.status = "disable"; |
|||
return item; |
|||
}); |
|||
} |
|||
}); |
|||
|
|||
function addEctiveDate() { |
|||
const randomNum = Math.floor(Math.random() * 1000); |
|||
const item = { |
|||
key: randomNum.toString() + Date.now().toString().substring(0, 6), |
|||
}; |
|||
console.log(effectiveDateList); |
|||
setEffectiveDateList([...effectiveDateList, item]); |
|||
} |
|||
|
|||
function removeEffectiveDate(key) { |
|||
const _effectiveDateList = effectiveDateList |
|||
.map((item) => item.key !== key && item) |
|||
.filter((item) => item.key !== undefined); |
|||
setEffectiveDateList(_effectiveDateList); |
|||
} |
|||
//提交成功后函数 |
|||
function submitSuccess() { |
|||
research(); |
|||
close(); |
|||
} |
|||
//提交接口 |
|||
function fetch(params) { |
|||
if (status === "add") { |
|||
ajax.addChargeRule(params).then((res) => { |
|||
if (res.status === 20000) { |
|||
message.success("添加成功"); |
|||
submitSuccess(); |
|||
} else { |
|||
message.error(res.message); |
|||
} |
|||
}); |
|||
} else { |
|||
ajax.editChargeRule(params).then((res) => { |
|||
if (res.status === 20000) { |
|||
message.success("编辑成功"); |
|||
submitSuccess(); |
|||
} else { |
|||
message.error(res.message); |
|||
} |
|||
}); |
|||
} |
|||
} |
|||
//提交按钮 |
|||
function submit() { |
|||
form |
|||
.validateFields() |
|||
.then((res) => { |
|||
const params = { |
|||
...res, |
|||
property: effectiveDateList, |
|||
}; |
|||
fetch(params); |
|||
}) |
|||
.catch((err) => console.error(err)); |
|||
} |
|||
return ( |
|||
<Modal |
|||
open={visible} |
|||
width={1200} |
|||
onCancel={close} |
|||
title="添加" |
|||
onOk={submit} |
|||
> |
|||
<div> |
|||
<Form |
|||
form={form} |
|||
labelCol={{ span: 6 }} |
|||
colon={false} |
|||
initialValues={record} |
|||
> |
|||
<Row gutter={[30]}> |
|||
<Col span={12}> |
|||
<Form.Item |
|||
label="计费规则名称" |
|||
name="feeName" |
|||
rules={[{ required: true }]} |
|||
> |
|||
<Input style={{ width: "40%" }} /> |
|||
</Form.Item> |
|||
</Col> |
|||
<Col span={12}> |
|||
<Form.Item |
|||
label="规则编码" |
|||
name="feeCode" |
|||
rules={[{ required: true }]} |
|||
> |
|||
<Input style={{ width: "40%" }} /> |
|||
</Form.Item> |
|||
</Col> |
|||
<Col style={{ width: "50%" }}> |
|||
<Form.Item |
|||
label="所属商户" |
|||
name="operationId" |
|||
rules={[{ required: true }]} |
|||
> |
|||
<Select |
|||
disabled={isEdit} |
|||
style={{ width: "40%" }} |
|||
options={[ |
|||
{ |
|||
label: "测试", |
|||
value: 1, |
|||
}, |
|||
]} |
|||
/> |
|||
</Form.Item> |
|||
</Col> |
|||
<Col style={{ width: "50%" }}> |
|||
<Form.Item |
|||
label="描述" |
|||
name="description" |
|||
rules={[{ required: true }]} |
|||
> |
|||
<Input.TextArea /> |
|||
</Form.Item> |
|||
</Col> |
|||
<Col span={12}> |
|||
<Form.Item label="24小时最大收费金额" name="limit24hour"> |
|||
<Input addonAfter={"元"} style={{ width: "57%" }} /> |
|||
</Form.Item> |
|||
</Col> |
|||
<Col span={13}> |
|||
<Form.Item |
|||
label="免费分钟数" |
|||
name="freeTime" |
|||
rules={[{ required: true }]} |
|||
> |
|||
<Input addonAfter={"分"} style={{ width: "50%" }} /> |
|||
</Form.Item> |
|||
</Col> |
|||
<Col span={11}> |
|||
<Form.Item name="freeTimeAbleF"> |
|||
<Checkbox.Group |
|||
options={[ |
|||
{ |
|||
label: "免费分钟数纳入计费时间", |
|||
value: 1, |
|||
}, |
|||
]} |
|||
/> |
|||
</Form.Item> |
|||
</Col> |
|||
<Col span={12}> |
|||
<Form.Item |
|||
label="特殊车辆优惠" |
|||
name="typeF" |
|||
rules={[{ required: true }]} |
|||
initialValue={1} |
|||
> |
|||
<Radio.Group |
|||
options={[ |
|||
{ |
|||
label: "启用", |
|||
value: 1, |
|||
}, |
|||
{ |
|||
label: "禁用", |
|||
value: 0, |
|||
}, |
|||
]} |
|||
></Radio.Group> |
|||
</Form.Item> |
|||
</Col> |
|||
<Form.Item |
|||
shouldUpdate={(prev, cur) => prev.typeF !== cur.typeF} |
|||
noStyle |
|||
> |
|||
{({ getFieldValue, setFieldsValue }) => { |
|||
const type = getFieldValue("typeF"); |
|||
if (type === 0) { |
|||
setFieldsValue({ evFreeTime: "", evFreeTimeAble: [] }); |
|||
} |
|||
return ( |
|||
<> |
|||
<Col span={13}> |
|||
<Form.Item |
|||
label="新能源车辆免费分钟" |
|||
name="evFreeTime" |
|||
initialValue={type === 0 || ""} |
|||
> |
|||
<Input |
|||
disabled={type === 0} |
|||
addonAfter={"分"} |
|||
style={{ width: "50%" }} |
|||
/> |
|||
</Form.Item> |
|||
</Col> |
|||
<Col span={11}> |
|||
<Form.Item |
|||
name="evFreeTimeAble" |
|||
initialValue={type === 0 && []} |
|||
> |
|||
<Checkbox.Group |
|||
disabled={type === 0} |
|||
options={[ |
|||
{ |
|||
label: "免费分钟数纳入计费时间", |
|||
value: 1, |
|||
}, |
|||
]} |
|||
/> |
|||
</Form.Item> |
|||
</Col> |
|||
</> |
|||
); |
|||
}} |
|||
</Form.Item> |
|||
</Row> |
|||
</Form> |
|||
<div> |
|||
<Button |
|||
onClick={addEctiveDate} |
|||
type="primary" |
|||
style={{ margin: "0 0 20px 0" }} |
|||
> |
|||
添加生效日期 |
|||
</Button> |
|||
</div> |
|||
<Divider /> |
|||
{effectiveDateList.map((item, index) => { |
|||
return ( |
|||
<EffectiveDate |
|||
disable={item.status === "disable"} |
|||
record={item} |
|||
key={item.key} |
|||
index={index + 1} |
|||
itemKey={item.key} |
|||
remove={removeEffectiveDate} |
|||
onChange={(value, key) => { |
|||
const _effectiveDateList = effectiveDateList.map((item) => { |
|||
if (item.key === key) { |
|||
item = { ...item, ...value }; |
|||
} |
|||
return item; |
|||
}); |
|||
setEffectiveDateList(_effectiveDateList); |
|||
}} |
|||
/> |
|||
); |
|||
})} |
|||
</div> |
|||
</Modal> |
|||
); |
|||
} |
|||
|
|||
export default AddModal; |
@ -0,0 +1,182 @@ |
|||
import React, { useState, useEffect } from "react"; |
|||
import { |
|||
Modal, |
|||
Form, |
|||
Input, |
|||
Select, |
|||
Button, |
|||
Row, |
|||
Col, |
|||
Divider, |
|||
Checkbox, |
|||
Descriptions, |
|||
Radio, |
|||
} from "antd"; |
|||
import EffectiveDate from "./EffectiveDate"; |
|||
import ajax from "@/services"; |
|||
function Detail(props) { |
|||
const { record, visible = false, close = () => {} } = props; |
|||
const [form] = Form.useForm(); |
|||
const [effectiveDateList, setEffectiveDateList] = useState(record.property); |
|||
useEffect(() => { |
|||
setEffectiveDateList(record.property); |
|||
console.log(record.property); |
|||
}, []); |
|||
return ( |
|||
<Modal |
|||
open={visible} |
|||
destroyOnClose |
|||
onCancel={close} |
|||
width={1200} |
|||
title="详情" |
|||
> |
|||
<div> |
|||
<Descriptions column={2}> |
|||
<Descriptions.Item label="规则名称" span={1}> |
|||
{record.feeName} |
|||
</Descriptions.Item> |
|||
<Descriptions.Item label="编码" span={1}> |
|||
{record.feeCode} |
|||
</Descriptions.Item> |
|||
<Descriptions.Item label="描述" span={1}> |
|||
{record.description} |
|||
</Descriptions.Item> |
|||
<Descriptions.Item label="所属商户" span={1}> |
|||
{record.operationName} |
|||
</Descriptions.Item> |
|||
<Descriptions.Item label="操作时间" span={1}> |
|||
{record.createdTime} |
|||
</Descriptions.Item> |
|||
<Descriptions.Item label="14小时最大收费金额" span={1}> |
|||
{record.limit24hour} |
|||
</Descriptions.Item> |
|||
<Descriptions.Item label="免费分钟数" span={1}> |
|||
{record.freeTime} |
|||
<div style={{ margin: "0 10px" }}> |
|||
<Checkbox disabled defaultChecked={record.freeTimeAbleF}> |
|||
免费分钟数纳入计费时间 |
|||
</Checkbox> |
|||
</div> |
|||
</Descriptions.Item> |
|||
<Descriptions.Item label="特殊车辆优惠" span={2}> |
|||
<Radio.Group |
|||
disabled |
|||
defaultValue={record.typeF} |
|||
options={[ |
|||
{ |
|||
label: "启用", |
|||
value: 1, |
|||
}, |
|||
{ |
|||
label: "禁用", |
|||
value: 0, |
|||
}, |
|||
]} |
|||
/> |
|||
</Descriptions.Item> |
|||
<Descriptions.Item label="新能源车辆免费分钟" span={1}> |
|||
{record.evFreeTime} |
|||
<div style={{ margin: "0 10px" }}> |
|||
<Checkbox disabled defaultChecked={record.evFreeTimeAble}> |
|||
免费分钟数纳入计费时间 |
|||
</Checkbox> |
|||
</div> |
|||
</Descriptions.Item> |
|||
</Descriptions> |
|||
<Divider /> |
|||
{effectiveDateList && |
|||
effectiveDateList.map((item, index) => { |
|||
console.log(item); |
|||
return <EffectiveDetail record={item} key={index} />; |
|||
})} |
|||
</div> |
|||
</Modal> |
|||
); |
|||
} |
|||
|
|||
function EffectiveDetail(props) { |
|||
const { record } = props; |
|||
console.log(123); |
|||
return ( |
|||
<> |
|||
<Descriptions column={2}> |
|||
<Descriptions.Item label="生效日期" span={1}> |
|||
{record.effective_date} |
|||
</Descriptions.Item> |
|||
<Descriptions.Item span={2}> |
|||
<Checkbox.Group |
|||
defaultValue={record.unit_fee_type_group} |
|||
disabled |
|||
options={[ |
|||
{ |
|||
label: "跨段延续计费", |
|||
value: 1, |
|||
}, |
|||
{ |
|||
label: "出场时不满计费单元部分补齐计费单元收费", |
|||
value: 2, |
|||
}, |
|||
]} |
|||
></Checkbox.Group> |
|||
</Descriptions.Item> |
|||
</Descriptions> |
|||
{record.time_part_arr.map((item, index) => { |
|||
return <TimePartDetail index={index + 1} record={item} />; |
|||
})} |
|||
</> |
|||
); |
|||
} |
|||
|
|||
function TimePartDetail(props) { |
|||
const { record, index } = props; |
|||
function partName(type) { |
|||
switch (type) { |
|||
case 1: |
|||
return "基础时段"; |
|||
case 2: |
|||
return "周期计费"; |
|||
case 3: |
|||
return "按次计费"; |
|||
} |
|||
} |
|||
return ( |
|||
<> |
|||
<Descriptions column={2}> |
|||
<Descriptions.Item label={`时段${index}`}> |
|||
{`${record.time_part[0]}-${record.time_part[1]}`} |
|||
</Descriptions.Item> |
|||
{(record.interval === 1 || record.interval === 2) && ( |
|||
<Descriptions.Item label="时段最高金额"> |
|||
{record.time_max_money} |
|||
</Descriptions.Item> |
|||
)} |
|||
<Descriptions.Item label={`区间${index}`} span={2}> |
|||
{partName(record.interval)} |
|||
</Descriptions.Item> |
|||
{record.interval === 1 && ( |
|||
<> |
|||
<Descriptions.Item span={2}> |
|||
<div>{`前:${record.time_before} 分钟,${record.time_before_money}元/${record.time_before_minute}分钟`}</div> |
|||
</Descriptions.Item> |
|||
<Descriptions.Item span={2}> |
|||
<div>{`满:${record.time_before} 分钟后,${record.time_after_money}元/${record.time_after_minute}分钟`}</div> |
|||
</Descriptions.Item> |
|||
</> |
|||
)} |
|||
{record.interval === 2 && ( |
|||
<Descriptions.Item span={2}> |
|||
<div>{`${record.time_money}元/${record.time_minute}分钟`}</div> |
|||
</Descriptions.Item> |
|||
)} |
|||
{record.interval === 3 && ( |
|||
<Descriptions.Item span={2}> |
|||
<div>{`${record.money_per_time}元/次`}</div> |
|||
</Descriptions.Item> |
|||
)} |
|||
</Descriptions> |
|||
<Divider /> |
|||
</> |
|||
); |
|||
} |
|||
|
|||
export default Detail; |
@ -0,0 +1,193 @@ |
|||
import React, { useEffect, useState } from "react"; |
|||
import { |
|||
Form, |
|||
Input, |
|||
Button, |
|||
Select, |
|||
DatePicker, |
|||
Checkbox, |
|||
Row, |
|||
Col, |
|||
Divider, |
|||
message, |
|||
} from "antd"; |
|||
import TimePart from "./TimePart"; |
|||
import moment from "moment"; |
|||
function EffectiveDate(props) { |
|||
const { |
|||
remove = () => {}, |
|||
itemKey, |
|||
onChange = () => {}, |
|||
index, |
|||
disable = false, |
|||
record = {}, |
|||
} = props; |
|||
const [form] = Form.useForm(); |
|||
const [timePartList, setTimePartList] = useState(() => { |
|||
if (!disable) { |
|||
return [ |
|||
{ |
|||
key: |
|||
Math.floor(Math.random() * 1000).toString() + |
|||
Date.now().toString().substring(0, 6), |
|||
}, |
|||
]; |
|||
} else { |
|||
return record.time_part_arr.map((item) => { |
|||
item.status = "disable"; |
|||
item.key = |
|||
Math.floor(Math.random() * 1000).toString() + |
|||
Date.now().toString().substring(0, 6); |
|||
return item; |
|||
}); |
|||
} |
|||
}); |
|||
const addTimePart = () => { |
|||
const randomNum = Math.floor(Math.random() * 1000); |
|||
const item = { |
|||
key: randomNum.toString() + Date.now().toString().substring(0, 6), |
|||
}; |
|||
setTimePartList([...timePartList, item]); |
|||
}; |
|||
const removeTimePart = (key) => { |
|||
const _timePartList = timePartList |
|||
.map((item) => item.key !== key && item) |
|||
.filter((item) => item.key !== undefined); |
|||
setTimePartList(_timePartList); |
|||
}; |
|||
|
|||
//判断时间是否是一天时间 |
|||
function isOneDay(time) { |
|||
let total = 0; |
|||
for (let i = 0; i < timePartList.length; i++) { |
|||
if (timePartList[i].time_part) { |
|||
total += Math.abs( |
|||
moment(timePartList[i].time_part[1], "HH:mm:ss").diff( |
|||
moment(timePartList[i].time_part[0], "HH:mm:ss"), |
|||
"minutes" |
|||
) |
|||
); |
|||
} |
|||
} |
|||
total += 1; |
|||
console.log(total); |
|||
if (total === 1440) { |
|||
return true; |
|||
} |
|||
return false; |
|||
} |
|||
function submit() { |
|||
form |
|||
.validateFields() |
|||
.then((values) => { |
|||
if (isOneDay(values)) { |
|||
message.success("时段检验通过"); |
|||
} else { |
|||
message.error("时段检验未通过"); |
|||
} |
|||
}) |
|||
.catch((err) => { |
|||
console.error(err); |
|||
}); |
|||
} |
|||
|
|||
return ( |
|||
<div> |
|||
<Form |
|||
form={form} |
|||
initialValues={{ |
|||
...record, |
|||
effective_date: moment(record.effective_date), |
|||
}} |
|||
disabled={disable} |
|||
> |
|||
<Row> |
|||
<Col span={12}> |
|||
<Form.Item |
|||
label="生效日期" |
|||
name="effective_date" |
|||
rules={[{ required: true }]} |
|||
> |
|||
<DatePicker /> |
|||
</Form.Item> |
|||
</Col> |
|||
<Col span={12}> |
|||
{index !== 1 && ( |
|||
<Button type="primary" onClick={() => remove(itemKey)}> |
|||
移除 |
|||
</Button> |
|||
)} |
|||
</Col> |
|||
</Row> |
|||
<Form.Item name="unit_fee_type_group"> |
|||
<Checkbox.Group |
|||
options={[ |
|||
{ |
|||
label: "跨段延续计费", |
|||
value: 1, |
|||
}, |
|||
{ |
|||
label: "出场时不满计费单元部分补齐计费单元收费", |
|||
value: 2, |
|||
}, |
|||
]} |
|||
></Checkbox.Group> |
|||
</Form.Item> |
|||
</Form> |
|||
{!disable && ( |
|||
<> |
|||
<Button |
|||
onClick={addTimePart} |
|||
type="primary" |
|||
style={{ margin: "0 0 20px 0 " }} |
|||
> |
|||
添加时段 |
|||
</Button> |
|||
<Button type="primary" style={{ margin: "0 10px" }} onClick={submit}> |
|||
检验时段 |
|||
</Button> |
|||
</> |
|||
)} |
|||
<Divider /> |
|||
{timePartList.map((item, index) => { |
|||
console.log(item); |
|||
return ( |
|||
<TimePart |
|||
disable={item.status === "disable"} |
|||
record={item} |
|||
index={index + 1} |
|||
key={item.key} |
|||
remove={removeTimePart} |
|||
itemKey={item.key} |
|||
onChange={(value) => { |
|||
const _timePartList = timePartList.map((item) => { |
|||
if (item.key === value.key) { |
|||
if (value.time_part) { |
|||
value.time_part = value.time_part.map((item) => { |
|||
item = item.format("HH:mm:ss"); |
|||
return item; |
|||
}); |
|||
} |
|||
return value; |
|||
} else { |
|||
return item; |
|||
} |
|||
}); |
|||
const obj = { |
|||
...form.getFieldsValue(), |
|||
time_part_arr: _timePartList, |
|||
}; |
|||
if (obj.effective_date !== void 0) { |
|||
obj.effective_date = obj.effective_date.format("YYYY-MM-DD"); |
|||
} |
|||
onChange(obj, itemKey); |
|||
setTimePartList(_timePartList); |
|||
}} |
|||
/> |
|||
); |
|||
})} |
|||
</div> |
|||
); |
|||
} |
|||
|
|||
export default EffectiveDate; |
@ -0,0 +1,178 @@ |
|||
import React, { useEffect, useState } from "react"; |
|||
import { |
|||
Form, |
|||
Input, |
|||
Button, |
|||
Select, |
|||
DatePicker, |
|||
TimePicker, |
|||
Row, |
|||
Col, |
|||
Divider, |
|||
} from "antd"; |
|||
import moment from "moment"; |
|||
function TimePart(props) { |
|||
const [form] = Form.useForm(); |
|||
const { |
|||
index, |
|||
remove, |
|||
itemKey, |
|||
onChange = () => {}, |
|||
record, |
|||
disable = false, |
|||
} = props; |
|||
console.log(disable); |
|||
const valueChange = (value, all) => { |
|||
all.key = itemKey; |
|||
onChange(all); |
|||
}; |
|||
|
|||
|
|||
return ( |
|||
<div> |
|||
<Form |
|||
form={form} |
|||
onValuesChange={valueChange} |
|||
disabled={disable} |
|||
initialValues={ |
|||
disable |
|||
? { |
|||
...record, |
|||
time_part: [ |
|||
moment(record.time_part[0], "HH:mm:ss"), |
|||
moment(record.time_part[1], "HH:mm:ss"), |
|||
], |
|||
} |
|||
: {} |
|||
} |
|||
> |
|||
<Row gutter={[30]}> |
|||
<Col span={16}> |
|||
<Form.Item label={`时段${index}`} name="time_part"> |
|||
<TimePicker.RangePicker style={{ width: "50%" }} order={false} /> |
|||
</Form.Item> |
|||
</Col> |
|||
<Col span={8}> |
|||
{index === 1 ? null : ( |
|||
<Button type="primary" onClick={() => remove(itemKey)}> |
|||
移除 |
|||
</Button> |
|||
)} |
|||
</Col> |
|||
|
|||
<Col span={24}> |
|||
<Form.Item label={`区间${index}`} name="interval" initialValue={1}> |
|||
<Select |
|||
style={{ width: "20%" }} |
|||
options={[ |
|||
{ |
|||
label: "基础时段", |
|||
value: 1, |
|||
}, |
|||
{ |
|||
label: "周期计价", |
|||
value: 2, |
|||
}, |
|||
{ |
|||
label: "按次计价", |
|||
value: 3, |
|||
}, |
|||
]} |
|||
/> |
|||
</Form.Item> |
|||
</Col> |
|||
<Col span={24}> |
|||
<Form.Item |
|||
shouldUpdate={(prev, next) => prev.interval !== next.interval} |
|||
> |
|||
{({ getFieldValue }) => { |
|||
const type = getFieldValue("interval"); |
|||
switch (type) { |
|||
case 1: |
|||
return ( |
|||
<> |
|||
<Input.Group compact> |
|||
<Form.Item name="time_before" label="前:"> |
|||
<Input addonAfter={"分钟"} /> |
|||
</Form.Item> |
|||
<Form.Item name="time_before_money" noStyle> |
|||
<Input |
|||
addonAfter={"元/"} |
|||
style={{ width: "20%" }} |
|||
/> |
|||
</Form.Item> |
|||
<Form.Item name="time_before_minute" noStyle> |
|||
<Input |
|||
addonAfter={"分钟"} |
|||
style={{ width: "20%" }} |
|||
/> |
|||
</Form.Item> |
|||
</Input.Group> |
|||
<Input.Group compact> |
|||
<Form.Item name="time_before" label="满:"> |
|||
<Input addonAfter={"分钟"} disabled /> |
|||
</Form.Item> |
|||
<Form.Item name="time_after_money" noStyle> |
|||
<Input |
|||
addonAfter={"元/"} |
|||
style={{ width: "20%" }} |
|||
/> |
|||
</Form.Item> |
|||
<Form.Item name="time_after_minute" noStyle> |
|||
<Input |
|||
addonAfter={"分钟"} |
|||
style={{ width: "20%" }} |
|||
/> |
|||
</Form.Item> |
|||
</Input.Group> |
|||
</> |
|||
); |
|||
case 2: |
|||
return ( |
|||
<Input.Group compact> |
|||
<Form.Item name="time_money" noStyle> |
|||
<Input addonAfter={"元/"} style={{ width: "20%" }} /> |
|||
</Form.Item> |
|||
<Form.Item name="time_minute" noStyle> |
|||
<Input addonAfter={"分钟"} style={{ width: "20%" }} /> |
|||
</Form.Item> |
|||
</Input.Group> |
|||
); |
|||
case 3: |
|||
return ( |
|||
<Form.Item name="money_per_time"> |
|||
<Input addonAfter={"元/次"} style={{ width: "20%" }} /> |
|||
</Form.Item> |
|||
); |
|||
} |
|||
}} |
|||
</Form.Item> |
|||
</Col> |
|||
<Form.Item |
|||
shouldUpdate={(prev, next) => prev.interval !== next.interval} |
|||
> |
|||
{({ getFieldValue }) => { |
|||
return ( |
|||
(getFieldValue("interval") === 1 || |
|||
getFieldValue("interval") === 2) && ( |
|||
<Col span={24}> |
|||
<Form.Item |
|||
label="时段最高收费金额" |
|||
name="time_max_money" |
|||
rules={[{ required: true }]} |
|||
> |
|||
<Input /> |
|||
</Form.Item> |
|||
</Col> |
|||
) |
|||
); |
|||
}} |
|||
</Form.Item> |
|||
</Row> |
|||
</Form> |
|||
<Divider></Divider> |
|||
</div> |
|||
); |
|||
} |
|||
|
|||
export default TimePart; |
@ -1,5 +1,82 @@ |
|||
@import "@/assets/css/mixin.scss"; |
|||
$color-container-bg : var(--color-container-bg); |
|||
$color-user-list-bg : var(--color-user-list-bg); |
|||
$color-text : var(--color-text); |
|||
$color-primary : var(--color-primary); |
|||
$color-container-bg: var(--color-container-bg); |
|||
$color-user-list-bg: var(--color-user-list-bg); |
|||
$color-text: var(--color-text); |
|||
$color-primary: var(--color-primary); |
|||
.ant-modal-content { |
|||
.charge-rule-bottom-button { |
|||
display: flex; |
|||
justify-content: center; |
|||
margin-top: 20px; |
|||
button { |
|||
margin: 0 10px; |
|||
} |
|||
} |
|||
textarea, |
|||
input { |
|||
background: var(--color-search-list-item-bg); |
|||
} |
|||
.ant-select-selection-placeholder { |
|||
color: var(--color-placeholder); |
|||
} |
|||
.ant-select-disabled.ant-select-single:not(.ant-select-customize-input) .ant-select-selector { |
|||
background: var(--color-input-disabled-bg); |
|||
color: var(--color-placeholder); |
|||
} |
|||
.ant-select-disabled .ant-select-arrow { |
|||
color: var(--color-placeholder); |
|||
} |
|||
.ant-select-disabled.ant-select:not(.ant-select-customize-input) .ant-select-selector { |
|||
background-color: var(--color-input-disabled-bg); |
|||
color: var(--color-input-disabled-color); |
|||
cursor: not-allowed; |
|||
} |
|||
.ant-select-multiple { |
|||
.ant-select-selector { |
|||
.ant-select-selection-item { |
|||
background-color: var(--color-bg-body); |
|||
border-color: var(--color-border); |
|||
.ant-select-selection-item-remove { |
|||
color: var(--color-text); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
.ant-select-arrow { |
|||
color: var(--color-text); |
|||
} |
|||
.ant-select-clear { |
|||
border-radius: 50%; |
|||
} |
|||
.ant-select-dropdown-menu { |
|||
background-color: var(--color-input-bg); |
|||
.ant-select-dropdown-menu-item { |
|||
color: var(--color-text); |
|||
&.ant-select-dropdown-menu-item-active { |
|||
color: #fff; |
|||
// background-color: var(--radio-button-bg-checked); |
|||
} |
|||
&.ant-select-dropdown-menu-item-selected { |
|||
color: #fff; |
|||
// background-color: var(--radio-button-bg-checked); |
|||
} |
|||
&:hover { |
|||
color: #fff; |
|||
// background-color: var(--radio-button-bg-checked); |
|||
} |
|||
} |
|||
} |
|||
.ant-select-selector { |
|||
background-color: var(--color-search-list-item-bg) !important; |
|||
box-shadow: none !important; |
|||
border-radius: 4px; |
|||
color: var(--color-search-list-item-value); |
|||
border-color: var(--color-search-list-item-bd) !important; |
|||
} |
|||
.ant-select-selection { |
|||
background-color: var(--color-input-bg); |
|||
box-shadow: none; |
|||
color: var(--color-text); |
|||
// border-color:var(--checkable-tag-border); |
|||
} |
|||
} |
@ -0,0 +1,207 @@ |
|||
import React, { useEffect, useState } from "react"; |
|||
import { Button, Modal, Table, Descriptions, message } from "antd"; |
|||
import ajax from "@/services"; |
|||
import copy from "copy-to-clipboard"; |
|||
function QRModal(props) { |
|||
const { |
|||
visible = false, |
|||
close = () => {}, |
|||
itemData = {}, |
|||
id: road_id, |
|||
} = props; |
|||
console.log(road_id); |
|||
const columns_12 = [ |
|||
{ |
|||
title: "停车场", |
|||
dataIndex: "road_name", |
|||
key: "road_name", |
|||
}, |
|||
{ |
|||
title: "通道名称", |
|||
dataIndex: "channel_name", |
|||
key: "channel_name", |
|||
}, |
|||
{ |
|||
title: "链接地址", |
|||
dataIndex: "link", |
|||
key: "link", |
|||
}, |
|||
{ |
|||
title: "操作", |
|||
dataIndex: "action", |
|||
key: "action", |
|||
render: (_, record) => { |
|||
return ( |
|||
<div> |
|||
<Button onClick={() => getLink(record)}>复制链接</Button> |
|||
<Button |
|||
onClick={() => { |
|||
getPicById(record.id); |
|||
}} |
|||
> |
|||
导出二维码 |
|||
</Button> |
|||
</div> |
|||
); |
|||
}, |
|||
}, |
|||
]; |
|||
const columns_3 = [ |
|||
{ |
|||
title: "停车场", |
|||
dataIndex: "road_name", |
|||
key: "road_name", |
|||
}, |
|||
{ |
|||
title: "链接地址", |
|||
dataIndex: "link", |
|||
key: "link", |
|||
}, |
|||
{ |
|||
title: "操作", |
|||
dataIndex: "action", |
|||
key: "action", |
|||
align: "center", |
|||
width: 200, |
|||
render: (_, record) => { |
|||
return ( |
|||
<div className="buttons"> |
|||
<Button type="primary" onClick={() => getLink(record)}> |
|||
复制链接 |
|||
</Button> |
|||
<Button |
|||
onClick={() => { |
|||
getPicById(record.id); |
|||
}} |
|||
type="primary" |
|||
> |
|||
导出二维码 |
|||
</Button> |
|||
</div> |
|||
); |
|||
}, |
|||
}, |
|||
]; |
|||
const [qrcode1, setQrcode1] = useState([]); |
|||
const [qrcode2, setQrcode2] = useState([]); |
|||
const [qrcode3, setQrcode3] = useState([]); |
|||
function getData() { |
|||
ajax.getRoadQRcodeInfo({ road_id }).then((res) => { |
|||
if (res.status === 20000) { |
|||
setQrcode1(res.data.qrcode_1); |
|||
setQrcode2(res.data.qrcode_2); |
|||
setQrcode3(res.data.qrcode_3); |
|||
} |
|||
}); |
|||
} |
|||
//复制 |
|||
const getLink = (record) => { |
|||
if (copy(record.link)) { |
|||
message.success("复制成功"); |
|||
} else message.error("复制失败,请手动复制"); |
|||
}; |
|||
//获取二维码图片 |
|||
const getPicById = (id) => { |
|||
ajax.getRoadQRcodePic({ id }).then((res) => { |
|||
if (res.status === 20000) { |
|||
const name = res.data.url |
|||
.split("/") |
|||
[res.data.url.split("/").length - 1].split("?")[0]; |
|||
downloadImage(res.data.url, name); |
|||
} |
|||
}); |
|||
}; |
|||
//批量获取二维码 |
|||
const getNmae = (url) => { |
|||
if (!url) return false; |
|||
else if (url === "") return false; |
|||
return url.split("/")[url.split("/").length - 1].split("?")[0]; |
|||
}; |
|||
const getPicByIds = (road_id) => { |
|||
ajax.getRoadQRcodePicBatch({ road_id }).then((res) => { |
|||
if (res.status === 20000) { |
|||
const { url1, url2, url3 } = res.data; |
|||
const name1 = getNmae(url1); |
|||
const name2 = getNmae(url2); |
|||
const name3 = getNmae(url3); |
|||
if (name1) { |
|||
downloadImage(url1, name1); |
|||
} |
|||
if (name2) { |
|||
downloadImage(url2, name2); |
|||
} |
|||
if (name3) { |
|||
downloadImage(url3, name3); |
|||
} |
|||
} |
|||
}); |
|||
}; |
|||
//下载图片 |
|||
const downloadImage = (url, filename) => { |
|||
fetch(url) |
|||
.then((response) => response.blob()) |
|||
.then((blob) => { |
|||
const url = URL.createObjectURL(blob); |
|||
const a = document.createElement("a"); |
|||
a.href = url; |
|||
a.download = filename; |
|||
a.click(); |
|||
}) |
|||
.catch((err) => console.log(err)); |
|||
}; |
|||
useEffect(() => { |
|||
getData(); |
|||
}, []); |
|||
return ( |
|||
<Modal title="二维码下载" open={visible} onCancel={close} width={1200}> |
|||
<header className="QR-header"> |
|||
<h3>{itemData.road_name}</h3> |
|||
<div className="buttons"> |
|||
<Button |
|||
type="primary" |
|||
onClick={() => { |
|||
getPicByIds(road_id); |
|||
}} |
|||
> |
|||
导出全部二维码 |
|||
</Button> |
|||
</div> |
|||
</header> |
|||
<main> |
|||
<Descriptions title="入场无牌车二维码"> |
|||
<Descriptions.Item span={3}> |
|||
<Table |
|||
columns={columns_12} |
|||
className="yisa-table" |
|||
dataSource={qrcode1} |
|||
pagination={false} |
|||
/> |
|||
</Descriptions.Item> |
|||
</Descriptions> |
|||
<Descriptions title="出场缴费二维码"> |
|||
<Descriptions.Item span={3}> |
|||
<Table |
|||
columns={columns_12} |
|||
className="yisa-table" |
|||
dataSource={qrcode2} |
|||
pagination={false} |
|||
/> |
|||
</Descriptions.Item> |
|||
</Descriptions> |
|||
|
|||
<Descriptions title="出场缴费二维码"> |
|||
<Descriptions.Item span={3}> |
|||
<Table |
|||
columns={columns_3} |
|||
className="yisa-table" |
|||
dataSource={qrcode3} |
|||
pagination={false} |
|||
/> |
|||
</Descriptions.Item> |
|||
</Descriptions> |
|||
</main> |
|||
</Modal> |
|||
); |
|||
} |
|||
|
|||
export default QRModal; |
@ -0,0 +1,48 @@ |
|||
import ajax from "@/config/ajax"; |
|||
///api/orp/bill/get_rule_list 计费规则列表查询展示
|
|||
const getChargeRuleList = (params) => { |
|||
return ajax({ |
|||
url: "/api/orp/bill/get_rule_list", |
|||
type: "post", |
|||
data: params, |
|||
}); |
|||
}; |
|||
///api/orp/bill/del_rule 删除计费规则
|
|||
const delChargeRule = (params) => { |
|||
return ajax({ |
|||
url: "/api/orp/bill/del_rule", |
|||
type: "get", |
|||
data: params, |
|||
}); |
|||
}; |
|||
///api/orp/bill/get_rule_info 获取详情
|
|||
const getChargeRuleInfo = (params) => { |
|||
return ajax({ |
|||
url: "/api/orp/bill/get_rule_info", |
|||
type: "get", |
|||
data: params, |
|||
}); |
|||
}; |
|||
///api/orp/bill/add_rule 新增计费规则
|
|||
const addChargeRule = (params) => { |
|||
return ajax({ |
|||
url: "/api/orp/bill/add_rule", |
|||
type: "post", |
|||
data: params, |
|||
}); |
|||
}; |
|||
///api/orp/bill/edit_rule 编辑计费规则
|
|||
const editChargeRule = (params) => { |
|||
return ajax({ |
|||
url: "/api/orp/bill/edit_rule", |
|||
type: "post", |
|||
data: params, |
|||
}); |
|||
}; |
|||
export default { |
|||
getChargeRuleList, |
|||
delChargeRule, |
|||
getChargeRuleInfo, |
|||
addChargeRule, |
|||
editChargeRule, |
|||
}; |
@ -0,0 +1,12 @@ |
|||
import ajax from "@/config/ajax"; |
|||
// /api/orp/business/get_payment_list 支付订单-列表
|
|||
const getOutPayOrdersList = (params) => { |
|||
return ajax({ |
|||
url: "/api/orp/business/get_payment_list", |
|||
type: "post", |
|||
data: params, |
|||
}); |
|||
}; |
|||
export default { |
|||
getOutPayOrdersList, |
|||
}; |
Write
Preview
Loading…
Cancel
Save
Reference in new issue