提交 4ba9c70d 作者: ZhangLingKun

功能:上架服务

上级 ef1f3cf4
......@@ -217,3 +217,92 @@ export type inspectionUpdateType = InterFunction<
export type industryRemoveType = 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<
>;
//服务-上下移动
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 {
industryListPagesType,
industryRemoveType,
industryUpdateType,
inspectionDetailType,
inspectionInsertType,
inspectionRemoveType,
inspectionTagDeleteType,
inspectionTagInsertType,
inspectionTagUpdateType,
inspectionUpdateType,
listByInspectionIdType,
updatePrimaryCategoryType,
updateSubCategoryType,
} from '~/api/interface/categoryManage';
......@@ -157,4 +162,19 @@ export class CategoryManageAPI {
// 删除服务
static inspectionRemove: inspectionRemoveType = (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 {
deleteServiceType,
serviceDetailType,
exChangeServiceType,
listCompanyInspectionPageType,
companyInspectionInsertType,
companyInspectionUpdateType,
getCompanyInspectionByIdType,
listInspectionPriceUnitType,
companyInspectionRemoveType,
} from '~/api/interface/mallManageType';
export class MallManageAPI {
......@@ -56,4 +62,22 @@ export class MallManageAPI {
// 服务-上下移
static exChangeService: exChangeServiceType = (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 { DownOutlined, UpOutlined } from '@ant-design/icons';
import { Button, Dropdown, Image, MenuProps, Modal } from 'antd';
......
......@@ -19,6 +19,7 @@ export interface searchColumns {
name?: string;
value?: string | number | boolean | null;
label?: string;
children?: any;
}[];
onSelect?: (value: any) => void;
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 { Image } from 'antd';
import './index.scss';
// 参数类型
interface propsType {
......@@ -31,7 +32,14 @@ const Video: React.FC<propsType> = (props) => {
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';
import Video from '~/components/video';
import AddEditModalView from '~/pages/categoryManage/serviceCategoryList/comp/addEditModal';
import AddEditChildrenView from '~/pages/categoryManage/serviceCategoryList/comp/addEditChildren';
import { useNavigate } from 'react-router-dom';
import qs from 'query-string';
// 列表的类型
type TableType = InterListType<industryListPagesType>;
function ServiceCategoryList() {
// 路由钩子
const navigate = useNavigate();
// 新增编辑弹窗是否显示
const [addEditVisible, setAddEditVisible] = useState(false);
// 新增编辑子分类弹窗是否显示
......@@ -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]> = [
{
......@@ -147,7 +158,7 @@ function ServiceCategoryList() {
<Button
type='link'
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 { InterDataType } from '~/api/interface';
import { serviceDetailType } from '~/api/interface/mallManageType';
import { Button, Cascader, Form, Input, message, Modal, Select } from 'antd';
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>;
const ServiceDetail = () => {
const navigate = useNavigate();
const [searchParams] = useSearchParams();
// 表单类型
type ReqType = InterReqType<getCompanyInspectionByIdType>;
const [serviceDetail, setServiceDetail] = useState<detailType>();
//服务详情
const getServiceDetail = (id: number) => {
MallManageAPI.getServiceDetail({ id }).then(({ result }) => {
setServiceDetail(result);
function ServiceDetailView() {
// 路由钩子
const location = useLocation();
// 导航钩子
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,
};
//返回
const backRoute = () => {
navigate(-1);
}),
})),
);
setIndustryOriginList(list);
}
};
// 上传图片
const handleUpload = ({
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(() => {
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 (
<div className='service-detail'>
<div className='service-detail-operate'>
<Button type='primary' onClick={backRoute}>
<>
<SearchBox
preFixBtn={
<div
style={{
width: '100%',
display: 'flex',
justifyContent: 'space-between',
alignItems: 'center',
}}
>
<div style={{ fontSize: '16px', fontWeight: 'bold' }}>新增服务</div>
<div>
<Button type={'primary'} icon={<SaveOutlined />} onClick={() => handleValid()}>
保存
</Button>
<Button type={'default'} icon={<ArrowLeftOutlined />} onClick={() => handleBack()}>
返回
</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 ? '上架' : '下架'}
</div>
}
/>
<Form form={form} labelAlign='right' labelCol={{ span: 3 }} wrapperCol={{ span: 10 }}>
<Form.Item
label='服务主图'
name='companyInspectionFiles1'
rules={[{ required: true, message: '请上传服务主图' }]}
>
<Uploader
listType={'picture-card'}
fileUpload
fileLength={1}
fileSize={10}
fileType={['image/png', 'image/jpeg', 'image/jpg', 'image/gif', 'image/bmp']}
onChange={(e) =>
handleUpload({ fileList: e, name: 'companyInspectionFiles1', type: 1, file: 0 })
}
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='所属单位'>{serviceDetail?.companyName}</Form.Item>
<Form.Item label='封面图'>
<Image src={serviceDetail?.coverPlan} width={100} height={100} />
<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='分享卡片'>
{serviceDetail?.shareCard ? (
<Image src={serviceDetail.shareCard} width={100} height={100} />
) : (
'暂无'
)}
<Form.Item
label='服务地区'
name='serviceArea'
rules={[{ required: true, message: '请选择服务地区' }]}
>
<Select placeholder={'请选择服务地区'} options={districtList} allowClear />
</Form.Item>
<Form.Item label='视频'>
{serviceDetail?.video ? (
<video
src={serviceDetail?.video}
controls
style={{ width: '200px', height: '200px' }}
<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>
</div>
</div>
</>
);
};
export default ServiceDetail;
}
export default ServiceDetailView;
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 { useEffect, useState } from 'react';
import { Button, Image, message, Modal, Table } from 'antd';
import { PlusOutlined } from '@ant-design/icons';
import SearchView from '~/components/search-box';
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';
import { InterListType, InterReqListType } from '~/api/interface';
import { listCompanyInspectionPageType } from '~/api/interface/mallManageType';
import { ColumnsType } from 'antd/es/table';
import { useNavigate } from 'react-router-dom';
//分类返回类型
type categoryType = InterDataType<categoryListType>['list'];
//服务返回类型
type serviceListType = InterDataType<serviceType>['list'];
//服务列表请求类型
type serviceParametersType = InterReqType<serviceType>;
// 列表类型
type TableType = InterListType<listCompanyInspectionPageType>;
// 请求的参数
type ReqType = InterReqListType<listCompanyInspectionPageType>;
// 搜索表单的数据
let query: ReqType = {};
const ServiceList: FC<any> = () => {
const searchRef = useRef<any>();
const ServiceListView = () => {
// 路由钩子
const navigate = useNavigate();
const [searchParams, setSearchParams] = useSearchParams();
const tabList = [
{
key: '1',
tab: '全部',
},
{
key: '2',
tab: '上架中',
},
{
key: '3',
tab: '仓库中',
// 行业应用列表
const [industryList, setIndustryList] = useState<
{ label: string; value: number; children: { label: string; value: number }[] }[]
>([]);
// 获取行业列表
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,
};
}),
})),
);
}
};
// 表格数据
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 [activeTabKey, setActiveTabKey] = useState<string>('1');
const [searchColumnsData, setSearchColumnsData] = useState<searchColumns[]>([
{
type: 'input',
placeholder: '请输入服务名称',
label: '服务名称',
name: 'serviceName',
});
};
// 上下架
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: 'select',
placeholder: '请选择应用类型',
label: '应用类型',
name: 'applicationId',
options: [],
title: '序号',
dataIndex: 'id',
align: 'center',
width: '50px',
render: (_text, _record, index) => (pagination.current - 1) * pagination.pageSize + index + 1,
},
{
type: 'select',
placeholder: '请选择对应行业',
label: '对应行业',
name: 'industryId',
options: [],
title: '服务编号',
dataIndex: 'id',
align: 'center',
render: (_text, record) => record.inspectionDTO.inspectionNo,
},
]);
const tableColumns: ColumnsType<serviceListType[0]> = [
{
title: '序号',
title: '服务名称',
dataIndex: 'id',
align: 'center',
render: (_text: any, _record: any, index: number) =>
(pagination.pageNo - 1) * pagination.pageSize + index + 1,
render: (_text, record) => record.inspectionDTO.inspectionName,
},
{ title: '服务名称', align: 'center', dataIndex: 'serviceName', width: '20%' },
{ title: '应用', align: 'center', dataIndex: 'applicationName' },
{ title: '对应行业', align: 'center', dataIndex: 'industryName' },
{
title: '封面图',
title: '行业应用',
dataIndex: 'id',
align: 'center',
dataIndex: 'coverPlan',
render: (text: string) => <Image src={text} width={50} height={50} />,
render: (_text, record) => record.industryTypeDTO.typeName,
},
{
title: '分享卡片',
title: '作业团队',
dataIndex: 'companyName',
align: 'center',
dataIndex: 'shareCard',
render: (text: string) => (text ? <Image src={text} width={50} height={50} /> : '暂无'),
width: '150px',
ellipsis: true,
},
{
title: '视频',
title: '服务主图',
dataIndex: 'inspectionFirstImg',
align: 'center',
dataIndex: 'video',
render: (text: string) =>
text ? (
<Button type='link' onClick={() => previewVideo(text)}>
查看
</Button>
) : (
'暂无'
render: (text) => (
<>
<Image src={text} width={40} height={40} />
</>
),
},
{
title: '服务介绍',
title: '价格',
dataIndex: 'price',
align: 'center',
dataIndex: 'serviceIntroduction',
render: (_text: string, record) => (
<Button type='link' onClick={() => toServiceIntroduce(record)}>
编辑
</Button>
),
render: (text) => <>{text.toLocaleString()}</>,
},
{
title: '状态',
dataIndex: 'saleState',
align: 'center',
render: (text) => (text === 1 ? '上架' : '下架'),
},
{
title: '备注',
dataIndex: 'remark',
align: 'center',
dataIndex: 'displayState',
render: (text: number) => (text === 0 ? '上架' : '下架'),
width: '100px',
ellipsis: true,
},
{
title: '操作',
dataIndex: 'id',
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
type={'link'}
onClick={() => {
handleDetail(record);
}}
>
详情
</Button>
<Button
type={'link'}
danger
onClick={() => {
handleDelete(record);
}}
>
删除
</Button>
<Button
type={'link'}
onClick={() => {
handleState(record);
}}
>
{record.saleState === 1 ? '下架' : '上架'}
</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}
<>
<SearchView
child={
<Button
type='primary'
icon={<PlusOutlined />}
onClick={() => addOrEditServiceModalShow()}
>
<>
<Button type='primary' onClick={() => handleAdd()} icon={<PlusOutlined />}>
新增服务
</Button>
</>
}
searchData={searchSuccess}
baseRef={searchRef}
search={[
{
label: '服务名称',
placeholder: '请输入服务编号、名称',
type: 'input',
name: 'keyword',
},
{
label: '行业应用',
placeholder: '请选择行业应用',
type: 'Cascader',
name: 'cascaderData',
options: industryList,
},
]}
searchData={onFinish}
/>
<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'
size='small'
dataSource={tableData}
columns={columns}
rowKey='id'
scroll={{ x: 1000 }}
bordered
pagination={{
total: pagination.totalCount,
total: pagination.total,
pageSize: pagination.pageSize,
current: pagination.pageNo,
current: pagination.current,
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;
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
const ServiceDetailView = React.lazy(
() => import('~/pages/mallManage/serviceManage/serviceDetail'),
); //服务详情
const ServiceIntroduceView = React.lazy(
() => import('~/pages/mallManage/serviceManage/serviceIntroduce'),
); //服务介绍
// const ServiceIntroduceView = React.lazy(
// () => import('~/pages/mallManage/serviceManageOld/serviceIntroduce'),
// ); //服务介绍
const RentListView = React.lazy(() => import('~/pages/rentManage/rentGoods/rentList')); //租赁列表
const RentAddOrEditView = React.lazy(() => import('~/pages/rentManage/rentGoods/rentAddOrEdit')); //租赁新增、编辑、详情
......@@ -153,6 +153,7 @@ const CompanyDetailView = React.lazy(
import AccountLimit from '~/pages/systemManage/limitManage/roleList'; //账号权限
import LimitInfo from '~/pages/systemManage/limitManage/limitInfo';
import CustomListDetail from '~/pages/customManage/customList/detail';
import ServiceCategoryDetail from '~/pages/categoryManage/serviceCategoryList/detail';
// const IndustryListView = React.lazy(() => import('~/pages/mallManage/industryManage/industryList')); //行业列表
// const IndustryDetailView = React.lazy(
......@@ -592,6 +593,7 @@ export const routerList: Array<RouteObjectType> = [
id: 1020,
icon: <SmileOutlined />,
title: '服务管理',
develop: true,
},
},
{
......@@ -599,23 +601,23 @@ export const routerList: Array<RouteObjectType> = [
element: withLoadingComponent(<ServiceDetailView />),
errorElement: <ErrorPage />,
meta: {
id: 10120,
id: 1020,
icon: <SmileOutlined />,
title: '服务详情',
hidden: true,
},
},
{
path: '/mallManage/serviceIntroduce',
element: withLoadingComponent(<ServiceIntroduceView />),
errorElement: <ErrorPage />,
meta: {
id: 10120,
icon: <SmileOutlined />,
title: '服务介绍',
hidden: true,
},
},
// {
// path: '/mallManage/serviceIntroduce',
// element: withLoadingComponent(<ServiceIntroduceView />),
// errorElement: <ErrorPage />,
// meta: {
// id: 10120,
// icon: <SmileOutlined />,
// title: '服务介绍',
// hidden: true,
// },
// },
{
path: '/mallManage/mallGoods',
element: withLoadingComponent(<MallGoodsView />),
......@@ -843,6 +845,17 @@ export const routerList: Array<RouteObjectType> = [
icon: <AppstoreOutlined />,
},
},
{
path: '/categoryManage/mallCategoryList/detail',
element: withLoadingComponent(<ServiceCategoryDetail />),
errorElement: <ErrorPage />,
meta: {
id: 18600,
title: '分类详情',
icon: '',
hidden: true,
},
},
// {
// path: '/categoryManage/jobServicesCategory/4',
// element: withLoadingComponent(<CategoryManage />),
......
......@@ -117,3 +117,18 @@ export const regPriceNumber = (value: string): boolean => {
export const isEmptyBol = (value: any): boolean => {
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 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论