diff --git a/src/components/CarTableTreeAuth/SelectSpec.tsx b/src/components/CarTableTreeAuth/SelectSpec.tsx new file mode 100644 index 0000000..77aace3 --- /dev/null +++ b/src/components/CarTableTreeAuth/SelectSpec.tsx @@ -0,0 +1,62 @@ +import React, { useEffect, useState } from "react"; +import { + Table, + Select, +} from "antd"; +import { + CarOptionVo, +} from "@/pages/stock/Components/api"; +import { ColumnsType } from 'antd/lib/table'; + +interface Props { + onChange?: (pa: any) => void; + value?: any[]; + disabled?: boolean; + specList?: CarOptionVo[] +} + +interface Item { + label: string; + value: number; + key?: number; +} +const { Column } = Table; +const { Option } = Select; + +const columns: ColumnsType = [ + { + title: '车型', + dataIndex: 'name', + }, + { + title: '配置代码', + dataIndex: 'specConfigCodeList', + render: (t) => t.map((i: string, key: number) => (
{key + 1}.{i}
)) + }, +]; +export default function index({ onChange: onSelected, value, disabled, specList = [] }: Props) { + const rowSelection = { + onChange: (selectedRowKeys: React.Key[], selectedRows: CarOptionVo[]) => { + onSelected && onSelected(selectedRows); + }, + }; + + return ( + <> + item.id), + ...rowSelection, + }} + pagination={false} + // loading={} + rowKey="id" + size="small" + scroll={{ y: 500 }} + columns={columns} + dataSource={specList} + /> + + ); +} diff --git a/src/components/CarTableTreeAuth/entity.ts b/src/components/CarTableTreeAuth/entity.ts new file mode 100644 index 0000000..fb3b11b --- /dev/null +++ b/src/components/CarTableTreeAuth/entity.ts @@ -0,0 +1,18 @@ +export interface CarAuthList { + authType: number; + brandId: number; + brandName: number; + children?: Array +} + +interface SeriesAuth { + authType: number; + seriesId: number; + seriesName: string; + children?: Array +} +interface SpecAuth { + authType: number; + specId: number; + specName: string; +} \ No newline at end of file diff --git a/src/components/CarTableTreeAuth/index.tsx b/src/components/CarTableTreeAuth/index.tsx new file mode 100644 index 0000000..9c6ff07 --- /dev/null +++ b/src/components/CarTableTreeAuth/index.tsx @@ -0,0 +1,373 @@ +import React, { useEffect, useState } from "react"; +import { + Button, + Card, + Table, + Modal, + Form, + Select, + Space, + Spin, + message, +} from "antd"; +import { + CarOptionVo, + getOnsaleSeriesApi, + getOnsaleSpecApi, +} from "@/pages/stock/Components/api"; +import { PlusOutlined } from '@ant-design/icons'; +import { ColumnsType } from 'antd/lib/table'; +import SelectSpec from './SelectSpec'; +import { CarAuthList } from './entity'; +import { getBrandFilterApi } from '@/common/api'; + +interface Props { + onChange?: (pa: any) => void; + value?: CarAuthList[]; + disabled?: boolean; + brandList?: CommonApi.OptionVO[]; + /**品牌是否多选,默认true */ + brandMultiple?: boolean; +} + +interface Item { + label: string; + value: number; + key?: number; +} +const { Column } = Table; +const { Option } = Select; + +export default function index({ onChange, value, disabled, brandMultiple = true, brandList }: Props) { + const [form] = Form.useForm(); + // 控制Modal是否可见 + const [visible, setVisible] = useState(false); + // 控制是否可见车型下拉框 + const [level, setLevel] = useState(1); + //存储表格当前车系 + const [currentItem, setCurrentItem] = useState(); + const [brandData, setBrandData] = useState([]); + //存储Modal中可选的车系 + const [series, setSeries] = useState([]); + //存储接口返回的车型 + const [specList, setSpecList] = useState([]); + //存储Modal选择的品牌和车系作为表格的数据源 + const [savaData, setSavadata] = useState([]); + // 存储已经选中的车系 + const [selectedSeries, setSelectedSeries] = useState([]); + const [fetchLoading, setFetchLoading] = useState(false); + + useEffect(() => { + if (value && value.length) { + setSelectedSeries([...value]); + setSavadata([...value]); + } + }, [value]); + + useEffect(() => { + if (brandList && Array.isArray(brandList)) { + setBrandData(brandList || []); + } + }, [brandList]); + + function getBrands() { + if (brandData.length) { + return; + } + setFetchLoading(true); + getBrandFilterApi().then(res => { + setBrandData(res.data || []); + setFetchLoading(false); + }).catch(err => { + message.error(err.message); + setFetchLoading(false); + }); + } + + const _onOk = () => { + form + .validateFields() + .then((fileds) => { + if (level === 2) { + const { series } = fileds; + const _series = series.map((item: Item) => ({ + seriesId: item.value, + seriesName: item.label, + authType: 1, + })); + + const currentSeries = (savaData.filter((i: any) => i.brandId === currentItem.brandId)[0] || {}).children || []; + /**判断已有数据保留 */ + if (currentSeries.length) { + const selectedIds = currentSeries.map(i => i.seriesId); + let newAuthSeries: any[] = []; + _series.forEach((item: any) => { + if (selectedIds.includes(item.seriesId)) { + newAuthSeries = newAuthSeries.concat(currentSeries.filter((list: any) => list.seriesId === item.seriesId)); + } else { + newAuthSeries.push(item); + } + }); + currentItem.children = newAuthSeries; + } else { + currentItem.children = _series; + } + + const tempData = savaData.map((item: any) => (item.brandId === currentItem.brandId ? { ...currentItem, authType: series.length ? 2 : 1 } : { ...item, authType: 1 })); + setSavadata([...tempData]); + onChange && onChange(tempData); + setVisible(false); + return; + } + if (level === 3) { + const { spec } = fileds; + const _spec = spec.map((item: any) => ({ + specId: item.id, + specName: item.name, + })); + currentItem.children = _spec; + currentItem.authType = 2; + const tempData = savaData.map((item: any) => { + if (item.children) { + const newChildren = item.children.map((i: any) => (i.seriesId === currentItem.seriesId ? { ...currentItem, authType: spec.length ? 2 : 1 } : i)); + item.children = newChildren; + } + return { ...item, authType: 1 }; + }); + setSavadata([...tempData]); + onChange && onChange(tempData); + setVisible(false); + return; + } + const { brand } = fileds; + const tempArray = (brandMultiple ? brand : [brand]).map((item: any) => ({ + brandName: item.label, + brandId: item.value, + authType: 1, //1全部2部分 + })); + const selectedBrands: number[] = savaData.map((i: any) => i.brandId); + let newAuthCar: any[] = []; + tempArray.forEach((item: any) => { + if (selectedBrands.includes(item.brandId)) { + newAuthCar = newAuthCar.concat(savaData.filter(list => list.brandId === item.brandId)); + } else { + newAuthCar.push(item); + } + }); + setSavadata(newAuthCar); + onChange && onChange(newAuthCar); + setVisible(false); + }) + .catch((err) => console.log(err.message)); + }; + + // 选择部分车辆表格==》删除车系 + const onDelete = (record: any) => { + const _savaData = savaData.filter( + (item: any) => item.seriesId != record.seriesId + ); + const _selectedSeries = selectedSeries.filter( + (item) => item.seriesId != record.seriesId + ); + setSavadata([..._savaData]); + onChange && onChange(_savaData); + setSelectedSeries([..._selectedSeries]); + }; + + // 选择部分车辆表格==》编辑选择部分车系、车型 + const onSelectSpec = async (record: any) => { + setCurrentItem(record); + setVisible(true); + if (record.brandId) { + setLevel(2); + setFetchLoading(true); + try { + const { data } = await getOnsaleSeriesApi(record.brandId); + const selectedSeries = savaData.filter((brand: any) => brand.brandId === record.brandId)[0].children; + selectedSeries && form.setFieldValue("series", selectedSeries.map(i => ({ value: i.seriesId, label: i.seriesName }))); + setSeries(data); + setFetchLoading(false); + } catch (err: any) { + message.error(err.message); + setFetchLoading(false); + } + } + if (record.seriesId) { + setLevel(3); + setFetchLoading(true); + try { + const { data } = await getOnsaleSpecApi(record.seriesId); + record.children && form.setFieldValue("spec", record.children.map(i => ({ id: i.specId, name: i.specName }))); + setSpecList(data); + setFetchLoading(false); + } catch (err: any) { + message.error(err.message); + setFetchLoading(false); + } + } + }; + + return ( + <> + + {!disabled && ( +
+ +
+ )} + +
String(record.brandId || record.seriesId || record.specId)} + > + + { + return (text || record.specName || (record.children && record.children.length !== 0) ? ( + + {text} + + ) : ( + 全部车系 + )); + }} + /> + { + return (text || (record.children && record.children.length !== 0) ? ( + + {text} + + ) : ( + 全部车型 + )); + }} + /> + {!disabled && ( + { + return ( + + + {/* onDelete(record)} + > + + */} + + ); + }} + /> + )} +
+ + + {/* 选择品牌和车系 */} + form.submit()} + onCancel={() => { + setVisible(false); + }} + maskClosable={false} + afterClose={() => { + form.resetFields(); + setCurrentItem({}); + }} + > + +
+ {level === 1 ? ( + + + + ) : null} + + {/* 车系 */} + {level === 2 && ( + + + + )} + {level === 3 ? ( + + {/* */} + + + ) : null} +
+
+
+ + ); +} diff --git a/src/pages/coupon/CouponConfig/components/UsesceneItems/PreDecoration/Components/WorkItemLimit.tsx b/src/pages/coupon/CouponConfig/components/UsesceneItems/PreDecoration/Components/WorkItemLimit.tsx index c043bd5..a9a10d8 100644 --- a/src/pages/coupon/CouponConfig/components/UsesceneItems/PreDecoration/Components/WorkItemLimit.tsx +++ b/src/pages/coupon/CouponConfig/components/UsesceneItems/PreDecoration/Components/WorkItemLimit.tsx @@ -6,9 +6,9 @@ import * as API from '../api'; import * as IF from '../interface'; import usePagination from '@/hooks/usePagination'; import { deRepetition } from '@/components/Condition/SeriesSelector/components/utils'; -import useDebounce from '@/hooks/useDebounce'; import useInitial from '@/hooks/useInitail'; -import { getBrandFilterApi } from '@/common/api'; +import { getBrandFilterApi, getSeriesApi } from '@/common/api'; +import { debounce } from 'lodash'; const st = require('@/pages/coupon/CouponConfig/style.less'); @@ -30,19 +30,23 @@ function PartItem(props: Props, ref?: Ref) { const params = useScene === 1 ? { workTypes: "1,2,5,9" } : { workType: useScene }; const { loading, setLoading, list, setParams, paginationConfig, innerParams } = usePagination(API.fetchListApi, params); const { data: brandList } = useInitial(getBrandFilterApi, [], {}); + const [seriesList, setSeriesList] = useState([]); const [visible, setVisible] = useState(false); const [listData, setListData] = useState([]); - const [keyWords, setKeyWords] = useState(''); - const keyWordsTerm = useDebounce(keyWords, 800); useEffect(() => { value && setListData(value.map((v: any) => ({ itemCode: v.applyValue, itemName: v.applyName }))); }, []); - useEffect(() => { - setParams({ keywords: keyWordsTerm || undefined, current: 1 }, true); - }, [keyWordsTerm]); + function getSeries(brandId: number) { + getSeriesApi(brandId).then((res) => { + setSeriesList(res.data || []); + }).catch((err) => { + message.error(err.message); + }); + } + const onFilter = debounce((params) => setParams({ ...innerParams, ...params }, true), 600); function selectedItems(value: any[]) { const partIds = value.length && value.map((i: any) => i.applyValue).toString(); API.fetItemsApi({ partIds }).then(res => { @@ -93,7 +97,7 @@ function PartItem(props: Props, ref?: Ref) { width="20%" render={(text, record: IF.ListVO) => { return ( - remove(record.itemCode)}>删除 + remove(record.itemCode!)}>删除 ); }} /> @@ -120,16 +124,38 @@ function PartItem(props: Props, ref?: Ref) { showSearch allowClear placeholder="搜索品牌" - style={{ width: 200, marginRight: 15 }} - onChange={(value) => setParams({ ...innerParams, brandId: value }, true)} + style={{ width: 200, margin: 5 }} + onChange={(value) => { + setParams({ ...innerParams, brandId: value }, true); + getSeries(value); + }} > {brandList.map((item) => {item.name})} , + , setKeyWords(e.target.value)} + onChange={(e) => onFilter({ keywords: e.target.value })} + />, + onFilter({ specCode: e.target.value })} /> ]} /> diff --git a/src/pages/coupon/CouponConfig/components/UsesceneItems/PreDecoration/interface.d.ts b/src/pages/coupon/CouponConfig/components/UsesceneItems/PreDecoration/interface.d.ts index 4230867..dbcb0a3 100644 --- a/src/pages/coupon/CouponConfig/components/UsesceneItems/PreDecoration/interface.d.ts +++ b/src/pages/coupon/CouponConfig/components/UsesceneItems/PreDecoration/interface.d.ts @@ -3,7 +3,8 @@ export interface QueryList { workType?: number, //作业项类型 1:机修 2:电器 3:钣喷 4:装潢 5:基础保养 6:贴膜 workTypes?: string, //多个作业项组合参数 keywords?: string, //关键词 - specGroupCode?: string, //车型分组代码 + seriesIds?:string, //车系id集合,查询多个车系 + specCode?: string, //整车代码 current?: number, pageSize?: number, seriesId?: number, @@ -48,51 +49,51 @@ export interface PartListVO { /**查询保养套餐卡列表通用接口 */ export interface MpList { - id: number, //null - maintainId: number, //套餐卡配置ID - name: string, //套餐卡名称 - remark: string, // 备注 - times: number, // 套餐次数 - validity: number, // 有效期(年) - mainItemCode: string, //机油项编码 - mainItemName: string, // 机油项名称 - groupId: number, //集团id - brandName: string, //品牌名称 - seriesName: string, //车系名称 - status: number, //状态 1待发布 2已发布 3已下架 + id: number, //null + maintainId: number, //套餐卡配置ID + name: string, //套餐卡名称 + remark: string, // 备注 + times: number, // 套餐次数 + validity: number, // 有效期(年) + mainItemCode: string, //机油项编码 + mainItemName: string, // 机油项名称 + groupId: number, //集团id + brandName: string, //品牌名称 + seriesName: string, //车系名称 + status: number, //状态 1待发布 2已发布 3已下架 } /**保养套餐卡查询条件 */ export interface Params { - mpName?: string, // 套餐名称 - startDate?: number, // 创建日期开始 - endDate?: number, // 创建日期结束 + mpName?: string, // 套餐名称 + startDate?: number, // 创建日期开始 + endDate?: number, // 创建日期结束 brandId?: string, //品牌ID - status?: number, // 状态 1:待发布 4:已发 + status?: number, // 状态 1:待发布 4:已发 current?: number, pageSize?: number, } /**查询集团VIP卡列表 */ export interface VipList { - id: number, //null - warrantyId: number, // 质保卡id - name: string, // 质保卡名称 - price: number, // 价格 - remark: string, //备注 - groupId: number, //集团id - brandId: number, //品牌id - brandName: string, //品牌名称 - seriesId: number, //车系id - seriesName: string, // 车系名称 - status: number, //状态 1 待上架 2 已上架 2 已下架 + id: number, //null + warrantyId: number, // 质保卡id + name: string, // 质保卡名称 + price: number, // 价格 + remark: string, //备注 + groupId: number, //集团id + brandId: number, //品牌id + brandName: string, //品牌名称 + seriesId: number, //车系id + seriesName: string, // 车系名称 + status: number, //状态 1 待上架 2 已上架 2 已下架 } /**vip卡查询条件 */ export interface VipParams { - brandId?: number, // 品牌ID - status?: number, // 状态 1:待发布 4:已发 + brandId?: number, // 品牌ID + status?: number, // 状态 1:待发布 4:已发 current?: number, pageSize?: number, - name?: number, //质保卡名称 + name?: number, //质保卡名称 }