feat: 新增组合商品组件

This commit is contained in:
wangsongsole 2024-02-06 09:47:33 +08:00
parent c58c1c4f79
commit 08bd3701ec
4 changed files with 863 additions and 33 deletions

View File

@ -0,0 +1,393 @@
import FormItem from "@/components/form-item/main"
import Form from "@/components/form/main"
import Grid from "@/components/gird/main.js"
import Ipt from "@/components/input/main"
import KnockGold from "@/components/knockGold"
import { knockGoldFun } from "@/tools/index"
import { useSetState } from "ahooks"
import { isSameDay } from "date-fns"
import { map } from "lodash-es"
import moment from "moment"
import React, { forwardRef, useEffect, useImperativeHandle, useRef } from "react"
import { Button, Card, DateRangePicker, Input, Notify, Select, Drawer } from "zent"
import { codeInfoRules, rulesInfoRules, tableColumn } from "./static"
function initArray(targetNum) {
return Array.from({ length: targetNum }, (_, index) => index)
}
const Combining = forwardRef((props, ref) => {
const { propsData } = props
const codeInfoEl = useRef(null)
const codeRuleEl = useRef(null)
const table_el = useRef(null)
const knockGoldRef = useRef(null)
const [state, setState] = useSetState({
rankOptions: [],
rank: [],
tableData: [],
visible: false,
info: {
describe: "",
code_name: "",
issued: "",
date_time: ""
}
})
useEffect(() => {
if (propsData && propsData !== "") {
setState({ id: propsData.id, status: propsData.status })
editFun()
} else {
//
let deDateTime = sessionStorage.getItem("knockGold_effectDate")
if (deDateTime) {
}
}
}, [])
useImperativeHandle(ref, () => ({
submit,
getModel
}))
/* 提交 */
function submit() {
let validator = false
if (codeInfoEl.current.validator()) {
validator = true
} else {
validator = false
return validator
}
if (codeRuleEl.current.validator()) {
validator = true
} else {
validator = false
return validator
}
if (validator) {
if (state.rank.length > 0) {
let arr = state.tableData.filter((item) => item.checked)
//
//
let sum = 0
arr.map((item) => {
sum += parseInt(item.quantity)
})
// if (sum < Number(info.issued)) {
// Notify.error("")
// return false
// }
} else {
Notify.error(`请选择商品范围`)
return false
}
}
return validator
}
/* 商品提交 */
function productSubmit() {
if (knockGoldRef.current.submit()) {
}
}
/* 获取数据 */
function getModel() {
let param = {
id: state.id,
status: state.status,
product: {
legal: [],
reduce: [],
cash: []
}
}
let arr = state.tableData.filter((item) => item.checked)
param.product.legal = arr.filter((item) => item.type === 1) //
let param_lj = arr.filter((item) => item.type === 2) //
const redPacketsData = arr.filter((item) => item.type === 3) //
param.product.reduce = param_lj.map((item) => {
return {
...item.only
}
})
param.product.cash = redPacketsData.map((item) => {
return {
...item.only
}
})
return param
}
function editFun() {
//
let lj_arr = propsData.product.reduce.map((item) => {
let table_obj = knockGoldFun(item)
return table_obj
})
let arr = map(lj_arr, (res) => {
let obj = {}
obj.key = res.product_id
obj.text = res.product_name
return obj
})
setState({
rankOptions: arr,
rank: arr,
tableData: arr
})
}
/* 选择商品 */
function onRankChange(e) {
let new_table_data = state.tableData.map((item) => {
item.checked =
e.findIndex((checks) => {
return checks.key == item.product_id
}) > -1
return item
})
setState({ tableData: new_table_data, rank: e })
}
/* 新增 */
function addProduct() {
sessionStorage.setItem(
"knockGold_effectDate",
JSON.stringify({
// begin_time: info.date_time[0],
// end_time: info.date_time[1]
})
)
setState({ visible: true })
}
/* 编辑 */
function productEdit(rowData, index) {
let obj = rowData.only
setState({ productData: obj })
}
/* 表格选择 */
function selectionFun(e) {
let arr = []
map(e, (res) => {
let obj = {}
obj.key = res.product_id
obj.text = res.product_name
arr.push(obj)
return obj
})
setState({ rank: arr })
}
function onDisabledTime(date, type) {
let step1 = JSON.parse(sessionStorage.getItem("knockGold_effectDate"))
const min = new Date(step1.begin_time)
const hour = min.getHours()
const minute = min.getMinutes()
const second = min.getSeconds()
const isSame = isSameDay(date, min)
return isSame
? {
disabledHours: () => initArray(hour),
disabledMinutes: (hourValue) => (hourValue === hour ? initArray(minute) : []),
disabledSeconds: (hourValue, minuteValue) =>
hourValue === hour && minuteValue === minute ? initArray(second) : []
}
: {}
}
function onDisabledRange(date, type) {
let step1 = JSON.parse(sessionStorage.getItem("knockGold_effectDate"))
let isdisabled = false
let str = moment(date).format("YYYY-MM-DD HH:mm:ss")
const isDay = moment(step1.end_time).format("HH:mm:ss")
if (type == "start") {
if (isDay < "23:59:59") {
isdisabled =
moment(str).isBefore(step1.begin_time) ||
moment(str).subtract(1, "days").isAfter(step1.end_time)
} else {
isdisabled = moment(str).isBefore(step1.begin_time) || moment(str).isAfter(step1.end_time)
}
}
if (type == "end") {
isdisabled =
moment(str).add(1, "days").isBefore(step1.begin_time) || moment(str).isAfter(step1.end_time)
}
return isdisabled
}
return (
<div className="draw">
<Card style={{ width: "95%", margin: "10px auto" }} title={"基本信息"}>
<div className="addcode">
<Form model={state.info} rules={codeInfoRules} ref={codeInfoEl} className="addform">
<FormItem labelname="兑换码名称" prop="code_name" id="code_name">
<Ipt
onChange={(e) => {}}
onClearItem={(e) => {}}
value={state.info.code_name}
placeholder={"请输入兑换码名称"}
labelWidth={"0px"}
maxLength={10}
height={"36px"}
width={"520px"}
alignment={"left"}
/>
</FormItem>
<FormItem labelname="发放总量" prop="issued" id="issued">
<Ipt
onChange={(e) => {}}
onClearItem={(e) => {}}
unit="条"
countShow={false}
value={state.info.issued}
placeholder={"请输入发放总量"}
labelWidth={"0px"}
maxLength={12}
height={"36px"}
width={"520px"}
alignment={"left"}
/>
</FormItem>
<FormItem labelname="使用说明" prop="describe" id="describe" required={false}>
<Input
type="textarea"
autoSize
width="520px"
maxLength={100}
maxCharacterCount={100}
showCount
value={state.info.describe}
onChange={(e) => {}}
/>
</FormItem>
</Form>
</div>
</Card>
<Card style={{ width: "95%", margin: "10px auto" }} title={"基本规则"}>
<div>
<Form model={state.info} rules={rulesInfoRules} ref={codeRuleEl} className="addform">
<FormItem labelname="生效时间段" prop="date_time" id="date_time">
<DateRangePicker
className="zent-datepicker-plan"
showTime={{
format: "HH:mm:ss",
defaultTime: ["00:00:00", "23:59:59"]
}}
format="YYYY-MM-DD HH:mm:ss"
value={state.info.date_time}
onChange={(e) => {}}
disabledTime={onDisabledTime}
disabledDate={onDisabledRange}
/>
</FormItem>
<FormItem labelname="商品范围" prop="rank" id="rank">
<div className="goods-boxs">
<Select
options={state.rankOptions}
multiple
value={state.rank}
placeholder="选择一项"
width={405}
onChange={(e) => {
onRankChange(e)
}}
/>
<Button
type="primary"
style={{ marginLeft: "20px" }}
onClick={() => {
addProduct("addKnockGold")
}}
>
新建立减金
</Button>
</div>
</FormItem>
</Form>
</div>
<FormItem labelname="" prop="range" id="range">
<Grid
headBackgroud="#f9fafc"
isBorder={true}
spliteColor={"#fff"}
tableData={state.tableData}
Column={tableColumn}
countbarVisible={false}
maxheight={state.tableHeight}
isSwitch={false}
isShowPageBar={false}
page={state.page}
ref={table_el}
dataCount={state.dataCount}
emptyText={"抱歉,暂无相关数据记录"}
checkChange={(data) => selectionFun(data)}
ComponentHandler={(com, rowData, rowIndex) => {
if (com === "opearo") {
return (
<div>
<span className="grid-link" onClick={() => productEdit(rowData, rowIndex)}>
编辑
</span>
</div>
)
}
if (com === "cost_price") {
return <>{rowData.type === 2 ? rowData.official_price : rowData.cost_price}</>
}
}}
/>
</FormItem>
</Card>
<Drawer
className="draw"
width={"86%"}
title={"新建立减金"}
footer={
<div style={{ textAlign: "center" }}>
<Button type="primary" onClick={productSubmit}>
提交
</Button>
<Button
onClick={(e) => {
setState({ visible: false })
}}
>
取消
</Button>
</div>
}
visible={state.visible}
onClose={(e) => {
setState({ visible: false })
}}
maskClosable={false}
>
<div className="draw2">
<Card style={{ width: "95%", margin: "10px auto", border: 0 }}>
<KnockGold ref={knockGoldRef} />
</Card>
</div>
</Drawer>
</div>
)
})
export default Combining

View File

@ -0,0 +1,300 @@
.addkey-btn-group {
margin-left: 10px;
margin-top: 15px;
button {
width: 100px;
height: 36px;
}
}
.btn-add {
width: 50%;
margin: 0 auto;
height: 36px;
margin-top: 20px;
text-align: center;
line-height: 36px;
background-color: rgb(249, 250, 252);
}
#addkey .zent-radio-button--disabled[data-zv="9.11.0"].zent-radio-button--checked {
color: #8a96aa;
background: #dfe8fc !important;
border: 1px solid #8a96aa !important;
}
.line-value {
width: 388px !important;
}
.import-excel {
width: 451px;
height: 600px;
background-color: #FFFFFF;
border-radius: 5px;
position: fixed;
top: 50%;
margin-top: -280px;
left: 50%;
margin-left: -215px;
z-index: 100;
.import-header {
width: 100%;
height: 48px;
display: flex;
align-items: center;
.import-title {
width: 70%;
font-size: 18px;
font-weight: bold;
margin-left: 20px;
}
.closebtn {
width: 30%;
}
.import-close {
margin-left: 70px;
font-size: 20px;
font-weight: bold;
}
}
.step-bar {
width: 80%;
height: 60px;
margin: 10px auto;
display: flex;
justify-content: center;
}
.step-code {
width: 24px;
height: 24px;
border-radius: 50%;
border: 1px solid #e8e8e8;
display: flex;
align-items: center;
justify-content: center;
color: #e8e8e8;
}
.step-code.active {
background-color: #1890ff;
}
.step-group {
width: 150px;
height: 50px;
display: flex;
align-items: center;
}
.step-center {
width: 60px;
height: 50px;
display: flex;
align-items: center;
margin-right: 40px;
}
.step-line {
width: 50px;
height: 1px;
background-color: #e8e8e8;
}
.step-line.active {
background-color: #1890ff;
}
.step-label {
color: #8d8d8d;
font-size: 14px;
margin-left: 10px;
font-weight: bold;
}
.step-label.active {
color: #000000;
}
.upload-panel1 {
width: 80%;
margin: 10px auto;
margin-bottom: 20px;
.upload-label {
font-size: 15px;
font-weight: bold;
margin-bottom: 20px;
}
.upload-info {
color: #626366;
}
}
.btn-upload {
margin-top: 10px;
margin-left: 40px;
margin-bottom: 20px;
background-color: #1890ff;
}
.btn-download {
margin-top: 10px;
margin-left: 40px;
}
.foot-bar {
width: 100%;
height: 50px;
position: absolute;
bottom: 20px;
.btn-group {
width: 240px;
margin-left: 160px;
}
button {
width: 100px;
}
}
.upload-msgbar {
width: 82%;
background-color: #f5f5f5;
margin: 0 auto;
min-height: 40px;
border-radius: 5px;
display: flex;
.execel-name {
width: 75%;
display: flex;
min-height: 40px;
align-items: center;
.excel-txt {
font-size: 12px;
margin-left: 10px;
}
.doc-flag {
font-size: 20px;
margin-left: 5px;
}
}
.file-tag {
width: 25%;
font-size: 12px;
display: flex;
align-items: center;
color: #1890ff;
.upload-flag {
font-size: 20px;
margin-left: 5px;
color: #1890ff;
margin-right: 3px;
}
}
}
.file-tip {
margin-left: 45px;
margin-top: 10px;
margin-bottom: 50px;
}
.error {
color: #e83f2e;
}
.success {
color: #98d673;
}
.error-icon {
color: #e83f2e;
font-size: 18px;
margin-right: 10px;
}
.success-icon {
color: #98d673;
font-size: 18px;
margin-right: 10px;
}
.file-upload-tip {
color: #000000;
font-size: 14px;
font-weight: bold;
margin-left: 40px;
margin-top: 20px;
}
.file-errmsg {
color: #000000;
font-size: 14px;
margin-left: 40px;
margin-top: 40px;
}
.gridpanel {
width: 90%;
height: 400px;
margin: 0 auto;
margin-top: 50px;
}
}
.audit-obj {
margin-left: 30px;
margin-bottom: 10px;
}
.upload-input {
opacity: 0;
width: 300px;
height: 48px;
position: absolute;
z-index: 5;
}
.file-loading {
font-size: 24px;
}
.isImport {
cursor: "pointer";
}
.goods-boxs {
display: flex;
justify-content: flex-start;
}

View File

@ -0,0 +1,101 @@
export const tableColumn = [
{
title: "商品ID",
name: "product_id",
prop: "product_id",
width: "auto",
type: "normal"
},
{
title: "商品名称",
width: "auto",
prop: "product_name",
name: "product_name",
type: "normal"
},
{
title: "平台批次号",
width: "250px",
prop: "channel_activity_id",
name: "channel_activity_id",
type: "normal"
},
{
title: "类型",
width: "auto",
prop: "type",
name: "type",
type: "normal"
},
{
title: "上游平台",
width: "auto",
prop: "upstream",
name: "upstream",
type: "normal"
},
{
title: "有效时间段",
width: "350px",
prop: "effectDate",
name: "effectDate",
type: "normal"
},
{
title: "总预算",
prop: "all_budget",
name: "all_budget",
width: "auto",
type: "normal"
},
{
title: "当前成本价格",
prop: "cost_price",
name: "cost_price",
width: "200px",
type: "slot"
},
{
title: "合同价",
name: "contract_price",
prop: "contract_price",
type: "normal",
width: "auto"
},
{
title: "商品官方价",
type: "normal",
prop: "official_price",
width: "auto"
},
{
title: "库存",
type: "normal",
prop: "quantity",
width: "auto"
},
{
title: "操作",
prop: "opearo",
name: "opearo",
type: "slot",
width: "auto"
}
]
export const codeInfoRules = {
code_name: [{ type: "required", message: "请输入兑换码名称" }],
issued: [
{ type: "required", message: "请输入发放总量" },
{
type: "regExp",
message: "请输入正整数",
reg: "^([1-9][0-9]*){1,3}$"
}
]
}
export const rulesInfoRules = {
date_time: [{ type: "required", message: "请选择生效时间段" }],
rank: [{ type: "required", message: "请选择商品范围" }]
}

View File

@ -9,6 +9,7 @@ import {
} from "@/assets/api.js"
import UseCouponAddEdit from "@/components/UseCouponAddEdit" //
import UseExchangeAddEdit from "@/components/UseExchangeAddEdit" //
import Combining from "@/components/combining" //
import FormItem from "@/components/form-item/main"
import Form from "@/components/form/main"
import Grid from "@/components/gird/main.js"
@ -28,7 +29,8 @@ import {
RadioButton,
RadioGroup,
Sweetalert,
Switch
Switch,
Pop
} from "zent"
const formRules = {
@ -94,6 +96,7 @@ const UseKeyAddEdit = () => {
myfile: {},
audit_visible: false,
key_status: -1,
exchangeType: 1 /* 兑换码类型 */,
keyType: Number(sessionStorage.getItem("keyType")),
rowIndex: -1,
distdata: [],
@ -520,16 +523,24 @@ const UseKeyAddEdit = () => {
//
const planAddExchangeCoupon = (type) => {
if (type === 0) {
setState({ draw_title: "新建兑换码" })
setTimeout(() => {
addEditExchangeEl.current.clearExchangeForm()
}, 300)
} else {
setState({ draw_title: "新建优惠券" })
setTimeout(() => {
addEditCouponEl.current.clearCouponForm()
}, 300)
switch (type) {
case 0:
setState({ draw_title: "新建兑换码", exchangeType: 1 })
setTimeout(() => {
addEditExchangeEl.current.clearExchangeForm()
}, 300)
break
case 1:
setState({ draw_title: "新建优惠券" })
setTimeout(() => {
addEditCouponEl.current.clearCouponForm()
}, 300)
break
case 2:
setState({ draw_title: "新建组合商品", exchangeType: 2 })
break
default:
break
}
setState({ drawerVisible: true, rowIndex: -1 })
}
@ -933,6 +944,34 @@ const UseKeyAddEdit = () => {
couponTools()
}
}
/* 动态组件 */
function dynamicComponents() {
if (state.keyType === 1) {
if (state.exchangeType === 1) {
return (
<UseExchangeAddEdit
direct_reseller_id={state.direct_reseller_id}
editData={state.rowExChangeData}
ref={addEditExchangeEl}
/>
)
} else {
return <Combining propsData={state.rowExChangeData} ref={addEditExchangeEl} />
}
} else {
return (
<UseCouponAddEdit
couponType={1}
editData={state.rowCouponData}
isAuditButton={false}
ref={addEditCouponEl}
direct_reseller_id={state.direct_reseller_id}
/>
)
}
}
//#endRegion submit ************************/
return (
@ -1066,13 +1105,24 @@ const UseKeyAddEdit = () => {
<FormItem labelname="" prop="btn" required={false}>
{state.keyType === 1 ? (
<Button
onClick={(e) => {
planAddExchangeCoupon(0)
}}
>
新建兑换码
</Button>
<>
<Button
onClick={(e) => {
planAddExchangeCoupon(0)
}}
>
新建兑换码
</Button>
<Pop trigger="hover" content="一次性充值多张立减金">
<Button
onClick={(e) => {
planAddExchangeCoupon(2)
}}
>
新建组合商品
</Button>
</Pop>
</>
) : (
<Button
onClick={(e) => {
@ -1191,21 +1241,7 @@ const UseKeyAddEdit = () => {
}}
maskClosable={false}
>
{state.keyType === 1 ? (
<UseExchangeAddEdit
direct_reseller_id={state.direct_reseller_id}
editData={state.rowExChangeData}
ref={addEditExchangeEl}
></UseExchangeAddEdit>
) : (
<UseCouponAddEdit
couponType={1}
editData={state.rowCouponData}
isAuditButton={false}
ref={addEditCouponEl}
direct_reseller_id={state.direct_reseller_id}
></UseCouponAddEdit>
)}
{dynamicComponents()}
</Drawer>
{state.audit_visible ? (