提交 4ba9c70d 作者: ZhangLingKun

功能:上架服务

上级 ef1f3cf4
...@@ -217,3 +217,92 @@ export type inspectionUpdateType = InterFunction< ...@@ -217,3 +217,92 @@ export type inspectionUpdateType = InterFunction<
export type industryRemoveType = InterFunction<{ id: number }, NonNullable<unknown>>; export type industryRemoveType = InterFunction<{ id: number }, NonNullable<unknown>>;
// 删除服务 // 删除服务
export type inspectionRemoveType = InterFunction<{ id: number }, NonNullable<unknown>>; export type inspectionRemoveType = InterFunction<{ id: number }, NonNullable<unknown>>;
// 根据服务id查询标签列表
export type listByInspectionIdType = InterFunction<
{ id: number },
{
id: number;
inspectionId: number;
tagName: string;
}[]
>;
// 新增服务标签
export type inspectionTagInsertType = InterFunction<
{
id?: number;
inspectionId?: number;
tagName?: string;
},
NonNullable<unknown>
>;
// 修改服务标签
export type inspectionTagUpdateType = InterFunction<
{
id?: number;
inspectionId?: number;
tagName?: string;
},
NonNullable<unknown>
>;
// 删除服务标签
export type inspectionTagDeleteType = InterFunction<
{
id: number;
},
NonNullable<unknown>
>;
// 服务详情
export type inspectionDetailType = InterFunction<
{
id: number;
},
{
caseImg: string;
caseVideo: string;
companyInspectionDTOS: Array<{
companyInfoId: number;
companyName: string;
detailPage: string;
id: number;
industryTypeDTO: {
createTime: string;
description: string;
id: number;
inspectionDTOS: null;
saleState: number;
typeImg: string;
typeName: string;
};
inspectionDTO: null;
inspectionFileDTOS: Array<{
companyInspectionId: number;
fileType: number;
fileUrl: string;
first: number;
id: number;
}>;
inspectionFirstImg: string;
inspectionId: number;
inspectionPriceUnitId: number;
inspectionTagDTO: {
id: number;
inspectionId: number;
tagName: string;
};
inspectionTagId: number;
price: number;
priceRemark: string;
remark: string;
saleState: number;
serviceArea: string;
}>;
createTime: string;
id: number;
industryTypeId: number;
inspectionDescription: string;
inspectionImg: string;
inspectionName: string;
inspectionNo: string;
saleState: number;
}
>;
...@@ -174,3 +174,196 @@ export type serviceDetailType = InterFunction< ...@@ -174,3 +174,196 @@ export type serviceDetailType = InterFunction<
>; >;
//服务-上下移动 //服务-上下移动
export type exChangeServiceType = InterFunction<{ id: number; sort: number }[], any>; export type exChangeServiceType = InterFunction<{ id: number; sort: number }[], any>;
// pc-单位服务列表
export type listCompanyInspectionPageType = InterListFunction<
{
companyInfoId?: number;
industryTypeId?: number;
inspectionId?: number;
keyword?: string;
},
{
companyInfoId: number;
companyName: string;
detailPage: string;
id: number;
industryTypeDTO: {
createTime: string;
description: string;
id: number;
inspectionDTOS: Array<{
caseImg: string;
caseVideo: string;
companyInspectionDTOS: null;
id: number;
industryTypeId: number;
inspectionDescription: string;
inspectionImg: string;
inspectionName: string;
inspectionNo: string;
saleState: number;
}>;
saleState: number;
typeImg: string;
typeName: string;
};
inspectionDTO: {
caseImg: string;
caseVideo: string;
companyInspectionDTOS: null;
id: number;
industryTypeId: number;
inspectionDescription: string;
inspectionImg: string;
inspectionName: string;
inspectionNo: string;
saleState: number;
};
inspectionFileDTOS: Array<{
companyInspectionId: number;
fileType: number;
fileUrl: string;
first: number;
id: number;
}>;
inspectionFirstImg: string;
inspectionId: number;
inspectionPriceUnitId: number;
inspectionTagDTO: {
id: number;
inspectionId: number;
tagName: string;
};
inspectionTagId: number;
price: number;
priceRemark: string;
remark: string;
saleState: number;
serviceArea: string;
}
>;
// 新增服务
export type companyInspectionInsertType = InterFunction<
{
companyInfoId?: number;
companyInspectionFiles?: Array<{
companyInspectionId?: number;
fileType?: number;
fileUrl?: string;
first?: number;
id?: number;
}>;
detailPage?: string;
id?: number;
inspectionId?: number;
inspectionPriceUnitId?: number;
inspectionTagId?: number;
price?: number;
priceRemark?: string;
remark?: string;
saleState?: number;
serviceArea?: string;
},
NonNullable<unknown>
>;
// 修改服务
export type companyInspectionUpdateType = InterFunction<
{
companyInfoId?: number;
companyInspectionFiles?: Array<{
companyInspectionId?: number;
fileType?: number;
fileUrl?: string;
first?: number;
id?: number;
}>;
detailPage?: string;
id?: number;
inspectionId?: number;
inspectionPriceUnitId?: number;
inspectionTagId?: number;
price?: number;
priceRemark?: string;
remark?: string;
saleState?: number;
serviceArea?: string;
},
NonNullable<unknown>
>;
// 单位服务详情
export type getCompanyInspectionByIdType = InterFunction<
{
id: number;
},
{
companyInfoId: number;
companyName: string;
detailPage: string;
id: number;
industryTypeDTO: {
createTime: string;
description: string;
id: number;
inspectionDTOS: Array<{
caseImg: string;
caseVideo: string;
companyInspectionDTOS: null;
createTime: string;
id: number;
industryTypeId: number;
inspectionDescription: string;
inspectionImg: string;
inspectionName: string;
inspectionNo: string;
saleState: number;
}>;
saleState: number;
typeImg: string;
typeName: string;
};
inspectionDTO: {
caseImg: string;
caseVideo: string;
companyInspectionDTOS: null;
createTime: string;
id: number;
industryTypeId: number;
inspectionDescription: string;
inspectionImg: string;
inspectionName: string;
inspectionNo: string;
saleState: number;
};
inspectionFileDTOS: Array<{
companyInspectionId: number;
fileType: number;
fileUrl: string;
first: number;
id: number;
}>;
inspectionFirstImg: string;
inspectionId: number;
inspectionPriceUnitId: number;
inspectionTagDTO: {
id: number;
inspectionId: number;
tagName: string;
};
inspectionTagId: number;
price: number;
priceRemark: string;
remark: string;
saleState: number;
serviceArea: string;
}
>;
// 价格单位列表
export type listInspectionPriceUnitType = InterFunction<
NonNullable<unknown>,
{
id: number;
unitName: string;
}[]
>;
// 删除单位服务
export type companyInspectionRemoveType = InterFunction<{ id: number }, NonNullable<unknown>>;
...@@ -15,9 +15,14 @@ import { ...@@ -15,9 +15,14 @@ import {
industryListPagesType, industryListPagesType,
industryRemoveType, industryRemoveType,
industryUpdateType, industryUpdateType,
inspectionDetailType,
inspectionInsertType, inspectionInsertType,
inspectionRemoveType, inspectionRemoveType,
inspectionTagDeleteType,
inspectionTagInsertType,
inspectionTagUpdateType,
inspectionUpdateType, inspectionUpdateType,
listByInspectionIdType,
updatePrimaryCategoryType, updatePrimaryCategoryType,
updateSubCategoryType, updateSubCategoryType,
} from '~/api/interface/categoryManage'; } from '~/api/interface/categoryManage';
...@@ -157,4 +162,19 @@ export class CategoryManageAPI { ...@@ -157,4 +162,19 @@ export class CategoryManageAPI {
// 删除服务 // 删除服务
static inspectionRemove: inspectionRemoveType = (params) => static inspectionRemove: inspectionRemoveType = (params) =>
axios.get('/pms/inspection/remove', { params }); axios.get('/pms/inspection/remove', { params });
// 根据服务id查询标签列表
static listByInspectionId: listByInspectionIdType = (params) =>
axios.get('/pms/inspection-tag/listByInspectionId', { params });
// 新增服务标签
static inspectionTagInsert: inspectionTagInsertType = (params) =>
axios.post('/pms/inspection-tag/insert', params);
// 修改服务标签
static inspectionTagUpdate: inspectionTagUpdateType = (params) =>
axios.post('/pms/inspection-tag/update', params);
// 删除服务标签
static inspectionTagDelete: inspectionTagDeleteType = (params) =>
axios.get('/pms/inspection-tag/delete', { params });
// 服务详情
static inspectionDetail: inspectionDetailType = (params) =>
axios.get('/pms/inspection/detail', { params });
} }
...@@ -13,6 +13,12 @@ import { ...@@ -13,6 +13,12 @@ import {
deleteServiceType, deleteServiceType,
serviceDetailType, serviceDetailType,
exChangeServiceType, exChangeServiceType,
listCompanyInspectionPageType,
companyInspectionInsertType,
companyInspectionUpdateType,
getCompanyInspectionByIdType,
listInspectionPriceUnitType,
companyInspectionRemoveType,
} from '~/api/interface/mallManageType'; } from '~/api/interface/mallManageType';
export class MallManageAPI { export class MallManageAPI {
...@@ -56,4 +62,22 @@ export class MallManageAPI { ...@@ -56,4 +62,22 @@ export class MallManageAPI {
// 服务-上下移 // 服务-上下移
static exChangeService: exChangeServiceType = (data) => static exChangeService: exChangeServiceType = (data) =>
axios.post('/pms/backstage/work/exchange', data); axios.post('/pms/backstage/work/exchange', data);
// pc-单位服务列表
static listCompanyInspectionPage: listCompanyInspectionPageType = (data) =>
axios.post('/pms/company-inspection/listCompanyInspectionPage', data);
// 新增服务
static companyInspectionInsert: companyInspectionInsertType = (data) =>
axios.post('/pms/company-inspection/insert', data);
// 修改服务
static companyInspectionUpdate: companyInspectionUpdateType = (data) =>
axios.post('/pms/company-inspection/update', data);
// 单位服务详情
static getCompanyInspectionById: getCompanyInspectionByIdType = (params) =>
axios.get('/pms/company-inspection/getCompanyInspectionById', { params });
// 价格单位列表
static listInspectionPriceUnit: listInspectionPriceUnitType = (params) =>
axios.get('/pms/company-inspection/listInspectionPriceUnit', { params });
// 删除单位服务
static companyInspectionRemove: companyInspectionRemoveType = (params) =>
axios.get('/pms/company-inspection/remove', { params });
} }
import React, { useState } from 'react'; import { useState } from 'react';
import { Header } from 'antd/es/layout/layout'; import { Header } from 'antd/es/layout/layout';
import { DownOutlined, UpOutlined } from '@ant-design/icons'; import { DownOutlined, UpOutlined } from '@ant-design/icons';
import { Button, Dropdown, Image, MenuProps, Modal } from 'antd'; import { Button, Dropdown, Image, MenuProps, Modal } from 'antd';
......
...@@ -19,6 +19,7 @@ export interface searchColumns { ...@@ -19,6 +19,7 @@ export interface searchColumns {
name?: string; name?: string;
value?: string | number | boolean | null; value?: string | number | boolean | null;
label?: string; label?: string;
children?: any;
}[]; }[];
onSelect?: (value: any) => void; onSelect?: (value: any) => void;
disable?: boolean; disable?: boolean;
......
.video-preview {
position: fixed;
top: 0;
left: 0;
width: 100vw;
height: 100vh;
z-index: 100;
display: flex;
justify-content: center;
align-items: center;
.preview-mask{
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(0,0,0,0.35);
}
.button{
position: absolute;
top: 0;
right: 0;
width: 40px;
height: 40px;
background: rgba(0,0,0,0.35);
border-radius: 50%;
display: flex;
justify-content: center;
align-items: center;
color: #fff;
font-size: 20px;
cursor: pointer;
}
.video{
height: 80%;
z-index: 200;
}
}
import React from 'react'; import React from 'react';
import { Image } from 'antd'; import { Image } from 'antd';
import './index.scss';
// 参数类型 // 参数类型
interface propsType { interface propsType {
...@@ -31,7 +32,14 @@ const Video: React.FC<propsType> = (props) => { ...@@ -31,7 +32,14 @@ const Video: React.FC<propsType> = (props) => {
setIsPreview(true); setIsPreview(true);
}} }}
/> />
{isPreview && <div className='video-preview'>12312</div>} {isPreview && (
<div className='video-preview'>
<view className='preview-mask' onClick={() => setIsPreview(false)}></view>
{/*<Button className='button' shape='circle' icon={<CloseOutlined />} />*/}
{/* eslint-disable-next-line jsx-a11y/media-has-caption */}
<video className='video' src={props?.src} autoPlay controls></video>
</div>
)}
</> </>
); );
}; };
......
import React, { useEffect } from 'react';
import { Form, Input, message, Modal, ModalProps } from 'antd';
import { InterItemType, InterReqType } from '~/api/interface';
import { listByInspectionIdType, industryUpdateType } from '~/api/interface/categoryManage';
import { CategoryManageAPI } from '~/api';
// 表格类型
type TableType = InterItemType<listByInspectionIdType>;
// 表单参数
type ReqType = InterReqType<industryUpdateType>;
// 参数类型
interface selfProps {
id: number;
data?: TableType[0];
onCancel: () => void;
}
const AddEditTagModalView: React.FC<ModalProps & selfProps> = ({
id,
open,
title,
onCancel,
data,
}) => {
// 表格数据类型
const [form] = Form.useForm<ReqType>();
// 关闭事件
const handleCancel = () => {
form.resetFields();
onCancel();
};
// 确定事件
const handleOk = () => {
form
.validateFields()
.then(async (values) => {
await handleSubmit(values);
})
.catch((err) => {
message
.warning({
content: err.errorFields[0].errors[0],
})
.then();
});
};
// 提交数据
const handleSubmit = async (values: ReqType) => {
const res = await CategoryManageAPI[data?.id ? 'inspectionTagUpdate' : 'inspectionTagInsert']({
...values,
inspectionId: id,
id: data?.id || undefined,
});
if (res && res.code === '200') {
handleCancel();
}
};
// componentDidMount
useEffect(() => {
if (!open) return;
if (!data) return;
form.setFieldsValue(data);
// console.log('data --->', data);
}, [open]);
return (
<Modal title={title} open={open} onCancel={handleCancel} onOk={handleOk} destroyOnClose>
<Form form={form} labelAlign='right' labelCol={{ span: 4 }} wrapperCol={{ span: 10 }}>
<Form.Item
label='标签名称'
name='tagName'
rules={[{ required: true, message: '请输入标签名称' }]}
>
<Input placeholder='请输入标签名称' maxLength={15} allowClear />
</Form.Item>
</Form>
</Modal>
);
};
export default AddEditTagModalView;
import { FC } from 'react';
import { Form, Input, Modal, ModalProps } from 'antd';
interface selfProps {
onCancel: () => void;
onOk: () => void;
}
const AddOrEditModal: FC<ModalProps & selfProps> = ({ open, onCancel, onOk }) => {
const handleCancel = () => {
onCancel();
};
const handleOk = () => {
onOk();
};
return (
<Modal title='新增分类' open={open} onCancel={handleCancel} onOk={handleOk}>
<Form>
<Form.Item label='分类名称'>
<Input placeholder='请输入分类名称' />
</Form.Item>
<Form.Item label='分类图标'></Form.Item>
<Form.Item label='分类描述'></Form.Item>
</Form>
</Modal>
);
};
export default AddOrEditModal;
import React, { useEffect, useState } from 'react';
import { useLocation, useNavigate } from 'react-router-dom';
import { Button, Descriptions, Image, message, Modal, Table } from 'antd';
import { ArrowLeftOutlined, PlusOutlined } from '@ant-design/icons';
import SearchBox from '~/components/search-box';
import qs from 'query-string';
import { inspectionDetailType, listByInspectionIdType } from '~/api/interface/categoryManage';
import { InterDataType, InterItemType } from '~/api/interface';
import { CategoryManageAPI } from '~/api';
import { ColumnsType } from 'antd/es/table';
import AddEditTagModalView from '~/pages/categoryManage/serviceCategoryList/comp/addEditTagModal';
import Video from '~/components/video';
// 表格类型
type TableType = InterItemType<listByInspectionIdType>;
const ServiceCategoryDetail: React.FC = () => {
// 路由钩子
const location = useLocation();
// 导航钩子
const navigate = useNavigate();
// 返回上一页
const handleBack = () => {
navigate(-1);
};
// 新增编辑标签是否显示
const [addEditVisible, setAddEditVisible] = useState(false);
// 编辑的数据
const [recordData, setRecordData] = useState<TableType[0]>();
// 表格数据
const [tableData, setTableData] = useState<TableType>([]);
// 加载列表
const getTableList = async () => {
// 只需要修改这个地方的接口即可
const res = await CategoryManageAPI.listByInspectionId({
id: Number(qs.parse(location.search).id),
});
if (res && res.code === '200') {
const { result } = res; // 解构
setTableData(result || []);
}
};
// 删除数据
const handleDelete = (record: TableType[0]) => {
Modal.confirm({
title: '提示',
content: '是否删除该场景标签?',
onOk: async () => {
const res = await CategoryManageAPI.inspectionTagDelete({
id: record.id,
});
if (res && res.code === '200') {
message.success('删除成功');
await getTableList();
}
},
});
};
// 服务详情
const [inspectionDetail, setInspectionDetail] = useState<InterDataType<inspectionDetailType>>();
// 获取服务详情
const getInspectionDetail = async () => {
const res = await CategoryManageAPI.inspectionDetail({
id: Number(qs.parse(location.search).id),
});
if (res && res.code === '200') {
setInspectionDetail(res.result);
}
};
// 组件挂载
useEffect(() => {
getInspectionDetail().then();
getTableList().then();
}, []);
// 表格结构
const columns: ColumnsType<TableType[0]> = [
{
title: '序号',
dataIndex: 'tagName',
align: 'center',
render: (_text, _record, index) => `${index + 1}`,
},
{
title: '场景标签',
dataIndex: 'tagName',
align: 'center',
},
{
title: '操作',
dataIndex: 'id',
align: 'center',
width: 200,
render: (_text, record) => (
<>
<Button
type='link'
size='small'
onClick={() => {
setRecordData(record);
setAddEditVisible(true);
}}
>
编辑
</Button>
<Button type='link' size='small' onClick={() => handleDelete(record)} danger>
删除
</Button>
</>
),
},
];
return (
<>
<SearchBox
child={
<Button type={'primary'} icon={<ArrowLeftOutlined />} onClick={() => handleBack()}>
返回
</Button>
}
/>
<Descriptions
title='子分类详情'
bordered
style={{ marginBottom: '20px', width: '60%' }}
column={2}
labelStyle={{ width: '15%' }}
contentStyle={{ width: '30%' }}
>
<Descriptions.Item label='分类名称'>{inspectionDetail?.inspectionName}</Descriptions.Item>
<Descriptions.Item label='分类图标'>
<Image src={inspectionDetail?.inspectionImg} width={40} height={40} />
</Descriptions.Item>
<Descriptions.Item label='分类描述'>
{inspectionDetail?.inspectionDescription}
</Descriptions.Item>
<Descriptions.Item label='服务编号'>{inspectionDetail?.inspectionNo}</Descriptions.Item>
<Descriptions.Item label='业务案例图片'>
<Image src={inspectionDetail?.caseImg} width={40} height={40} />
</Descriptions.Item>
<Descriptions.Item label='业务案例视频'>
{inspectionDetail?.caseVideo && (
<Video src={inspectionDetail?.caseVideo} width={40} height={40} />
)}
</Descriptions.Item>
</Descriptions>
<SearchBox
sufFixBtn={
<Button
type={'primary'}
icon={<PlusOutlined />}
onClick={() => {
setRecordData(undefined);
setAddEditVisible(true);
}}
>
新增场景标签
</Button>
}
/>
<Table
style={{ width: '60%' }}
size='small'
dataSource={tableData}
columns={columns}
rowKey='id'
// scroll={{ x: 1500 }}
bordered
pagination={{
showTotal: (total, range) => `当前 ${range[0]}-${range[1]} 条记录 / 共 ${total} 条数据`,
}}
/>
<AddEditTagModalView
title={recordData ? '编辑场景标签' : '新增场景标签'}
open={addEditVisible}
data={recordData}
id={Number(qs.parse(location.search).id)}
onCancel={() => {
setAddEditVisible(false);
setRecordData(undefined);
getTableList().then();
}}
/>
</>
);
};
export default ServiceCategoryDetail;
...@@ -9,11 +9,15 @@ import { CategoryManageAPI } from '~/api'; ...@@ -9,11 +9,15 @@ import { CategoryManageAPI } from '~/api';
import Video from '~/components/video'; import Video from '~/components/video';
import AddEditModalView from '~/pages/categoryManage/serviceCategoryList/comp/addEditModal'; import AddEditModalView from '~/pages/categoryManage/serviceCategoryList/comp/addEditModal';
import AddEditChildrenView from '~/pages/categoryManage/serviceCategoryList/comp/addEditChildren'; import AddEditChildrenView from '~/pages/categoryManage/serviceCategoryList/comp/addEditChildren';
import { useNavigate } from 'react-router-dom';
import qs from 'query-string';
// 列表的类型 // 列表的类型
type TableType = InterListType<industryListPagesType>; type TableType = InterListType<industryListPagesType>;
function ServiceCategoryList() { function ServiceCategoryList() {
// 路由钩子
const navigate = useNavigate();
// 新增编辑弹窗是否显示 // 新增编辑弹窗是否显示
const [addEditVisible, setAddEditVisible] = useState(false); const [addEditVisible, setAddEditVisible] = useState(false);
// 新增编辑子分类弹窗是否显示 // 新增编辑子分类弹窗是否显示
...@@ -82,6 +86,13 @@ function ServiceCategoryList() { ...@@ -82,6 +86,13 @@ function ServiceCategoryList() {
}, },
}); });
}; };
// 跳转详情
const handleNavigation = (record: TableType[0]) => {
const search = {
id: record.id,
};
navigate(`/categoryManage/mallCategoryList/detail?${qs.stringify(search)}`);
};
// 表格列 // 表格列
const columns: ColumnsType<TableType[0]> = [ const columns: ColumnsType<TableType[0]> = [
{ {
...@@ -147,7 +158,7 @@ function ServiceCategoryList() { ...@@ -147,7 +158,7 @@ function ServiceCategoryList() {
<Button <Button
type='link' type='link'
onClick={() => { onClick={() => {
console.log('click --->', record); handleNavigation(record);
}} }}
> >
详情 详情
......
import { Button, Table } from 'antd';
import { ArrowDownOutlined, ArrowUpOutlined, PlusOutlined } from '@ant-design/icons';
import { ColumnsType } from 'antd/es/table';
import AddOrEditModal from './components/addOrEditModal';
import { useState } from 'react';
const ServiceCategoryList = () => {
const tableColumns: ColumnsType<any> = [
{
title: '分类名称',
align: 'center',
},
{
title: '图片',
align: 'center',
},
{
title: '描述',
align: 'center',
},
{
title: '业务案例图片',
align: 'center',
},
{
title: '业务案例视频',
align: 'center',
},
{
title: '创建时间',
align: 'center',
},
{
title: '操作',
align: 'center',
render: () => (
<>
<Button type='link'>新增子分类</Button>
<Button type='link'>编辑</Button>
<Button type='link'>删除</Button>
</>
),
},
];
// const [tableData, setTableData] = useState<any>([{ id: 1 }]);
const [addOrEditModalShow, setAddOrEditModalShow] = useState<boolean>(false);
//新增分类弹窗
const addOrEditModalClick = () => {
setAddOrEditModalShow(true);
};
const addOrEditModalOk = () => {
setAddOrEditModalShow(false);
};
const addOrEditModalCancel = () => {
setAddOrEditModalShow(false);
};
return (
<div className='service-category-list'>
<div className='list-operate' style={{ marginBottom: '10px' }}>
<Button
type='primary'
icon={<PlusOutlined />}
style={{ marginRight: '10px' }}
onClick={addOrEditModalClick}
>
新增分类
</Button>
<Button icon={<ArrowUpOutlined />} style={{ marginRight: '10px' }} type='primary'></Button>
<Button icon={<ArrowDownOutlined />} type='primary'></Button>
</div>
<Table columns={tableColumns} bordered rowKey='id' />
<AddOrEditModal
open={addOrEditModalShow}
onOk={addOrEditModalOk}
onCancel={addOrEditModalCancel}
/>
</div>
);
};
export default ServiceCategoryList;
import { Button, Form, Image } from 'antd';
import { useNavigate, useSearchParams } from 'react-router-dom';
import './index.scss';
import { MallManageAPI } from '~/api';
import { useEffect, useState } from 'react'; import { useEffect, useState } from 'react';
import { InterDataType } from '~/api/interface'; import { Button, Cascader, Form, Input, message, Modal, Select } from 'antd';
import { serviceDetailType } from '~/api/interface/mallManageType'; import { ArrowLeftOutlined, PlusOutlined, SaveOutlined } from '@ant-design/icons';
import SearchBox from '~/components/search-box';
import { useLocation, useNavigate } from 'react-router-dom';
import { InterDataType, InterListType, InterReqType } from '~/api/interface';
import { getCompanyInspectionByIdType } from '~/api/interface/mallManageType';
import { Uploader } from '~/components/uploader';
import { commonPriceValidator } from '~/utils/validateUtils';
import { CategoryManageAPI, MallManageAPI } from '~/api';
import RichText from '~/components/richText';
import DistrictJson from '~/assets/json/district.json';
import { useSelector } from 'react-redux';
import qs from 'query-string';
import { industryListPagesType } from '~/api/interface/categoryManage';
//服务详情-返回类型 // 表单类型
type detailType = InterDataType<serviceDetailType>; type ReqType = InterReqType<getCompanyInspectionByIdType>;
const ServiceDetail = () => {
const navigate = useNavigate();
const [searchParams] = useSearchParams();
const [serviceDetail, setServiceDetail] = useState<detailType>(); function ServiceDetailView() {
//服务详情 // 路由钩子
const getServiceDetail = (id: number) => { const location = useLocation();
MallManageAPI.getServiceDetail({ id }).then(({ result }) => { // 导航钩子
setServiceDetail(result); const navigate = useNavigate();
// 返回上一页
const handleBack = () => {
navigate(-1);
// Modal.confirm({
// title: '提示',
// content: '请确认是否保存?未保存的数据返回后将丢失',
// okText: '返回',
// cancelText: '取消',
// onOk: () => {
// navigate(-1);
// },
// });
};
// 用户信息
const { userInfo } = useSelector((state: any) => state.UserInfo);
// 表格数据类型
const [form] = Form.useForm<ReqType>();
// 地区列表
const [districtList, setDistrictList] = useState<{ value: string; label: string }[]>();
// 价格单位列表
const [priceUnitList, setPriceUnitList] = useState<{ value: number; label: string }[]>();
// 原始数据
const [industryOriginList, setIndustryOriginList] =
useState<InterListType<industryListPagesType>>();
// 行业应用列表
const [industryList, setIndustryList] = useState<
{ label: string; value: number; children: { label: string; value: number }[] }[]
>([]);
// 获取价格单位列表
const getUnitList = async () => {
const res = await MallManageAPI.listInspectionPriceUnit();
if (res && res.code === '200') {
setPriceUnitList(res.result?.map((i) => ({ label: i.unitName, value: i.id })) || []);
}
};
// 获取地区列表
const getDistrictList = () => {
const list = DistrictJson.map((i) => ({
label: i.name,
value: String(i.id),
}));
setDistrictList(list || []);
};
// 获取行业列表
const getIndustryList = async () => {
const res = await CategoryManageAPI.industryListPages({
pageNo: 1,
pageSize: 9999,
}); });
if (res && res.code === '200') {
const list = res.result?.list || [];
setIndustryList(
list.map((i) => ({
label: i.typeName,
value: i.id,
children: i.inspectionDTOS?.map((j) => {
return {
label: j.inspectionName,
value: j.id,
};
}),
})),
);
setIndustryOriginList(list);
}
}; };
//返回 // 上传图片
const backRoute = () => { const handleUpload = ({
navigate(-1); fileList,
name,
type,
file,
}: {
fileList: { url: string }[];
name: string;
type: number;
file: number;
}) => {
form.setFieldValue(
name,
fileList.map((i) => ({
fileType: file,
fileUrl: i.url,
first: type,
companyInspectionId: location.search ? Number(qs.parse(location.search).id) : undefined,
})),
);
// console.log('上传图片 --->', list);
};
// 获取默认图片列表
const getDefaultFileList = ({ name }: { name: string }) => {
return (
form.getFieldValue(name)?.map((i: { fileUrl: string }) => ({
url: i.fileUrl,
})) || []
);
};
// 所属服务id
const [inspectionId, setInspectionId] = useState<number>();
// 服务标签列表
const [inspectionTagList, setInspectionTagList] = useState<{ label: string; value: number }[]>();
// 获取服务标签列表
const getInspectionTagList = async () => {
const res = await CategoryManageAPI.listByInspectionId({
id: Number(inspectionId),
});
if (res && res.code === '200') {
setInspectionTagList(res.result?.map((i) => ({ label: i.tagName, value: i.id })) || []);
// console.log(res.result);
}
}; };
// 表单提交
const handleValid = () => {
form
.validateFields()
.then((values) => {
Modal.confirm({
title: '提示',
content: '请确认信息是否填写完成?',
onOk: async () => {
await handleSubmit(values);
},
});
})
.catch((err) => {
message
.warning({
content: err.errorFields[0].errors[0],
})
.then();
});
};
// 提交数据
const handleSubmit = async (values: any) => {
const id = Number(qs.parse(location.search).id);
const res = await MallManageAPI[id ? 'companyInspectionUpdate' : 'companyInspectionInsert']({
...values,
companyInspectionFiles: [
...(values.companyInspectionFiles1 || []),
...(values.companyInspectionFiles2 || []),
...(values.companyInspectionFiles3 || []),
],
inspectionId: values.inspectionId.at(-1),
companyInfoId: userInfo.companyInfoVO.id,
saleState: id ? serviceDetail?.saleState : 1,
id: id || undefined,
});
if (res && res.code === '200') {
message.success('操作成功');
handleBack();
}
};
// 服务详情
const [serviceDetail, setServiceDetail] = useState<InterDataType<getCompanyInspectionByIdType>>();
// 当前编辑的服务详情
const getCompanyInspectionById = async ({ id }: { id: number }) => {
const res = await MallManageAPI.getCompanyInspectionById({
id,
});
if (res && res.code === '200') {
setServiceDetail(res.result);
form.setFieldsValue({
...res.result,
companyInspectionFiles1: res.result.inspectionFileDTOS.filter((i) => i.first === 1),
companyInspectionFiles2: res.result.inspectionFileDTOS.filter(
(i) => i.first === 0 && i.fileType === 0,
),
companyInspectionFiles3: res.result.inspectionFileDTOS.filter((i) => i.fileType === 1),
});
}
};
// 获取子分类的父分类id
const getParentId = () => {
if (!location.search) return;
const list = industryOriginList?.map((i) => i.inspectionDTOS).flat() || [];
const item = list.find((i) => i?.id === serviceDetail?.inspectionId);
form.setFieldValue('inspectionId', [item?.industryTypeId, item?.id]);
};
// 组件挂载
useEffect(() => { useEffect(() => {
getServiceDetail(Number(searchParams.get('id'))); getDistrictList();
getUnitList().then();
getIndustryList().then();
if (!location.search) return;
getCompanyInspectionById({ id: Number(qs.parse(location.search)?.id) }).then();
// console.log('用户信息 --->', qs.parse(location.search));
}, []); }, []);
// 监听服务id
useEffect(() => {
if (!inspectionId) return;
getInspectionTagList().then();
}, [inspectionId]);
// 监听行业列表
useEffect(() => {
if (!industryOriginList || industryOriginList.length === 0) return;
getParentId();
}, [industryOriginList]);
return ( return (
<div className='service-detail'> <>
<div className='service-detail-operate'> <SearchBox
<Button type='primary' onClick={backRoute}> preFixBtn={
返回 <div
</Button> style={{
</div> width: '100%',
<div className='service-detail-form'> display: 'flex',
<Form labelCol={{ span: 2 }} wrapperCol={{ span: 16 }}> justifyContent: 'space-between',
<Form.Item label='服务名称'>{serviceDetail?.serviceName}</Form.Item> alignItems: 'center',
<Form.Item label='应用类型'>{serviceDetail?.applicationName}</Form.Item> }}
<Form.Item label='对应行业'>{serviceDetail?.industryName}</Form.Item> >
<Form.Item label='展示状态'> <div style={{ fontSize: '16px', fontWeight: 'bold' }}>新增服务</div>
{serviceDetail?.displayState === 0 ? '上架' : '下架'} <div>
</Form.Item> <Button type={'primary'} icon={<SaveOutlined />} onClick={() => handleValid()}>
<Form.Item label='所属单位'>{serviceDetail?.companyName}</Form.Item> 保存
<Form.Item label='封面图'> </Button>
<Image src={serviceDetail?.coverPlan} width={100} height={100} /> <Button type={'default'} icon={<ArrowLeftOutlined />} onClick={() => handleBack()}>
</Form.Item> 返回
<Form.Item label='分享卡片'> </Button>
{serviceDetail?.shareCard ? ( </div>
<Image src={serviceDetail.shareCard} width={100} height={100} /> </div>
) : ( }
'暂无' />
)} <Form form={form} labelAlign='right' labelCol={{ span: 3 }} wrapperCol={{ span: 10 }}>
</Form.Item> <Form.Item
<Form.Item label='视频'> label='服务主图'
{serviceDetail?.video ? ( name='companyInspectionFiles1'
<video rules={[{ required: true, message: '请上传服务主图' }]}
src={serviceDetail?.video} >
controls <Uploader
style={{ width: '200px', height: '200px' }} listType={'picture-card'}
/> fileUpload
) : ( fileLength={1}
'暂无' fileSize={10}
)} fileType={['image/png', 'image/jpeg', 'image/jpg', 'image/gif', 'image/bmp']}
</Form.Item> onChange={(e) =>
</Form> handleUpload({ fileList: e, name: 'companyInspectionFiles1', type: 1, file: 0 })
</div> }
</div> defaultFileList={getDefaultFileList({ name: 'companyInspectionFiles1' })}
>
<PlusOutlined />
</Uploader>
</Form.Item>
<Form.Item
label='服务副图'
name='companyInspectionFiles2'
rules={[{ required: false, message: '请上传服务副图' }]}
>
<Uploader
listType={'picture-card'}
fileUpload
fileLength={5}
fileSize={10}
fileType={['image/png', 'image/jpeg', 'image/jpg', 'image/gif', 'image/bmp']}
onChange={(e) =>
handleUpload({ fileList: e, name: 'companyInspectionFiles2', type: 0, file: 0 })
}
defaultFileList={getDefaultFileList({ name: 'companyInspectionFiles2' })}
>
<PlusOutlined />
</Uploader>
</Form.Item>
<Form.Item
label='服务视频'
name='companyInspectionFiles3'
rules={[{ required: false, message: '请上传服务视频' }]}
>
<Uploader
listType={'picture-card'}
fileUpload
fileLength={1}
fileSize={10}
fileType={['video/mp4', 'video/wmv', 'video/avi', 'video/mov', 'video/flv']}
onChange={(e) =>
handleUpload({ fileList: e, name: 'companyInspectionFiles3', type: 0, file: 1 })
}
defaultFileList={getDefaultFileList({ name: 'companyInspectionFiles3' })}
>
<PlusOutlined />
</Uploader>
</Form.Item>
<Form.Item
label='服务地区'
name='serviceArea'
rules={[{ required: true, message: '请选择服务地区' }]}
>
<Select placeholder={'请选择服务地区'} options={districtList} allowClear />
</Form.Item>
<Form.Item
label='所属服务'
name='inspectionId'
rules={[
{ required: true, message: '请选择所属服务' },
() => ({
validator(_, value) {
if (value && value.length === 2) {
return Promise.resolve();
}
return Promise.reject(new Error('请选择所属服务'));
},
}),
]}
>
<Cascader
placeholder={'请选择所属行业'}
options={industryList}
allowClear
onChange={(e) => {
if (e.length === 2) setInspectionId(Number(e?.at(-1)));
}}
/>
</Form.Item>
<Form.Item
label='场景标签'
name='inspectionTagId'
rules={[{ required: true, message: '请选择场景标签' }]}
>
<Select placeholder={'请选择场景标签'} options={inspectionTagList} allowClear />
</Form.Item>
<Form.Item
label='服务报价'
name='price'
rules={[{ required: true, validator: commonPriceValidator }]}
>
<Input placeholder='请输入服务报价' maxLength={15} allowClear type={'number'} />
</Form.Item>
<Form.Item
label='报价说明'
name='priceRemark'
rules={[{ required: true, message: '请输入报价说明' }]}
>
<Input.TextArea placeholder='请输入报价说明' maxLength={50} allowClear showCount />
</Form.Item>
<Form.Item
label='价格单位'
name='inspectionPriceUnitId'
rules={[{ required: true, message: '请选择价格单位' }]}
>
<Select placeholder={'请选择价格单位'} options={priceUnitList} allowClear />
</Form.Item>
<Form.Item label='备注' name='remark' rules={[{ required: false, message: '请输入备注' }]}>
<Input.TextArea placeholder='请输入备注' maxLength={50} allowClear showCount />
</Form.Item>
<Form.Item
label='详情页'
name='detailPage'
rules={[{ required: true, message: '请输入详情页' }]}
wrapperCol={{ span: 20 }}
>
<RichText
richTextContent={form.getFieldValue('detailPage')}
onChange={(e) => form.setFieldValue('detailPage', e)}
height={250}
/>
</Form.Item>
</Form>
</>
); );
}; }
export default ServiceDetail;
export default ServiceDetailView;
import React, { FC, useEffect, useRef, useState } from 'react'; import { useEffect, useState } from 'react';
import { useNavigate, useSearchParams } from 'react-router-dom'; import { Button, Image, message, Modal, Table } from 'antd';
import { searchColumns } from '~/components/search-box'; import { PlusOutlined } from '@ant-design/icons';
import SearchBox from '~/components/search-box'; import SearchView from '~/components/search-box';
import AddOrEditServiceModal from './components/addOrEditServiceModal';
import PreviewImageVideo from '~/components/previewImageVideo';
import { Button, Card, Image, message, Modal, Table } from 'antd';
import {
PlusOutlined,
ArrowUpOutlined,
ArrowDownOutlined,
DeleteOutlined,
} from '@ant-design/icons';
import { ColumnsType } from 'antd/es/table';
import { CategoryManageAPI, MallManageAPI } from '~/api'; import { CategoryManageAPI, MallManageAPI } from '~/api';
import { InterDataType, InterReqType, PaginationProps } from '~/api/interface'; import { InterListType, InterReqListType } from '~/api/interface';
import { categoryListType } from '~/api/interface/categoryManage'; import { listCompanyInspectionPageType } from '~/api/interface/mallManageType';
import { serviceType } from '~/api/interface/mallManageType'; import { ColumnsType } from 'antd/es/table';
import qs from 'query-string'; import { useNavigate } from 'react-router-dom';
//分类返回类型 // 列表类型
type categoryType = InterDataType<categoryListType>['list']; type TableType = InterListType<listCompanyInspectionPageType>;
//服务返回类型 // 请求的参数
type serviceListType = InterDataType<serviceType>['list']; type ReqType = InterReqListType<listCompanyInspectionPageType>;
//服务列表请求类型 // 搜索表单的数据
type serviceParametersType = InterReqType<serviceType>; let query: ReqType = {};
const ServiceList: FC<any> = () => { const ServiceListView = () => {
const searchRef = useRef<any>(); // 路由钩子
const navigate = useNavigate(); const navigate = useNavigate();
const [searchParams, setSearchParams] = useSearchParams(); // 行业应用列表
const tabList = [ const [industryList, setIndustryList] = useState<
{ { label: string; value: number; children: { label: string; value: number }[] }[]
key: '1', >([]);
tab: '全部', // 获取行业列表
}, const getIndustryList = async () => {
{ const res = await CategoryManageAPI.industryListPages({
key: '2', pageNo: 1,
tab: '上架中', pageSize: 9999,
}, });
{ if (res && res.code === '200') {
key: '3', const list = res.result?.list || [];
tab: '仓库中', setIndustryList(
}, list.map((i) => ({
]; label: i.typeName,
const [activeTabKey, setActiveTabKey] = useState<string>('1'); value: i.id,
const [searchColumnsData, setSearchColumnsData] = useState<searchColumns[]>([ children: i.inspectionDTOS?.map((j) => {
return {
label: j.inspectionName,
value: j.id,
};
}),
})),
);
}
};
// 表格数据
const [tableData, setTableData] = useState<TableType>([]);
// 表格分页配置
const [pagination, setPagination] = useState({
total: 0,
pageSize: 10,
current: 1,
totalPage: 0,
});
// 加载列表
const getTableList = async (value = {}) => {
// 只需要修改这个地方的接口即可
const res = await MallManageAPI.listCompanyInspectionPage({
pageNo: pagination.current,
pageSize: pagination.pageSize,
...value,
...query,
});
if (res && res.code === '200') {
const { list, pageNo, totalCount, pageSize, totalPage } = res.result; // 解构
setPagination({
total: totalCount,
current: pageNo,
pageSize,
totalPage,
});
setTableData(list || []);
// console.log(list);
} else {
message.warning(res.message);
}
};
// 翻页
const paginationChange = (pageNo: number, pageSize: number) => {
getTableList({ pageNo, pageSize }).then();
};
// 表单提交
const onFinish = (data: ReqType & { cascaderData: number[] }) => {
const obj = {
...data,
industryTypeId: data.cascaderData.length >= 1 ? data.cascaderData[0] : undefined,
inspectionId: data.cascaderData.length === 2 ? data.cascaderData[1] : undefined,
};
pagination.current = 1;
query = obj;
getTableList(obj).then();
};
// 新增服务
const handleAdd = () => {
navigate('/mallManage/serviceDetail');
};
// 跳转详情
const handleDetail = (record: TableType[0]) => {
navigate(`/mallManage/serviceDetail?id=${record.id}`);
};
// 删除服务
const handleDelete = (record: TableType[0]) => {
Modal.confirm({
title: '提示',
content: '是否删除该服务?',
onOk: async () => {
const res = await MallManageAPI.companyInspectionRemove({ id: record.id });
if (res && res.code === '200') {
message.success('删除成功');
paginationChange(pagination.current, pagination.pageSize);
}
},
});
};
// 上下架
const handleState = (record: TableType[0]) => {
Modal.confirm({
title: '提示',
content: `是否${record.saleState === 1 ? '下架' : '上架'}该服务?`,
onOk: async () => {
const res = await MallManageAPI.companyInspectionUpdate({
id: record.id,
saleState: record.saleState === 1 ? 0 : 1,
});
if (res && res.code === '200') {
message.success(`${record.saleState === 1 ? '下架' : '上架'}成功`);
paginationChange(pagination.current, pagination.pageSize);
}
},
});
};
// 组件挂载
useEffect(() => {
getIndustryList().then();
getTableList().then();
}, []);
// 表格结构
const columns: ColumnsType<TableType[0]> = [
{ {
type: 'input', title: '序号',
placeholder: '请输入服务名称', dataIndex: 'id',
label: '服务名称', align: 'center',
name: 'serviceName', width: '50px',
render: (_text, _record, index) => (pagination.current - 1) * pagination.pageSize + index + 1,
}, },
{ {
type: 'select', title: '服务编号',
placeholder: '请选择应用类型', dataIndex: 'id',
label: '应用类型', align: 'center',
name: 'applicationId', render: (_text, record) => record.inspectionDTO.inspectionNo,
options: [],
}, },
{ {
type: 'select', title: '服务名称',
placeholder: '请选择对应行业', dataIndex: 'id',
label: '对应行业', align: 'center',
name: 'industryId', render: (_text, record) => record.inspectionDTO.inspectionName,
options: [],
}, },
]);
const tableColumns: ColumnsType<serviceListType[0]> = [
{ {
title: '序号', title: '行业应用',
dataIndex: 'id',
align: 'center', align: 'center',
render: (_text: any, _record: any, index: number) => render: (_text, record) => record.industryTypeDTO.typeName,
(pagination.pageNo - 1) * pagination.pageSize + index + 1,
}, },
{ title: '服务名称', align: 'center', dataIndex: 'serviceName', width: '20%' },
{ title: '应用', align: 'center', dataIndex: 'applicationName' },
{ title: '对应行业', align: 'center', dataIndex: 'industryName' },
{ {
title: '封面图', title: '作业团队',
dataIndex: 'companyName',
align: 'center', align: 'center',
dataIndex: 'coverPlan', width: '150px',
render: (text: string) => <Image src={text} width={50} height={50} />, ellipsis: true,
}, },
{ {
title: '分享卡片', title: '服务主图',
dataIndex: 'inspectionFirstImg',
align: 'center', align: 'center',
dataIndex: 'shareCard', render: (text) => (
render: (text: string) => (text ? <Image src={text} width={50} height={50} /> : '暂无'), <>
<Image src={text} width={40} height={40} />
</>
),
}, },
{ {
title: '视频', title: '价格',
dataIndex: 'price',
align: 'center', align: 'center',
dataIndex: 'video', render: (text) => <>{text.toLocaleString()}</>,
render: (text: string) =>
text ? (
<Button type='link' onClick={() => previewVideo(text)}>
查看
</Button>
) : (
'暂无'
),
}, },
{ {
title: '服务介绍', title: '状态',
dataIndex: 'saleState',
align: 'center', align: 'center',
dataIndex: 'serviceIntroduction', render: (text) => (text === 1 ? '上架' : '下架'),
render: (_text: string, record) => (
<Button type='link' onClick={() => toServiceIntroduce(record)}>
编辑
</Button>
),
}, },
{ {
title: '状态', title: '备注',
dataIndex: 'remark',
align: 'center', align: 'center',
dataIndex: 'displayState', width: '100px',
render: (text: number) => (text === 0 ? '上架' : '下架'), ellipsis: true,
}, },
{ {
title: '操作', title: '操作',
dataIndex: 'id',
align: 'center', align: 'center',
render: (_text: any, record) => ( width: '150px',
fixed: 'right',
render: (_text, record) => (
<> <>
<Button type='link' onClick={() => addOrEditServiceModalShow(record)}>
编辑
</Button>
<Button type='link' onClick={() => toServiceDetail(record)}>
详情
</Button>
</>
),
},
];
const [loading, setLoading] = useState<boolean>(false);
const [tableData, setTableData] = useState<serviceListType>([]); //表格数据
const [allServiceData, setAllServiceData] = useState<serviceListType>([]);
const [currentServiceData, setCurrentServiceData] = useState<serviceListType[0]>();
// 表格多选
const [selectedRowKeys, setSelectedRowKeys] = useState<React.Key[]>([]);
const [pagination, setPagination] = useState<
PaginationProps & { totalCount: number; totalPage: number }
>({
pageNo: 1,
pageSize: 10,
totalCount: 0,
totalPage: 1,
});
//筛选
const [query, setQuery] = useState<serviceParametersType>({
displayState: undefined,
});
//行业分类列表
const [industryCategoryList, setIndustryCategoryList] = useState<categoryType>([]);
//应用分类列表
const [applicationCategoryList, setApplicationCategoryList] = useState<categoryType>([]);
//新增、编辑服务弹窗
const [addOrEditServiceModalOpen, setAddOrEditServiceModalOpen] = useState<boolean>(false);
const [addOrEditServiceModalTitle, setAddOrEditServiceModalTitle] = useState<string>('新增服务');
//预览视频、图片
const [previewShow, setPreviewShow] = useState<boolean>(false);
const [previewUrl, setPreviewUrl] = useState<string>('');
const onTabChange = (key: string) => {
pagination.pageNo = 1;
pagination.pageSize = 10;
setQuery({ ...query, displayState: key === '1' ? undefined : key === '2' ? 0 : 1 });
setSearchParams(
qs.stringify({ ...query, displayState: key === '1' ? 'all' : key === '2' ? 0 : 1 }),
);
setActiveTabKey(key);
getServiceList({ ...query, displayState: key === '1' ? undefined : key === '2' ? 0 : 1 });
getServiceList(
{
...query,
displayState: key === '1' ? undefined : key === '2' ? 0 : 1,
pageNo: 1,
pageSize: 9999,
},
true,
);
};
//新增服务
const addOrEditServiceModalShow = (record?: serviceListType[0]) => {
setAddOrEditServiceModalTitle(record ? '编辑服务' : '新增服务');
setAddOrEditServiceModalOpen(true);
setCurrentServiceData(record && { ...record });
};
const addOrEditServiceModalCancel = () => {
setAddOrEditServiceModalOpen(false);
};
const addOrEditServiceModalOk = () => {
setAddOrEditServiceModalOpen(false);
getServiceList(query);
};
//服务-列表
const getServiceList = (query?: serviceParametersType, isAll?: boolean) => {
setLoading(true);
MallManageAPI.getServiceList({
pageNo: pagination.pageNo,
pageSize: pagination.pageSize,
...query,
}).then(({ result }) => {
setLoading(false);
if (isAll) {
setAllServiceData(result.list || []);
} else {
setTableData(result.list || []);
pagination.totalCount = result.totalCount;
pagination.totalPage = result.totalPage;
setPagination(pagination);
}
});
};
//行业分类列表
const getIndustryCategoryList = () => {
CategoryManageAPI.getCategoryList({ directoryId: 2, pageSize: 99999, pageNo: 1 }).then(
({ result }) => {
setIndustryCategoryList(result.list || []);
searchColumnsData[2].options =
result.list?.map((v) => ({
id: v.id,
name: v.classifyName,
})) || [];
setSearchColumnsData(searchColumnsData);
},
);
};
//应用分类列表
const getApplicationCategoryList = () => {
CategoryManageAPI.getCategoryList({ directoryId: 3, pageSize: 99999, pageNo: 1 }).then(
({ result }) => {
setApplicationCategoryList(result.list || []);
searchColumnsData[1].options =
result.list?.map((v) => ({
id: v.id,
name: v.classifyName,
})) || [];
setSearchColumnsData(searchColumnsData);
},
);
};
//服务详情
const toServiceDetail = (record: serviceListType[0]) => {
navigate({ pathname: '/mallManage/serviceDetail', search: `id=${record.id}` });
};
//服务介绍
const toServiceIntroduce = (record: serviceListType[0]) => {
navigate({ pathname: '/mallManage/serviceIntroduce', search: `id=${record.id}` });
};
//上下架
const groundingOrOffService = (status: number) => {
if (selectedRowKeys.length === 0) {
message.warning('请先选择服务');
return;
}
MallManageAPI.batchUpAndDownWorkService({
displayState: status,
ids: selectedRowKeys as number[],
}).then(({ code }) => {
if (code === '200') {
message.success(status ? '下架成功' : '上架成功');
getServiceList(query);
setSelectedRowKeys([]);
}
});
};
//服务删除
const deleteService = () => {
if (selectedRowKeys.length === 0) {
message.warning('请先选择服务');
return;
}
Modal.confirm({
title: '提示',
content: '删除后数据将会丢失,确定删除吗?',
onOk() {
MallManageAPI.deleteService(selectedRowKeys as number[]).then(({ code }) => {
if (code === '200') {
if (pagination.pageNo !== 1 && tableData.length === 1) {
pagination.pageNo -= 1;
}
message.success('删除成功');
getServiceList(query);
}
});
},
});
};
//分页事件
const paginationChange = (pageNo: number, pageSize: number) => {
pagination.pageNo = pageNo;
pagination.pageSize = pageSize;
setSearchParams(
qs.stringify({
...query,
pageNo,
pageSize,
displayState: query.displayState === undefined ? 'all' : query.displayState,
}),
);
getServiceList(query);
getServiceList({ ...query, pageNo: 1, pageSize: 9999 }, true);
};
// 表格多选事件
const onSelectChange = (newSelectedRowKeys: React.Key[]) => {
setSelectedRowKeys(newSelectedRowKeys);
};
//筛选
const searchSuccess = (data: any) => {
pagination.pageNo = 1;
pagination.pageSize = 10;
setSearchParams(
qs.stringify({
...data,
pageNo: pagination.pageNo,
pageSize: pagination.pageSize,
displayState: query.displayState === undefined ? 'all' : query.displayState,
}),
);
setQuery(data);
getServiceList(data);
getServiceList({ ...data, pageNo: 1, pageSize: 9999 }, true);
};
//预览视频
const previewVideo = (url: string) => {
setPreviewShow(true);
setPreviewUrl(url);
};
const previewCancel = () => {
setPreviewShow(false);
};
//上移
const upServiceClick = () => {
if (selectedRowKeys.length === 0) {
message.warning('请选择服务');
} else if (selectedRowKeys.length > 1) {
message.warning('最多选择一个服务');
} else {
const index = tableData.findIndex((v) => v.id === selectedRowKeys[0]);
const allIndex = allServiceData.findIndex((v) => v.id === selectedRowKeys[0]);
if (index === 0 && pagination.pageNo === 1) {
message.warning('位置已到最前列,无法上移');
} else {
const exReqData =
index === 0
? allServiceData
.filter((_v, index) => index === allIndex - 1 || index === allIndex)
.map((v) => ({ id: v.id, sort: v.sort }))
: tableData
.filter((_v, i) => index - 1 === i || index === i)
.map((v) => ({ id: v.id, sort: v.sort }));
MallManageAPI.exChangeService(exReqData).then(({ code }) => {
if (code === '200') {
message.success('上移成功');
if (index === 0 && pagination.pageNo !== 1) {
pagination.pageNo -= 1;
setSearchParams(
qs.stringify({
...query,
pageNo: pagination.pageNo,
pageSize: pagination.pageSize,
displayState: query.displayState === undefined ? 'all' : query.displayState,
}),
);
}
getServiceList(query);
getServiceList({ ...query, pageNo: 1, pageSize: 9999 }, true);
}
});
}
}
};
//下移
const downServiceClick = () => {
if (selectedRowKeys.length === 0) {
message.warning('请选择服务');
} else if (selectedRowKeys.length > 1) {
message.warning('最多选择一个服务');
} else {
const index = tableData.findIndex((v) => v.id === selectedRowKeys[0]);
const allIndex = allServiceData.findIndex((v) => v.id === selectedRowKeys[0]);
if (index === tableData.length - 1 && pagination.pageNo === pagination.totalPage) {
message.warning('位置已到最后,无法下移');
} else {
const exReqData =
index === tableData.length - 1
? allServiceData
.filter((_v, index) => index === allIndex + 1 || index === allIndex)
.map((v) => ({ id: v.id, sort: v.sort }))
: tableData
.filter((_v, i) => index + 1 === i || index === i)
.map((v) => ({ id: v.id, sort: v.sort }));
MallManageAPI.exChangeService(exReqData).then(({ code }) => {
if (code === '200') {
message.success('下移成功');
if (index === tableData.length - 1 && pagination.pageNo !== pagination.totalPage) {
pagination.pageNo += 1;
setSearchParams(
qs.stringify({
...query,
pageNo: pagination.pageNo,
pageSize: pagination.pageSize,
displayState: query.displayState === undefined ? 'all' : query.displayState,
}),
);
}
getServiceList(query);
getServiceList({ ...query, pageNo: 1, pageSize: 9999 }, true);
}
});
}
}
};
useEffect(() => {
pagination.pageNo = Number(searchParams.get('pageNo') || 1);
pagination.pageSize = Number(searchParams.get('pageSize') || 10);
searchRef.current.getForm().setFieldsValue({
serviceName: searchParams.get('serviceName') || undefined,
applicationId: searchParams.get('applicationId')
? Number(searchParams.get('applicationId'))
: undefined,
industryId: searchParams.get('industryId')
? Number(searchParams.get('industryId'))
: undefined,
});
const queryObj = {
serviceName: searchParams.get('serviceName') || undefined,
applicationId: searchParams.get('applicationId')
? Number(searchParams.get('applicationId'))
: undefined,
industryId: searchParams.get('industryId')
? Number(searchParams.get('industryId'))
: undefined,
displayState:
searchParams.get('displayState') === 'all' || searchParams.get('displayState') === null
? undefined
: Number(searchParams.get('displayState')),
};
setQuery(queryObj);
setActiveTabKey(
searchParams.get('displayState') === 'all' || searchParams.get('displayState') === null
? '1'
: Number(searchParams.get('displayState')) === 0
? '2'
: '3',
);
getServiceList(queryObj);
getServiceList({ ...queryObj, pageNo: 1, pageSize: 9999 }, true);
getIndustryCategoryList();
getApplicationCategoryList();
}, []);
return (
<div className='service-list'>
<SearchBox
search={searchColumnsData}
child={
<Button <Button
type='primary' type={'link'}
icon={<PlusOutlined />} onClick={() => {
onClick={() => addOrEditServiceModalShow()} handleDetail(record);
}}
> >
新增服务 详情
</Button> </Button>
}
searchData={searchSuccess}
baseRef={searchRef}
/>
<Card tabList={tabList} activeTabKey={activeTabKey} onTabChange={onTabChange}>
<div className='header-operate' style={{ marginBottom: '10px' }}>
<Button <Button
type='primary' type={'link'}
style={{ marginRight: '10px' }} danger
icon={<ArrowUpOutlined />} onClick={() => {
onClick={upServiceClick} handleDelete(record);
}}
> >
上移 删除
</Button> </Button>
<Button <Button
type='primary' type={'link'}
style={{ marginRight: '10px' }} onClick={() => {
icon={<ArrowDownOutlined />} handleState(record);
onClick={downServiceClick} }}
> >
下移 {record.saleState === 1 ? '下架' : '上架'}
</Button> </Button>
{activeTabKey !== '2' ? ( </>
<Button ),
type='primary' },
style={{ marginRight: '10px' }} ];
icon={<ArrowUpOutlined />} return (
onClick={() => groundingOrOffService(0)} <>
> <SearchView
上架 child={
</Button> <>
) : ( <Button type='primary' onClick={() => handleAdd()} icon={<PlusOutlined />}>
'' 新增服务
)}
{activeTabKey !== '3' ? (
<Button
type='primary'
style={{ marginRight: '10px' }}
icon={<ArrowDownOutlined />}
onClick={() => groundingOrOffService(1)}
>
下架
</Button> </Button>
) : ( </>
'' }
)} search={[
{
<Button danger icon={<DeleteOutlined />} onClick={deleteService}> label: '服务名称',
删除 placeholder: '请输入服务编号、名称',
</Button> type: 'input',
</div> name: 'keyword',
<Table },
columns={tableColumns} {
loading={loading} label: '行业应用',
bordered placeholder: '请选择行业应用',
rowKey='id' type: 'Cascader',
dataSource={tableData} name: 'cascaderData',
pagination={{ options: industryList,
total: pagination.totalCount, },
pageSize: pagination.pageSize, ]}
current: pagination.pageNo, searchData={onFinish}
showSizeChanger: true,
showQuickJumper: true,
onChange: (page: number, pageSize: number) => paginationChange(page, pageSize),
showTotal: (total, range) => `当前 ${range[0]}-${range[1]} 条记录 / 共 ${total} 条数据`,
}}
rowSelection={{
selectedRowKeys,
onChange: onSelectChange,
}}
/>
</Card>
{/*新增/编辑服务弹窗*/}
<AddOrEditServiceModal
open={addOrEditServiceModalOpen}
title={addOrEditServiceModalTitle}
handleCancel={addOrEditServiceModalCancel}
industryCategoryList={industryCategoryList}
applicationCategoryList={applicationCategoryList}
handleOk={addOrEditServiceModalOk}
currentServiceData={currentServiceData}
/> />
{/* 预览*/} <Table
<PreviewImageVideo size='small'
open={previewShow} dataSource={tableData}
onCancel={previewCancel} columns={columns}
type='video' rowKey='id'
url={previewUrl} scroll={{ x: 1000 }}
bordered
pagination={{
total: pagination.total,
pageSize: pagination.pageSize,
current: pagination.current,
showSizeChanger: true,
showQuickJumper: true,
onChange: (page: number, pageSize: number) => paginationChange(page, pageSize),
showTotal: (total, range) => `当前 ${range[0]}-${range[1]} 条记录 / 共 ${total} 条数据`,
}}
/> />
</div> </>
); );
}; };
export default ServiceList;
export default ServiceListView;
import { Button, Form, Image } from 'antd';
import { useNavigate, useSearchParams } from 'react-router-dom';
import './index.scss';
import { MallManageAPI } from '~/api';
import { useEffect, useState } from 'react';
import { InterDataType } from '~/api/interface';
import { serviceDetailType } from '~/api/interface/mallManageType';
//服务详情-返回类型
type detailType = InterDataType<serviceDetailType>;
const ServiceDetail = () => {
const navigate = useNavigate();
const [searchParams] = useSearchParams();
const [serviceDetail, setServiceDetail] = useState<detailType>();
//服务详情
const getServiceDetail = (id: number) => {
MallManageAPI.getServiceDetail({ id }).then(({ result }) => {
setServiceDetail(result);
});
};
//返回
const backRoute = () => {
navigate(-1);
};
useEffect(() => {
getServiceDetail(Number(searchParams.get('id')));
}, []);
return (
<div className='service-detail'>
<div className='service-detail-operate'>
<Button type='primary' onClick={backRoute}>
返回
</Button>
</div>
<div className='service-detail-form'>
<Form labelCol={{ span: 2 }} wrapperCol={{ span: 16 }}>
<Form.Item label='服务名称'>{serviceDetail?.serviceName}</Form.Item>
<Form.Item label='应用类型'>{serviceDetail?.applicationName}</Form.Item>
<Form.Item label='对应行业'>{serviceDetail?.industryName}</Form.Item>
<Form.Item label='展示状态'>
{serviceDetail?.displayState === 0 ? '上架' : '下架'}
</Form.Item>
<Form.Item label='所属单位'>{serviceDetail?.companyName}</Form.Item>
<Form.Item label='封面图'>
<Image src={serviceDetail?.coverPlan} width={100} height={100} />
</Form.Item>
<Form.Item label='分享卡片'>
{serviceDetail?.shareCard ? (
<Image src={serviceDetail.shareCard} width={100} height={100} />
) : (
'暂无'
)}
</Form.Item>
<Form.Item label='视频'>
{serviceDetail?.video ? (
<video
src={serviceDetail?.video}
controls
style={{ width: '200px', height: '200px' }}
/>
) : (
'暂无'
)}
</Form.Item>
</Form>
</div>
</div>
);
};
export default ServiceDetail;
import React, { FC, useEffect, useRef, useState } from 'react';
import { useNavigate, useSearchParams } from 'react-router-dom';
import { searchColumns } from '~/components/search-box';
import SearchBox from '~/components/search-box';
import AddOrEditServiceModal from './components/addOrEditServiceModal';
import PreviewImageVideo from '~/components/previewImageVideo';
import { Button, Card, Image, message, Modal, Table } from 'antd';
import {
PlusOutlined,
ArrowUpOutlined,
ArrowDownOutlined,
DeleteOutlined,
} from '@ant-design/icons';
import { ColumnsType } from 'antd/es/table';
import { CategoryManageAPI, MallManageAPI } from '~/api';
import { InterDataType, InterReqType, PaginationProps } from '~/api/interface';
import { categoryListType } from '~/api/interface/categoryManage';
import { serviceType } from '~/api/interface/mallManageType';
import qs from 'query-string';
//分类返回类型
type categoryType = InterDataType<categoryListType>['list'];
//服务返回类型
type serviceListType = InterDataType<serviceType>['list'];
//服务列表请求类型
type serviceParametersType = InterReqType<serviceType>;
const ServiceList: FC<any> = () => {
const searchRef = useRef<any>();
const navigate = useNavigate();
const [searchParams, setSearchParams] = useSearchParams();
const tabList = [
{
key: '1',
tab: '全部',
},
{
key: '2',
tab: '上架中',
},
{
key: '3',
tab: '仓库中',
},
];
const [activeTabKey, setActiveTabKey] = useState<string>('1');
const [searchColumnsData, setSearchColumnsData] = useState<searchColumns[]>([
{
type: 'input',
placeholder: '请输入服务名称',
label: '服务名称',
name: 'serviceName',
},
{
type: 'select',
placeholder: '请选择应用类型',
label: '应用类型',
name: 'applicationId',
options: [],
},
{
type: 'select',
placeholder: '请选择对应行业',
label: '对应行业',
name: 'industryId',
options: [],
},
]);
const tableColumns: ColumnsType<serviceListType[0]> = [
{
title: '序号',
align: 'center',
render: (_text: any, _record: any, index: number) =>
(pagination.pageNo - 1) * pagination.pageSize + index + 1,
},
{ title: '服务名称', align: 'center', dataIndex: 'serviceName', width: '20%' },
{ title: '应用', align: 'center', dataIndex: 'applicationName' },
{ title: '对应行业', align: 'center', dataIndex: 'industryName' },
{
title: '封面图',
align: 'center',
dataIndex: 'coverPlan',
render: (text: string) => <Image src={text} width={50} height={50} />,
},
{
title: '分享卡片',
align: 'center',
dataIndex: 'shareCard',
render: (text: string) => (text ? <Image src={text} width={50} height={50} /> : '暂无'),
},
{
title: '视频',
align: 'center',
dataIndex: 'video',
render: (text: string) =>
text ? (
<Button type='link' onClick={() => previewVideo(text)}>
查看
</Button>
) : (
'暂无'
),
},
{
title: '服务介绍',
align: 'center',
dataIndex: 'serviceIntroduction',
render: (_text: string, record) => (
<Button type='link' onClick={() => toServiceIntroduce(record)}>
编辑
</Button>
),
},
{
title: '状态',
align: 'center',
dataIndex: 'displayState',
render: (text: number) => (text === 0 ? '上架' : '下架'),
},
{
title: '操作',
align: 'center',
render: (_text: any, record) => (
<>
<Button type='link' onClick={() => addOrEditServiceModalShow(record)}>
编辑
</Button>
<Button type='link' onClick={() => toServiceDetail(record)}>
详情
</Button>
</>
),
},
];
const [loading, setLoading] = useState<boolean>(false);
const [tableData, setTableData] = useState<serviceListType>([]); //表格数据
const [allServiceData, setAllServiceData] = useState<serviceListType>([]);
const [currentServiceData, setCurrentServiceData] = useState<serviceListType[0]>();
// 表格多选
const [selectedRowKeys, setSelectedRowKeys] = useState<React.Key[]>([]);
const [pagination, setPagination] = useState<
PaginationProps & { totalCount: number; totalPage: number }
>({
pageNo: 1,
pageSize: 10,
totalCount: 0,
totalPage: 1,
});
//筛选
const [query, setQuery] = useState<serviceParametersType>({
displayState: undefined,
});
//行业分类列表
const [industryCategoryList, setIndustryCategoryList] = useState<categoryType>([]);
//应用分类列表
const [applicationCategoryList, setApplicationCategoryList] = useState<categoryType>([]);
//新增、编辑服务弹窗
const [addOrEditServiceModalOpen, setAddOrEditServiceModalOpen] = useState<boolean>(false);
const [addOrEditServiceModalTitle, setAddOrEditServiceModalTitle] = useState<string>('新增服务');
//预览视频、图片
const [previewShow, setPreviewShow] = useState<boolean>(false);
const [previewUrl, setPreviewUrl] = useState<string>('');
const onTabChange = (key: string) => {
pagination.pageNo = 1;
pagination.pageSize = 10;
setQuery({ ...query, displayState: key === '1' ? undefined : key === '2' ? 0 : 1 });
setSearchParams(
qs.stringify({ ...query, displayState: key === '1' ? 'all' : key === '2' ? 0 : 1 }),
);
setActiveTabKey(key);
getServiceList({ ...query, displayState: key === '1' ? undefined : key === '2' ? 0 : 1 });
getServiceList(
{
...query,
displayState: key === '1' ? undefined : key === '2' ? 0 : 1,
pageNo: 1,
pageSize: 9999,
},
true,
);
};
//新增服务
const addOrEditServiceModalShow = (record?: serviceListType[0]) => {
setAddOrEditServiceModalTitle(record ? '编辑服务' : '新增服务');
setAddOrEditServiceModalOpen(true);
setCurrentServiceData(record && { ...record });
};
const addOrEditServiceModalCancel = () => {
setAddOrEditServiceModalOpen(false);
};
const addOrEditServiceModalOk = () => {
setAddOrEditServiceModalOpen(false);
getServiceList(query);
};
//服务-列表
const getServiceList = (query?: serviceParametersType, isAll?: boolean) => {
setLoading(true);
MallManageAPI.getServiceList({
pageNo: pagination.pageNo,
pageSize: pagination.pageSize,
...query,
}).then(({ result }) => {
setLoading(false);
if (isAll) {
setAllServiceData(result.list || []);
} else {
setTableData(result.list || []);
pagination.totalCount = result.totalCount;
pagination.totalPage = result.totalPage;
setPagination(pagination);
}
});
};
//行业分类列表
const getIndustryCategoryList = () => {
CategoryManageAPI.getCategoryList({ directoryId: 2, pageSize: 99999, pageNo: 1 }).then(
({ result }) => {
setIndustryCategoryList(result.list || []);
searchColumnsData[2].options =
result.list?.map((v) => ({
id: v.id,
name: v.classifyName,
})) || [];
setSearchColumnsData(searchColumnsData);
},
);
};
//应用分类列表
const getApplicationCategoryList = () => {
CategoryManageAPI.getCategoryList({ directoryId: 3, pageSize: 99999, pageNo: 1 }).then(
({ result }) => {
setApplicationCategoryList(result.list || []);
searchColumnsData[1].options =
result.list?.map((v) => ({
id: v.id,
name: v.classifyName,
})) || [];
setSearchColumnsData(searchColumnsData);
},
);
};
//服务详情
const toServiceDetail = (record: serviceListType[0]) => {
navigate({ pathname: '/mallManage/serviceDetail', search: `id=${record.id}` });
};
//服务介绍
const toServiceIntroduce = (record: serviceListType[0]) => {
navigate({ pathname: '/mallManage/serviceIntroduce', search: `id=${record.id}` });
};
//上下架
const groundingOrOffService = (status: number) => {
if (selectedRowKeys.length === 0) {
message.warning('请先选择服务');
return;
}
MallManageAPI.batchUpAndDownWorkService({
displayState: status,
ids: selectedRowKeys as number[],
}).then(({ code }) => {
if (code === '200') {
message.success(status ? '下架成功' : '上架成功');
getServiceList(query);
setSelectedRowKeys([]);
}
});
};
//服务删除
const deleteService = () => {
if (selectedRowKeys.length === 0) {
message.warning('请先选择服务');
return;
}
Modal.confirm({
title: '提示',
content: '删除后数据将会丢失,确定删除吗?',
onOk() {
MallManageAPI.deleteService(selectedRowKeys as number[]).then(({ code }) => {
if (code === '200') {
if (pagination.pageNo !== 1 && tableData.length === 1) {
pagination.pageNo -= 1;
}
message.success('删除成功');
getServiceList(query);
}
});
},
});
};
//分页事件
const paginationChange = (pageNo: number, pageSize: number) => {
pagination.pageNo = pageNo;
pagination.pageSize = pageSize;
setSearchParams(
qs.stringify({
...query,
pageNo,
pageSize,
displayState: query.displayState === undefined ? 'all' : query.displayState,
}),
);
getServiceList(query);
getServiceList({ ...query, pageNo: 1, pageSize: 9999 }, true);
};
// 表格多选事件
const onSelectChange = (newSelectedRowKeys: React.Key[]) => {
setSelectedRowKeys(newSelectedRowKeys);
};
//筛选
const searchSuccess = (data: any) => {
pagination.pageNo = 1;
pagination.pageSize = 10;
setSearchParams(
qs.stringify({
...data,
pageNo: pagination.pageNo,
pageSize: pagination.pageSize,
displayState: query.displayState === undefined ? 'all' : query.displayState,
}),
);
setQuery(data);
getServiceList(data);
getServiceList({ ...data, pageNo: 1, pageSize: 9999 }, true);
};
//预览视频
const previewVideo = (url: string) => {
setPreviewShow(true);
setPreviewUrl(url);
};
const previewCancel = () => {
setPreviewShow(false);
};
//上移
const upServiceClick = () => {
if (selectedRowKeys.length === 0) {
message.warning('请选择服务');
} else if (selectedRowKeys.length > 1) {
message.warning('最多选择一个服务');
} else {
const index = tableData.findIndex((v) => v.id === selectedRowKeys[0]);
const allIndex = allServiceData.findIndex((v) => v.id === selectedRowKeys[0]);
if (index === 0 && pagination.pageNo === 1) {
message.warning('位置已到最前列,无法上移');
} else {
const exReqData =
index === 0
? allServiceData
.filter((_v, index) => index === allIndex - 1 || index === allIndex)
.map((v) => ({ id: v.id, sort: v.sort }))
: tableData
.filter((_v, i) => index - 1 === i || index === i)
.map((v) => ({ id: v.id, sort: v.sort }));
MallManageAPI.exChangeService(exReqData).then(({ code }) => {
if (code === '200') {
message.success('上移成功');
if (index === 0 && pagination.pageNo !== 1) {
pagination.pageNo -= 1;
setSearchParams(
qs.stringify({
...query,
pageNo: pagination.pageNo,
pageSize: pagination.pageSize,
displayState: query.displayState === undefined ? 'all' : query.displayState,
}),
);
}
getServiceList(query);
getServiceList({ ...query, pageNo: 1, pageSize: 9999 }, true);
}
});
}
}
};
//下移
const downServiceClick = () => {
if (selectedRowKeys.length === 0) {
message.warning('请选择服务');
} else if (selectedRowKeys.length > 1) {
message.warning('最多选择一个服务');
} else {
const index = tableData.findIndex((v) => v.id === selectedRowKeys[0]);
const allIndex = allServiceData.findIndex((v) => v.id === selectedRowKeys[0]);
if (index === tableData.length - 1 && pagination.pageNo === pagination.totalPage) {
message.warning('位置已到最后,无法下移');
} else {
const exReqData =
index === tableData.length - 1
? allServiceData
.filter((_v, index) => index === allIndex + 1 || index === allIndex)
.map((v) => ({ id: v.id, sort: v.sort }))
: tableData
.filter((_v, i) => index + 1 === i || index === i)
.map((v) => ({ id: v.id, sort: v.sort }));
MallManageAPI.exChangeService(exReqData).then(({ code }) => {
if (code === '200') {
message.success('下移成功');
if (index === tableData.length - 1 && pagination.pageNo !== pagination.totalPage) {
pagination.pageNo += 1;
setSearchParams(
qs.stringify({
...query,
pageNo: pagination.pageNo,
pageSize: pagination.pageSize,
displayState: query.displayState === undefined ? 'all' : query.displayState,
}),
);
}
getServiceList(query);
getServiceList({ ...query, pageNo: 1, pageSize: 9999 }, true);
}
});
}
}
};
useEffect(() => {
pagination.pageNo = Number(searchParams.get('pageNo') || 1);
pagination.pageSize = Number(searchParams.get('pageSize') || 10);
searchRef.current.getForm().setFieldsValue({
serviceName: searchParams.get('serviceName') || undefined,
applicationId: searchParams.get('applicationId')
? Number(searchParams.get('applicationId'))
: undefined,
industryId: searchParams.get('industryId')
? Number(searchParams.get('industryId'))
: undefined,
});
const queryObj = {
serviceName: searchParams.get('serviceName') || undefined,
applicationId: searchParams.get('applicationId')
? Number(searchParams.get('applicationId'))
: undefined,
industryId: searchParams.get('industryId')
? Number(searchParams.get('industryId'))
: undefined,
displayState:
searchParams.get('displayState') === 'all' || searchParams.get('displayState') === null
? undefined
: Number(searchParams.get('displayState')),
};
setQuery(queryObj);
setActiveTabKey(
searchParams.get('displayState') === 'all' || searchParams.get('displayState') === null
? '1'
: Number(searchParams.get('displayState')) === 0
? '2'
: '3',
);
getServiceList(queryObj);
getServiceList({ ...queryObj, pageNo: 1, pageSize: 9999 }, true);
getIndustryCategoryList();
getApplicationCategoryList();
}, []);
return (
<div className='service-list'>
<SearchBox
search={searchColumnsData}
child={
<Button
type='primary'
icon={<PlusOutlined />}
onClick={() => addOrEditServiceModalShow()}
>
新增服务
</Button>
}
searchData={searchSuccess}
baseRef={searchRef}
/>
<Card tabList={tabList} activeTabKey={activeTabKey} onTabChange={onTabChange}>
<div className='header-operate' style={{ marginBottom: '10px' }}>
<Button
type='primary'
style={{ marginRight: '10px' }}
icon={<ArrowUpOutlined />}
onClick={upServiceClick}
>
上移
</Button>
<Button
type='primary'
style={{ marginRight: '10px' }}
icon={<ArrowDownOutlined />}
onClick={downServiceClick}
>
下移
</Button>
{activeTabKey !== '2' ? (
<Button
type='primary'
style={{ marginRight: '10px' }}
icon={<ArrowUpOutlined />}
onClick={() => groundingOrOffService(0)}
>
上架
</Button>
) : (
''
)}
{activeTabKey !== '3' ? (
<Button
type='primary'
style={{ marginRight: '10px' }}
icon={<ArrowDownOutlined />}
onClick={() => groundingOrOffService(1)}
>
下架
</Button>
) : (
''
)}
<Button danger icon={<DeleteOutlined />} onClick={deleteService}>
删除
</Button>
</div>
<Table
columns={tableColumns}
loading={loading}
bordered
rowKey='id'
dataSource={tableData}
pagination={{
total: pagination.totalCount,
pageSize: pagination.pageSize,
current: pagination.pageNo,
showSizeChanger: true,
showQuickJumper: true,
onChange: (page: number, pageSize: number) => paginationChange(page, pageSize),
showTotal: (total, range) => `当前 ${range[0]}-${range[1]} 条记录 / 共 ${total} 条数据`,
}}
rowSelection={{
selectedRowKeys,
onChange: onSelectChange,
}}
/>
</Card>
{/*新增/编辑服务弹窗*/}
<AddOrEditServiceModal
open={addOrEditServiceModalOpen}
title={addOrEditServiceModalTitle}
handleCancel={addOrEditServiceModalCancel}
industryCategoryList={industryCategoryList}
applicationCategoryList={applicationCategoryList}
handleOk={addOrEditServiceModalOk}
currentServiceData={currentServiceData}
/>
{/* 预览*/}
<PreviewImageVideo
open={previewShow}
onCancel={previewCancel}
type='video'
url={previewUrl}
/>
</div>
);
};
export default ServiceList;
...@@ -93,9 +93,9 @@ const ServiceListView = React.lazy(() => import('~/pages/mallManage/serviceManag ...@@ -93,9 +93,9 @@ const ServiceListView = React.lazy(() => import('~/pages/mallManage/serviceManag
const ServiceDetailView = React.lazy( const ServiceDetailView = React.lazy(
() => import('~/pages/mallManage/serviceManage/serviceDetail'), () => import('~/pages/mallManage/serviceManage/serviceDetail'),
); //服务详情 ); //服务详情
const ServiceIntroduceView = React.lazy( // const ServiceIntroduceView = React.lazy(
() => import('~/pages/mallManage/serviceManage/serviceIntroduce'), // () => import('~/pages/mallManage/serviceManageOld/serviceIntroduce'),
); //服务介绍 // ); //服务介绍
const RentListView = React.lazy(() => import('~/pages/rentManage/rentGoods/rentList')); //租赁列表 const RentListView = React.lazy(() => import('~/pages/rentManage/rentGoods/rentList')); //租赁列表
const RentAddOrEditView = React.lazy(() => import('~/pages/rentManage/rentGoods/rentAddOrEdit')); //租赁新增、编辑、详情 const RentAddOrEditView = React.lazy(() => import('~/pages/rentManage/rentGoods/rentAddOrEdit')); //租赁新增、编辑、详情
...@@ -153,6 +153,7 @@ const CompanyDetailView = React.lazy( ...@@ -153,6 +153,7 @@ const CompanyDetailView = React.lazy(
import AccountLimit from '~/pages/systemManage/limitManage/roleList'; //账号权限 import AccountLimit from '~/pages/systemManage/limitManage/roleList'; //账号权限
import LimitInfo from '~/pages/systemManage/limitManage/limitInfo'; import LimitInfo from '~/pages/systemManage/limitManage/limitInfo';
import CustomListDetail from '~/pages/customManage/customList/detail'; import CustomListDetail from '~/pages/customManage/customList/detail';
import ServiceCategoryDetail from '~/pages/categoryManage/serviceCategoryList/detail';
// const IndustryListView = React.lazy(() => import('~/pages/mallManage/industryManage/industryList')); //行业列表 // const IndustryListView = React.lazy(() => import('~/pages/mallManage/industryManage/industryList')); //行业列表
// const IndustryDetailView = React.lazy( // const IndustryDetailView = React.lazy(
...@@ -592,6 +593,7 @@ export const routerList: Array<RouteObjectType> = [ ...@@ -592,6 +593,7 @@ export const routerList: Array<RouteObjectType> = [
id: 1020, id: 1020,
icon: <SmileOutlined />, icon: <SmileOutlined />,
title: '服务管理', title: '服务管理',
develop: true,
}, },
}, },
{ {
...@@ -599,23 +601,23 @@ export const routerList: Array<RouteObjectType> = [ ...@@ -599,23 +601,23 @@ export const routerList: Array<RouteObjectType> = [
element: withLoadingComponent(<ServiceDetailView />), element: withLoadingComponent(<ServiceDetailView />),
errorElement: <ErrorPage />, errorElement: <ErrorPage />,
meta: { meta: {
id: 10120, id: 1020,
icon: <SmileOutlined />, icon: <SmileOutlined />,
title: '服务详情', title: '服务详情',
hidden: true, hidden: true,
}, },
}, },
{ // {
path: '/mallManage/serviceIntroduce', // path: '/mallManage/serviceIntroduce',
element: withLoadingComponent(<ServiceIntroduceView />), // element: withLoadingComponent(<ServiceIntroduceView />),
errorElement: <ErrorPage />, // errorElement: <ErrorPage />,
meta: { // meta: {
id: 10120, // id: 10120,
icon: <SmileOutlined />, // icon: <SmileOutlined />,
title: '服务介绍', // title: '服务介绍',
hidden: true, // hidden: true,
}, // },
}, // },
{ {
path: '/mallManage/mallGoods', path: '/mallManage/mallGoods',
element: withLoadingComponent(<MallGoodsView />), element: withLoadingComponent(<MallGoodsView />),
...@@ -843,6 +845,17 @@ export const routerList: Array<RouteObjectType> = [ ...@@ -843,6 +845,17 @@ export const routerList: Array<RouteObjectType> = [
icon: <AppstoreOutlined />, icon: <AppstoreOutlined />,
}, },
}, },
{
path: '/categoryManage/mallCategoryList/detail',
element: withLoadingComponent(<ServiceCategoryDetail />),
errorElement: <ErrorPage />,
meta: {
id: 18600,
title: '分类详情',
icon: '',
hidden: true,
},
},
// { // {
// path: '/categoryManage/jobServicesCategory/4', // path: '/categoryManage/jobServicesCategory/4',
// element: withLoadingComponent(<CategoryManage />), // element: withLoadingComponent(<CategoryManage />),
......
...@@ -117,3 +117,18 @@ export const regPriceNumber = (value: string): boolean => { ...@@ -117,3 +117,18 @@ export const regPriceNumber = (value: string): boolean => {
export const isEmptyBol = (value: any): boolean => { export const isEmptyBol = (value: any): boolean => {
return _.isNull(value) || _.isNaN(value) || _.isNull(value) || _.isUndefined(value); return _.isNull(value) || _.isNaN(value) || _.isNull(value) || _.isUndefined(value);
}; };
// 通用价格判断
export const commonPriceValidator = (_rules: any, value: number) => {
if (!isEmptyBol(value)) {
if (regPriceNumber(value.toString())) {
if (value > 99999999 || value < 0) {
return Promise.reject(new Error('价格最大为99999999且大于0'));
}
return Promise.resolve();
} else {
return Promise.reject(new Error('为整数且最多保留两位小数'));
}
} else {
return Promise.reject(new Error('请输入价格'));
}
};
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论