提交 22137be3 作者: 龚洪江

Merge remote-tracking branch 'origin/master'

# Conflicts:
#	src/router/router.tsx
FROM node:18-alpine
FROM node:18-alpine as builder
WORKDIR /app
COPY package.json .
COPY package-lock.json .
RUN npm ci
COPY . .
EXPOSE 5173
CMD ["npm", "run", "dev"]
\ No newline at end of file
#EXPOSE 5173
#CMD ["npm", "run", "dev"]
RUN npm run build
# nginx
FROM nginx:alpine as production
ENV NODE_ENV production
# Set working directory to nginx asset directory
COPY --from=builder /app/dist /usr/share/nginx/html
#COPY nginx.conf /etc/nginx/conf.d/default.conf
COPY nginx.conf /etc/nginx/nginx.conf
EXPOSE 80
# Containers run nginx with global directives and daemon off
ENTRYPOINT ["nginx", "-g", "daemon off;"]
\ No newline at end of file
#请求接口地址
VITE_REQUEST_BASE_URL='https://www.iuav.shop'
#VITE_REQUEST_BASE_URL='https://test.iuav.shop'
#VITE_REQUEST_BASE_URL='https://www.iuav.shop'
VITE_REQUEST_BASE_URL='https://test.iuav.shop'
#VITE_REQUEST_BASE_URL='/api'
#旧版接口地址
#VITE_REQUEST_BASE_URL='https://iuav.mmcuav.cn'
#VITE_REQUEST_BASE_URL='https://test.iuav.mmcuav.cn'
......
......@@ -23,4 +23,4 @@ spec:
memory: 512Mi
cpu: 100m
ports:
- containerPort: 5173
\ No newline at end of file
- containerPort: 80
\ No newline at end of file
......@@ -6,7 +6,6 @@ metadata:
spec:
selector:
app: admin
type: NodePort
ports:
- protocol: TCP
port: 5173
port: 80
......@@ -10,4 +10,8 @@ commonAnnotations:
note: This is dev!
patches:
- path: ./increase_replicas.yaml
- path: ./configMap.yaml
\ No newline at end of file
- path: ./configMap.yaml
images:
- name: REGISTRY/NAMESPACE/IMAGE:TAG
newName: mmc-registry.cn-shenzhen.cr.aliyuncs.com/sharefly-dev/admin
newTag: fc6718648897f381269cb10c9fafa0c95dacf0e1
......@@ -10,4 +10,8 @@ commonAnnotations:
note: This is prod!
patches:
- path: increase_replicas.yaml
- path: configMap.yaml
\ No newline at end of file
- path: configMap.yaml
images:
- name: REGISTRY/NAMESPACE/IMAGE:TAG
newName: mmc-registry.cn-shenzhen.cr.aliyuncs.com/sharefly/admin
newTag: 7075ed8a992197acf49f443b0694ae9b9bd8ad5b
user nginx;
worker_processes 1;
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile on;
keepalive_timeout 65;
client_max_body_size 100M;
server {
listen 80;
server_name _;
add_header 'Access-Control-Allow-Origin' '*';
add_header 'Access-Control-Allow-Credentials' 'true';
add_header 'Access-Control-Allow-Methods' '*';
add_header 'Access-Control-Allow-Headers' '*';
location / {
root /usr/share/nginx/html;
include /etc/nginx/mime.types;
try_files $uri $uri/ /index.html;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
}
}
\ No newline at end of file
......@@ -8,6 +8,8 @@ import { CouponManageAPI } from './modules/couponManage';
import { MakeManageAPI } from './modules/makeManage';
import { CategoryManageAPI } from './modules/categoryManage';
import { SystemManageAPI } from './modules/systemManage';
import { CustomManageAPI } from './modules/customManage';
import { MallManageAPI } from './modules/mallManage';
export {
CommonAPI,
......@@ -20,4 +22,6 @@ export {
MakeManageAPI,
CategoryManageAPI,
SystemManageAPI,
CustomManageAPI,
MallManageAPI,
};
import { InterFunction, InterListFunction } from '~/api/interface';
// 客户列表
export type listAppUserType = InterListFunction<
{
companyAuthStatus?: number;
endTime?: string;
keyword?: string;
phoneNum?: string;
startTime?: string;
},
{
id: number;
accountType: number;
uid: string;
accountNo: null;
phoneNum: string;
userName: null;
nickName: string;
userImg: string;
userSex: number;
email: null;
source: null;
accountStatus: number;
remark: null;
portType: number;
createTime: string;
companyAuthStatus: number;
cooperationTagId: number;
companyName: null;
tagName: null;
}
>;
// 加盟标签列表
export type CompanyListTag = InterFunction<
NonNullable<unknown>,
{
id: number;
tagName: string;
tagImg: null;
tagDescription: string;
createTime: string;
}[]
>;
// 修改用户信息
export type userAccountUpdateType = InterFunction<
{
accountNo?: string;
accountStatus?: number;
accountType?: number;
companyAuthStatus?: number;
companyName?: string;
cooperationTagId?: number;
createTime?: string;
email?: string;
id: number;
nickName?: string;
phoneNum?: string;
portType?: number;
remark?: string;
source?: number;
tagName?: string;
uid?: string;
userImg?: string;
userName?: string;
userSex?: number;
},
NonNullable<unknown>
>;
// 后台设置小程序用户标签
export type changeUserTagType = InterFunction<
{
cooperationTagId: number;
userAccountId: number;
},
NonNullable<unknown>
>;
import { InterFunction, InterListFunction } from '~/api/interface';
// V1.0.1课程视频列表
export type queryCurriculumInfoListType = InterListFunction<
{
curriculumName?: string;
flightSkillsId?: number;
licenseId?: number;
regionId?: number;
},
{
curriculumDesc: string;
curriculumName: string;
detailContent: null;
flightSkills: number;
flightSkillsName1: string;
flightSkillsName2: string;
free: number;
id: number;
price: null;
supplierName: string;
surfaceUrl: null;
videoUrl: string;
}
>;
// V1.0.1新增课程
export type addCurriculumType = InterFunction<
{
curriculumDesc?: string;
curriculumName: string;
detailContent?: string;
flightSkills: number;
flightSkillsName1: string;
flightSkillsName2: string;
free: number;
id: number;
price: number;
supplierName: string;
surfaceUrl: string;
videoUrl: string;
},
NonNullable<unknown>
>;
import axios from '../request';
import {
changeUserTagType,
CompanyListTag,
listAppUserType,
userAccountUpdateType,
} from '~/api/interface/customManageType';
export class CustomManageAPI {
// 客户列表
static listAppUser: listAppUserType = (params) =>
axios.post('/userapp/user-account/listAppUser', params);
// 加盟列表
static CompanyListTag: CompanyListTag = (params) =>
axios.get('/userapp/cooperation/listTag', { params });
// 客户列表
static userAccountUpdate: userAccountUpdateType = (params) =>
axios.post('/userapp/user-account/update', params);
// 后台设置小程序用户标签
static changeUserTag: changeUserTagType = (params) =>
axios.get('/userapp/cooperation/changeUserTag', { params });
}
import axios from '~/api/request';
import { addCurriculumType, queryCurriculumInfoListType } from '~/api/interface/mallManageType';
export class MallManageAPI {
// V1.0.1课程视频列表
static queryCurriculumInfoList: queryCurriculumInfoListType = (params) =>
axios.post('/release/curriculum/queryCurriculumInfoList', params);
// V1.0.1新增课程
static addCurriculum: addCurriculumType = (params) =>
axios.post('/release/curriculum/addCurriculum', params);
}
......@@ -13,7 +13,7 @@ const service = axios.create({
});
service.interceptors.request.use(
(config: any) => {
const token = Cookies.get('SHAREFLY_TOKEN');
const token = Cookies.get('SHAREFLY-TOKEN');
// console.log('token --->', token);
if (token) {
config.headers.token = token;
......
......@@ -10,7 +10,7 @@
// min-width: 200px;
//}
.ant-form-item {
margin-inline-end: 20px;
margin-inline-end: 15px;
}
.ant-row {
......
import { Form, Input, Button, Select, DatePicker } from 'antd';
import { Form, Input, Button, Select, DatePicker, TreeSelect, Cascader } from 'antd';
import moment from 'dayjs';
import { SearchOutlined, ReloadOutlined, ExportOutlined } from '@ant-design/icons';
import React, { useImperativeHandle } from 'react';
......@@ -8,7 +8,7 @@ const { RangePicker } = DatePicker;
// 搜索列表的类型
export interface searchColumns {
type: 'input' | 'select' | 'rangePicker' | 'DatePicker' | 'Select';
type: 'input' | 'select' | 'rangePicker' | 'DatePicker' | 'Select' | 'TreeSelect' | 'Cascader';
label?: string;
name: string;
placeholder: string;
......@@ -155,6 +155,33 @@ const Index: React.FC<propsType> = (props) => {
showTime={item.showTime}
style={{ width: item.width ? `${item.width}px` : '180px' }}
/>
) : item.type === 'TreeSelect' ? (
<TreeSelect
allowClear
treeDefaultExpandAll
placeholder={item.placeholder}
treeData={item.options}
fieldNames={{
label: 'name',
value: 'id',
children: 'childNodes',
}}
popupClassName='head-search-treeSelect'
style={{ width: item.width ? `${item.width}px` : '180px' }}
/>
) : item.type === 'Cascader' ? (
<Cascader
allowClear
changeOnSelect
placeholder={item.placeholder}
options={item.options}
fieldNames={{
label: 'name',
value: 'id',
children: 'childNodes',
}}
style={{ width: item.width ? `${item.width}px` : '180px' }}
/>
) : (
''
)}
......
......@@ -9,7 +9,7 @@ import './index.scss';
function Index(props: any) {
const headers: any = {
token: Cookies.get('SXTB-TOKEN'),
token: Cookies.get('SHAREFLY-TOKEN'),
};
const [form] = Form.useForm();
const [imageUrl, setImageUrl] = useState('');
......
import { Modal, Form, Input, Button, Row, Col, message } from 'antd';
import React, { useEffect, useState } from 'react';
import { PlusOutlined, MinusOutlined } from '@ant-design/icons';
import { PropsType } from '~/common/interface/modal';
import { categoryDec } from '~/api/modules/goods';
import { CategoryManageAPI } from '~/api';
interface selfPropsType {
directoryList: categoryDec[];
refreshDec: Function;
}
const AddOrEditDec: React.FC<PropsType & selfPropsType> = ({
isModalVisible,
handleOk,
handleCancel,
directoryList,
refreshDec,
}) => {
const [form] = Form.useForm<any>();
// 表单目录标题列表
const [addOrEditDirectoryList, setAddOrEditDirectoryList] = useState<categoryDec[]>([]);
// 是否点击删除按钮
const [isClickDle, setIsClickDle] = useState<boolean>(false);
useEffect(() => {
if (directoryList.length != 0 && !isClickDle) {
setAddOrEditDirectoryList(directoryList);
const defaultFormValue = directoryList.reduce((pre: any, cur: categoryDec) => {
Object.keys(cur).map((item: string) => {
if (item === 'id') {
pre[cur[item]] = cur.sortName;
}
});
return pre;
}, {});
form.setFieldsValue(defaultFormValue);
}
}, [directoryList]);
// 新增或修改目录
const addDirectoryTitle = () => {
const decList: categoryDec[] = [...addOrEditDirectoryList].sort(
(a: categoryDec, b: categoryDec) => a.id - b.id,
);
setAddOrEditDirectoryList([
...addOrEditDirectoryList,
{
id: decList[decList.length - 1].id + 1,
defaultType: 1,
sortName: '',
},
]);
};
// 删除目录
const deleteDirectory = async (id: number) => {
const bol: boolean = directoryList.some((item: categoryDec) => item.id === id);
const index = addOrEditDirectoryList.findIndex((item: categoryDec) => item.id === id);
if (bol) {
const res: any = await CategoryManageAPI.removeDirectory(id);
if (res.code === '200') {
message.success('删除成功');
setIsClickDle(true);
refreshDec(id);
} else {
return message.warning(res.message);
}
}
const obj: any = {};
obj[id] = undefined;
form.setFieldsValue(obj);
addOrEditDirectoryList.splice(index, 1);
setAddOrEditDirectoryList([...addOrEditDirectoryList]);
};
const directorySureEvent = () => {
form.validateFields().then(async (value: any) => {
const requestList = Object.keys(value).reduce((pre: any, cur: string) => {
const bol: boolean = directoryList.some((item: any) => item.id === Number(cur));
if (bol) {
pre.push({
id: Number(cur),
directoryName: value[cur],
});
} else {
pre.push({
directoryName: value[cur],
});
}
return pre;
}, []);
const res: any = await CategoryManageAPI.addOrEditDirectory(requestList);
if (res.code === '200') {
message.success('操作成功');
form.resetFields();
setIsClickDle(false);
handleOk();
} else {
message.warning(res.message);
}
});
};
const directoryCancel = () => {
form.resetFields();
setIsClickDle(false);
handleCancel();
};
return (
<Modal
title='目录管理'
open={isModalVisible}
onOk={directorySureEvent}
onCancel={directoryCancel}
>
<Form form={form} labelCol={{ span: 6 }} wrapperCol={{ span: 16 }}>
<Form.Item label='添加目录' labelCol={{ span: 4 }} wrapperCol={{ span: 16 }}>
<Button icon={<PlusOutlined />} onClick={addDirectoryTitle} />
</Form.Item>
{addOrEditDirectoryList.map((item: categoryDec) => (
<Row key={item.id} gutter={{ xs: 8, sm: 16, md: 24 }}>
<Col span={16}>
<Form.Item
label='目录名称'
name={item.id}
rules={[{ required: true, message: '请输入目录名称' }]}
>
<Input placeholder='请输入目录名称' maxLength={30} />
</Form.Item>
</Col>
<Col>
{item.defaultType ? (
<Button
icon={<MinusOutlined />}
type='primary'
onClick={() => deleteDirectory(item.id)}
/>
) : (
''
)}
</Col>
</Row>
))}
</Form>
</Modal>
);
};
export default AddOrEditDec;
......@@ -57,19 +57,20 @@ const AddOrEditDec: React.FC<PropsType & selfPropsType> = ({
const [hasPid, setHasPid] = useState(false); //是否有上级目录
const [submitLoading, setSubmitLoading] = useState(false); //提交按钮的loading
const [directoryOptions, setDirectoryOptions] = useState([]); //目录options
const id = editData?.id;
useEffect(() => {
if (isModalVisible) {
form.setFieldValue('type', editData.type);
form.setFieldValue('pid', editData.pid);
form.setFieldValue('directoryName', editData.directoryName);
onChangeType(editData.type);
if (editData) {
form.setFieldValue('type', editData.type);
form.setFieldValue('pid', editData.pid);
form.setFieldValue('directoryName', editData.directoryName);
onChangeType(editData.type);
if (editData.pid) {
setHasPid(true);
} else {
setHasPid(false);
if (editData.pid) {
setHasPid(true);
} else {
setHasPid(false);
}
}
}
}, [isModalVisible]);
......@@ -90,7 +91,7 @@ const AddOrEditDec: React.FC<PropsType & selfPropsType> = ({
try {
const res = await CategoryManageAPI.addOrEditDirectory({
...values,
id,
id: editData?.id,
pid: hasPid ? values.pid : null,
});
res.code == '200' && message.success('新增成功');
......@@ -122,7 +123,7 @@ const AddOrEditDec: React.FC<PropsType & selfPropsType> = ({
<Form.Item label='分类模块' name='type' rules={[{ required: true }]}>
<Select options={typeOptions} allowClear={true} onChange={onChangeType}></Select>
</Form.Item>
<Form.Item label='目录类型'>
{/* <Form.Item label='目录类型'>
<Radio.Group onChange={(e: RadioChangeEvent) => setHasPid(e.target.value)} value={hasPid}>
<Radio value={false}>无关联目录</Radio>
<Radio value={true}>有关联目录</Radio>
......@@ -136,7 +137,7 @@ const AddOrEditDec: React.FC<PropsType & selfPropsType> = ({
allowClear={true}
></Select>
</Form.Item>
)}
)} */}
<Form.Item label='目录名称' name='directoryName' rules={[{ required: true }]}>
<Input placeholder='请输入目录名称' allowClear={true}></Input>
......
......@@ -71,7 +71,7 @@ const DirectoryManage: FC = (props: any) => {
});
return <div>{find?.label}</div>;
},
},
} /*
{
title: '目录类型',
dataIndex: 'directoryType',
......@@ -83,7 +83,7 @@ const DirectoryManage: FC = (props: any) => {
dataIndex: 'relevanceName',
key: 'relevanceName',
align: 'center',
},
}, */,
{
title: '操作',
key: 'action',
......
import { FC, useEffect, useState } from 'react';
import { Form, Modal, Select } from 'antd';
// import { tagLevelEntity } from "@/api/modules/user";
// import { UserAPI } from "@/api";
import { InterListType } from '~/api/interface';
import { listAppUserType } from '~/api/interface/customManageType';
import { CustomManageAPI } from '~/api';
// 表格数据类型
type TableType = InterListType<listAppUserType>;
// 数据的类型
interface PropsType {
visible: boolean;
open: boolean;
closed: any;
data: any;
state: any;
data?: TableType[0];
}
// 修改等级标签
interface tagLevelForm {
channelLevelId: number;
mallOperator: number;
mallSaleManager: number;
cooperationTagId: number;
}
export const ChangeModal: FC<PropsType> = (props) => {
ChangeModal.defaultProps = {
data: undefined,
};
// 父组件传参
const { visible, closed, data, state } = props;
const { open, closed, data } = props;
// 个人等级标签
const [tagLevelForm] = Form.useForm<tagLevelForm>();
const [form] = Form.useForm<tagLevelForm>();
// 相关运营列表
const [operationList] = useState([]);
const [operationList] = useState<{ value: number; label: string }[]>([]);
// 等级标签列表
const [cooperationTagIdList, setCooperationTagIdList] = useState<
{ value: number; label: string }[]
>([]);
// 关闭事件
const handleClosed = () => {
tagLevelForm.resetFields();
form.resetFields();
closed();
};
// 提交数据
const handleSubmit = () => {
tagLevelForm.validateFields().then(async (value: tagLevelForm) => {
// 提交表单数据
const SubmitFuc = async () => {
// const res: any = await UserAPI.mallUserChangeInfo({
// ...value,
// userAccountId: data.id,
// });
// if (res.code === '200') {
// message.success('修改成功');
// handleClosed();
// } else {
// message.warning(res.message);
// }
};
// 如果之前填过等级标签,现在又删除了的话,调用删除等级标签的接口
if (data.channelClass && !value.channelLevelId) {
// 删除等级标签
// const res: any = await UserAPI.mallUserDeleteInfo({
// userAccountId: data.id,
// });
// if (res && res.code === '200') {
// await SubmitFuc();
// } else {
// message.warning(res.message);
// }
} else {
await SubmitFuc();
form.validateFields().then(async (value) => {
const res = await CustomManageAPI.changeUserTag({
userAccountId: Number(data?.id),
cooperationTagId: value.cooperationTagId,
});
if (res && res.code === '200') {
handleClosed();
}
});
};
// 获取运营人员列表
const getListOperate = () => {
// UserAPI.getKbtUserList({ keyword: '' }).then(({ result }) => {
// if (result) {
// setOperationList(
// result.map((i: any) => {
// return {
// label: `${i.userName || i.nickName}(${i.uid})`,
// value: i.id,
// };
// }),
// );
// }
// });
// 获取加盟列表
const getCompanyListTag = async () => {
const res = await CustomManageAPI.CompanyListTag({});
if (res && res.code === '200') {
setCooperationTagIdList(res.result.map((i) => ({ value: i.id, label: i.tagName })));
// console.log(res.result);
}
};
// 组件启动
useEffect(() => {
if (data) {
getListOperate();
tagLevelForm.setFieldsValue({
channelLevelId: data.channelClass || undefined,
mallOperator: data.mallOperator || undefined,
mallSaleManager: data.mallSaleManager || undefined,
});
}
}, [data]);
if (!data) return;
getCompanyListTag().then();
form.setFieldsValue({
cooperationTagId: data.cooperationTagId,
});
}, [open]);
return (
<Modal open={visible} title='变更' onCancel={handleClosed} destroyOnClose onOk={handleSubmit}>
<Form form={tagLevelForm} labelCol={{ span: 5 }} wrapperCol={{ span: 16 }}>
<Form.Item label='等级标签' name='channelLevelId'>
<Modal open={open} title='变更' onCancel={handleClosed} destroyOnClose onOk={handleSubmit}>
<Form form={form} labelCol={{ span: 5 }} wrapperCol={{ span: 16 }}>
<Form.Item label='等级标签' name='cooperationTagId'>
<Select
placeholder='请选择等级标签'
disabled={!data?.realAuthStatus && !data?.entAuthStatus}
disabled={!data?.userName && !data?.companyName}
allowClear
>
{state.levelTags.map((item: any, index: number) => (
<Select.Option value={item.id} key={index}>
{item.tagName}
</Select.Option>
))}
</Select>
options={cooperationTagIdList}
/>
</Form.Item>
<Form.Item label='相关运营' name='mallOperator'>
<Select placeholder='请选择相关运营' allowClear>
<Select placeholder='请选择相关运营' allowClear disabled>
{operationList.map((item: any, index: number) => (
<Select.Option value={item.value} key={index}>
{item.label}
......@@ -113,7 +86,7 @@ export const ChangeModal: FC<PropsType> = (props) => {
</Select>
</Form.Item>
<Form.Item label='相关销售' name='mallSaleManager'>
<Select placeholder='请选择相关销售' allowClear>
<Select placeholder='请选择相关销售' allowClear disabled>
{operationList.map((item: any, index: number) => (
<Select.Option value={item.value} key={index}>
{item.label}
......
import { useState } from 'react';
import { useEffect, useState } from 'react';
import SearchBox from '~/components/search-box';
import { Button, Table } from 'antd';
import { ColumnsType } from 'antd/es/table';
import { ChangeModal } from '~/pages/customManage/customList/comp/changeModal';
import { InterListType, InterReqType } from '~/api/interface';
import { listAppUserType } from '~/api/interface/customManageType';
import { CustomManageAPI } from '~/api';
// 表格数据类型
type TableType = any;
type TableType = InterListType<listAppUserType>;
// 请求数据的类型
type ReqType = InterReqType<listAppUserType>;
// 搜索表单的数据
let query: ReqType = {};
//来源列表
const portTypeList = [
{ value: 100, label: '自然流' },
{ value: 200, label: '海报' },
{ value: 300, label: '抖音' },
{ value: 400, label: '公众号' },
{ value: 500, label: '社群' },
{ value: 600, label: '招投标' },
];
function CustomListView() {
// 等级标签列表
const [cooperationTagIdList, setCooperationTagIdList] = useState<
{ value: number; label: string }[]
>([]);
// 是否打开变更弹窗
const [isChangeVisModal, setIsChangeVisModal] = useState<boolean>(false);
// 表格分页配置
const [pagination] = useState({
const [pagination, setPagination] = useState({
total: 0,
pageSize: 10,
current: 1,
totalPage: 0,
});
// 表格数据
const [tableData] = useState<TableType>([{ id: 1 }]);
const [tableData, setTableData] = useState<TableType>([]);
// 需要编辑的数据
const [editData] = useState<TableType[0]>();
const [editData, setEditData] = useState<TableType[0]>();
// 加载列表
const getTableList = async (value = {}) => {
// 只需要修改这个地方的接口即可
const res = await CustomManageAPI.listAppUser({
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);
}
};
// 翻页
const paginationChange = (pageNo: number, pageSize: number) => {
getTableList({ pageNo, pageSize }).then();
};
// 表单提交
const onFinish = (data: ReqType) => {
pagination.current = 1;
query = data;
getTableList(data).then();
};
// 获取加盟列表
const getCompanyListTag = async () => {
const res = await CustomManageAPI.CompanyListTag({});
if (res && res.code === '200') {
setCooperationTagIdList(res.result.map((i) => ({ value: i.id, label: i.tagName })));
// console.log(res.result);
}
};
// componentDidMount
useEffect(() => {
query = {};
(async () => {
await getCompanyListTag();
await getTableList();
})();
}, []);
// 表格结构
const columns: ColumnsType<TableType[0]> = [
{
title: '用户UID',
dataIndex: 'userName',
dataIndex: 'uid',
align: 'center',
render: (_text, _record) => `--`,
width: '100px',
render: (text) => `UID${text}`,
},
{
title: '用户名称',
dataIndex: 'userName',
align: 'center',
render: (_text, _record) => `--`,
render: (text, record) => text || record.nickName,
},
{
title: '手机号',
dataIndex: 'userName',
dataIndex: 'phoneNum',
align: 'center',
render: (_text, _record) => `--`,
},
{
title: '认证企业',
dataIndex: 'userName',
dataIndex: 'companyName',
align: 'center',
render: (_text, _record) => `--`,
},
{
title: '企业认证',
dataIndex: 'userName',
dataIndex: 'companyAuthStatus',
align: 'center',
render: (_text, _record) => `--`,
render: (text) => (text === 0 ? '未认证' : '已认证'),
},
{
title: '电子签约认证',
dataIndex: 'userName',
align: 'center',
render: (_text, _record) => `--`,
render: (_text) => `未认证`,
},
{
title: '用户来源',
dataIndex: 'userName',
dataIndex: 'portType',
align: 'center',
render: (_text, _record) => `--`,
render: (text) => portTypeList.find((i) => i.value === text)?.label || text,
},
{
title: '创建时间',
dataIndex: 'userName',
dataIndex: 'createTime',
align: 'center',
render: (_text, _record) => `--`,
},
{
title: '账号类型',
dataIndex: 'userName',
dataIndex: 'phoneNum',
align: 'center',
render: (_text, _record) => `--`,
render: (text) => (text ? '普通用户' : '游客用户'),
},
{
title: '渠道等级',
dataIndex: 'remark',
dataIndex: 'cooperationTagId',
align: 'center',
render: (_text, _record) => `--`,
render: (text) => cooperationTagIdList.find((i) => i.value === text)?.label || text,
},
{
title: '上级推荐人',
dataIndex: 'remark',
align: 'center',
render: (_text, _record) => `--`,
render: (_text) => `--`,
},
{
title: '推荐伙伴',
dataIndex: 'remark',
align: 'center',
render: (_text, _record) => `--`,
render: (_text) => `--`,
},
{
title: '相关运营',
dataIndex: 'remark',
align: 'center',
render: (_text, _record) => `--`,
render: (_text) => `--`,
},
{
title: '相关销售',
dataIndex: 'remark',
align: 'center',
render: (_text, _record) => `--`,
render: (_text) => `--`,
},
{
title: '操作',
dataIndex: 'action',
align: 'center',
fixed: 'right',
width: '150px',
render: (_text, _record) => (
width: '100px',
render: (_text, record) => (
<>
<Button
type={'link'}
onClick={() => {
setEditData(JSON.parse(JSON.stringify(record)));
setIsChangeVisModal(true);
}}
>
......@@ -148,46 +214,39 @@ function CustomListView() {
},
{
label: '来源',
name: 'form',
name: 'portType',
type: 'Select',
placeholder: '请选择相关来源',
options: [
{ value: 1, label: '自然流' },
{ value: 2, label: '海报' },
{ value: 3, label: '抖音' },
{ value: 4, label: '公众号' },
{ value: 5, label: '社群' },
{ value: 6, label: '招投标' },
],
options: portTypeList,
},
{
label: '创建时间',
name: 'time',
name: 'rangeTime',
type: 'rangePicker',
placeholder: '请选择创建时间',
},
{
label: '企业认证',
name: 'enterprise',
type: 'Select',
placeholder: '请选择是否认证',
options: [
{ value: 1, label: '未认证' },
{ value: 2, label: '已认证' },
],
},
{
label: '电子签约认证',
name: 'contract',
name: 'companyAuthStatus',
type: 'Select',
placeholder: '请选择是否认证',
options: [
{ value: 1, label: '未认证' },
{ value: 2, label: '已认证' },
{ value: 0, label: '未认证' },
{ value: 1, label: '已认证' },
],
},
// {
// label: '电子签约认证',
// name: 'contract',
// type: 'Select',
// placeholder: '请选择是否认证',
// options: [
// { value: 1, label: '未认证' },
// { value: 2, label: '已认证' },
// ],
// },
]}
searchData={(e: any) => console.log('提交数据 --->', e)}
searchData={onFinish}
/>
<Table
size='small'
......@@ -201,19 +260,18 @@ function CustomListView() {
current: pagination.current,
showSizeChanger: true,
showQuickJumper: true,
// onChange: (page: number, pageSize: number) =>
// paginationChange(page, pageSize),
onChange: (page: number, pageSize: number) => paginationChange(page, pageSize),
showTotal: (total, range) => `当前 ${range[0]}-${range[1]} 条记录 / 共 ${total} 条数据`,
}}
// rowSelection={{ selectedRowKeys, onChange: onSelectChange }}
/>
<ChangeModal
visible={isChangeVisModal}
open={isChangeVisModal}
closed={() => {
setIsChangeVisModal(false);
paginationChange(pagination.current, pagination.pageSize);
}}
data={editData}
state={{ levelTags: [] }}
/>
</>
);
......
import { InterListType, InterReqType } from '~/api/interface';
import React, { useEffect } from 'react';
import { Col, Form, Input, message, Modal, Radio, Row, Select } from 'antd';
import { Uploader } from '~/components/uploader';
import { PlusOutlined } from '@ant-design/icons';
import { OrderManageAPI } from '~/api';
import { addCurriculumType, queryCurriculumInfoListType } from '~/api/interface/mallManageType';
// 表格数据类型
type TableType = InterListType<queryCurriculumInfoListType>;
// 请求数据的类型
type ReqType = InterReqType<addCurriculumType>;
// 传参类型
interface propType {
title: string;
open: boolean;
closed: any;
data?: TableType[0];
}
const AddEditModal: React.FC<propType> = (props) => {
AddEditModal.defaultProps = {
data: undefined,
};
// 参数
const { title, open, closed, data } = props;
// 物流列表
const [expressList, setExpressList] = React.useState<{ label: string; value: string }[]>([]);
// 表单钩子
const [form] = Form.useForm<ReqType>();
// 关闭弹窗
const handleCancel = () => {
form.resetFields();
closed();
};
// 确认事件
const handleOk = () => {
form
.validateFields()
.then(async (values) => {
// console.log('确认事件 --->', values);
await handleSubmit(values);
})
.catch((err) => {
message
.warning({
content: err.errorFields[0].errors[0],
})
.then();
});
};
// 提交事件
const handleSubmit = async (values: ReqType) => {
const res = await OrderManageAPI.sendOrderWare({
...values,
orderInfoId: Number(data?.id),
});
if (res && res.code === '200') {
message.success('操作成功');
handleCancel();
}
};
// 获取物流信息
const getListExpressInfo = async () => {
const res = await OrderManageAPI.listExpressInfo({});
if (res && res.code === '200') {
setExpressList(res.result.map((item) => ({ label: item.exName, value: item.exCode })));
// console.log(res);
}
};
// componentDidMount
useEffect(() => {
if (!open) return;
if (!data) return;
getListExpressInfo().then();
// console.log('data --->', data);
}, [open]);
return (
<Modal
open={open}
title={title}
onCancel={handleCancel}
onOk={handleOk}
destroyOnClose
width={600}
>
<Form
name='addForm'
form={form}
labelAlign='right'
labelCol={{ span: 8 }}
wrapperCol={{ span: 16 }}
autoComplete='new-password'
>
<Form.Item label='收货地址' labelCol={{ span: 4 }}>
{data?.receipt?.takeName} {data?.receipt?.takePhone} {data?.receipt?.detailAddress}
</Form.Item>
<Form.Item label='发货方式' labelCol={{ span: 4 }}>
物流发货
</Form.Item>
<Row gutter={{ xs: 8, sm: 16, md: 24 }}>
<Col span={11}>
<Form.Item
label='物流单号'
name='sendExNo'
rules={[{ required: true, message: '请输入物流单号' }]}
>
<Input placeholder={'请输入物流单号'} maxLength={20} allowClear />
</Form.Item>
</Col>
<Col span={11}>
<Form.Item
label='物流公司'
name='sendExCode'
rules={[{ required: true, message: '请选择物流公司' }]}
>
<Select placeholder={'请选择物流公司'} options={expressList} allowClear />
</Form.Item>
</Col>
</Row>
<Row gutter={{ xs: 8, sm: 16, md: 24 }}>
<Col span={11}>
<Form.Item
label='归还联系人'
name='renName'
rules={[{ required: true, message: '请输入归还联系人' }]}
>
<Input placeholder={'请输入归还联系人'} maxLength={20} allowClear />
</Form.Item>
</Col>
<Col span={11}>
<Form.Item
label='归还电话'
name='renPhone'
rules={[
{ required: true, message: '请输入归还联系人电话' },
// 校验手机号
() => ({
validator(_, value) {
if (!value || /^1[3-9]\d{9}$/.test(value)) {
return Promise.resolve();
}
return Promise.reject('请输入正确的手机号');
},
}),
]}
>
<Input
placeholder={'请输入归还联系人电话'}
maxLength={20}
allowClear
type={'number'}
/>
</Form.Item>
</Col>
</Row>
<Row gutter={{ xs: 8, sm: 16, md: 24 }}>
<Col span={11}>
<Form.Item
label='归还地址'
name='renAddress'
rules={[{ required: true, message: '请输入归还地址' }]}
>
<Input placeholder={'请输入归还地址'} maxLength={20} allowClear />
</Form.Item>
</Col>
</Row>
<Row gutter={{ xs: 8, sm: 16, md: 24 }}>
<Col span={11}>
<Form.Item
label='质检照片'
name='imgs'
rules={[{ required: true, message: '请上传质检照片' }]}
>
<Uploader
listType={'picture-card'}
fileUpload
fileLength={3}
onChange={(e) => {
form.setFieldValue(
'imgs',
e.map((item) => item.url),
);
}}
>
<PlusOutlined />
</Uploader>
</Form.Item>
</Col>
<Col span={11}>
<Form.Item
label='质检视频'
name='videoUrl'
rules={[{ required: true, message: '请上传质检视频' }]}
>
<Uploader
listType={'picture-card'}
fileUpload
fileLength={1}
fileType={['video/mp4', 'video/avi', 'video/wmv', 'video/rmvb']}
fileSize={10}
onChange={(e) => {
form.setFieldValue('videoUrl', e[0].url);
}}
>
<PlusOutlined />
</Uploader>
</Form.Item>
</Col>
</Row>
<Row gutter={{ xs: 8, sm: 16, md: 24 }}>
<Col span={11}>
<Form.Item
label='设备状态'
name='vcuSatus'
rules={[{ required: true, message: '请选择设备状态' }]}
initialValue={0}
>
<Radio.Group
options={[
{ label: '正常', value: 0 },
{ label: '故障', value: 1 },
]}
onChange={(e) => {
form.setFieldValue('vcuSatus', e.target.value);
}}
/>
</Form.Item>
</Col>
<Col span={11}>
<Form.Item
label='操作密码'
name='authPwd'
rules={[{ required: true, message: '请输入操作密码' }]}
>
<Input.Password
placeholder={'请输入操作密码'}
maxLength={20}
allowClear
autoComplete='new-password'
/>
</Form.Item>
</Col>
</Row>
</Form>
</Modal>
);
};
export default AddEditModal;
import { useEffect, useState } from 'react';
import SearchBox from '~/components/search-box';
import { Button, Table, Image } from 'antd';
import { PlusOutlined } from '@ant-design/icons';
import { queryCurriculumInfoListType } from '~/api/interface/mallManageType';
import { InterListType, InterReqType } from '~/api/interface';
import { MallManageAPI } from '~/api';
import { ColumnsType } from 'antd/es/table';
import AddEditModal from './comp/addEditModal';
// 表格数据类型
type TableType = InterListType<queryCurriculumInfoListType>;
// 请求数据的类型
type ReqType = InterReqType<queryCurriculumInfoListType>;
// 搜索表单的数据
let query: ReqType = {};
const CourseManageView = () => {
// 是否打开变更弹窗
const [isAddEditVisModal, setIsAddEditVisModal] = useState<boolean>(false);
// 表格分页配置
const [pagination, setPagination] = useState({
total: 0,
pageSize: 10,
current: 1,
totalPage: 0,
});
// 表格数据
const [tableData, setTableData] = useState<TableType>([]);
// 需要编辑的数据
const [editData, setEditData] = useState<TableType[0]>();
// 加载列表
const getTableList = async (value = {}) => {
// 只需要修改这个地方的接口即可
const res = await MallManageAPI.queryCurriculumInfoList({
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);
}
};
// 翻页
const paginationChange = (pageNo: number, pageSize: number) => {
getTableList({ pageNo, pageSize }).then();
};
// 表单提交
const onFinish = (data: ReqType) => {
pagination.current = 1;
query = data;
getTableList(data).then();
};
// 表格结构
const columns: ColumnsType<TableType[0]> = [
{
title: '课程名称',
dataIndex: 'curriculumName',
align: 'center',
width: '150px',
},
{
title: '课程类型',
dataIndex: 'flightSkillsName1',
align: 'center',
width: '150px',
render: (text, record) => `${text}/${record.flightSkillsName2}`,
},
{
title: '课程类型',
dataIndex: 'curriculumDesc',
align: 'center',
width: '150px',
ellipsis: true,
},
{
title: '封面图',
dataIndex: 'surfaceUrl',
align: 'center',
width: '150px',
render: (text, record) => (
<>
<Image
src={text ? text : `${record.videoUrl}?x-oss-process=video/snapshot,t_1000,m_fast`}
alt={'封面图'}
style={{ width: '35px', height: '35px' }}
/>
</>
),
},
{
title: '操作',
dataIndex: 'action',
align: 'center',
fixed: 'right',
width: '100px',
render: (_text, record) => (
<>
<Button
type={'link'}
onClick={() => {
setEditData(JSON.parse(JSON.stringify(record)));
setIsAddEditVisModal(true);
}}
>
编辑
</Button>
<Button type={'link'} danger>
删除
</Button>
</>
),
},
];
// componentDidMount
useEffect(() => {
query = {};
(async () => {
await getTableList();
})();
}, []);
return (
<>
<SearchBox
search={[
{
label: '课程名称',
name: 'keyword',
type: 'input',
placeholder: '请输入课程名称',
},
{
label: '课程类型',
name: 'companyAuthStatus',
type: 'Select',
placeholder: '请选择是否认证',
options: [
{ value: 0, label: '未认证' },
{ value: 1, label: '已认证' },
],
},
]}
searchData={onFinish}
child={
<>
<Button
type={'primary'}
icon={<PlusOutlined />}
onClick={() => {
setIsAddEditVisModal(true);
}}
>
新建课程
</Button>
</>
}
/>
<Table
size='small'
dataSource={tableData}
columns={columns}
rowKey='id'
// scroll={{ x: 1200 }}
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} 条数据`,
}}
// rowSelection={{ selectedRowKeys, onChange: onSelectChange }}
/>
<AddEditModal
open={isAddEditVisModal}
closed={() => {
setIsAddEditVisModal(false);
paginationChange(pagination.current, pagination.pageSize);
}}
data={editData}
title={editData?.id ? '编辑' : '新增'}
/>
</>
);
};
export default CourseManageView;
......@@ -95,6 +95,7 @@ const OrderConfirm: React.FC<propType> = (props) => {
labelAlign='right'
labelCol={{ span: 8 }}
wrapperCol={{ span: 16 }}
autoComplete='new-password'
>
<Form.Item label='收货方式' labelCol={{ span: 4 }}>
物流归还
......
......@@ -91,6 +91,7 @@ const OrderDeliver: React.FC<propType> = (props) => {
labelAlign='right'
labelCol={{ span: 8 }}
wrapperCol={{ span: 16 }}
autoComplete='new-password'
>
<Form.Item label='收货地址' labelCol={{ span: 4 }}>
{data?.receipt?.takeName} {data?.receipt?.takePhone} {data?.receipt?.detailAddress}
......
......@@ -11,7 +11,7 @@ function PrivateRouter() {
const beforeEach = () => {
// TODO: 判断是否登录 (需要改为实时获取地址栏的路由)
const path = location.pathname;
const token = Cookies.get('SHAREFLY_TOKEN');
const token = Cookies.get('SHAREFLY-TOKEN');
if (!token && path !== '/login') {
location.replace('/login');
return;
......
......@@ -16,12 +16,15 @@ import {
ReconciliationOutlined,
SolutionOutlined,
RedEnvelopeOutlined,
SettingOutlined,
UserOutlined,
SendOutlined,
RocketOutlined,
AppstoreAddOutlined,
AppstoreOutlined,
CoffeeOutlined,
UnorderedListOutlined,
BookOutlined,
} from '@ant-design/icons';
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
......@@ -41,6 +44,8 @@ import DivideRules from '~/pages/pointManage/divideRules';
import CustomListView from '~/pages/customManage/customList';
import CustomMoneyView from '~/pages/customManage/customMoney';
import CustomMoneyDetail from '~/pages/customManage/customMoney/detail';
import AccountManageView from '~/pages/systemManage/accountManage';
import CourseManageView from '~/pages/mallManage/courseManage';
// 活动
const ActivityList = React.lazy(() => import('src/pages/activityManage/activityList')); //活动管理
......@@ -223,6 +228,15 @@ export const routerList: Array<RouteObjectType> = [
},
children: [
{
path: '/mallManage/courseManage',
element: withLoadingComponent(<CourseManageView />),
meta: {
id: 10190,
icon: <BookOutlined />,
title: '课程管理',
},
},
{
path: '/mallManage/serviceList',
element: withLoadingComponent(<ServiceListView />),
meta: {
......@@ -349,6 +363,82 @@ export const routerList: Array<RouteObjectType> = [
],
},
{
path: '/categoryManage',
element: <LayoutView />,
errorElement: <ErrorPage />,
meta: {
id: 18000,
icon: <ReconciliationOutlined />,
title: '分类管理',
},
children: [
{
path: '/categoryManage/jobServicesCategory/1',
element: withLoadingComponent(<CategoryManage />),
meta: {
id: 18100,
title: '作业服务分类',
icon: <SendOutlined />,
},
},
{
path: '/categoryManage/jobServicesCategory/2',
element: withLoadingComponent(<CategoryManage />),
meta: {
id: 18200,
title: '设备租赁分类',
icon: <RocketOutlined />,
},
},
{
path: '/categoryManage/jobServicesCategory/3',
element: withLoadingComponent(<CategoryManage />),
meta: {
id: 18300,
title: '飞手培训分类',
icon: <AppstoreAddOutlined />,
},
},
{
path: '/categoryManage/jobServicesCategory/4',
element: withLoadingComponent(<CategoryManage />),
meta: {
id: 18400,
title: '产品商城分类',
icon: <AppstoreOutlined />,
},
},
{
path: '/categoryManage/jobServicesCategory/0',
element: withLoadingComponent(<CategoryManage />),
meta: {
id: 18500,
title: '通用分类',
icon: <CoffeeOutlined />,
},
},
{
path: '/categoryManage/detail/:id',
element: withLoadingComponent(<CategoryDetail />),
meta: {
id: 18600,
title: '分类详情',
icon: '',
hidden: true,
},
},
{
path: '/categoryManage/DirectoryManage',
element: withLoadingComponent(<DirectoryManage />),
meta: {
id: 18700,
title: '目录管理',
icon: <UnorderedListOutlined />,
},
},
],
},
{
path: '/customManage',
element: <LayoutView />,
errorElement: <ErrorPage />,
......@@ -374,6 +464,7 @@ export const routerList: Array<RouteObjectType> = [
id: 26200,
title: '现金管理',
icon: <RedEnvelopeOutlined />,
hidden: true,
},
},
{
......@@ -556,77 +647,22 @@ export const routerList: Array<RouteObjectType> = [
],
},
{
path: '/categoryManage',
path: '/systemManage',
element: <LayoutView />,
errorElement: <ErrorPage />,
meta: {
id: 18000,
icon: <ReconciliationOutlined />,
title: '分类管理',
id: 28000,
icon: <SettingOutlined />,
title: '系统管理',
},
children: [
{
path: '/categoryManage/jobServicesCategory/1',
element: withLoadingComponent(<CategoryManage />),
path: '/systemManage/accountManage',
element: withLoadingComponent(<AccountManageView />),
meta: {
id: 18100,
title: '作业服务分类',
icon: <SendOutlined />,
},
},
{
path: '/categoryManage/jobServicesCategory/2',
element: withLoadingComponent(<CategoryManage />),
meta: {
id: 18200,
title: '设备租赁分类',
icon: <RocketOutlined />,
},
},
{
path: '/categoryManage/jobServicesCategory/3',
element: withLoadingComponent(<CategoryManage />),
meta: {
id: 18300,
title: '飞手培训分类',
icon: <AppstoreAddOutlined />,
},
},
{
path: '/categoryManage/jobServicesCategory/4',
element: withLoadingComponent(<CategoryManage />),
meta: {
id: 18400,
title: '产品商城分类',
icon: <AppstoreOutlined />,
},
},
{
path: '/categoryManage/jobServicesCategory/0',
element: withLoadingComponent(<CategoryManage />),
meta: {
id: 18500,
title: '通用分类',
icon: <CoffeeOutlined />,
},
},
{
path: '/categoryManage/detail/:id',
element: withLoadingComponent(<CategoryDetail />),
meta: {
id: 18600,
title: '分类详情',
icon: '',
hidden: true,
},
},
{
path: '/categoryManage/DirectoryManage',
element: withLoadingComponent(<DirectoryManage />),
meta: {
id: 18700,
title: '目录管理',
icon: <UnorderedListOutlined />,
id: 28100,
title: '账号管理',
icon: <UserOutlined />,
},
},
],
......
......@@ -5,7 +5,7 @@ import { resolve } from 'path';
// https://vitejs.dev/config/
export default defineConfig({
base: './',
base: '/',
plugins: [react(), tsconfigPaths()],
server: {
host: '0.0.0.0',
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论