提交 3a4eeb83 作者: ZhangLingKun

优化:飞手团队店铺管理

上级 2f67e697
流水线 #8614 已通过 于阶段
in 1 分 6 秒
......@@ -212,11 +212,14 @@ export type editUserApplyTag = InterFunction<
address?: string;
content?: string;
cooperationTagId?: number;
id: number;
id?: number;
lat?: number;
lon?: number;
name?: string;
score?: number;
attachmentList?: any;
profileUrl?: string;
companyInfoId?: number;
},
NonNullable<unknown>
>;
......@@ -308,3 +311,32 @@ export type getListPartnerType = InterListFunction<
intention: null;
}
>;
// 后台--添加(修改)后台用户建议
export type updateSuggestionType = InterFunction<
{
coverUrl?: string;
id?: number;
suggestFile?: string;
title?: string;
},
NonNullable<unknown>
>;
// 后台--获取后台用户建议
export type getSuggestionType = InterFunction<
{
backUserId: number;
},
{
coverUrl: string;
id: number;
suggestFile: string;
title: string;
}[]
>;
// 后台--删除后台用户建议
export type deleteSuggestionType = InterFunction<
{
id: number;
},
NonNullable<unknown>
>;
......@@ -205,6 +205,13 @@ export type getCompanyInfoByIdType = InterFunction<
phoneNum: string;
province: string;
remark: string;
licenseImg: string;
contractNo?: string;
attachmentList: any;
brandLogo: string;
content: string;
profileUrl: string;
backUserId: number;
}
>;
//单位-成员列表
......
......@@ -9,14 +9,17 @@ import {
CompanyListTag,
cooperationListTag,
deleteApplyTag,
deleteSuggestionType,
editUserApplyTag,
editUserApplyTagDetails,
getListPartnerType,
getSuggestionType,
listAppUserCountType,
listAppUserType,
listAuthPageType,
listUserApplyTag,
listUserRcdType,
updateSuggestionType,
userAccountUpdateType,
} from '~/api/interface/customManageType';
......@@ -76,4 +79,14 @@ export class CustomManageAPI {
// 合伙人列表
static getListPartner: getListPartnerType = (data) =>
axios.post('/userapp/Partner/listPartner', data);
// 后台--添加(修改)后台用户建议
static updateSuggestion: updateSuggestionType = (params) =>
axios.post('/userapp/back-user/updateSuggestion', params);
// 后台--获取后台用户建议
static getSuggestion: getSuggestionType = (params) =>
axios.get('/userapp/back-user/getSuggestion', { params });
// 后台--删除后台用户建议
static deleteSuggestion: deleteSuggestionType = (params) =>
axios.get('/userapp/back-user/deleteSuggestion', { params });
}
......@@ -21,7 +21,7 @@ interface PropsType {
url: string;
}[],
) => void; // 上传文件改变时的状态
defaultFileList?: any[]; // 默认文件列表
defaultFileList?: { url: string }[]; // 默认文件列表
disabled?: boolean; // 是否禁用
}
export const Uploader: React.FC<PropsType> = (props) => {
......
import React, { useEffect, useState } from 'react';
import { Form, Input, message, Modal, ModalProps } from 'antd';
import { InterDataType, InterReqType } from '~/api/interface';
import { getCompanyInfoByIdType } from '~/api/interface/systemManageType';
import { UploadOutlined } from '@ant-design/icons';
import { Uploader } from '~/components/uploader';
import { getSuggestionType, updateSuggestionType } from '~/api/interface/customManageType';
import { CustomManageAPI } from '~/api';
// 店铺类型
type DetailType = InterDataType<getCompanyInfoByIdType>;
// 请求类型
type ReqType = InterReqType<updateSuggestionType>;
// 列表类型
type DataType = InterDataType<getSuggestionType>[0];
const AddSolutionModal: React.FC<
ModalProps & { detail: DetailType; onCancel?: () => void; data?: DataType }
> = ({ open, onCancel, data }) => {
// 表单数据
const [form] = Form.useForm<ReqType>();
// 封面图列表
const [coverUrlList, setCoverUrlList] = useState<{ url: string }[]>();
// 文件列表
const [suggestFileList, setSuggestFileList] = useState<{ url: string }[]>();
// 封面上传回调
const coverUrlChange = (e: { url: string }[]) => {
setCoverUrlList(e);
form.setFieldValue('coverUrl', e[0].url);
// console.log('封面上传回调 --->', e);
};
// 方案文件回调
const suggestFileChange = (e: { url: string }[]) => {
setSuggestFileList(e);
form.setFieldValue('suggestFile', e[0].url);
// console.log('方案文件回调 --->', e);
};
// 取消事件
const handleCancel = () => {
form.resetFields();
setCoverUrlList([]);
setSuggestFileList([]);
onCancel?.();
};
// 确定事件
const handleOk = () => {
form
.validateFields()
.then(async (values) => {
await handleSubmit(values);
})
.catch((err) => {
// console.log('确定事件 --->', err);
message
.warning({
content: err.errorFields[0].errors[0],
})
.then();
});
};
// 提交事件
const handleSubmit = async (values: ReqType) => {
const res = await CustomManageAPI.updateSuggestion({ ...data, ...values });
if (res && res.code === '200') {
message.success({ content: '操作成功' });
handleCancel();
// console.log('提交事件 --->', values);
}
};
// 组件挂载
useEffect(() => {
if (!data?.id) return;
form.setFieldsValue(data);
setCoverUrlList([{ url: data.coverUrl }]);
setSuggestFileList([{ url: data.suggestFile }]);
}, [data]);
return (
<Modal open={open} title={'添加方案'} width={450} onCancel={handleCancel} onOk={handleOk}>
<Form form={form} labelCol={{ span: 4 }} wrapperCol={{ span: 16 }}>
<Form.Item
label='方案标题'
name='title'
rules={[{ required: true, message: '请输入方案标题' }]}
>
<Input placeholder={'请输入方案标题'} maxLength={6} allowClear />
</Form.Item>
<Form.Item
label='方案封面'
name='coverUrl'
rules={[{ required: true, message: '请上传方案封面' }]}
>
<Uploader
fileUpload
listType='picture-card'
defaultFileList={coverUrlList}
onChange={coverUrlChange}
fileLength={1}
>
<UploadOutlined />
</Uploader>
</Form.Item>
<Form.Item
label='方案文件'
name='suggestFile'
rules={[{ required: true, message: '请输入方案文件' }]}
>
<Uploader
fileUpload
listType='picture-card'
defaultFileList={suggestFileList}
onChange={suggestFileChange}
fileType={['application/pdf']}
fileLength={1}
>
<UploadOutlined />
</Uploader>
</Form.Item>
</Form>
</Modal>
);
};
export default AddSolutionModal;
import React, { useEffect, useState } from 'react';
import { getCompanyInfoByIdType } from '~/api/interface/systemManageType';
import { InterDataType, InterReqType } from '~/api/interface';
import SelectMapModal from '~/components/select-map';
import { Button, Form, Image, Input, Modal, message } from 'antd';
import { Uploader } from '~/components/uploader';
import { UploadOutlined } from '@ant-design/icons';
import { editUserApplyTag } from '~/api/interface/customManageType';
import { useNavigate } from 'react-router-dom';
import { CustomManageAPI } from '~/api';
// 店铺类型
type StoreType = InterDataType<getCompanyInfoByIdType>;
// 请求的表单类型
type ReqType = InterReqType<editUserApplyTag>;
const StoreFormView: React.FC<{
detail: StoreType;
onRefresh?: () => void;
}> = ({ detail, onRefresh }) => {
// 导航钩子
const navigate = useNavigate();
// 表单数据
const [form] = Form.useForm<ReqType>();
// 是否选择地址弹窗
const [openAddress, setOpenAddress] = useState<boolean>(false);
// 选择的地址
const [address, setAddress] = useState<{ lat: number; lon: number; address: string }>();
// 品牌logo文件
const [logoFileList, setLogoFileList] = useState<any>([]);
// 品牌logo更换
const brandLogoChange = (value: any) => {
setLogoFileList(value);
form.setFieldValue('brandLogo', value[0].url);
};
// 店铺图片列表
const [imageList, setImageList] = useState<any>([]);
// 店铺图片列表上传
const imageListChange = (value: any) => {
setImageList(value);
};
// 店铺视频列表
const [videoList, setVideoList] = useState<any>([]);
// 店铺视频列表上传
const videoListChange = (value: any) => {
setVideoList(value);
};
// 返回上一级
const handleBack = () => {
Modal.confirm({
title: '提示',
content: '未保存的内容将丢失,是否确认返回?',
onOk: () => {
navigate(-1);
},
});
};
// 表单验证
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 profileUrl = [
...(imageList?.map((i: { url: string }) => ({ url: i.url, type: 1 })) || []),
...(videoList?.map((i: { url: string }) => ({ url: i.url, type: 2 })) || []),
];
const res = await CustomManageAPI.editUserApplyTag({
companyInfoId: detail?.id,
...detail,
...address,
...values,
profileUrl: JSON.stringify(profileUrl || []),
});
if (res && res.code === '200') {
message.success('操作成功');
onRefresh?.();
}
};
// 获取图片视频回显
const getImageVideo = () => {
try {
const profileUrl = JSON.parse(detail?.profileUrl || `[]`);
setImageList(
profileUrl
?.filter((i: { type: number }) => i.type === 1)
?.map((i: { url: string }) => ({
url: i?.url,
})),
);
setVideoList(
profileUrl
?.filter((i: { type: number }) => i.type === 2)
?.map((i: { url: string }) => ({
url: i?.url,
})),
);
} catch (e) {
console.log(e);
}
};
// componentDidMount
useEffect(() => {
if (!detail?.id) return;
form.setFieldsValue({
...detail,
content: detail?.content || '航拍航测',
address: detail?.address,
name: detail?.companyName,
attachmentList: detail?.attachmentList,
});
setLogoFileList([
{
id: Math.random(),
uid: Math.random().toString(),
name: 'brandLogo',
url: detail?.brandLogo,
},
]);
getImageVideo();
}, []);
return (
<>
<div className={'store-title flex-between'}>
<div className='title'>店铺页面</div>
<div className='action flex-between'>
<Button type={'primary'} onClick={handleOk}>
保存
</Button>
<Button onClick={handleBack}>返回</Button>
</div>
</div>
<Form form={form} labelCol={{ span: 3 }}>
<Form.Item
label='企业名称'
name='name'
rules={[{ required: true, message: '请输入企业名称' }]}
>
<Input placeholder={'请输入企业名称'} maxLength={25} allowClear />
</Form.Item>
<Form.Item
label='网点地址'
name='address'
rules={[{ required: true, message: '请选择网点地址' }]}
>
<Input
value={detail?.address}
placeholder='请选择网点地址'
maxLength={50}
allowClear
style={{ width: '300px', marginRight: '20px' }}
/>
<Button
type='primary'
onClick={() => {
setOpenAddress(true);
}}
>
选择位置
</Button>
</Form.Item>
<Form.Item label='店铺图片' name='imageList'>
<Uploader
fileUpload
listType='picture-card'
defaultFileList={imageList}
onChange={imageListChange}
fileLength={6}
>
<UploadOutlined />
</Uploader>
</Form.Item>
<Form.Item label='店铺视频' name='videoList'>
<Uploader
fileUpload
listType='picture-card'
defaultFileList={videoList}
onChange={videoListChange}
fileLength={1}
fileType={['video/mp4', 'video/avi', 'video/wmv', 'video/rmvb']}
>
<UploadOutlined />
</Uploader>
</Form.Item>
<Form.Item
label='服务资质'
name='content'
rules={[{ required: true, message: '请输入服务资质' }]}
>
<Input.TextArea
placeholder={'请输入服务资质(“;”号换行)'}
maxLength={140}
allowClear
showCount
/>
</Form.Item>
<Form.Item label='品牌logo' name='brandLogo'>
<Uploader
fileUpload
listType='picture-card'
defaultFileList={logoFileList}
onChange={brandLogoChange}
>
<UploadOutlined />
</Uploader>
</Form.Item>
<Form.Item label='营业执照'>
<Image src={detail?.licenseImg} width={45} height={45} />
</Form.Item>
<Form.Item label='备注' name='remark'>
<Input.TextArea placeholder='请输入备注' maxLength={70} showCount rows={4} />
</Form.Item>
</Form>
<SelectMapModal
title='选择位置'
open={openAddress}
closed={() => {
setOpenAddress(false);
}}
submit={(e: { lat: number; lon: number; address: string }) => {
form.setFieldValue('address', e.address);
setAddress(e);
setOpenAddress(false);
}}
/>
</>
);
};
export default StoreFormView;
import React, { useEffect, useState } from 'react';
import { InterDataType } from '~/api/interface';
import { getCompanyInfoByIdType } from '~/api/interface/systemManageType';
import { CustomManageAPI } from '~/api';
import { Button, Table, Image, Modal, message } from 'antd';
import { PlusOutlined } from '@ant-design/icons';
import AddSolutionModal from '../addSolutionModal/index';
import { getSuggestionType } from '~/api/interface/customManageType';
import { ColumnsType } from 'antd/es/table';
// 店铺类型
type DetailType = InterDataType<getCompanyInfoByIdType>;
// 列表类型
type ListType = InterDataType<getSuggestionType>;
const StoreSolutionView: React.FC<{
detail: DetailType;
}> = ({ detail }) => {
// 添加解决方案是否显示
const [isAddSolution, setIsAddSolution] = useState<boolean>(false);
// 当前编辑的数据
const [editData, setEditData] = useState<ListType[0]>();
// 解决方案列表
const [solutionList, setSolutionList] = useState<ListType>([]);
// 获取解决方案列表
const getSolutionList = async () => {
const res = await CustomManageAPI.getSuggestion({
backUserId: detail?.backUserId,
});
if (res && res.code === '200') {
setSolutionList(res.result);
// console.log('获取解决方案列表 --->', res.result);
}
};
// 删除事件
const handleDelete = (record: ListType[0]) => {
Modal.confirm({
title: '提示',
content: '删除后将无法恢复,是否确认删除?',
onOk: async () => {
const res = await CustomManageAPI.deleteSuggestion({
id: record?.id,
});
if (res && res.code === '200') {
await getSolutionList();
message.success('删除成功');
}
},
});
};
// 组件挂载
useEffect(() => {
if (detail?.backUserId) getSolutionList().then();
// console.log('storeSolutionView --->', detail);
}, []);
const columns: ColumnsType<ListType[0]> = [
{
title: '序号',
dataIndex: 'accountNo',
align: 'center',
width: '50px',
render: (_text, _record, index) => index + 1,
},
{
title: '方案名称',
dataIndex: 'title',
align: 'center',
},
{
title: '方案封面',
dataIndex: 'coverUrl',
align: 'center',
render: (text) => <Image src={text} width={35} height={35} />,
},
{
title: '方案文件',
dataIndex: 'suggestFile',
align: 'center',
render: (text) => (
<a href={text} target={'_blank'} rel='noreferrer'>
查看
</a>
),
},
{
title: '操作',
dataIndex: 'action',
align: 'center',
render: (_text, record) => (
<>
<Button
type={'link'}
onClick={() => {
setEditData(record);
setIsAddSolution(true);
}}
>
编辑
</Button>
<Button type={'link'} onClick={() => handleDelete(record)} danger>
删除
</Button>
</>
),
},
];
return (
<>
<div className={'store-title flex-between'}>
<div className='title'>行业解决方案</div>
<div className='action'>
<Button icon={<PlusOutlined />} type={'primary'} onClick={() => setIsAddSolution(true)}>
添加解决方案
</Button>
</div>
</div>
<Table
dataSource={solutionList}
rowKey={'id'}
columns={columns}
size={'small'}
bordered={true}
></Table>
<AddSolutionModal
open={isAddSolution}
detail={detail}
data={editData}
onCancel={() => {
setIsAddSolution(false);
setEditData(undefined);
getSolutionList().then();
}}
/>
</>
);
};
export default StoreSolutionView;
.store-decorate-wrap {
position: relative;
width: 100%;
min-width: 1200px;
box-sizing: border-box;
align-items: flex-start !important;
.store-form,.store-solution {
width: 40%;
margin-right: 5%;
.store-title {
position: relative;
width: 100%;
box-sizing: border-box;
margin-bottom: 15px;
padding: 10px 0 0 15px;
.title {
font-weight: bold;
font-size: 18px;
}
.action {
width: 110px;
}
}
}
.store-solution {
width: 50%;
margin-right: 0;
.store-title{
padding-left: 0;
}
}
}
import React, { useEffect, useState } from 'react';
import { store } from '~/store';
import { InterDataType } from '~/api/interface';
import { SystemManageAPI } from '~/api';
import { getCompanyInfoByIdType } from '~/api/interface/systemManageType';
import './index.scss';
import StoreFormView from '~/pages/resourceManage/storeDecorate/comp/storeFormView';
import StoreSolutionView from '~/pages/resourceManage/storeDecorate/comp/storeSolutionView';
// 店铺类型
type StoreType = InterDataType<getCompanyInfoByIdType>;
const StoreDecoratePage: React.FC = () => {
const [storeDetail, setStoreDetail] = useState<StoreType>();
// 获取店铺数据
const getStoreApplyDetail = async () => {
const res = await SystemManageAPI.getCompanyInfoById({
id: store.getState().UserInfo.userInfo?.companyInfoVO?.id,
});
if (res && res.code === '200') {
setStoreDetail(res.result);
console.log('获取店铺数据 --->', res.result);
}
};
// 页面挂载
useEffect(() => {
if (store.getState().UserInfo?.userInfo?.companyInfoVO?.id) getStoreApplyDetail().then();
// console.log('页面挂载 --->', store.getState().UserInfo?.userInfo);
}, []);
return (
<div className={'store-decorate-wrap flex-start'}>
<div className={'store-form'}>
{!!storeDetail?.id && (
<StoreFormView detail={storeDetail} onRefresh={getStoreApplyDetail} />
)}
</div>
<div className={'store-solution'}>
{!!storeDetail?.id && <StoreSolutionView detail={storeDetail} />}
</div>
</div>
);
};
export default StoreDecoratePage;
......@@ -173,6 +173,7 @@ import CompanyMemberView from '~/pages/systemManage/companyManage/companyMember'
import CourseCategoryView from '~/pages/pilotTraining/courseCategory';
import NoticeManageView from '~/pages/resourceManage/noticeManage';
import CustomApplyPage from '~/pages/customManage/customApply';
import StoreDecoratePage from 'src/pages/resourceManage/storeDecorate';
const AddressManageView = React.lazy(() => import('~/pages/systemManage/addressManage'));
// const IndustryListView = React.lazy(() => import('~/pages/mallManage/industryManage/industryList')); //行业列表
......@@ -994,6 +995,16 @@ export const routerList: Array<RouteObjectType> = [
icon: <CommentOutlined />,
},
},
{
path: '/resourceManage/storeDecorate',
element: withLoadingComponent(<StoreDecoratePage />),
errorElement: <ErrorPage />,
meta: {
id: 880,
title: '店铺页面',
icon: <ShopOutlined />,
},
},
],
},
{
......
......@@ -17,3 +17,71 @@
background: #1677ff !important;
}
}
.flex-center {
display: flex;
flex-wrap: wrap;
justify-content: center;
align-items: center;
}
.flex-start {
display: flex;
flex-wrap: wrap;
justify-content: flex-start;
align-items: center;
}
.flex-baseline {
display: flex;
flex-wrap: wrap;
justify-content: flex-start;
align-items: baseline;
}
.flex-end {
display: flex;
flex-wrap: wrap;
justify-content: flex-end;
align-items: center;
}
.flex-between {
display: flex;
flex-wrap: wrap;
justify-content: space-between;
align-items: center;
}
.flex-around {
display: flex;
flex-wrap: wrap;
justify-content: space-around;
align-items: center;
}
.text-ellipsis {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.select-none{
user-select: none;
-moz-user-select: none;
-webkit-user-select: none;
-ms-user-select: none;
}
.align-start {
align-items: flex-start;
}
.cursor-pointer {
cursor: pointer;
}
.two-line-ellipsis {
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
}
// 下划线
.text-underline {
text-decoration: underline;
}
// 删除线
.text-line-through {
text-decoration: line-through;
}
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论