提交 23f61049 作者: 翁进城

分类管理开发

上级 185fd540
......@@ -9,20 +9,25 @@ export interface GoodsInfo {
// 分类列表
export interface categoryEntity {
goodsMasterType: string;
id: number;
directoryId: number;
classifyName: string;
pid: number;
description?: any;
icon: string;
remark: string;
desc: string;
remark?: any;
type: number;
createTime: string;
goodsMasterTypeId: number | string;
goodsSlaveTypeDTO: Partial<categoryEntity>[];
pid: number | string;
children: any[];
isADD?: boolean;
level?: number;
}
// 分类目录
export interface categoryDec {
defaultType: number;
id: number;
sortName: string;
"id": number,
"directoryName": string,
"pid": null,
"type": number,
directoryType: string
}
......@@ -4,28 +4,38 @@ import { PaginationEntity } from '~/common/interface/PaginationEntity';
export class CategoryManageAPI {
// 分类管理
// 分类目录
static directoryList = () => {
return axios.get('uavgoods/directory/directoryList');
static directoryList = (params) => {
return axios.get("pms/classify/directoryList", {
params
});
};
//目录列表不含分页
static getDirectoryList = (params) => {
return axios.get("pms/classify/getDirectoryList", {
params
});
};
// 新增或编辑目录
static addOrEditDirectory = (data: { id?: number; directoryName: string }[]) => {
return axios.post('uavgoods/directory/addOrEditDirectory', data);
static addOrEditDirectory = (data: { id?: number; directoryName: string, type: number, relevance: number }[]) => {
return axios.post('/pms/classify/addOrEditDirectory', data);
};
// 删除目录
static removeDirectory = (id: number) => {
return axios.get('uavgoods/directory/removeDirectory', { params: { id } });
return axios.get('/pms/classify/removeDirectory', { params: { id } });
};
// 分类新增
static addClassification = (data: object): any => {
return axios.post('uavgoods/mgoods/addClassification', data);
return axios.post('/pms/classify/addClassification', data);
};
// 分类列表
static getListGoodsTypeList = (type: number): any => {
return axios.get(`uavgoods/mgoods/getGoodsTypeInfoList/${type}`);
static getClassificationList = (data: object): any => {
return axios.post(`/pms/classify/getClassificationList`, data);
};
// PC端-根据分类信息新增自定义规格-下拉选项 (只查产品类型)
......@@ -40,7 +50,7 @@ export class CategoryManageAPI {
// 分类修改
static updateClassification = (data: object): any => {
return axios.post('uavgoods/mgoods/updateClassification', data);
return axios.post('/pms/classify/updateClassification', data);
};
// 删除分类
......@@ -65,14 +75,14 @@ export class CategoryManageAPI {
// 分类上下移动
static exchangeSortType = (params: object): any => {
return axios.get('uavgoods/mgoods/exchangeSortType', { params });
return axios.get('/pms/classify/exchangeSortType', { params });
};
// 分类详情
static getGoodsTypeDetail = (
obj: { id: number } & Pick<PaginationEntity, 'pageNo' | 'pageSize'>,
obj: { id: number },
) => {
return axios.get('uavgoods/mgoods/getGoodsTypeDetail', { params: obj });
return axios.get('/pms/classify/getClassifyDetails', { params: obj });
};
// 分类详情-安全编码开发修改
......
......@@ -4,9 +4,9 @@ import Cookies from 'js-cookie';
import { Base64 } from 'js-base64';
const { VITE_REQUEST_BASE_URL } = import.meta.env;
export const uploadImgURL = `${VITE_REQUEST_BASE_URL}ossservlet/upload/imgOss`;
export const uploadVideoURL = `${VITE_REQUEST_BASE_URL}ossservlet/upload/videoOss`;
export const uploadFileURL = `${VITE_REQUEST_BASE_URL}ossservlet/upload/oss`;
export const uploadImgURL = `${VITE_REQUEST_BASE_URL}/pms/upload/imgOsses`;
export const uploadVideoURL = `${VITE_REQUEST_BASE_URL}/ossservlet/upload/videoOss`;
export const uploadFileURL = `${VITE_REQUEST_BASE_URL}/ossservlet/upload/oss`;
const service = axios.create({
baseURL: VITE_REQUEST_BASE_URL,
timeout: 6000,
......
......@@ -62,9 +62,9 @@ function Index(props: any) {
setFileList([]);
form.setFieldsValue({ icon: '' });
} else if (val.file.status === 'done') {
setImageUrl(val.file.response.result[0]);
setImageUrl(val.file.response.result?.filePath);
setFileList(val.fileList);
form.setFieldsValue({ icon: val.file.response.result[0] });
form.setFieldsValue({ icon: val.file.response.result?.filePath });
} else {
setFileList(val.fileList);
}
......@@ -85,7 +85,7 @@ function Index(props: any) {
return (
<Modal
title={props.title}
visible={props.isVisable}
open={props.isVisable}
onOk={() => props.handleOk()}
onCancel={() => props.handleCancel()}
>
......@@ -101,7 +101,7 @@ function Index(props: any) {
>
<Form.Item
label='分类名称'
name='groupName'
name='classifyName'
rules={[{ required: true, message: '请输入分类名称' }]}
>
<Input placeholder='请输入分类名称' maxLength={15} allowClear />
......
......@@ -106,7 +106,7 @@ const AddOrEditDec: React.FC<PropsType & selfPropsType> = ({
return (
<Modal
title='目录管理'
visible={isModalVisible}
open={isModalVisible}
onOk={directorySureEvent}
onCancel={directoryCancel}
>
......
......@@ -4,7 +4,7 @@ function Index(props: any) {
return (
<Modal
title='分类删除'
visible={props.isDeleteVisable}
open={props.isDeleteVisable}
onOk={() => props.deleteHandleOk()}
onCancel={() => props.deleteHandleCancel()}
>
......
......@@ -21,6 +21,7 @@ import { categoryDetailEntity, GoodsInfo } from '~/api/modules/goods';
import { CategoryManageAPI } from '~/api';
import useOption from '~/common/hook/optionHook';
import './index.scss';
import { useLocation, useParams, useNavigate } from 'react-router-dom';
const CategoryDetail: FC = (props: any) => {
const [selectedRowKeys, setSelectedRowKeys] = useState<React.Key[]>([]);
......@@ -32,7 +33,7 @@ const CategoryDetail: FC = (props: any) => {
const [categoryId, setCategoryId] = useState<number>(0);
const [isEdit, setIsEdit] = useState<boolean>(false);
const [detailForm] =
Form.useForm<Pick<categoryDetailEntity, 'description' | 'groupName' | 'icon'>>();
Form.useForm<Pick<categoryDetailEntity, 'description' | 'classifyName' | 'icon'>>();
const [fileList, setFileList] = useState<any>([]);
const [goodsInfo, setGoodsInfo] = useState<GoodsInfo[]>([]);
const [viewerVisible, setViewerVisible] = useState<boolean>(false);
......@@ -45,6 +46,12 @@ const CategoryDetail: FC = (props: any) => {
const [currentImgList, setcurrentImgList]: any = useState([]);
const [sortTypeId, setSortTypeId] = useState<number>(-1);
const [pid, setPid] = useState<number>(-1);
const { id } = useParams();
const _id = Number(id);
const location = useLocation();
const searchParams: any = new URLSearchParams(location.search);
const navigate = useNavigate();
const columns: ColumnsType<GoodsInfo> = [
{
title: '序号',
......@@ -111,19 +118,19 @@ const CategoryDetail: FC = (props: any) => {
const btnCode = useOption(22111);
useEffect(() => {
// 分页数据
getGoodsTypeDetail(props.match.params.id);
getGoodsTypeDetail(_id);
}, [pagination]);
useEffect(() => {
// 全部数据
getAllGoodsTypeDetail(props.match.params.id);
setSortTypeId(Number(qs.parse(props.location.search).sortTypeId));
setPid(Number(qs.parse(props.location.search).pid));
setCategoryId(props.match.params.id);
getAllGoodsTypeDetail(_id);
setSortTypeId(Number(searchParams.directoryId));
setPid(Number(searchParams.pid));
setCategoryId(_id);
}, []);
const backRoute = () => {
props.history.go(-1);
navigate(-1);
};
// 关联商品新增
const addModalShowEvent = () => {
......@@ -139,7 +146,7 @@ const CategoryDetail: FC = (props: any) => {
const getGoodsTypeDetail = async (id: number) => {
const res: any = await CategoryManageAPI.getGoodsTypeDetail({ id, ...pagination });
detailForm.setFieldsValue({
groupName: res.result.groupName ? res.result.groupName : undefined,
classifyName: res.result.classifyName ? res.result.classifyName : undefined,
description: res.result.description ? res.result.description : undefined,
icon: res.result.icon ? res.result.icon : '',
});
......@@ -160,10 +167,8 @@ const CategoryDetail: FC = (props: any) => {
const getAllGoodsTypeDetail = async (id: number) => {
const res: any = await CategoryManageAPI.getGoodsTypeDetail({
id,
pageNo: 1,
pageSize: 99999,
});
setAllGoodsInfo(res.result.goodsInfo || []);
setAllGoodsInfo(res.result || []);
};
// 自定义上传
const selfUploadRequest = async (val: any) => {
......@@ -232,7 +237,7 @@ const CategoryDetail: FC = (props: any) => {
});
if (res.code === '200') {
message.success('修改成功');
getGoodsTypeDetail(props.match.params.id);
getGoodsTypeDetail(_id);
}
};
......@@ -246,11 +251,11 @@ const CategoryDetail: FC = (props: any) => {
const sureChangeDetailInfo = () => {
detailForm
.validateFields()
.then(async (value: Pick<categoryDetailEntity, 'description' | 'groupName' | 'icon'>) => {
.then(async (value: Pick<categoryDetailEntity, 'description' | 'classifyName' | 'icon'>) => {
// console.log("数据--->", value);
const res = await CategoryManageAPI.updateClassification({
// description:value.description,
// groupName:value.groupName,
// classifyName:value.classifyName,
// icon:fileList.length?fileList[0].url:'',
...value,
sortTypeId,
......@@ -378,13 +383,13 @@ const CategoryDetail: FC = (props: any) => {
<Form form={detailForm} labelCol={{ span: 2 }} wrapperCol={{ span: 5 }}>
<Form.Item
label='行业名称'
name='groupName'
name='classifyName'
rules={[{ required: true, message: '请输入行业名称' }]}
>
{isEdit ? (
<Input placeholder='请输入行业名称' disabled={!isEdit} maxLength={15} />
) : (
<span>{detailData?.groupName}</span>
<span>{detailData?.classifyName}</span>
)}
</Form.Item>
<Form.Item label='分类描述' name='description'>
......@@ -452,7 +457,7 @@ const CategoryDetail: FC = (props: any) => {
<Table
size='small'
columns={
Number(qs.parse(props.location.search).sortTypeId) === 1
Number(searchParams.directoryId) === 1
? columns.filter((item: ColumnType<GoodsInfo>) => item.title != '安全编码开关')
: columns
}
......
import { FC, useEffect, useState, useRef } from 'react';
import { Button, Table, Form, message, Tooltip, Checkbox, Card, Modal } from 'antd';
import { CardTabListType } from 'antd/lib/card/Card';
import { Router } from 'react-router-dom';
import { Router, useNavigate, useLocation } from 'react-router-dom';
import FileSaver from 'file-saver';
import qs from 'query-string';
import {
......@@ -19,20 +19,19 @@ import {
import AddCgyDailog from './components/addCgyDailog';
import DeleteCgyDailog from './components/deleteCgyDailog';
import EditableCell from './components/EditableCell';
import AddOrEditDec from './components/addOrEditDec';
import { CategoryManageAPI } from '~/api';
import { categoryEntity, categoryDec } from '~/api/interface/categoryManage';
import Viewer from '~/components/viewer';
import useOption from '~/common/hook/optionHook';
import './index.scss';
import events from '~/events';
const Category: FC = (props: any) => {
let location = useLocation();
console.log('location', location);
const navigate = useNavigate();
const baseRef: any = useRef();
// 分类目录
const [tabList, setTabList] = useState<CardTabListType[]>([]);
const [directoryList, setDirectoryList] = useState<categoryDec[]>([]);
const [isAddOrEditDecModal, setIsAddOrEditDecModal] = useState<boolean>(false);
// 分类列表
const [categoryList, setCategoryList] = useState<categoryEntity[]>([]);
const [isLoading, setIsLoading] = useState<boolean>(false);
......@@ -43,33 +42,32 @@ const Category: FC = (props: any) => {
// 编辑的行
const [editingKey, setEditingKey]: any = useState([]);
const isEditing = (record: categoryEntity) => {
const index: number = editingKey.findIndex((item: any) => item == record.goodsMasterTypeId);
const index: number = editingKey.findIndex((item: any) => item == record.id);
if (index != -1) {
return true;
}
return false;
};
let pathArr = window.location.pathname.split('/');
let type = pathArr.pop(); //分类所属模块id(0:通用分类 1:作业服务分类 2:设备租赁分类 3:飞手培训分类 4:产品商城分类)
const columns = [
{
title: '分类名称',
dataIndex: 'goodsMasterType',
key: 'goodsMasterType',
dataIndex: 'classifyName',
key: 'classifyName',
// align: "center",
width: '12%',
editable: true,
ellipsis: true,
render: (text: string, record: categoryEntity, index: number) => {
return (
<Tooltip placement='top' title={<span>{record.goodsMasterType}</span>}>
<Tooltip placement='top' title={<span>{record.classifyName}</span>}>
<span
style={{
marginLeft:
record.goodsSlaveTypeDTO && record.goodsSlaveTypeDTO.length != 0
? '10px'
: '24px',
marginLeft: record.children && record.children.length != 0 ? '10px' : '24px',
}}
>
{record.goodsMasterType}
{record.classifyName}
</span>
</Tooltip>
);
......@@ -102,16 +100,16 @@ const Category: FC = (props: any) => {
},
{
title: '描述',
key: 'desc',
dataIndex: 'desc',
key: 'description',
dataIndex: 'description',
width: '20%',
align: 'center',
editable: true,
ellipsis: true,
render: (text: string, record: categoryEntity, index: number) => {
return (
<Tooltip placement='right' title={<span>{record.desc}</span>}>
<span>{record.desc}</span>
<Tooltip placement='right' title={<span>{record.description}</span>}>
<span>{record.description}</span>
</Tooltip>
);
},
......@@ -131,7 +129,7 @@ const Category: FC = (props: any) => {
render: (text: string, record: categoryEntity, index: number) => {
return (
<div className='table-option-wrap'>
{record.goodsSlaveTypeDTO ? (
{record.children?.length > 0 ? (
<>
{btnAddChildCgy ? (
<Button
......@@ -148,7 +146,7 @@ const Category: FC = (props: any) => {
''
)}
{activeTabKey === 2 && btnShareCode ? (
{/* {activeTabKey === 2 && btnShareCode ? (
<Button
type='link'
icon={<ShareAltOutlined />}
......@@ -158,7 +156,7 @@ const Category: FC = (props: any) => {
</Button>
) : (
''
)}
)} */}
</>
) : (
''
......@@ -247,50 +245,83 @@ const Category: FC = (props: any) => {
// 是否编辑
const [isEdit, setIsEdit] = useState<boolean>(false);
const [selectedRowKeys, setSelectedRowKeys] = useState<any>([]);
const [activeTabKey, setActiveTabKey] = useState<number>(2);
const [activeTabKey, setActiveTabKey] = useState<number>(-1);
// 分享码弹窗显示/隐藏
const [isShareCodeVble, setShareCodeVble] = useState<boolean>(false);
const [shareCodeUrl, setShareCodeUrl] = useState<string>('');
// 按钮权限
const btnAdd = useOption(22101);
const btnUpperDown = useOption(22102);
const btnDir = useOption(22103);
const btnAddChildCgy = useOption(22104);
const btnShareCode = useOption(22105);
const btnEdit = useOption(22106);
const btnDelete = useOption(22107);
const btnDetail = useOption(22108);
const btnAdd = true; //useOption(22101);
const btnUpperDown = true; //useOption(22102);
const btnDir = true; //useOption(22103);
const btnAddChildCgy = true; //useOption(22104);
const btnShareCode = true; //useOption(22105);
const btnEdit = true; //useOption(22106);
const btnDelete = true; //useOption(22107);
const btnDetail = true; //useOption(22108);
const searchParams: any = new URLSearchParams(location.search);
// 获取请求数据
useEffect(() => {
if (qs.parse(props.location?.search).activeTabKey) {
// console.log("当前数据--->", qs.parse(props.location?.search).activeTabKey);
setActiveTabKey(Number(qs.parse(props.location?.search).activeTabKey));
}
getCategoryList(Number(qs.parse(props.location?.search).activeTabKey) || Number(activeTabKey));
setTabList([]);
setCategoryList([]);
getDirectoryList();
}, []);
setActiveTabKey(-1);
}, [location.pathname]); //url改变时,重新获取数据
//目录列表取到后设置第一个目录为激活状态
useEffect(() => {
if (activeTabKey == -1 && tabList.length > 0) {
let key = Number(searchParams.get('activeTabKey') || tabList[0]?.key || -1);
setActiveTabKey(key);
handleTabChange(String(key));
}
}, [tabList, searchParams, activeTabKey]);
// tab变更后触发更新列表
/* useEffect(() => {
if (activeTabKey !== -1) {
getCategoryList(activeTabKey);
} else {
setCategoryList([]);
}
}, [activeTabKey]); */
// 获取分类目录
const getDirectoryList = async () => {
const res: any = await CategoryManageAPI.directoryList();
const tabList: CardTabListType[] = res.result.map((item: categoryDec) => {
const res: any = await CategoryManageAPI.directoryList({
pageNo: 1,
pageSize: 999,
type,
});
const tabList: CardTabListType[] = res.result?.list?.map((item: categoryDec) => {
return {
key: item.id.toString(),
tab: item.sortName,
tab: item.directoryName,
};
});
setTabList([...tabList]);
setDirectoryList([...res.result]);
};
// 分类列表
const getCategoryList = async (type: number) => {
const getCategoryList = async (directoryId: number) => {
setIsLoading(true);
const res = await CategoryManageAPI.getListGoodsTypeList(type);
setIsLoading(false);
setCategoryList(res.result || []);
const arr: number[] = res.result.map((item: any) => {
return item.goodsMasterTypeId;
const res = await CategoryManageAPI.getClassificationList({
type,
pageSize: 999,
pageNo: 1,
directoryId: directoryId,
});
setIsLoading(false);
setCategoryList(
res.result.list?.map((item: categoryEntity) => {
item.level = 1;
return item;
}) || [],
);
const arr: number[] =
res.result.list?.map((item: any) => {
return item.id;
}) || [];
setExpandedRowKeys([...arr]);
};
// 新增分类弹窗
......@@ -307,7 +338,8 @@ const Category: FC = (props: any) => {
const res = await CategoryManageAPI.addClassification({
...values,
pid: 0,
sortTypeId: activeTabKey,
directoryId: activeTabKey,
type,
});
if (res.code == 200) {
events.emit('removeFileList');
......@@ -324,7 +356,7 @@ const Category: FC = (props: any) => {
.then(async (values: any) => {
const res = await CategoryManageAPI.updateClassification({
...values,
id: currentRecord.goodsMasterTypeId,
id: currentRecord.id,
pid: currentRecord.pid,
sortTypeId: activeTabKey,
});
......@@ -350,37 +382,37 @@ const Category: FC = (props: any) => {
const addChildrenCgy = (record: categoryEntity) => {
if (editingKey.length === 0) {
const item: categoryEntity | undefined = categoryList.find(
(item: categoryEntity) => item.goodsMasterTypeId === record.goodsMasterTypeId,
(item: categoryEntity) => item.id === record.id,
);
item?.goodsSlaveTypeDTO.push({
goodsMasterTypeId: `${record.goodsMasterTypeId}self`,
goodsMasterType: '',
desc: '',
item?.children.push({
id: `${record.id}self`,
classifyName: '',
description: '',
isADD: true,
pid: record.goodsMasterTypeId,
pid: record.id,
});
setCategoryList([...categoryList]);
form.setFieldsValue({ goodsMasterType: '', desc: '' });
editingKey.push(`${record.goodsMasterTypeId}self`);
form.setFieldsValue({ classifyName: '', description: '' });
editingKey.push(`${record.id}self`);
setEditingKey(editingKey);
setIsEdit(false);
}
const bol = expandedRowKeys.some((item: any) => item == record.goodsMasterTypeId);
const bol = expandedRowKeys.some((item: any) => item == record.id);
if (!bol) {
const arr: any = [];
expandedRowKeys.push(record.goodsMasterTypeId);
expandedRowKeys.push(record.id);
arr.push(...expandedRowKeys);
setExpandedRowKeys(arr);
}
};
// 展开监听
const onExpand = (expanded: boolean, record: categoryEntity) => {
const index = expandedRowKeys.findIndex((item: any) => item === record.goodsMasterTypeId);
const index = expandedRowKeys.findIndex((item: any) => item === record.id);
if (index != -1) {
expandedRowKeys.splice(index, 1);
setExpandedRowKeys(expandedRowKeys);
} else {
expandedRowKeys.push(record.goodsMasterTypeId);
expandedRowKeys.push(record.id);
setExpandedRowKeys(expandedRowKeys);
}
};
......@@ -388,26 +420,27 @@ const Category: FC = (props: any) => {
const sureAddChildrenCgy = (record: categoryEntity) => {
let pid: string | number = -1;
categoryList.map((item: categoryEntity) => {
if (item.goodsSlaveTypeDTO && item.goodsSlaveTypeDTO.length != 0) {
const bol: boolean = item.goodsSlaveTypeDTO.some(
(item1: Partial<categoryEntity>) => item1.goodsMasterTypeId === record.goodsMasterTypeId,
if (item.children && item.children.length != 0) {
const bol: boolean = item.children.some(
(item1: Partial<categoryEntity>) => item1.id === record.id,
);
if (bol) {
pid = item.goodsMasterTypeId;
pid = item.id;
}
}
});
form.validateFields().then(async (val: any) => {
const obj: any = {
pid,
groupName: val.goodsMasterType,
description: val.desc,
sortTypeId: activeTabKey,
classifyName: val.classifyName,
description: val.description,
directoryId: activeTabKey,
type,
};
if (isEdit) {
const res = await CategoryManageAPI.updateClassification({
...obj,
id: record.goodsMasterTypeId,
id: record.id,
});
if (res.code === '200') {
message.success('修改成功');
......@@ -433,16 +466,16 @@ const Category: FC = (props: any) => {
// 取消新增子分类
const cancelAddCldCgy = (record: categoryEntity, index: number) => {
categoryList.map((item: categoryEntity) => {
if (item.goodsSlaveTypeDTO && item.goodsSlaveTypeDTO.length != 0) {
const index: number = item.goodsSlaveTypeDTO.findIndex(
(item1: Partial<categoryEntity>) => item1.goodsMasterTypeId === record.goodsMasterTypeId,
if (item.children && item.children.length != 0) {
const index: number = item.children.findIndex(
(item1: Partial<categoryEntity>) => item1.id === record.id,
);
if (index != -1) {
if (isEdit) {
item.goodsSlaveTypeDTO[index].isADD = false;
item.children[index].isADD = false;
setIsEdit(false);
} else {
item.goodsSlaveTypeDTO.splice(index, 1);
item.children.splice(index, 1);
}
}
}
......@@ -452,12 +485,12 @@ const Category: FC = (props: any) => {
};
// 删除分类
const deleteCgy = (record: categoryEntity) => {
setCgyId(Number(record.goodsMasterTypeId));
setCgyId(Number(record.id));
setIsDeleteVisible(true);
};
// 删除弹窗确认
const deleteHandleOk = async () => {
const bol = categoryList.some((item: categoryEntity) => item.goodsMasterTypeId === cgyId);
const bol = categoryList.some((item: categoryEntity) => item.id === cgyId);
if (bol) {
const res = await CategoryManageAPI.deleteGoodsTypeByOneLevel({
id: cgyId,
......@@ -490,15 +523,13 @@ const Category: FC = (props: any) => {
// 编辑分类
const editCgy = (record: categoryEntity) => {
setCurrentRecord(record);
const bol = categoryList.some(
(item: categoryEntity) => item.goodsMasterTypeId === record.goodsMasterTypeId,
);
const bol = categoryList.some((item: categoryEntity) => item.id === record.id);
if (bol) {
setTitle('修改分类');
const addForm = baseRef.current.getForm();
addForm.setFieldsValue({
groupName: record.goodsMasterType,
description: record.desc,
directoryName: record.classifyName,
description: record.description,
remark: record.remark,
});
events.emit('setImgFile', record.icon);
......@@ -507,18 +538,17 @@ const Category: FC = (props: any) => {
// 编辑状态
setIsEdit(true);
categoryList.map((item: categoryEntity) => {
if (item.goodsSlaveTypeDTO && item.goodsSlaveTypeDTO.length != 0) {
const index: number = item.goodsSlaveTypeDTO.findIndex(
(item1: Partial<categoryEntity>) =>
item1.goodsMasterTypeId === record.goodsMasterTypeId,
if (item.children && item.children.length != 0) {
const index: number = item.children.findIndex(
(item1: Partial<categoryEntity>) => item1.id === record.id,
);
if (index != -1) {
item.goodsSlaveTypeDTO[index].isADD = true;
item.children[index].isADD = true;
}
}
});
setCategoryList([...categoryList]);
setEditingKey([record.goodsMasterTypeId]);
setEditingKey([record.id]);
form.setFieldsValue(record);
}
};
......@@ -531,14 +561,12 @@ const Category: FC = (props: any) => {
};
// 排序选择
const onSelectChange = (record: categoryEntity) => {
const index: number = selectedRowKeys.findIndex(
(item: any) => item === record.goodsMasterTypeId,
);
const index: number = selectedRowKeys.findIndex((item: any) => item === record.id);
if (index != -1) {
selectedRowKeys.splice(index, 1);
setSelectedRowKeys([...selectedRowKeys]);
} else {
setSelectedRowKeys([...selectedRowKeys, record.goodsMasterTypeId]);
setSelectedRowKeys([...selectedRowKeys, record.id]);
}
};
// 上移
......@@ -549,15 +577,14 @@ const Category: FC = (props: any) => {
message.error('分类只能选择一个');
} else {
const index: number = categoryList.findIndex(
(item: categoryEntity) => item.goodsMasterTypeId === selectedRowKeys[0],
(item: categoryEntity) => item.id === selectedRowKeys[0],
);
if (index === 0) {
message.error('已经是最上面了');
} else {
const res = await CategoryManageAPI.exchangeSortType({
firstId: selectedRowKeys[0],
secondId: categoryList[index - 1].goodsMasterTypeId,
sortTypeId: activeTabKey,
secondId: categoryList[index - 1].id,
});
if (res.code === '200') {
getCategoryList(Number(activeTabKey));
......@@ -574,15 +601,14 @@ const Category: FC = (props: any) => {
message.error('分类只能选择一个');
} else {
const index = categoryList.findIndex(
(item: categoryEntity) => item.goodsMasterTypeId === selectedRowKeys[0],
(item: categoryEntity) => item.id === selectedRowKeys[0],
);
if (index === categoryList.length - 1) {
message.error('已经是最下面了');
} else {
const res = await CategoryManageAPI.exchangeSortType({
firstId: selectedRowKeys[0],
secondId: categoryList[index + 1].goodsMasterTypeId,
sortTypeId: activeTabKey,
secondId: categoryList[index + 1].id,
});
if (res.code === '200') {
getCategoryList(Number(activeTabKey));
......@@ -596,21 +622,13 @@ const Category: FC = (props: any) => {
onChange: onSelectChange,
hideSelectAll: true,
renderCell: (checked: boolean, record: categoryEntity) => {
return (
<>
{record.goodsSlaveTypeDTO != null ? (
<Checkbox onChange={() => onSelectChange(record)} />
) : (
''
)}
</>
);
return <>{record.level === 1 ? <Checkbox onChange={() => onSelectChange(record)} /> : ''}</>;
},
};
// 页签改变监听
const handleTabChange = (key: string) => {
Router.push({
pathname: '/goodsManage/category',
navigate({
pathname: '',
search: qs.stringify({ activeTabKey: key }),
});
setSelectedRowKeys([]);
......@@ -619,16 +637,16 @@ const Category: FC = (props: any) => {
};
// 分类详情
const toCategoryDetail = (record: categoryEntity) => {
Router.push({
pathname: `/goodsManage/category/detail/${record.goodsMasterTypeId}`,
search: qs.stringify({ sortTypeId: activeTabKey, pid: record.pid }),
navigate({
pathname: `/categoryManage/detail/${record.id}`,
search: qs.stringify({ directoryId: activeTabKey, pid: record.pid }),
});
};
// 分享码弹窗显示
const showShareCode = async (record: any) => {
const res: any = await CategoryManageAPI.getAppletQRCode({
page: 'page-sort/sortDetail/index',
scene: `?id=${record.goodsMasterTypeId}&backTip=1`,
scene: `?id=${record.id}&backTip=1`,
});
setShareCodeUrl(`data:image/png;base64,${res.result}`);
setShareCodeVble(true);
......@@ -640,33 +658,7 @@ const Category: FC = (props: any) => {
const downLoadCode = () => {
FileSaver.saveAs(shareCodeUrl, '无人机城行业分享码');
};
// 目录弹窗
const showDecModal = () => {
setDirectoryList([...directoryList]);
setIsAddOrEditDecModal(true);
};
const addOrEditDecHandleOk = () => {
getDirectoryList();
setIsAddOrEditDecModal(false);
};
const addOrEditDecHandleCancel = () => {
setIsAddOrEditDecModal(false);
};
const refreshDec = (id: number) => {
const index: number = directoryList.findIndex((item: categoryDec) => item.id === activeTabKey);
if (id === directoryList[index].id) {
setActiveTabKey(directoryList[index - 1].id);
Router.push({
pathname: '/goodsManage/category',
search: qs.stringify({ activeTabKey: directoryList[index - 1].id }),
});
getCategoryList(directoryList[index - 1].id);
}
getDirectoryList();
// if (qs.parse(props.location?.search).activeTabKey) {
// setActiveTabKey(Number(qs.parse(props.location?.search).activeTabKey));
// }
};
return (
<div className='category-wrap'>
<div className='option-wrap'>
......@@ -709,15 +701,6 @@ const Category: FC = (props: any) => {
tabList={tabList}
activeTabKey={String(activeTabKey)}
onTabChange={(key) => handleTabChange(key)}
tabBarExtraContent={
btnDir ? (
<Button type='link' onClick={showDecModal}>
目录管理
</Button>
) : (
''
)
}
>
<Form form={form} component={false}>
<Table
......@@ -725,11 +708,11 @@ const Category: FC = (props: any) => {
columns={mergedColumns}
dataSource={categoryList}
rowSelection={rowSelection}
rowKey='goodsMasterTypeId'
rowKey='id'
bordered
loading={isLoading}
rowClassName={(record: any, index: number) => {
if (record.goodsSlaveTypeDTO) {
if (record.children) {
return '';
}
return 'row-bg';
......@@ -741,16 +724,16 @@ const Category: FC = (props: any) => {
cell: EditableCell,
},
}}
childrenColumnName='goodsSlaveTypeDTO'
childrenColumnName='children'
expandable={{
rowExpandable: (record) => {
if (record.goodsSlaveTypeDTO && record.goodsSlaveTypeDTO.length != 0) {
if (record.children && record.children.length != 0) {
return true;
}
return false;
},
expandIcon: ({ expanded, onExpand, record }) => {
if (expanded && record.goodsSlaveTypeDTO && record.goodsSlaveTypeDTO.length != 0) {
if (expanded && record.children && record.children.length != 0) {
return (
<DownOutlined
onClick={(e) => onExpand(record, e)}
......@@ -758,7 +741,7 @@ const Category: FC = (props: any) => {
/>
);
}
if (record.goodsSlaveTypeDTO && record.goodsSlaveTypeDTO.length != 0) {
if (record.children && record.children.length != 0) {
return (
<RightOutlined
onClick={(e) => onExpand(record, e)}
......@@ -793,21 +776,9 @@ const Category: FC = (props: any) => {
activeViewerIndex={activeViewerIndex}
setVisible={setVisibleEvent}
/>
{/* 目录管理 */}
<AddOrEditDec
isModalVisible={isAddOrEditDecModal}
handleOk={addOrEditDecHandleOk}
handleCancel={addOrEditDecHandleCancel}
directoryList={directoryList}
refreshDec={refreshDec}
/>
{/* 分享码弹窗 */}
<Modal
visible={isShareCodeVble}
title='分享码'
footer={null}
onCancel={shareCodeHandleCancel}
>
<Modal open={isShareCodeVble} title='分享码' footer={null} onCancel={shareCodeHandleCancel}>
<div className='share-code'>
<img src={shareCodeUrl} alt='' onClick={() => imgClick(shareCodeUrl)} />
<div>
......
import { Modal, Form, Input, Button, Row, Col, message } from 'antd';
import React, { useEffect, useState } from 'react';
import { PlusOutlined, MinusOutlined } from '@ant-design/icons';
import { PropsType } from '~/common/interface/modal';
import { categoryDec } from '~/api/modules/goods';
import { CategoryManageAPI } from '~/api';
interface selfPropsType {
directoryList: categoryDec[];
refreshDec: Function;
}
const AddOrEditDec: React.FC<PropsType & selfPropsType> = ({
isModalVisible,
handleOk,
handleCancel,
directoryList,
refreshDec,
}) => {
const [form] = Form.useForm<any>();
// 表单目录标题列表
const [addOrEditDirectoryList, setAddOrEditDirectoryList] = useState<categoryDec[]>([]);
// 是否点击删除按钮
const [isClickDle, setIsClickDle] = useState<boolean>(false);
useEffect(() => {
if (directoryList.length != 0 && !isClickDle) {
setAddOrEditDirectoryList(directoryList);
const defaultFormValue = directoryList.reduce((pre: any, cur: categoryDec) => {
Object.keys(cur).map((item: string) => {
if (item === 'id') {
pre[cur[item]] = cur.sortName;
}
});
return pre;
}, {});
form.setFieldsValue(defaultFormValue);
}
}, [directoryList]);
// 新增或修改目录
const addDirectoryTitle = () => {
const decList: categoryDec[] = [...addOrEditDirectoryList].sort(
(a: categoryDec, b: categoryDec) => a.id - b.id,
);
setAddOrEditDirectoryList([
...addOrEditDirectoryList,
{
id: decList[decList.length - 1].id + 1,
defaultType: 1,
sortName: '',
},
]);
};
// 删除目录
const deleteDirectory = async (id: number) => {
const bol: boolean = directoryList.some((item: categoryDec) => item.id === id);
const index = addOrEditDirectoryList.findIndex((item: categoryDec) => item.id === id);
if (bol) {
const res: any = await CategoryManageAPI.removeDirectory(id);
if (res.code === '200') {
message.success('删除成功');
setIsClickDle(true);
refreshDec(id);
} else {
return message.warning(res.message);
}
}
const obj: any = {};
obj[id] = undefined;
form.setFieldsValue(obj);
addOrEditDirectoryList.splice(index, 1);
setAddOrEditDirectoryList([...addOrEditDirectoryList]);
};
const directorySureEvent = () => {
form.validateFields().then(async (value: any) => {
const requestList = Object.keys(value).reduce((pre: any, cur: string) => {
const bol: boolean = directoryList.some((item: any) => item.id === Number(cur));
if (bol) {
pre.push({
id: Number(cur),
directoryName: value[cur],
});
} else {
pre.push({
directoryName: value[cur],
});
}
return pre;
}, []);
const res: any = await CategoryManageAPI.addOrEditDirectory(requestList);
if (res.code === '200') {
message.success('操作成功');
form.resetFields();
setIsClickDle(false);
handleOk();
} else {
message.warning(res.message);
}
});
};
const directoryCancel = () => {
form.resetFields();
setIsClickDle(false);
handleCancel();
};
return (
<Modal
title='目录管理'
visible={isModalVisible}
onOk={directorySureEvent}
onCancel={directoryCancel}
>
<Form form={form} labelCol={{ span: 6 }} wrapperCol={{ span: 16 }}>
<Form.Item label='添加目录' labelCol={{ span: 4 }} wrapperCol={{ span: 16 }}>
<Button icon={<PlusOutlined />} onClick={addDirectoryTitle} />
</Form.Item>
{addOrEditDirectoryList.map((item: categoryDec) => (
<Row key={item.id} gutter={{ xs: 8, sm: 16, md: 24 }}>
<Col span={16}>
<Form.Item
label='目录名称'
name={item.id}
rules={[{ required: true, message: '请输入目录名称' }]}
>
<Input placeholder='请输入目录名称' maxLength={30} />
</Form.Item>
</Col>
<Col>
{item.defaultType ? (
<Button
icon={<MinusOutlined />}
type='primary'
onClick={() => deleteDirectory(item.id)}
/>
) : (
''
)}
</Col>
</Row>
))}
</Form>
</Modal>
);
};
export default AddOrEditDec;
import {
Modal,
Form,
Input,
Button,
Row,
Col,
message,
Select,
RadioChangeEvent,
Radio,
Space,
} from 'antd';
import React, { useEffect, useState } from 'react';
import { PropsType } from '~/common/interface/modal';
import { categoryDec } from '~/api/modules/goods';
import { CategoryManageAPI } from '~/api';
const typeOptions = [
{
value: 0,
label: '通用分类',
},
{
value: 1,
label: '作业服务分类',
},
{
value: 2,
label: '设备分类',
},
{
value: 3,
label: '飞手分类',
},
{
value: 4,
label: '商城分类',
},
];
interface selfPropsType {
isModalVisible: boolean;
handleOk?: () => void;
handleCancel?: () => void;
editData?: categoryDec; //编辑数据
}
const AddOrEditDec: React.FC<PropsType & selfPropsType> = ({
isModalVisible,
handleOk,
handleCancel,
editData,
}) => {
const [form] = Form.useForm<any>();
const [hasPid, setHasPid] = useState(false); //是否有上级目录
const [submitLoading, setSubmitLoading] = useState(false); //提交按钮的loading
const [directoryOptions, setDirectoryOptions] = useState([]); //目录options
const id = editData?.id;
useEffect(() => {
if (isModalVisible) {
form.setFieldValue('type', editData.type);
form.setFieldValue('pid', editData.pid);
form.setFieldValue('directoryName', editData.directoryName);
onChangeType(editData.type);
if (editData.pid) {
setHasPid(true);
} else {
setHasPid(false);
}
}
}, [isModalVisible]);
const onChangeType = (value) => {
console.log('value', value);
form.resetFields(['pid']);
CategoryManageAPI.directoryList({ pageNo: 1, pageSize: 999, type: value }).then((res) => {
setDirectoryOptions(res.result?.list || []);
});
};
//提交
const onFinish = async () => {
const values = await form.validateFields();
console.log('values', values);
setSubmitLoading(true);
try {
const res = await CategoryManageAPI.addOrEditDirectory({
...values,
id,
pid: hasPid ? values.pid : null,
});
res.code == '200' && message.success('新增成功');
handleOk();
setTimeout(() => {
form.resetFields();
}, 500);
} catch (e) {}
setSubmitLoading(false);
};
return (
<Modal
title='新增目录'
open={isModalVisible}
onOk={onFinish}
onCancel={() => {
form.resetFields();
handleCancel();
}}
okButtonProps={{ loading: submitLoading }}
>
<Form
form={form}
labelCol={{ span: 6 }}
wrapperCol={{ span: 16 }}
style={{ marginBottom: 40 }}
>
<Form.Item label='分类模块' name='type' rules={[{ required: true }]}>
<Select options={typeOptions} allowClear={true} onChange={onChangeType}></Select>
</Form.Item>
<Form.Item label='目录类型'>
<Radio.Group onChange={(e: RadioChangeEvent) => setHasPid(e.target.value)} value={hasPid}>
<Radio value={false}>无关联目录</Radio>
<Radio value={true}>有关联目录</Radio>
</Radio.Group>
</Form.Item>
{hasPid && (
<Form.Item label='上级目录' name='pid' rules={[{ required: true }]}>
<Select
options={directoryOptions}
fieldNames={{ label: 'directoryName', value: 'id' }}
allowClear={true}
></Select>
</Form.Item>
)}
<Form.Item label='目录名称' name='directoryName' rules={[{ required: true }]}>
<Input placeholder='请输入目录名称' allowClear={true}></Input>
</Form.Item>
</Form>
</Modal>
);
};
export default AddOrEditDec;
import { DeleteOutlined, EditOutlined, PlusOutlined } from '@ant-design/icons';
import { Tag, Space, Button, Table, Pagination, message, Modal } from 'antd';
import { ColumnsType, TablePaginationConfig } from 'antd/es/table';
import type { FilterValue, SorterResult } from 'antd/es/table/interface';
import { FC, useEffect, useState } from 'react';
import { CategoryManageAPI } from '~/api';
import { categoryEntity, categoryDec } from '~/api/interface/categoryManage';
import AddOrEditDec from './components/addOrEditDec';
interface DataType {
title: string;
dataIndex: string;
key: string;
align: string;
}
const typeOptions = [
{
value: 0,
label: '通用分类',
},
{
value: 1,
label: '作业服务分类',
},
{
value: 2,
label: '设备分类',
},
{
value: 3,
label: '飞手分类',
},
{
value: 4,
label: '商城分类',
},
];
const DirectoryManage: FC = (props: any) => {
const [data, setData] = useState<categoryDec[]>(); //table数据
const [loading, setLoading] = useState(false); //table获取数据的loading
const [pagination, setPagination] = useState<TablePaginationConfig>({
current: 1,
pageSize: 10,
total: 0,
showSizeChanger: true,
showQuickJumper: true,
showTotal: (total, range) => `当前 ${range[0]}-${range[1]} 条记录 / 共 ${total} 条数据`,
});
//目录modal
const [isAddOrEditDecModal, setIsAddOrEditDecModal] = useState<boolean>(false);
const [reload, setReload] = useState(false);
const [editData, setEditData] = useState<categoryDec | null>(null);
const columns: ColumnsType<DataType> = [
{
title: '目录名称',
dataIndex: 'directoryName',
key: 'directoryName',
align: 'center',
},
{
title: '分类模块',
dataIndex: 'type',
key: 'type',
align: 'center',
render: (value) => {
let find = typeOptions.find((item) => {
return item.value == value;
});
return <div>{find?.label}</div>;
},
},
{
title: '目录类型',
dataIndex: 'directoryType',
key: 'directoryType',
align: 'center',
},
{
title: '上级目录',
dataIndex: 'relevanceName',
key: 'relevanceName',
align: 'center',
},
{
title: '操作',
key: 'action',
render: (_, record) => (
<Space size='middle'>
<Button
type='link'
icon={<EditOutlined />}
onClick={() => {
console.log('record', record);
setEditData(record);
setIsAddOrEditDecModal(true);
}}
>
编辑
</Button>
<Button type='link' danger icon={<DeleteOutlined />} onClick={() => onDel(record.id)}>
删除
</Button>
</Space>
),
align: 'center',
},
];
// 目录弹窗
const showDecModal = () => {
setEditData(null);
setIsAddOrEditDecModal(true);
};
const addOrEditDecHandleOk = () => {
getDirectoryList();
setIsAddOrEditDecModal(false);
};
const addOrEditDecHandleCancel = () => {
setIsAddOrEditDecModal(false);
};
//获取所有目录列表
const getDirectoryList = () => {
setLoading(true);
CategoryManageAPI.directoryList({
pageNo: pagination!.current!,
pageSize: pagination!.pageSize!,
})
.then((res) => {
setData(
res.result?.list.map((item: categoryDec) => {
if (item.pid) {
item.directoryType = '有关联用户';
} else {
item.directoryType = '无关联用户';
}
return item;
}) || [],
);
setLoading(false);
setPagination({
...pagination,
current: res.result.pageNo,
pageSize: res.result.pageSize,
total: res.result.totalCount,
});
})
.catch((err) => {
setData([]);
setLoading(false);
});
};
// 删除
const onDel = (id: number) => {
Modal.confirm({
title: '目录删除',
content: '确认删除该目录?',
onOk() {
CategoryManageAPI.removeDirectory(id).then((res) => {
if (res.code == 200) {
message.success('删除成功');
setReload(!reload);
} else {
message.error(res.message);
}
});
},
});
};
useEffect(() => {
getDirectoryList();
}, [JSON.stringify(pagination), reload]);
const handleTableChange = (
pagination: TablePaginationConfig,
filters: Record<string, FilterValue>,
sorter: SorterResult<DataType>,
) => {
setPagination(pagination);
// `dataSource` is useless since `pageSize` changed
if (pagination.pageSize !== pagination?.pageSize) {
setData([]);
}
};
return (
<>
<div>
<Button
type='primary'
onClick={() => showDecModal()}
icon={<PlusOutlined />}
style={{
margin: '10px 0 15px 10px',
}}
>
新增目录
</Button>
<Table
rowKey='id'
columns={columns}
dataSource={data}
bordered
onChange={handleTableChange}
pagination={pagination}
loading={loading}
/>
;
</div>
{/* 目录管理 */}
<AddOrEditDec
isModalVisible={isAddOrEditDecModal}
handleOk={addOrEditDecHandleOk}
handleCancel={addOrEditDecHandleCancel}
editData={editData}
/>
</>
);
};
export default DirectoryManage;
......@@ -19,6 +19,12 @@ import {
SettingOutlined,
UserOutlined,
SisternodeOutlined,
SendOutlined,
RocketOutlined,
AppstoreAddOutlined,
AppstoreOutlined,
CoffeeOutlined,
UnorderedListOutlined,
} from '@ant-design/icons';
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
......@@ -85,8 +91,10 @@ const SplitCouponOperate = React.lazy(
const CouponDetailed = React.lazy(() => import('src/pages/couponManage/couponDetailed')); //优惠券明细
// 分类管理
const CategoryList = React.lazy(() => import('src/pages/categoryManage/index'));
// 路由列表类型
const CategoryManage = React.lazy(() => import('~/pages/categoryManage/category'));
const CategoryDetail = React.lazy(() => import('~/pages/categoryManage/category/detail'));
// 目录管理
const DirectoryManage = React.lazy(() => import('~/pages/categoryManage/directoryManage'));
export interface RouteObjectType {
path: AgnosticIndexRouteObject['path'];
element: any;
......@@ -542,33 +550,67 @@ export const routerList: Array<RouteObjectType> = [
},
children: [
{
path: '/categoryManage/categoryList',
element: withLoadingComponent(<CategoryList />),
path: '/categoryManage/jobServicesCategory/1',
element: withLoadingComponent(<CategoryManage />),
meta: {
id: 18100,
title: '分类列表',
icon: <SisternodeOutlined />,
title: '作业服务分类',
icon: <SendOutlined />,
},
},
],
{
path: '/categoryManage/jobServicesCategory/2',
element: withLoadingComponent(<CategoryManage />),
meta: {
id: 18200,
title: '设备租赁分类',
icon: <RocketOutlined />,
},
},
{
path: '/systemManage',
element: <LayoutView />,
errorElement: <ErrorPage />,
path: '/categoryManage/jobServicesCategory/3',
element: withLoadingComponent(<CategoryManage />),
meta: {
id: 28000,
icon: <SettingOutlined />,
title: '系统管理',
id: 18300,
title: '飞手培训分类',
icon: <AppstoreAddOutlined />,
},
},
{
path: '/categoryManage/jobServicesCategory/4',
element: withLoadingComponent(<CategoryManage />),
meta: {
id: 18400,
title: '产品商城分类',
icon: <AppstoreOutlined />,
},
},
{
path: '/categoryManage/jobServicesCategory/0',
element: withLoadingComponent(<CategoryManage />),
meta: {
id: 18500,
title: '通用分类',
icon: <CoffeeOutlined />,
},
},
{
path: '/categoryManage/detail/:id',
element: withLoadingComponent(<CategoryDetail />),
meta: {
id: 18600,
title: '分类详情',
icon: '',
hidden: true,
},
},
children: [
{
path: '/systemManage/accountManage',
element: withLoadingComponent(<AccountManageView />),
path: '/categoryManage/DirectoryManage',
element: withLoadingComponent(<DirectoryManage />),
meta: {
id: 28100,
title: '账号管理',
icon: <UserOutlined />,
id: 18700,
title: '目录管理',
icon: <UnorderedListOutlined />,
},
},
],
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论