提交 a6e6f059 作者: 龚洪江

功能:富文本修改,商品,产品类型,目录字段修改

上级 d5a039ef
......@@ -16,6 +16,8 @@
"dependencies": {
"@ant-design/icons": "^5.0.1",
"@reduxjs/toolkit": "^1.9.2",
"@wangeditor/editor": "^5.1.23",
"@wangeditor/editor-for-react": "^1.0.6",
"antd": "^5.4.2",
"axios": "^1.4.0",
"dayjs": "^1.11.7",
......
......@@ -464,26 +464,26 @@ const AddOrEditSkuModal: React.FC<ModalProps & selfProps> = ({
{currentDesc != 2 ? (
<>
<Form.Item
name='categoryId'
label='产品类型'
rules={[{ required: true, message: '请选择产品类型' }]}
>
<Select
placeholder='请选择产品类型'
onSelect={handleProdTypeSelect}
showSearch
filterOption={(input, option: any) =>
(option?.label ?? '').toLowerCase().includes(input.toLowerCase())
}
>
{categoryList.map((item) => (
<Select.Option value={item.id} key={item.id}>
{item.classifyName}
</Select.Option>
))}
</Select>
</Form.Item>
{/*<Form.Item*/}
{/* name='categoryId'*/}
{/* label='产品类型'*/}
{/* rules={[{ required: true, message: '请选择产品类型' }]}*/}
{/*>*/}
{/* <Select*/}
{/* placeholder='请选择产品类型'*/}
{/* onSelect={handleProdTypeSelect}*/}
{/* showSearch*/}
{/* filterOption={(input, option: any) =>*/}
{/* (option?.label ?? '').toLowerCase().includes(input.toLowerCase())*/}
{/* }*/}
{/* >*/}
{/* {categoryList.map((item) => (*/}
{/* <Select.Option value={item.id} key={item.id}>*/}
{/* {item.classifyName}*/}
{/* </Select.Option>*/}
{/* ))}*/}
{/* </Select>*/}
{/*</Form.Item>*/}
{!isCustomProd ? (
<Form.Item
name='skuId'
......
......@@ -288,7 +288,6 @@ const BaseInfo: React.FC<selfProps> = forwardRef(
placeholder='请选择所属目录'
style={{ width: '400px' }}
onChange={directorySelectChange}
disabled={!!goodsDetail}
>
{directoryList.map((v) => (
<Select.Option value={v.id} key={v.id}>
......
import React, { useEffect } from 'react';
import E from 'wangeditor';
import '@wangeditor/editor/dist/css/style.css'; // 引入 css
import React, { useState, useEffect } from 'react';
import { Editor, Toolbar } from '@wangeditor/editor-for-react';
import { IDomEditor, IEditorConfig, IToolbarConfig, InsertFnType } from '@wangeditor/editor';
import { message } from 'antd';
import { CommonAPI } from '~/api';
let editor: any = null;
interface PropsType {
onChange?: (html?: string) => void;
value: string | undefined;
// eslint-disable-next-line react/require-default-props
isDetail?: boolean;
isDetail?: boolean; //是否禁用
height?: number;
imgSize?: number;
videoSize?: number;
}
const RichText: React.FC<PropsType> = ({ onChange, value, isDetail, height }) => {
RichText.defaultProps = {
// eslint-disable-next-line @typescript-eslint/no-empty-function
onChange: () => {},
};
useEffect(() => {
// 注:class写法需要在componentDidMount 创建编辑器
editor = new E('.edit');
editor.config.uploadImgShowBase64 = false;
editor.config.zIndex = 1;
editor.config.height = height ? height : 550;
editor.config.uploadImgMaxLength = 5;
editor.config.uploadImgMaxSize = 1024 * 1024 * 3; // 2M
editor.config.customUploadImg = async (resultFiles: any, insertImgFn: any) => {
// resultFiles 是 input 中选中的文件列表
// insertImgFn 是获取图片 url 后,插入到编辑器的方法
const RichText: React.FC<PropsType> = ({
onChange,
value,
isDetail,
height,
imgSize,
videoSize,
}) => {
// editor 实例
const [editor, setEditor] = useState<IDomEditor | null>(null);
// 编辑器内容
const [html, setHtml] = useState<string>('');
// 工具栏配置
const toolbarConfig: Partial<IToolbarConfig> = {};
// 编辑器配置
const editorConfig: Partial<IEditorConfig> = {
// TS 语法
placeholder: '请输入内容...',
MENU_CONF: {
uploadImage: {
// 自定义上传
async customUpload(file: File, insertFn: InsertFnType) {
if (file.size / 1024 / 1024 > (imgSize || 5)) {
return message.warning(`上传文件大小最大${imgSize || 5}M`);
}
if (!file.type.includes('image/')) {
return message.warning('文件格式错误');
}
const formData = new FormData();
resultFiles.map(async (item: any) => {
formData.append('uploadFile', item);
formData.append('uploadFile', file);
CommonAPI.uploadOss(formData).then(({ result }) => {
insertFn(result.filePath);
});
const { code, result } = await CommonAPI.uploadOss(formData);
if (code === '200') {
insertImgFn(result.filePath);
message.success('上传成功');
} else {
message.error('上传失败');
},
},
uploadVideo: {
// 自定义上传
async customUpload(file: File, insertFn: InsertFnType) {
if (file.size / 1024 / 1024 > (videoSize || 5)) {
return message.warning(`上传文件大小最大${videoSize || 5}M`);
}
if (!file.type.includes('video/')) {
return message.warning('文件格式错误');
}
const formData = new FormData();
formData.append('uploadFile', file);
CommonAPI.uploadOss(formData).then(({ result }) => {
insertFn(result.filePath);
});
},
},
},
};
editor.config.onchange = (newHtml: string) => {
if (newHtml) {
onChange?.(newHtml);
} else {
onChange?.(undefined);
//富文本修改
const richTextChange = (editor: IDomEditor) => {
setHtml(editor.getHtml());
if (onChange) {
onChange(editor.getHtml() || '');
}
};
// 需要展示的菜单
editor.config.menus = [
'head',
'bold',
'fontSize',
'fontName',
'italic',
'underline',
'strikeThrough',
'indent',
'lineHeight',
'foreColor',
'backColor',
'link',
'list',
'todo',
'justify',
'quote',
'table',
'splitLine',
'undo',
'redo',
'image',
];
/** 一定要创建 */
editor.create();
// events.addListener('clearEdit', () => {
// editor.txt.html('');
// });
// 及时销毁 editor ,重要!
useEffect(() => {
return () => {
// 组件销毁时销毁编辑器 注:class写法需要在componentWillUnmount中调用
if (editor == null) return;
editor.destroy();
setEditor(null);
};
}, [editor]);
// 这里一定要加上下面的这个注释
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
useEffect(() => {
if (editor) {
editor.txt.html(value || '');
}
if (isDetail) {
setHtml(value || '');
}, [value]);
useEffect(() => {
if (editor && isDetail) {
editor.disable();
}
}, [value]);
}, [isDetail]);
return <div className='edit' />;
return (
<>
<div style={{ border: '1px solid #ccc', zIndex: 100 }}>
<Toolbar
editor={editor}
defaultConfig={toolbarConfig}
mode='default'
style={{ borderBottom: '1px solid #ccc' }}
/>
<Editor
defaultConfig={editorConfig}
value={html}
onCreated={setEditor}
onChange={richTextChange}
mode='default'
style={{ height: height || 500 + 'px', overflowY: 'hidden' }}
/>
</div>
</>
);
};
export default RichText;
......@@ -288,6 +288,12 @@ const GoodsList = () => {
/>
<Card tabList={tabList} activeTabKey={activeTabKey} onTabChange={onTabChange}>
<div className='header-operate' style={{ marginBottom: '10px' }}>
<Button type='primary' style={{ marginRight: '10px' }} icon={<ArrowUpOutlined />}>
上移
</Button>
<Button type='primary' style={{ marginRight: '10px' }} icon={<ArrowDownOutlined />}>
下移
</Button>
{activeTabKey !== '2' && (
<Button
type='primary'
......
import React, { FC, useEffect, useState } from 'react';
import React, { FC, useEffect } from 'react';
import { Form, Input, Modal, message, Select, ModalProps } from 'antd';
import { CategoryManageAPI, ProduceManageAPI } from '~/api';
import { ProduceManageAPI } from '~/api';
import { InterDataType, InterReqType } from '~/api/interface';
import { categoryListType, directoryListType } from '~/api/interface/categoryManage';
import { MakeListType } from '~/api/interface/makeManage';
import { addProductType } from '~/api/interface/produceManageType';
import { filterObjAttr } from '~/utils';
//目录返回类型
type directoryType = InterDataType<directoryListType>;
//分类返回类型
type categoryType = InterDataType<categoryListType>['list'];
//品牌返回类型
type makeListType = InterDataType<MakeListType>['list'];
//表单类型
......@@ -19,23 +14,19 @@ type addMakeParameterType = InterReqType<addProductType>;
interface PropsType {
closed: () => void;
data: (addMakeParameterType & { id: number; categoriesId: number }) | undefined;
decList: directoryType;
makeList: makeListType;
onOk: () => void;
}
const { Option } = Select;
const AddOrEditProduceModal: FC<ModalProps & PropsType> = ({
open,
closed,
data,
decList,
makeList,
onOk,
}) => {
// 产品类型下拉列表
const [productTypeSelectList, setProductTypeSelectList] = useState<categoryType>([]);
// const [productTypeSelectList, setProductTypeSelectList] = useState<categoryType>([]);
// 表格事件
const [form] = Form.useForm<addMakeParameterType>();
// 关闭弹窗
......@@ -64,22 +55,17 @@ const AddOrEditProduceModal: FC<ModalProps & PropsType> = ({
});
};
//根据目录获取分类
const getCategoryListByDirectory = (directoryId: number) => {
CategoryManageAPI.getCategoryList({ pageNo: 1, pageSize: 99999, directoryId, type: 4 }).then(
({ result }) => {
setProductTypeSelectList(result.list || []);
},
);
};
// 目录修改
const decSelectChange = (value: number) => {
form.setFieldValue('categoryId', undefined);
getCategoryListByDirectory(value);
};
// const getCategoryListByDirectory = (directoryId: number) => {
// CategoryManageAPI.getCategoryList({ pageNo: 1, pageSize: 99999, directoryId, type: 4 }).then(
// ({ result }) => {
// setProductTypeSelectList(result.list || []);
// },
// );
// };
// componentsDidMounted
useEffect(() => {
if (data) {
getCategoryListByDirectory(data.directoryId);
// getCategoryListByDirectory(data.directoryId);
form.setFieldsValue({
...data,
});
......@@ -108,39 +94,43 @@ const AddOrEditProduceModal: FC<ModalProps & PropsType> = ({
>
<Input placeholder='请输入产品名称' allowClear maxLength={30} />
</Form.Item>
<Form.Item
label='产品目录'
name='directoryId'
rules={[{ required: true, message: '请选择产品目录' }]}
>
<Select placeholder='请选择产品目录' onChange={decSelectChange}>
{decList.map((v: any, index: number) => (
<Select.Option value={v.id} key={index}>
{v.directoryName}
</Select.Option>
))}
</Select>
</Form.Item>
<Form.Item
name='categoryId'
label='产品类型'
rules={[{ required: true, message: '请选择产品类型' }]}
>
<Select
placeholder='请选择产品类型'
allowClear
showSearch
filterOption={(input, option) =>
(option!.children as unknown as string).toLowerCase().includes(input.toLowerCase())
}
>
{productTypeSelectList.map((i, j) => (
<Option value={i.id} key={j}>
{i.classifyName}
</Option>
))}
</Select>
<Form.Item label='归属商品'>
<Select.Option value={1}>商城商品</Select.Option>
<Select.Option value={2}>租赁商品</Select.Option>
</Form.Item>
{/*<Form.Item*/}
{/* label='产品目录'*/}
{/* name='directoryId'*/}
{/* rules={[{ required: true, message: '请选择产品目录' }]}*/}
{/*>*/}
{/* <Select placeholder='请选择产品目录' onChange={decSelectChange}>*/}
{/* {decList.map((v: any, index: number) => (*/}
{/* <Select.Option value={v.id} key={index}>*/}
{/* {v.directoryName}*/}
{/* </Select.Option>*/}
{/* ))}*/}
{/* </Select>*/}
{/*</Form.Item>*/}
{/*<Form.Item*/}
{/* name='categoryId'*/}
{/* label='产品类型'*/}
{/* rules={[{ required: true, message: '请选择产品类型' }]}*/}
{/*>*/}
{/* <Select*/}
{/* placeholder='请选择产品类型'*/}
{/* allowClear*/}
{/* showSearch*/}
{/* filterOption={(input, option) =>*/}
{/* (option!.children as unknown as string).toLowerCase().includes(input.toLowerCase())*/}
{/* }*/}
{/* >*/}
{/* {productTypeSelectList.map((i, j) => (*/}
{/* <Option value={i.id} key={j}>*/}
{/* {i.classifyName}*/}
{/* </Option>*/}
{/* ))}*/}
{/* </Select>*/}
{/*</Form.Item>*/}
<Form.Item
name='model'
label='产品型号'
......
......@@ -3,11 +3,11 @@ import './index.scss';
import { Button, Form, Input, message, Modal, Select, Table } from 'antd';
import { useNavigate } from 'react-router-dom';
import { ColumnsType } from 'antd/es/table';
import { CategoryManageAPI, MakeManageAPI, ProduceManageAPI } from '~/api';
import { MakeManageAPI, ProduceManageAPI } from '~/api';
import AddOrEditProduce from './components/addOrEditProduceModal';
import { InterDataType, InterReqType, PaginationProps } from '~/api/interface';
import { addProductType, productListType } from '~/api/interface/produceManageType';
import { categoryListType, directoryListType } from '~/api/interface/categoryManage';
import { categoryListType } from '~/api/interface/categoryManage';
import { MakeListType } from '~/api/interface/makeManage';
import { PlusOutlined } from '@ant-design/icons';
......@@ -17,8 +17,6 @@ type produceListType = InterDataType<productListType>['list'];
type produceParametersType = Omit<InterReqType<productListType>, 'pageSize' | 'pageNo'>;
//分类返回类型
type categoryType = InterDataType<categoryListType>['list'];
//目录返回类型
type directoryType = InterDataType<directoryListType>;
//品牌返回类型
type makeListType = InterDataType<MakeListType>['list'];
//新增编辑表单类型
......@@ -46,8 +44,6 @@ function ProduceManage() {
>();
// 品牌列表
const [makeList, setMakeList] = useState<makeListType>([]);
// 目录列表
const [decList, setDecList] = useState<directoryType>([]);
// 表格结构
const columns: ColumnsType<produceListType[0]> = [
{
......@@ -57,7 +53,7 @@ function ProduceManage() {
fixed: 'left',
},
{
title: '产品目录',
title: '归属产品',
dataIndex: 'directoryName',
align: 'center',
},
......@@ -188,30 +184,9 @@ function ProduceManage() {
setMakeList(result.list || []);
});
};
// 目录列表
const getDirectoryList = () => {
ProduceManageAPI.getProductDirectoryList().then(({ result }) => {
setDecList(result || []);
});
};
//根据目录获取分类
const getCategoryListByDirectory = (directoryId: number) => {
CategoryManageAPI.getCategoryList({ pageNo: 1, pageSize: 99999, directoryId, type: 4 }).then(
({ result }) => {
setProductTypeSelectList(result.list || []);
},
);
};
// 目录修改
const decSelectChange = (value: number) => {
if (value) {
getCategoryListByDirectory(value);
}
};
// componentDidMount
useEffect(() => {
getProduceList(query);
getDirectoryList();
}, []);
return (
......@@ -226,15 +201,6 @@ function ProduceManage() {
<Form.Item name='productName' label='产品名称'>
<Input placeholder='请输入产品名称' allowClear />
</Form.Item>
<Form.Item name='directoryId' label='产品目录'>
<Select placeholder='请选择产品目录' onChange={decSelectChange} allowClear>
{decList.map((v, index: number) => (
<Select.Option value={v.id} key={index}>
{v.directoryName}
</Select.Option>
))}
</Select>
</Form.Item>
<Form.Item name='goodsTypeId' label='产品类型'>
<Select placeholder='请选择产品类型' allowClear>
{productTypeSelectList.map((i, j) => (
......@@ -274,7 +240,6 @@ function ProduceManage() {
closed={handleAddEditClosed}
data={addEditData}
makeList={makeList}
decList={decList}
onOk={addOrEditProduceOk}
/>
</div>
......
......@@ -285,6 +285,12 @@ const RentList = () => {
/>
<Card tabList={tabList} activeTabKey={activeTabKey} onTabChange={onTabChange}>
<div className='header-operate' style={{ marginBottom: '10px' }}>
<Button type='primary' style={{ marginRight: '10px' }} icon={<ArrowUpOutlined />}>
上移
</Button>
<Button type='primary' style={{ marginRight: '10px' }} icon={<ArrowDownOutlined />}>
下移
</Button>
{activeTabKey !== '2' && (
<Button
type='primary'
......
......@@ -367,6 +367,12 @@ const ServiceList: FC<any> = () => {
/>
<Card tabList={tabList} activeTabKey={activeTabKey} onTabChange={onTabChange}>
<div className='header-operate' style={{ marginBottom: '10px' }}>
<Button type='primary' style={{ marginRight: '10px' }} icon={<ArrowUpOutlined />}>
上移
</Button>
<Button type='primary' style={{ marginRight: '10px' }} icon={<ArrowDownOutlined />}>
下移
</Button>
{activeTabKey !== '2' ? (
<Button
type='primary'
......
......@@ -88,7 +88,7 @@ video {
padding: 0;
border: 0;
font-size: 100%;
font: inherit;
//font: inherit;
vertical-align: baseline;
}
/* HTML5 display-role reset for older browsers */
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论