提交 87957d9f 作者: ZhangLingKun

Merge branch 'develop'

......@@ -47,6 +47,7 @@
],
"jsx-a11y/click-events-have-key-events": "off",
"jsx-a11y/no-static-element-interactions": "off",
"react/display-name": "off"
"react/display-name": "off",
"jsx-a11y/no-noninteractive-element-interactions": 'off'
}
}
......@@ -31,6 +31,14 @@ jobs:
- name: Checkout
uses: actions/checkout@v3
- name: WeChat Work notification by text
uses: chf007/action-wechat-work@master
env:
WECHAT_WORK_BOT_WEBHOOK: https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=9be1b073-1760-442d-8e3d-faa0fd32ea16
with:
msgtype: text
content: "GitHub提交信息\n - 提交人: ${{github.actor}}\n - 提交信息: ${{ github.event.head_commit.message }}\n - 提交到仓库: ${{github.repository}}\n - 提交到分支: ${{github.ref}}\n 即将开始更新,请关注Argocd同步状态..."
- name: Login to ACR EE with the AccessKey pair
uses: aliyun/acr-login@v1
with:
......
#请求接口地址
#VITE_REQUEST_BASE_URL='https://www.iuav.shop'
VITE_REQUEST_BASE_URL='https://test.iuav.shop'
VITE_REQUEST_BASE_URL='https://test.iuav.shop' // 测试服
#VITE_REQUEST_BASE_URL='https://iuav.mmcuav.cn'
#VITE_REQUEST_BASE_URL='/api'
#旧版接口地址
......
......@@ -4,7 +4,7 @@ metadata:
name: admin-deployment
namespace: default
spec:
minReadySeconds: 5
minReadySeconds: 10
revisionHistoryLimit: 2
replicas: 1
selector:
......@@ -27,6 +27,7 @@ spec:
cpu: 100m
ports:
- containerPort: 80
name: admin-port
volumes:
- name: log-of-nginx
hostPath:
......
......@@ -3,9 +3,9 @@ kind: Deployment
metadata:
name: admin-deployment
spec:
replicas: 2
replicas: 1
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 1
\ No newline at end of file
maxUnavailable: 0
......@@ -14,4 +14,4 @@ patches:
images:
- name: REGISTRY/NAMESPACE/IMAGE:TAG
newName: mmc-registry.cn-shenzhen.cr.aliyuncs.com/sharefly-dev/admin
newTag: c533f36fd07802ddc4791dbaaf1a0b66e0a38222
newTag: 682d7c8f7979b4524ab8018ee5e4ffc04baf18ed
......@@ -60,7 +60,7 @@
"prettier": "^2.6.2",
"sass": "^1.62.0",
"typescript": "^4.6.3",
"vite": "^4.3.5",
"vite": "^4.3.9",
"vite-tsconfig-paths": "^3.5.0"
}
}
......@@ -10,6 +10,8 @@ import { CategoryManageAPI } from './modules/categoryManage';
import { SystemManageAPI } from './modules/systemManage';
import { CustomManageAPI } from './modules/customManage';
import { MallManageAPI } from './modules/mallManage';
import { ResourceManageAPI } from './modules/resourceManageAPI';
import { ForumManageAPI } from './modules/forumManageAPI';
export {
CommonAPI,
......@@ -24,4 +26,6 @@ export {
SystemManageAPI,
CustomManageAPI,
MallManageAPI,
ResourceManageAPI,
ForumManageAPI,
};
......@@ -29,6 +29,14 @@ export type listAppUserType = InterListFunction<
cooperationTagId: number;
companyName: null;
tagName: null;
cooperationTagVOS: {
createTime: string;
id: number;
tagDescription: string;
tagImg: string;
tagName: string;
tagRequire: string;
}[];
}
>;
// 加盟标签列表
......@@ -75,3 +83,78 @@ export type changeUserTagType = InterFunction<
},
NonNullable<unknown>
>;
// 后台设置小程序用户标签
export type changeUserTagNew = InterFunction<
{
cooperationTagIds: number[];
userAccountId: number;
},
NonNullable<unknown>
>;
// 加盟标签列表
export type cooperationListTag = InterFunction<
NonNullable<unknown>,
{
createTime: string;
id: number;
tagDescription: string;
tagImg: string;
tagName: string;
}[]
>;
// 后台申请列表
export type listUserApplyTag = InterListFunction<
{
applyStatus?: number;
cooperationTagId?: number;
endTime?: string;
startTime?: string;
},
{
applyName: string;
applyPhone: string;
applyTime: string;
approvalStatus: number;
attachmentList: null;
cooperationTagId: number;
cooperationTagName: string;
id: number;
remark: string;
userAccountId: number;
}
>;
// 审批详情
export type applyTagDetails = InterFunction<
{
id?: number;
userAccountId?: number;
},
{
attachmentList: {
/**
* 附件类型:0:图片 1:文件
*/
type: number;
url: string;
}[];
companyName: string;
creditCode: string;
licenseImg: string;
remark: string;
}
>;
// 审批
export type approvalApplyTag = InterFunction<
{
id: number;
status: boolean;
},
NonNullable<unknown>
>;
// 强制删除
export type deleteApplyTag = InterFunction<
{
id: number;
},
NonNullable<unknown>
>;
import { InterFunction, InterItemFunction } from '~/api/interface';
//论坛-列表
export type forumListType = InterItemFunction<
{ keyword?: string },
{
description: string;
userBaseInfo: {
nickName: string;
phone: string;
uid: string;
userImg: string;
userName: string;
};
show: number;
id: number;
}[]
>;
//论坛-删除
export type deleteForumType = InterFunction<{ dynamicId: number }, any>;
//论坛-隐藏
export type hiddenForumType = InterFunction<{ dynamicId: number }, any>;
//论坛-详情
type detailResponseType = {
userBaseInfo: {
nickName: string;
phone: string;
uid: string;
userImg: string;
userName: string;
};
description: string;
dynamicPublishTime: string;
id: number;
likes: boolean;
likesCount: number;
mediaVO: { type: number; url: string }[];
commentCount: number;
commentAndReplyVO: detailResponseType[];
};
export type forumDetailType = InterFunction<{ dynamicId: number }, detailResponseType>;
//论坛-点赞信息
export type likeUserInfoType = InterFunction<
{ dynamicId: number },
{ nickName: string; userImg: string; userName: string }[]
>;
......@@ -305,19 +305,19 @@ export type orderDetailType = InterFunction<
// 后台管理——发货-订单/ 卖家发货
export type sendOrderWareType = InterFunction<
{
authPwd: string;
imgs: Array<string>;
orderInfoId: number;
orderRefundId: number;
remark: string;
renAddress: string;
renName: string;
renPhone: string;
sendAddress: string;
sendExCode: string;
sendExNo: string;
vcuSatus: number;
videoUrl: string;
authPwd?: string;
imgs?: Array<string>;
orderInfoId?: number;
orderRefundId?: number;
remark?: string;
renAddress?: string;
renName?: string;
renPhone?: string;
sendAddress?: string;
sendExCode?: string;
sendExNo?: string;
vcuSatus?: number;
videoUrl?: string;
},
NonNullable<unknown>
>;
......
import { InterFunction, InterItemFunction, InterListFunction } from '~/api/interface';
//需求列表
export type listPublishPageType = InterItemFunction<
{ requirementTypeId?: number; keyword?: string },
{
id: number;
publishName: string;
publishPhone: string;
requireDescription: string;
requirementTypeId: number;
requirementTypeName: string;
}[]
>;
//需求类型列表
export type requirementsListType = InterFunction<any, { id: number; typeName: string }[]>;
//需求-强制删除
export type deleteRequirementsType = InterFunction<{ requirementsInfoId: number }, any>;
// 查询招标快讯列表-分页
export type releaseTenderNews = InterListFunction<
{
endTime?: string;
startTime?: string;
tenderName?: string;
using?: number;
},
{
createTime: Date;
id: number;
port: number;
tenderName: string;
using: number;
}
>;
// 新增招标快讯
export type releaseTenderNewsAdd = InterFunction<any, any>;
// 修改招标快讯
export type releaseTenderNewsUpdate = InterFunction<any, any>;
// 删除招标快讯
export type releaseTenderNewsDelete = InterFunction<{ id: number }, any>;
// 查询-招标快讯详情列表-分页
export type releaseTenderNewsInfo = InterListFunction<
{
tenderNewsId?: number;
},
{
createTime: string;
id: number;
tenderContent: string;
tenderInfoNo: string;
tenderNewsId: number;
tenderPrice: number;
tenderTitle: string;
}
>;
// 修改-招标快讯详情
export type releaseTenderNewsInfoUpdate = InterListFunction<
{
id: number;
tenderContent?: string;
tenderPrice?: number;
tenderTitle?: string;
},
NonNullable<unknown>
>;
// 用户反馈列表-分页
export type releaseTenderNewsApplyList = InterListFunction<
{
tenderInfoId?: number;
tenderNewsId?: number;
userName?: string;
},
{
createTime: string;
id: number;
nickName: string;
phoneNum: string;
tenderInfoId: number;
tenderInfoNo: string;
tenderTitle: string;
userName: string;
}
>;
//行业新闻-列表
export type industryNewsListType = InterItemFunction<
{ newsTitle?: string },
{
id: number;
createTime: string;
newsAuthor: string;
newsContents: string;
newsTitle: string;
origin: string;
surfaceImg: string;
}[]
>;
//行业新闻-新增
export type addIndustryNewsType = InterFunction<
{
newsAuthor: string;
newsContents?: string;
newsTitle: string;
origin: string;
surfaceImg: string;
},
any
>;
//行业新闻-编辑
export type editIndustryNews = InterFunction<
{
newsAuthor: string;
newsContents?: string;
newsTitle: string;
origin: string;
surfaceImg: string;
id?: number;
},
any
>;
//行业新闻-删除
export type deleteIndustryNewsType = InterFunction<{ id: number }, any>;
//行业新闻-详情
export type industryNewsDetailType = InterFunction<
{ id: number },
{
id: number;
createTime: string;
newsAuthor: string;
newsContents: string;
newsTitle: string;
origin: string;
surfaceImg: string;
}
>;
// 案例列表
export type industryCaseListCasePage = InterListFunction<
{
cityCode?: number;
date?: string;
districtCode?: number;
keyword?: string;
provinceCode?: number;
requirementTypeId?: number;
},
{
caseAuthor: string;
caseContents: string;
caseTitle: string;
createTime: string;
id: number;
origin: string;
surfaceImg: null;
updateTime: string;
userAccountId: number;
}
>;
// 添加业务案例
export type industryCaseAddCase = InterFunction<
{
caseAuthor?: string;
caseContents?: string;
caseTitle?: string;
createTime?: string;
id?: number;
origin?: string;
surfaceImg?: string;
updateTime?: string;
userAccountId?: number;
},
NonNullable<unknown>
>;
// 修改业务案例
export type industryCaseUpdateCase = InterFunction<
{
caseAuthor?: string;
caseContents?: string;
caseTitle?: string;
createTime?: string;
id?: number;
origin?: string;
surfaceImg?: string;
updateTime?: string;
userAccountId?: number;
},
NonNullable<unknown>
>;
// 删除业务案例
export type industryCaseDeleteDetails = InterFunction<{ id: number }, NonNullable<unknown>>;
import axios from '../request';
import {
applyTagDetails,
approvalApplyTag,
changeUserTagNew,
changeUserTagType,
CompanyListTag,
cooperationListTag,
deleteApplyTag,
listAppUserType,
listUserApplyTag,
userAccountUpdateType,
} from '~/api/interface/customManageType';
......@@ -19,4 +25,22 @@ export class CustomManageAPI {
// 后台设置小程序用户标签
static changeUserTag: changeUserTagType = (params) =>
axios.get('/userapp/cooperation/changeUserTag', { params });
// 后台设置小程序用户标签
static changeUserTagNew: changeUserTagNew = (params) =>
axios.post('/userapp/cooperation/changeUserTag', params);
// 加盟标签列表
static cooperationListTag: cooperationListTag = (params) =>
axios.get('/userapp/cooperation/listTag', { params });
// 后台申请列表
static listUserApplyTag: listUserApplyTag = (params) =>
axios.post('/userapp/cooperation/listUserApplyTag', params);
// 审批详情
static applyTagDetails: applyTagDetails = (params) =>
axios.get('/userapp/cooperation/applyTagDetails', { params });
// 审批
static approvalApplyTag: approvalApplyTag = (params) =>
axios.get('/userapp/cooperation/approvalApplyTag', { params });
// 强制删除
static deleteApplyTag: deleteApplyTag = (params) =>
axios.get('/userapp/cooperation/deleteApplyTag', { params });
}
import {
deleteForumType,
forumDetailType,
forumListType,
hiddenForumType,
likeUserInfoType,
} from '~/api/interface/forumManageType';
import axios from '~/api/request';
export class ForumManageAPI {
//论坛-列表
static getForumList: forumListType = (data) =>
axios.post('/release/backstage/forum/listDynamic', data);
//论坛-删除
static deleteForum: deleteForumType = (params) =>
axios.get('/release/backstage/forum/deleteDynamic', { params });
//论坛-隐藏
static hiddenForum: hiddenForumType = (params) =>
axios.get('/release/backstage/forum/hiddenDynamic', { params });
// 论坛-详情
static getForumDetail: forumDetailType = (params) =>
axios.get('/release/dynamic/dynamicDetails', { params });
// 论坛-点赞人信息
static getLikeUserInfoList: likeUserInfoType = (params) =>
axios.get('/release/backstage/forum/likeUserInfo', { params });
}
import {
listPublishPageType,
requirementsListType,
releaseTenderNews,
releaseTenderNewsAdd,
releaseTenderNewsDelete,
releaseTenderNewsUpdate,
releaseTenderNewsInfo,
releaseTenderNewsInfoUpdate,
releaseTenderNewsApplyList,
addIndustryNewsType,
industryNewsListType,
editIndustryNews,
industryNewsDetailType,
industryCaseListCasePage,
industryCaseAddCase,
industryCaseUpdateCase,
industryCaseDeleteDetails,
deleteIndustryNewsType,
deleteRequirementsType,
} from '~/api/interface/resourceManageType';
import axios from '../request';
export class ResourceManageAPI {
//需求列表
static getListPublishPage: listPublishPageType = (data) =>
axios.post('/release/requirements/listPublishPage', data);
// 需求类型列表
static getRequirementTypeList: requirementsListType = () =>
axios.get('/release/requirements/listType');
//需求-强制删除
static deleteRequirement: deleteRequirementsType = (params) =>
axios.get('/release/requirements/deleteRequire', { params });
// 查询招标快讯列表-分页
static releaseTenderNews: releaseTenderNews = (params) =>
axios.get('/release/tender/news', { params });
// 新增招标快讯
static releaseTenderNewsAdd: releaseTenderNewsAdd = (params) =>
axios.post('/release/tender/news', params);
// 修改招标快讯
static releaseTenderNewsUpdate: releaseTenderNewsUpdate = (params) =>
axios.put('/release/tender/news', params);
// 删除招标快讯
static releaseTenderNewsDelete: releaseTenderNewsDelete = (params) =>
axios.delete(`/release/tender/news/${params?.id}`);
// 查询-招标快讯详情列表-分页
static releaseTenderNewsInfo: releaseTenderNewsInfo = (params) =>
axios.get('/release/tender/info', { params });
// 修改-招标快讯详情
static releaseTenderNewsInfoUpdate: releaseTenderNewsInfoUpdate = (params) =>
axios.put('/release/tender/info', params);
// 用户反馈列表-分页
static releaseTenderNewsApplyList: releaseTenderNewsApplyList = (params) =>
axios.post('/release/tender/applyList', params);
// 行业新闻-新增
static addIndustryNews: addIndustryNewsType = (data) =>
axios.post('/release/industry-news/insertIndustryNews', data);
// 行业新闻-列表
static getIndustryNewsList: industryNewsListType = (data) =>
axios.post('/release/industry-news/backgroundListNewsPage', data);
// 行业新闻-编辑
static editIndustryNews: editIndustryNews = (data) =>
axios.post('/release/industry-news/upDateIndustryNews', data);
// 行业新闻-详情
static getIndustryNewsDetail: industryNewsDetailType = (params) =>
axios.get('/release/industry-news/details', { params });
// 行业新闻-删除
static removeIndustryNews: deleteIndustryNewsType = (params) =>
axios.get('/release/industry-news/deleteIndustryNews', { params });
// 案例列表
static industryCaseListCasePage: industryCaseListCasePage = (params) =>
axios.post('/release/industry-case/listCasePage', params);
// 添加业务案例
static industryCaseAddCase: industryCaseAddCase = (params) =>
axios.post('/release/industry-case/addCase', params);
// 修改业务案例
static industryCaseUpdateCase: industryCaseUpdateCase = (params) =>
axios.post('/release/industry-case/updateCase', params);
// 删除业务案例
static industryCaseDeleteDetails: industryCaseDeleteDetails = (params) =>
axios.get('/release/industry-case/deleteDetails', { params });
}
......@@ -18,7 +18,7 @@ export class SystemManageAPI {
// 账号-删除
static removeBAccount: removeBAccountType = (params) =>
axios.get('/userapp/back-user/removeBAccount', { params });
axios.get('/userapp/user-account/removeAppAccount', { params });
// 账号-修改
static updateBAccount: updateBAccountType = (params) =>
......
import React, { useEffect } from 'react';
import E from 'wangeditor';
import { message } from 'antd';
// import events from '@/events';
import { CommonAPI } from '~/api';
let editor: any = null;
interface PropsType {
onChange: (html?: string) => void;
onChange?: (html?: string) => void;
value: string | undefined;
// eslint-disable-next-line react/require-default-props
isDetail?: boolean;
height?: number;
}
const RichText: React.FC<PropsType> = ({ onChange, value, isDetail, height }) => {
RichText.defaultProps = {
// eslint-disable-next-line @typescript-eslint/no-empty-function
onChange: () => {},
};
useEffect(() => {
// 注:class写法需要在componentDidMount 创建编辑器
editor = new E('.edit');
......@@ -40,9 +42,9 @@ const RichText: React.FC<PropsType> = ({ onChange, value, isDetail, height }) =>
};
editor.config.onchange = (newHtml: string) => {
if (newHtml) {
onChange(newHtml);
onChange?.(newHtml);
} else {
onChange(undefined);
onChange?.(undefined);
}
};
......
......@@ -2,6 +2,8 @@ import React, { useEffect, useState } from 'react';
import { message, Upload, UploadProps } from 'antd';
import { CommonAPI } from '~/api';
import './index.scss';
import Viewer from '~/components/viewer';
import saveAs from 'file-saver';
interface PropsType {
listType?: 'text' | 'picture' | 'picture-card'; // 上传列表的内建样式
......@@ -19,6 +21,7 @@ interface PropsType {
}[],
) => void; // 上传文件改变时的状态
defaultFileList?: any[]; // 默认文件列表
disabled?: boolean; // 是否禁用
}
export const Uploader: React.FC<PropsType> = (props) => {
Uploader.defaultProps = {
......@@ -29,6 +32,7 @@ export const Uploader: React.FC<PropsType> = (props) => {
// eslint-disable-next-line @typescript-eslint/no-empty-function
onChange: () => {},
defaultFileList: [],
disabled: false,
};
const {
fileType = ['image/png', 'image/jpeg', 'image/jpg', 'image/gif', 'image/bmp'],
......@@ -39,7 +43,13 @@ export const Uploader: React.FC<PropsType> = (props) => {
fileLength,
onChange,
defaultFileList,
disabled,
} = props;
// 是否上传图片
const [visible, setVisible] = useState<boolean>(false);
// 当前选择的文件
const [currentFile, setCurrentFile] = useState<string>();
// 文件列表
const [fileList, setFileList] = useState<any[]>([]);
// 上传文件配置
const uploadProps: UploadProps = {
......@@ -111,7 +121,20 @@ export const Uploader: React.FC<PropsType> = (props) => {
setFileList(newFileList);
onChange?.(newFileList);
},
// onPreview: { onPreview },
onPreview: (res) => {
const { url } = res;
const fileType = url?.substring(url?.lastIndexOf('.') + 1) || '';
if (['png', 'jpg', 'bmp', 'gif', 'jpeg', 'webp'].includes(fileType)) {
setCurrentFile(url);
setVisible(true);
} else {
if (url) {
saveAs(url.replace(/^http:/, 'https:'));
} else {
window.open(url);
}
}
},
};
useEffect(() => {
// 如果有默认文件列表
......@@ -124,14 +147,27 @@ export const Uploader: React.FC<PropsType> = (props) => {
return (
<div className='uploader-view'>
{listType === 'text' ? (
<Upload {...uploadProps} style={{ width: '100%' }}>
<Upload {...uploadProps} style={{ width: '100%' }} disabled={disabled}>
<>{fileList.length < (fileLength || 1) && children}</>
</Upload>
) : (
<Upload {...uploadProps} style={{ width: '100%' }}>
<Upload {...uploadProps} style={{ width: '100%' }} disabled={disabled}>
{fileList.length < (fileLength || 1) && children}
</Upload>
)}
<Viewer
visible={visible}
currentImgList={[
{
src: currentFile,
alt: '图片',
},
]}
activeViewerIndex={0}
setVisible={() => {
setVisible(false);
}}
/>
</div>
);
};
......@@ -5,6 +5,7 @@ interface propsType {
visible: boolean;
currentImgList: any;
activeViewerIndex: number;
// eslint-disable-next-line @typescript-eslint/ban-types
setVisible: Function;
}
......
......@@ -23,7 +23,7 @@ import Viewer from '~/components/viewer';
import './index.scss';
import events from '~/events';
const Category: FC = (props: any) => {
const Category: FC = () => {
const location = useLocation();
console.log('location', location);
const navigate = useNavigate();
......@@ -57,7 +57,7 @@ const Category: FC = (props: any) => {
width: '12%',
editable: true,
ellipsis: true,
render: (text: string, record: categoryEntity, index: number) => {
render: (_text: string, record: categoryEntity) => {
return (
<Tooltip placement='top' title={<span>{record.classifyName}</span>}>
<span
......@@ -84,12 +84,13 @@ const Category: FC = (props: any) => {
key: 'icon',
width: '12%',
align: 'center',
render: (text: string, record: categoryEntity, index: number) => {
render: (_text: string, record: categoryEntity) => {
return record.icon ? (
<img
src={record.icon}
style={{ width: '25px', height: '25px' }}
onClick={() => imgClick(record.icon)}
alt='图片'
/>
) : (
''
......@@ -104,7 +105,7 @@ const Category: FC = (props: any) => {
align: 'center',
editable: true,
ellipsis: true,
render: (text: string, record: categoryEntity, index: number) => {
render: (_text: string, record: categoryEntity) => {
return (
<Tooltip placement='right' title={<span>{record.description}</span>}>
<span>{record.description}</span>
......@@ -124,7 +125,7 @@ const Category: FC = (props: any) => {
width: '55%',
key: 'option',
align: 'center',
render: (text: string, record: categoryEntity, index: number) => {
render: (_text: string, record: categoryEntity) => {
return (
<div className='table-option-wrap'>
{record.level == 1 ? (
......@@ -165,7 +166,7 @@ const Category: FC = (props: any) => {
确定
</Button>
<Button type='link' onClick={() => cancelAddCldCgy(record, index)}>
<Button type='link' onClick={() => cancelAddCldCgy(record)}>
取消
</Button>
</>
......@@ -232,8 +233,6 @@ const Category: FC = (props: any) => {
const [activeViewerIndex] = useState<number>(0);
// 新增弹窗
const [isVisible, setIsVisible] = useState<boolean>(false);
// 删除分类id
const [cgyId, setCgyId] = useState<number>(0);
// 弹窗title
const [title, setTitle] = useState<string>('');
// 当前修改的行
......@@ -245,13 +244,13 @@ const Category: FC = (props: any) => {
// 分享码弹窗显示/隐藏
const [isShareCodeVble, setShareCodeVble] = useState<boolean>(false);
const [shareCodeUrl, setShareCodeUrl] = useState<string>('');
const [shareCodeUrl] = useState<string>('');
// 按钮权限
const btnAdd = true; //useOption(22101);
const btnUpperDown = true; //useOption(22102);
const btnDir = true; //useOption(22103);
// const btnDir = true; //useOption(22103);
const btnAddChildCgy = true; //useOption(22104);
const btnShareCode = true; //useOption(22105);
// const btnShareCode = true; //useOption(22105);
const btnEdit = true; //useOption(22106);
const btnDelete = true; //useOption(22107);
const btnDetail = true; //useOption(22108);
......@@ -328,44 +327,38 @@ const Category: FC = (props: any) => {
const handleOk = () => {
const addForm = baseRef.current.getForm();
if (title === '新增分类') {
addForm
.validateFields()
.then(async (values: any) => {
const res = await CategoryManageAPI.addClassification({
...values,
pid: 0,
directoryId: activeTabKey,
type,
});
if (res.code == 200) {
events.emit('removeFileList');
message.success('新增成功');
setIsVisible(false);
getCategoryList(Number(activeTabKey));
addForm.resetFields();
}
})
.catch((err: any) => {});
addForm.validateFields().then(async (values: any) => {
const res = await CategoryManageAPI.addClassification({
...values,
pid: 0,
directoryId: activeTabKey,
type,
});
if (res.code == 200) {
events.emit('removeFileList');
message.success('新增成功');
setIsVisible(false);
getCategoryList(Number(activeTabKey));
addForm.resetFields();
}
});
} else {
addForm
.validateFields()
.then(async (values: any) => {
const res = await CategoryManageAPI.updateClassification({
...values,
id: currentRecord.id,
pid: currentRecord.pid,
directoryId: activeTabKey,
type,
});
if (res.code === '200') {
message.success('修改成功');
getCategoryList(Number(activeTabKey));
setIsVisible(false);
events.emit('removeFileList');
addForm.resetFields();
}
})
.catch((err: any) => {});
addForm.validateFields().then(async (values: any) => {
const res = await CategoryManageAPI.updateClassification({
...values,
id: currentRecord.id,
pid: currentRecord.pid,
directoryId: activeTabKey,
type,
});
if (res.code === '200') {
message.success('修改成功');
getCategoryList(Number(activeTabKey));
setIsVisible(false);
events.emit('removeFileList');
addForm.resetFields();
}
});
}
};
const handleCancel = () => {
......@@ -403,7 +396,7 @@ const Category: FC = (props: any) => {
}
};
// 展开监听
const onExpand = (expanded: boolean, record: categoryEntity) => {
const onExpand = (_expanded: boolean, record: categoryEntity) => {
const index = expandedRowKeys.findIndex((item: any) => item === record.id);
if (index != -1) {
expandedRowKeys.splice(index, 1);
......@@ -461,7 +454,7 @@ const Category: FC = (props: any) => {
});
};
// 取消新增子分类
const cancelAddCldCgy = (record: categoryEntity, index: number) => {
const cancelAddCldCgy = (record: categoryEntity) => {
categoryList.map((item: categoryEntity) => {
if (item.children && item.children.length != 0) {
const index: number = item.children.findIndex(
......@@ -599,7 +592,7 @@ const Category: FC = (props: any) => {
selectedRowKeys,
onChange: onSelectChange,
hideSelectAll: true,
renderCell: (checked: boolean, record: categoryEntity) => {
renderCell: (_checked: boolean, record: categoryEntity) => {
return <>{record.level === 1 ? <Checkbox onChange={() => onSelectChange(record)} /> : ''}</>;
},
};
......@@ -621,14 +614,14 @@ const Category: FC = (props: any) => {
});
};
// 分享码弹窗显示
const showShareCode = async (record: any) => {
const res: any = await CategoryManageAPI.getAppletQRCode({
page: 'page-sort/sortDetail/index',
scene: `?id=${record.id}&backTip=1`,
});
setShareCodeUrl(`data:image/png;base64,${res.result}`);
setShareCodeVble(true);
};
// const showShareCode = async (record: any) => {
// const res: any = await CategoryManageAPI.getAppletQRCode({
// page: 'page-sort/sortDetail/index',
// scene: `?id=${record.id}&backTip=1`,
// });
// setShareCodeUrl(`data:image/png;base64,${res.result}`);
// setShareCodeVble(true);
// };
const shareCodeHandleCancel = () => {
setShareCodeVble(false);
};
......@@ -690,7 +683,7 @@ const Category: FC = (props: any) => {
rowKey='id'
bordered
loading={isLoading}
rowClassName={(record: any, index: number) => {
rowClassName={(record: any) => {
if (record.children) {
return '';
}
......
.apply-detail{
position: relative;
.detail-title{
font-size: 13px;
font-weight: bold;
margin-bottom: 10px;
}
.detail-text{
width: 100%;
text-align: center;
margin: 30px 0;
}
.detail-action{
width: 100%;
display: flex;
justify-content: flex-end;
align-items: center;
margin-bottom: 20px;
.ant-btn{
width: 100px;
}
.ant-btn:first-child{
margin-right: 20px;
}
}
.detail-item{
width: 100%;
display: flex;
justify-content: flex-start;
align-items: flex-start;
margin-bottom: 15px;
.item-label{
width: 100px;
font-weight: normal;
text-align: right;
box-sizing: border-box;
padding-right: 20px;
}
}
}
import { FC, useEffect, useState } from 'react';
import { Button, message, Modal } from 'antd';
import { InterDataType, InterListType, InterReqType } from '~/api/interface';
import { CustomManageAPI } from '~/api';
import {
applyTagDetails,
approvalApplyTag,
listUserApplyTag,
} from '~/api/interface/customManageType';
import './index.scss';
import { PlusOutlined } from '@ant-design/icons';
import { Uploader } from '~/components/uploader';
// 列表的类型
type DataType = InterDataType<applyTagDetails>;
// 列表的类型
type TableType = InterListType<listUserApplyTag>;
// 请求的表单类型
type ReqType = InterReqType<approvalApplyTag>;
// 传参类型
interface propType {
title: string;
open: boolean;
closed: any;
data?: TableType[0];
}
const AddEditModal: FC<propType> = (props) => {
AddEditModal.defaultProps = {
data: undefined,
};
// 参数
const { title, open, closed, data } = props;
const [applyTagDetail, setApplyTagDetail] = useState<DataType>();
// 关闭弹窗
const handleCancel = () => {
closed();
};
// 点击事件
const handleOk = async (status: boolean) => {
await handleSubmit({ id: Number(data?.id), status });
};
// 提交事件
const handleSubmit = async (values: ReqType) => {
const res = await CustomManageAPI.approvalApplyTag(values);
if (res && res.code === '200') {
message.success('操作成功');
handleCancel();
}
};
// 获取审批详情
const getApplyTagDetails = async () => {
const res = await CustomManageAPI.applyTagDetails({
id: data?.id,
userAccountId: data?.userAccountId,
});
if (res && res.code === '200') {
const { result } = res;
setApplyTagDetail(result);
}
};
// componentDidMount
useEffect(() => {
if (!open) return;
if (!data) return;
getApplyTagDetails().then();
// console.log('data --->', data);
}, [open]);
return (
<Modal open={open} title={title} onCancel={handleCancel} destroyOnClose footer={null}>
<div className='apply-detail'>
<div className='detail-text'>确定通过用户提交的加盟申请成为加盟商吗?</div>
<div className='detail-action'>
<Button type={'default'} onClick={() => handleOk(false)}>
驳回
</Button>
<Button type={'primary'} onClick={() => handleOk(true)}>
通过
</Button>
</div>
<div className='detail-title'>企业认证信息</div>
<div className='detail-item'>
<div className='item-label'>企业名称:</div>
<div className='item-value'>{applyTagDetail?.companyName || '无'}</div>
</div>
<div className='detail-item'>
<div className='item-label'>社会信用代码:</div>
<div className='item-value'>{applyTagDetail?.creditCode || '无'}</div>
</div>
<div className='detail-item'>
<div className='item-label'>工商营业执照:</div>
<div className='item-value'>
<Uploader
listType={'picture-card'}
fileUpload
fileLength={1}
fileSize={10}
fileType={['image/png', 'image/jpeg', 'image/jpg', 'image/gif', 'image/bmp']}
defaultFileList={
applyTagDetail?.licenseImg ? [{ url: applyTagDetail?.licenseImg }] : []
}
disabled={true}
>
<PlusOutlined />
</Uploader>
</div>
</div>
<div className='detail-item'>
<div className='item-label'>附件信息:</div>
<div className='item-value'>
<Uploader
listType={'picture-card'}
fileUpload
fileLength={1}
fileSize={10}
fileType={['image/png', 'image/jpeg', 'image/jpg', 'image/gif', 'image/bmp']}
defaultFileList={
applyTagDetail?.attachmentList?.length
? applyTagDetail?.attachmentList.map((i) => ({ url: i.url }))
: []
}
disabled={true}
>
<PlusOutlined />
</Uploader>
</div>
</div>
<div className='detail-item'>
<div className='item-label'>备注:</div>
<div className='item-value'>{applyTagDetail?.remark || '无'}</div>
</div>
</div>
</Modal>
);
};
export default AddEditModal;
import { useEffect, useState } from 'react';
import SearchBox from '~/components/search-box';
import { CustomManageAPI } from '~/api';
import { Button, message, Modal, Table } from 'antd';
import { ColumnsType } from 'antd/es/table';
import { InterListType, InterReqListType } from '~/api/interface';
import { listUserApplyTag } from '~/api/interface/customManageType';
import AddEditModal from './comp/addEditModal';
// 列表类型
type TableType = InterListType<listUserApplyTag>;
// 请求的参数
type ReqType = InterReqListType<listUserApplyTag>;
// 搜索表单的数据
let query: ReqType = {};
// 审批状态
const applyStatusList = [
{ label: '待审核', value: 0 },
{ label: '已通过', value: 1 },
{ label: '不通过', value: 2 },
];
const CustomIdentityView = () => {
const { confirm } = Modal;
// 加盟列表
const [cooperationList, setCooperationList] = useState<{ label: string; value: number }[]>([]);
// 新增弹窗
const [addModalVisible, setAddModalVisible] = useState<boolean>(false);
// 需要编辑的数据
const [editData, setEditData] = useState<TableType[0]>();
// 表格数据
const [tableData, setTableData] = useState<TableType>([]);
// 表格分页配置
const [pagination, setPagination] = useState({
total: 0,
pageSize: 10,
current: 1,
totalPage: 0,
});
// 加载列表
const getTableList = async (value = {}) => {
// 只需要修改这个地方的接口即可
const res = await CustomManageAPI.listUserApplyTag({
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);
}
};
// 翻页
const paginationChange = (pageNo: number, pageSize: number) => {
getTableList({ pageNo, pageSize }).then();
};
// 表单提交
const onFinish = (data: ReqType) => {
pagination.current = 1;
query = data;
getTableList(data).then();
};
// 获取加盟列表
const getCooperationList = async () => {
const res = await CustomManageAPI.cooperationListTag({});
if (res && res.code === '200') {
const list = res.result || [];
setCooperationList(list.map((i) => ({ label: i.tagName, value: i.id })));
}
};
// 删除数据
const handleDelete = (record: TableType[0]) => {
confirm({
title: '提示',
content: '是否删除该记录?',
onOk: async () => {
const res = await CustomManageAPI.deleteApplyTag({ id: record.id });
if (res && res.code === '200') {
message.success('删除成功');
paginationChange(
tableData.length === 1 ? pagination.current - 1 : pagination.current,
pagination.pageSize,
);
}
},
});
};
useEffect(() => {
getCooperationList().then();
getTableList().then();
}, []);
// 表格结构
const columns: ColumnsType<TableType[0]> = [
{
title: '序号',
dataIndex: 'accountNo',
align: 'center',
width: '50px',
render: (_text, _record, index) => (pagination.current - 1) * pagination.pageSize + index + 1,
},
{
title: '申请加盟类型',
dataIndex: 'cooperationTagId',
align: 'center',
render: (text) => cooperationList.find((i) => i.value === text)?.label || text,
},
{
title: '联系人',
dataIndex: 'applyName',
align: 'center',
},
{
title: '联系方式',
dataIndex: 'applyPhone',
align: 'center',
},
{
title: '申请时间',
dataIndex: 'applyTime',
align: 'center',
},
{
title: '审核状态',
dataIndex: 'approvalStatus',
align: 'center',
render: (text) => applyStatusList.find((i) => i.value === text)?.label || text,
},
{
title: '操作',
dataIndex: 'action',
align: 'center',
fixed: 'right',
width: '120px',
render: (_text, record) => (
<>
<Button
type={'link'}
onClick={() => {
setAddModalVisible(true);
setEditData(JSON.parse(JSON.stringify(record)));
}}
disabled={record.approvalStatus !== 0}
>
审批
</Button>
<Button type={'link'} danger onClick={() => handleDelete(record)}>
强制删除
</Button>
</>
),
},
];
return (
<>
<SearchBox
search={[
{
name: 'cooperationTagId',
label: '申请加盟类型',
type: 'Select',
placeholder: '请选择加盟类型',
options: cooperationList,
},
{
name: 'applyStatus',
label: '申请状态',
type: 'Select',
placeholder: '请选择申请状态',
options: applyStatusList,
},
{
name: 'rangeTime',
label: '申请时间',
type: 'rangePicker',
placeholder: '请选择开始时间和结束时间',
},
]}
searchData={onFinish}
/>
<Table
size='small'
dataSource={tableData}
columns={columns}
rowKey='id'
// scroll={{ x: 1500 }}
bordered
pagination={{
total: pagination.total,
pageSize: pagination.pageSize,
current: pagination.current,
showSizeChanger: true,
showQuickJumper: true,
onChange: (page: number, pageSize: number) => paginationChange(page, pageSize),
showTotal: (total, range) => `当前 ${range[0]}-${range[1]} 条记录 / 共 ${total} 条数据`,
}}
/>
<AddEditModal
open={addModalVisible}
title={editData?.id ? '审批' : '新增'}
data={editData}
closed={() => {
setAddModalVisible(false);
setEditData(undefined);
paginationChange(pagination.current, pagination.pageSize);
}}
/>
</>
);
};
export default CustomIdentityView;
import { FC, useEffect, useState } from 'react';
import { Form, Modal, Select } from 'antd';
import { InterListType } from '~/api/interface';
import { listAppUserType } from '~/api/interface/customManageType';
import { InterListType, InterReqType } from '~/api/interface';
import { changeUserTagNew, listAppUserType } from '~/api/interface/customManageType';
import { CustomManageAPI } from '~/api';
// 表单参数
type ReqType = InterReqType<changeUserTagNew>;
// 表格数据类型
type TableType = InterListType<listAppUserType>;
// 数据的类型
......@@ -13,11 +15,6 @@ interface PropsType {
data?: TableType[0];
}
// 修改等级标签
interface tagLevelForm {
cooperationTagId: number;
}
export const ChangeModal: FC<PropsType> = (props) => {
ChangeModal.defaultProps = {
data: undefined,
......@@ -25,7 +22,7 @@ export const ChangeModal: FC<PropsType> = (props) => {
// 父组件传参
const { open, closed, data } = props;
// 个人等级标签
const [form] = Form.useForm<tagLevelForm>();
const [form] = Form.useForm<ReqType>();
// 相关运营列表
const [operationList] = useState<{ value: number; label: string }[]>([]);
// 等级标签列表
......@@ -40,9 +37,9 @@ export const ChangeModal: FC<PropsType> = (props) => {
// 提交数据
const handleSubmit = () => {
form.validateFields().then(async (value) => {
const res = await CustomManageAPI.changeUserTag({
const res = await CustomManageAPI.changeUserTagNew({
userAccountId: Number(data?.id),
cooperationTagId: value.cooperationTagId,
cooperationTagIds: value?.cooperationTagIds || [],
});
if (res && res.code === '200') {
handleClosed();
......@@ -62,18 +59,19 @@ export const ChangeModal: FC<PropsType> = (props) => {
if (!data) return;
getCompanyListTag().then();
form.setFieldsValue({
cooperationTagId: data.cooperationTagId,
cooperationTagIds: data.cooperationTagVOS?.map((i) => i.id),
});
}, [open]);
return (
<Modal open={open} title='变更' onCancel={handleClosed} destroyOnClose onOk={handleSubmit}>
<Form form={form} labelCol={{ span: 5 }} wrapperCol={{ span: 16 }}>
<Form.Item label='等级标签' name='cooperationTagId'>
<Form.Item label='加盟身份' name='cooperationTagIds'>
<Select
placeholder='请选择等级标签'
placeholder='请选择加盟身份'
disabled={!data?.userName && !data?.companyName}
allowClear
options={cooperationTagIdList}
mode='multiple'
/>
</Form.Item>
<Form.Item label='相关运营' name='mallOperator'>
......
import { useEffect, useState } from 'react';
import SearchBox from '~/components/search-box';
import { Button, message, Modal, Table } from 'antd';
import { Button, message, Modal, Table, Tag } from 'antd';
import { ColumnsType } from 'antd/es/table';
import { ChangeModal } from '~/pages/customManage/customList/comp/changeModal';
import { InterListType, InterReqType } from '~/api/interface';
......@@ -25,10 +25,6 @@ const portTypeList = [
function CustomListView() {
const { confirm } = Modal;
// 等级标签列表
const [cooperationTagIdList, setCooperationTagIdList] = useState<
{ value: number; label: string }[]
>([]);
// 是否打开变更弹窗
const [isChangeVisModal, setIsChangeVisModal] = useState<boolean>(false);
// 表格分页配置
......@@ -73,14 +69,6 @@ function CustomListView() {
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);
}
};
// 删除用户
const handleDelete = (value: TableType[0]) => {
confirm({
......@@ -102,7 +90,6 @@ function CustomListView() {
useEffect(() => {
query = {};
(async () => {
await getCompanyListTag();
await getTableList();
})();
}, []);
......@@ -160,10 +147,15 @@ function CustomListView() {
render: (text) => (text ? '普通用户' : '游客用户'),
},
{
title: '渠道等级',
dataIndex: 'cooperationTagId',
title: '加盟身份',
dataIndex: 'cooperationTagVOS',
align: 'center',
render: (text) => cooperationTagIdList.find((i) => i.value === text)?.label || text,
render: (_text, record) =>
record.cooperationTagVOS?.map((i, j) => (
<Tag color='processing' key={j} style={{ marginBottom: '10px' }}>
{i.tagName}
</Tag>
)),
},
{
title: '上级推荐人',
......
.dynamic-detail{
padding: 20px 0;
&-media{
display: flex;
align-items: center;
flex-wrap: wrap;
.media-item{
margin-right: 10px;
margin-bottom: 10px;
}
}
&-info{
.info-title{
color: #000;
font-size: 15px;
font-weight: bold;
}
.info-meta{
margin-top: 10px;
}
.info-footer{
margin-top: 20px;
display: flex;
align-items: center;
justify-content: space-between;
border-bottom: 1px solid #999;
.operate{
display: flex;
align-items: center;
padding-bottom: 15px;
div:first-child{
margin-right: 10px;
}
}
}
}
&-comment{
margin-top: 40px;
.comment-title{
color: #000;
font-size: 15px;
font-weight: bold;
}
.comment-item{
margin-top: 10px;
&-header{
display: flex;
align-items: center;
.user-avatar{
margin-right: 10px;
img{
width: 20px;
height: 20px;
border-radius: 50%;
}
}
.user-name{
}
}
&-info{
margin-left: 30px;
border-bottom: 1px solid #999;
.info-content{
margin: 10px 0;
}
}
}
}
.no-comment{
text-align: center;
margin-top: 50px;
font-size: 15px;
color: rgba(0,0,0,0.5);
font-weight: bold;
}
}
.dynamic-like-user{
display: flex;
width: 200px;
min-height: 100px;
.user-info{
display: flex;
margin: 10px;
img{
width: 20px;
height: 20px;
border-radius: 50%;
margin-right: 5px;
}
}
}
import { FC, useEffect, useState } from 'react';
import { Button, Image, Modal, ModalProps, Tooltip } from 'antd';
import './index.scss';
import { InterDataType } from '~/api/interface';
import { forumDetailType, likeUserInfoType } from '~/api/interface/forumManageType';
import { ForumManageAPI } from '~/api';
//论坛详情返回类型
type detailType = InterDataType<forumDetailType>;
interface selfProps {
forumDetail?: detailType;
}
//点赞人返回类型
type likeUserType = InterDataType<likeUserInfoType>;
const DynamicDetailModal: FC<ModalProps & selfProps> = ({ open, onCancel, forumDetail }) => {
//点赞人列表
const [likeUserList, setLikeUserList] = useState<likeUserType>([]);
const getLikeUserInfo = (dynamicId: number) => {
ForumManageAPI.getLikeUserInfoList({ dynamicId }).then(({ result }) => {
setLikeUserList(result || []);
});
};
useEffect(() => {
if (forumDetail && forumDetail.likesCount) {
getLikeUserInfo(forumDetail.id);
} else {
setLikeUserList([]);
}
}, [forumDetail]);
return (
<Modal open={open} onCancel={onCancel} title='查看详情' width={800} footer={null}>
<div className='dynamic-detail'>
<div className='dynamic-detail-media'>
{forumDetail?.mediaVO?.map((v, index: number) => {
if (v.type === 0) {
return (
<div className='media-item' key={index}>
<Image src={v.url} width={200} height={200} />
</div>
);
} else {
return (
<div className='media-item' key={index}>
<video
src={v.url}
style={{
width: '200px',
height: '200px',
verticalAlign: 'top',
}}
controls
/>
</div>
);
}
})}
</div>
<div className='dynamic-detail-info'>
<div className='info-title'>{forumDetail?.description}</div>
<div className='info-footer'>
<div className='time'>发布于{forumDetail?.dynamicPublishTime}</div>
<div className='operate'>
<div>{forumDetail?.commentCount}人回答</div>
<Tooltip
placement='bottom'
title={
likeUserList.length ? (
<div className='dynamic-like-user'>
{likeUserList.map((v, index: number) => (
<div key={index} className='user-info'>
<img src={v.userImg} alt='头像' />
<span>{v.userName || v.nickName}</span>
</div>
))}
</div>
) : (
'暂无点赞'
)
}
>
<Button type='link'>{forumDetail?.likesCount}人爱心赞</Button>
</Tooltip>
</div>
</div>
</div>
{forumDetail?.commentAndReplyVO.length ? (
<div className='dynamic-detail-comment'>
<div className='comment-title'>{forumDetail?.commentCount}条评论</div>
{forumDetail.commentAndReplyVO.map((v, index: number) => (
<div className='comment-item' key={index}>
<div className='comment-item-header'>
<div className='user-avatar'>
<img src={v.userBaseInfo.userImg} alt='头像' />
</div>
<div className='user-name'>{v.userBaseInfo.nickName}</div>
</div>
<div className='comment-item-info'>
<div className='info-content'>{v.description}</div>
<div className='info-time'>{v.dynamicPublishTime}</div>
</div>
</div>
))}
</div>
) : (
<div className='no-comment'>暂无评论</div>
)}
</div>
</Modal>
);
};
export default DynamicDetailModal;
.forum-description{
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
cursor: pointer;
}
import SearchBox, { searchColumns } from '~/components/search-box';
import { Button, message, Modal, Table, Tooltip } from 'antd';
import { ColumnsType } from 'antd/es/table';
import { useEffect, useState } from 'react';
import DynamicDetailModal from './components/dynamicDetailModal';
import { ForumManageAPI } from '../../../api';
import { InterDataType, InterReqListType, PaginationProps } from '../../../api/interface';
import { forumDetailType, forumListType } from '../../../api/interface/forumManageType';
import './index.scss';
//论坛列表返回类型
type forumType = InterDataType<forumListType>['list'];
//论坛列表参数类型
type forumParameters = InterReqListType<forumListType>;
//论坛详情返回类型
type detailType = InterDataType<forumDetailType>;
const DynamicList = () => {
const searchColumnsData: searchColumns[] = [
{
label: '作者',
type: 'input',
name: 'keyword',
placeholder: '用户名称/用户UID/用户手机号码',
},
];
const tableColumns: ColumnsType<forumType[0]> = [
{
title: '动态描述信息',
align: 'center',
dataIndex: 'description',
width: '20%',
ellipsis: true,
render: (text: string) => (
<Tooltip title={text}>
<div className='forum-description'>{text}</div>
</Tooltip>
),
},
{
title: '作者(用户名称)',
align: 'center',
render: (_text: string, record) => (
<div>{record.userBaseInfo?.userName || record.userBaseInfo?.nickName || ''}</div>
),
},
{
title: '用户UID',
align: 'center',
render: (_text: string, record) => <div>{record.userBaseInfo?.uid || ''}</div>,
},
{
title: '用户手机号',
align: 'center',
render: (_text: string, record) => <div>{record.userBaseInfo?.phone || ''}</div>,
},
{
title: '操作',
align: 'center',
render: (_text: string, record) => (
<>
<Button type='link' onClick={() => lookDynamicDetail(record)}>
查看详情
</Button>
<Button type='link' onClick={() => deleteForumClick(record)}>
强制删除
</Button>
<Button type='link' onClick={() => hiddenForumClick(record)}>
{record.show ? '恢复显示' : '强制隐藏'}
</Button>
</>
),
},
];
const [tableData, setTableData] = useState<forumType>([]);
const [pagination, setPagination] = useState<PaginationProps & { totalCount: number }>({
pageNo: 1,
pageSize: 10,
totalCount: 0,
});
const [forumDetail, setForumDetail] = useState<detailType>();
const [query, setQuery] = useState<forumParameters>();
const [dynamicDetailModalShow, setDynamicDetailModalShow] = useState<boolean>(false);
//动态列表
const getDynamicList = (query?: forumParameters) => {
ForumManageAPI.getForumList({
pageNo: pagination.pageNo,
pageSize: pagination.pageSize,
...query,
}).then(({ result }) => {
setTableData(result.list || []);
pagination.totalCount = result.totalCount;
setPagination(pagination);
});
};
//筛选
const searchSuccess = (data: any) => {
pagination.pageNo = 1;
pagination.pageSize = 10;
setQuery(data);
getDynamicList(data);
};
//分页
const paginationChange = (pageNo: number, pageSize: number) => {
pagination.pageNo = pageNo;
pagination.pageSize = pageSize;
getDynamicList(query);
};
//强制删除论坛
const deleteForumClick = (record: forumType[0]) => {
Modal.confirm({
title: '强制删除',
content: '确认删除这条动态?',
onOk: () => {
ForumManageAPI.deleteForum({ dynamicId: record.id }).then(({ code }) => {
if (code === '200') {
message.success('删除成功');
if (pagination.pageNo !== 1 && tableData.length === 1) {
pagination.pageNo -= 1;
}
getDynamicList(query);
}
});
},
});
};
//强制隐藏
const hiddenForumClick = (record: forumType[0]) => {
Modal.confirm({
title: `${record.show ? '恢复显示' : '强制隐藏'}`,
content: `确认${record.show ? '显示' : '隐藏'}这条动态?`,
onOk: () => {
ForumManageAPI.hiddenForum({ dynamicId: record.id }).then(({ code }) => {
if (code === '200') {
message.success(`${record.show ? '显示' : '隐藏'}成功`);
getDynamicList(query);
}
});
},
});
};
const dynamicDetailModalOnCancel = () => {
setDynamicDetailModalShow(false);
};
//查看详情
const lookDynamicDetail = (record: forumType[0]) => {
getForumDetail(record.id);
};
//获取论坛-详情
const getForumDetail = (id: number) => {
ForumManageAPI.getForumDetail({ dynamicId: id }).then(({ code, result }) => {
if (code === '200') {
setDynamicDetailModalShow(true);
setForumDetail(result);
}
});
};
useEffect(() => {
getDynamicList();
}, []);
return (
<div className='dynamic-list'>
<SearchBox search={searchColumnsData} searchData={searchSuccess} />
<Table
bordered
columns={tableColumns}
dataSource={tableData}
rowKey='id'
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} 条数据`,
}}
/>
<DynamicDetailModal
open={dynamicDetailModalShow}
onCancel={dynamicDetailModalOnCancel}
forumDetail={forumDetail}
/>
</div>
);
};
export default DynamicList;
import { FC, useEffect } from 'react';
import { Form, Input, message, Modal } from 'antd';
import { InterListType, InterReqType } from '~/api/interface';
import { industryCaseAddCase, industryCaseListCasePage } from '~/api/interface/resourceManageType';
import { ResourceManageAPI } from '~/api';
import RichText from '~/components/richText';
// 列表的类型
type TableType = InterListType<industryCaseListCasePage>;
// 请求的表单类型
type ReqType = InterReqType<industryCaseAddCase>;
// 传参类型
interface propType {
title: string;
open: boolean;
closed: any;
data?: TableType[0];
}
const AddEditModal: FC<propType> = (props) => {
AddEditModal.defaultProps = {
data: undefined,
};
// 参数
const { title, open, closed, data } = props;
// 表单钩子
const [form] = Form.useForm<ReqType>();
// 关闭弹窗
const handleCancel = () => {
form.resetFields();
closed();
};
// 确认事件
const handleOk = () => {
form
.validateFields()
.then(async (values) => {
await handleSubmit(values as ReqType & { file: any[] });
})
.catch((err) => {
message
.warning({
content: err.errorFields[0].errors[0],
})
.then();
});
};
// 提交事件
const handleSubmit = async (values: ReqType) => {
const res = await ResourceManageAPI[
data?.id ? 'industryCaseUpdateCase' : 'industryCaseAddCase'
]({
...values,
id: data?.id ? Number(data?.id) : undefined,
});
if (res && res.code === '200') {
message.success('操作成功');
handleCancel();
}
};
// componentDidMount
useEffect(() => {
if (!open) return;
if (!data) return;
form.setFieldsValue(data);
// console.log('data --->', data);
}, [open]);
return (
<Modal
open={open}
title={title}
onCancel={handleCancel}
onOk={handleOk}
destroyOnClose
width={768}
>
<Form
name='Form'
form={form}
labelAlign='right'
labelCol={{ span: 3 }}
wrapperCol={{ span: 20 }}
>
<Form.Item
label='文章标题'
name='caseTitle'
rules={[{ required: true, message: '请输入文章标题' }]}
>
<Input placeholder={'请输入文章标题'} maxLength={50} allowClear />
</Form.Item>
<Form.Item
label='文章来源'
name='origin'
rules={[{ required: true, message: '请输入文章来源' }]}
>
<Input placeholder={'请输入文章来源'} maxLength={50} allowClear />
</Form.Item>
<Form.Item
label='文章详情'
name='caseContents'
rules={[{ required: true, message: '请输入文章详情' }]}
>
<RichText
value={form.getFieldValue('caseContents')}
onChange={(e) => form.setFieldValue('caseContents', e)}
height={250}
/>
</Form.Item>
</Form>
</Modal>
);
};
export default AddEditModal;
import { FC, useEffect } from 'react';
import { Modal } from 'antd';
import { InterListType } from '~/api/interface';
import { industryCaseListCasePage } from '~/api/interface/resourceManageType';
import RichText from '~/components/richText';
// 列表的类型
type TableType = InterListType<industryCaseListCasePage>;
// 传参类型
interface propType {
title: string;
open: boolean;
closed: any;
data?: TableType[0];
}
const PreviewModal: FC<propType> = (props) => {
PreviewModal.defaultProps = {
data: undefined,
};
// 参数
const { title, open, closed, data } = props;
// 关闭弹窗
const handleCancel = () => {
closed();
};
// componentDidMount
useEffect(() => {
if (!open) return;
if (!data) return;
// console.log('data --->', data);
}, [open]);
return (
<Modal
open={open}
title={title}
onCancel={handleCancel}
destroyOnClose
width={768}
footer={null}
>
<div
style={{
display: 'flex',
justifyContent: 'center',
alignItems: 'flex-start',
flexDirection: 'column',
}}
>
<div style={{ fontSize: '20px', fontWeight: 'bold' }}>{data?.caseTitle}</div>
<div style={{ fontSize: '15px', marginBottom: '10px' }}>
{data?.updateTime || data?.createTime}
</div>
</div>
<RichText value={data?.caseContents} height={350} isDetail={true} />
</Modal>
);
};
export default PreviewModal;
import { useEffect, useState } from 'react';
import SearchBox from '~/components/search-box';
import { Button, message, Modal, Table } from 'antd';
import { PlusOutlined } from '@ant-design/icons';
import { InterListType, InterReqListType } from '~/api/interface';
import { ResourceManageAPI } from '~/api';
import { industryCaseListCasePage } from '~/api/interface/resourceManageType';
import { ColumnsType } from 'antd/es/table';
import AddEditModal from '~/pages/resourceManage/businessCaseManage/comp/addEditModal';
import PreviewModal from '~/pages/resourceManage/businessCaseManage/comp/previewModal';
// 列表类型
type TableType = InterListType<industryCaseListCasePage>;
// 请求的参数
type ReqType = InterReqListType<industryCaseListCasePage>;
// 搜索表单的数据
let query: ReqType = {};
const BusinessCaseManage = () => {
const { confirm } = Modal;
// 新增弹窗
const [addModalVisible, setAddModalVisible] = useState<boolean>(false);
// 预览弹窗
const [previewVisible, setPreviewVisible] = useState<boolean>(false);
// 需要编辑的数据
const [editData, setEditData] = useState<TableType[0]>();
// 表格数据
const [tableData, setTableData] = useState<TableType>([]);
// 表格分页配置
const [pagination, setPagination] = useState({
total: 0,
pageSize: 10,
current: 1,
totalPage: 0,
});
// 加载列表
const getTableList = async (value = {}) => {
// 只需要修改这个地方的接口即可
const res = await ResourceManageAPI.industryCaseListCasePage({
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);
}
};
// 翻页
const paginationChange = (pageNo: number, pageSize: number) => {
getTableList({ pageNo, pageSize }).then();
};
// 表单提交
const onFinish = (data: ReqType) => {
pagination.current = 1;
query = data;
getTableList(data).then();
};
// 删除数据
const handleDelete = (record: TableType[0]) => {
confirm({
title: '提示',
content: '是否删除该记录?',
onOk: async () => {
const res = await ResourceManageAPI.industryCaseDeleteDetails({ id: record.id });
if (res && res.code === '200') {
message.success('删除成功');
paginationChange(
tableData.length === 1 ? pagination.current - 1 : pagination.current,
pagination.pageSize,
);
}
},
});
};
// componentDidMount
useEffect(() => {
query = {};
getTableList().then();
}, []);
// 表格结构
const columns: ColumnsType<TableType[0]> = [
{
title: '序号',
dataIndex: 'accountNo',
align: 'center',
width: '50px',
render: (_text, _record, index) => (pagination.current - 1) * pagination.pageSize + index + 1,
},
{
title: '文章名称',
dataIndex: 'caseTitle',
align: 'center',
ellipsis: true,
},
{
title: '发布时间',
dataIndex: 'updateTime',
align: 'center',
render: (text, record) => text || record.createTime,
},
{
title: '来源',
dataIndex: 'origin',
align: 'center',
},
{
title: '操作',
dataIndex: 'action',
align: 'center',
width: '150px',
fixed: 'right',
render: (_text, record) => (
<>
<Button
type={'link'}
onClick={() => {
setEditData(JSON.parse(JSON.stringify(record)));
setAddModalVisible(true);
}}
>
编辑
</Button>
<Button
type={'link'}
onClick={() => {
setEditData(JSON.parse(JSON.stringify(record)));
setPreviewVisible(true);
}}
>
预览
</Button>
<Button type={'link'} danger onClick={() => handleDelete(record)}>
删除
</Button>
</>
),
},
];
return (
<>
<SearchBox
search={[
{ name: 'keyword', label: '文章名称', type: 'input', placeholder: '请输入文章名称' },
]}
child={
<>
<Button
type={'primary'}
icon={<PlusOutlined />}
onClick={() => {
setAddModalVisible(true);
}}
>
新增
</Button>
</>
}
searchData={onFinish}
/>
<Table
size='small'
dataSource={tableData}
columns={columns}
rowKey='id'
// scroll={{ x: 1500 }}
bordered
pagination={{
total: pagination.total,
pageSize: pagination.pageSize,
current: pagination.current,
showSizeChanger: true,
showQuickJumper: true,
onChange: (page: number, pageSize: number) => paginationChange(page, pageSize),
showTotal: (total, range) => `当前 ${range[0]}-${range[1]} 条记录 / 共 ${total} 条数据`,
}}
/>
<AddEditModal
open={addModalVisible}
title={editData?.id ? '编辑' : '新增'}
data={editData}
closed={() => {
setAddModalVisible(false);
setEditData(undefined);
paginationChange(pagination.current, pagination.pageSize);
}}
/>
<PreviewModal
open={previewVisible}
title={editData?.id ? '预览' : '新增'}
data={editData}
closed={() => {
setPreviewVisible(false);
setEditData(undefined);
paginationChange(pagination.current, pagination.pageSize);
}}
/>
</>
);
};
export default BusinessCaseManage;
import { FC, useEffect, useState } from 'react';
import { Form, Input, message, Modal, ModalProps } from 'antd';
import { Uploader } from '~/components/uploader';
import { UploadOutlined } from '@ant-design/icons';
import RichText from '~/components/richText';
import { InterDataType, InterReqType } from '~/api/interface';
import { addIndustryNewsType, industryNewsListType } from '~/api/interface/resourceManageType';
import { ResourceManageAPI } from '~/api';
//行业新闻返回类型
type industryNewsType = InterDataType<industryNewsListType>['list'];
//新增请求类型
type addNewsParameters = InterReqType<addIndustryNewsType>;
interface selfProps {
handleOk: () => void;
onCancel: () => void;
currentIndustryNews?: industryNewsType[0];
}
const AddOrEditNewsModal: FC<ModalProps & selfProps> = ({
open,
onCancel,
handleOk,
currentIndustryNews,
}) => {
const [form] = Form.useForm<addNewsParameters>();
const [richTextValue, setRichTextValue] = useState<string>('');
//封面图文件
const [surfaceImgList, setSurfaceImgList] = useState<
{
id: number;
name: string;
uid: number;
url: string;
}[]
>([]);
const richTextChange = (html?: string) => {
form.setFieldValue('newsContents', html || undefined);
};
//封面图-上传成功
const uploadSuccess = (
fileList: {
id: number;
name: string;
uid: number;
url: string;
}[],
) => {
setSurfaceImgList(fileList);
form.setFieldValue('surfaceImg', fileList[0].url);
};
//提交-新增或编辑行业新闻
const addOrEditModalOk = () => {
form.validateFields().then((value: any) => {
ResourceManageAPI[currentIndustryNews ? 'editIndustryNews' : 'addIndustryNews']({
...value,
id: currentIndustryNews ? currentIndustryNews.id : undefined,
}).then(({ code }) => {
if (code === '200') {
message.success(currentIndustryNews ? '编辑成功' : '新增成功');
handleOk();
}
});
});
};
const addOrEditModalCancel = () => {
form.resetFields();
setSurfaceImgList([]);
setRichTextValue('');
onCancel();
};
useEffect(() => {
if (currentIndustryNews) {
form.setFieldsValue({
newsTitle: currentIndustryNews.newsTitle,
origin: currentIndustryNews.origin,
newsAuthor: currentIndustryNews.newsAuthor,
surfaceImg: currentIndustryNews.surfaceImg,
newsContents: currentIndustryNews.newsContents || undefined,
});
setSurfaceImgList([
{
id: Math.random(),
name: 'surfaceImg',
uid: Math.random(),
url: currentIndustryNews.surfaceImg,
},
]);
setRichTextValue(currentIndustryNews.newsContents || '');
}
}, [currentIndustryNews]);
return (
<Modal
open={open}
onCancel={addOrEditModalCancel}
onOk={addOrEditModalOk}
title={currentIndustryNews ? '编辑' : '新建'}
width={800}
>
<Form labelCol={{ span: 4 }} wrapperCol={{ span: 16 }} form={form}>
<Form.Item
label='文章标题'
name='newsTitle'
rules={[{ required: true, message: '请输入文章标题' }]}
>
<Input placeholder='请输入文章标题' maxLength={30} />
</Form.Item>
<Form.Item
label='文章来源'
name='origin'
rules={[{ required: true, message: '请输入文章来源' }]}
>
<Input placeholder='请输入文章来源' maxLength={30} />
</Form.Item>
<Form.Item
label='作者'
name='newsAuthor'
rules={[{ required: true, message: '请输入文章作者' }]}
>
<Input placeholder='请输入文章作者' maxLength={30} />
</Form.Item>
<Form.Item
label='封面图'
name='surfaceImg'
rules={[{ required: true, message: '请上传封面图' }]}
>
<Uploader
fileUpload
listType='picture-card'
onChange={uploadSuccess}
defaultFileList={surfaceImgList}
fileType={['image/png', 'image/jpeg', 'image/jpg', 'image/gif', 'image/bmp']}
>
<UploadOutlined />
</Uploader>
</Form.Item>
<Form.Item label='主题内容' name='newsContents'>
<RichText onChange={richTextChange} value={richTextValue} />
</Form.Item>
</Form>
</Modal>
);
};
export default AddOrEditNewsModal;
.industry-news-detail{
width: 600px;
margin: 0 auto;
&-title{
font-weight: 500;
font-size: 18px;
color: #000;
text-align: center;
line-height: 50px;
}
&-img{
text-align: center;
}
&-content{
margin-top: 10px;
}
}
import { FC, useEffect, useRef, useState } from 'react';
import { Image, Modal, ModalProps } from 'antd';
import { InterDataType } from '~/api/interface';
import { industryNewsDetailType, industryNewsListType } from '~/api/interface/resourceManageType';
import { ResourceManageAPI } from '~/api';
import './index.scss';
//行业新闻返回类型
type industryNewsType = InterDataType<industryNewsListType>['list'];
//行业新闻详情返回类型
type detailType = InterDataType<industryNewsDetailType>;
interface selfProps {
currentIndustryNews?: industryNewsType[0];
}
const PreviewNewsModal: FC<ModalProps & selfProps> = ({ open, onCancel, currentIndustryNews }) => {
const newsContentsRef = useRef<any>();
//行业新闻详情
const [industryNewsDetail, setIndustryNewsDetail] = useState<detailType>();
//获取行业详情
const getIndustryNewsDetail = (id: number) => {
ResourceManageAPI.getIndustryNewsDetail({ id }).then(({ result }) => {
setIndustryNewsDetail(result);
newsContentsRef.current.innerHTML = result.newsContents;
});
};
useEffect(() => {
if (currentIndustryNews) {
getIndustryNewsDetail(currentIndustryNews.id);
}
}, [currentIndustryNews]);
return (
<Modal open={open} onCancel={onCancel} title='预览' width={800} footer={null}>
<div className='industry-news-detail'>
<div className='industry-news-detail-title'>{industryNewsDetail?.newsTitle}</div>
<div className='industry-news-detail-img'>
<Image src={industryNewsDetail?.surfaceImg} height={200} width={600} />
</div>
<div className='industry-news-detail-content' ref={newsContentsRef}></div>
</div>
</Modal>
);
};
export default PreviewNewsModal;
import SearchBox, { searchColumns } from '~/components/search-box';
import { Button, Image, message, Modal, Table } from 'antd';
import { PlusOutlined } from '@ant-design/icons';
import { ColumnsType } from 'antd/es/table';
import AddOrEditNewsModal from './components/addOrEditNewsModal';
import PreviewNewsModal from './components/previewNewsModal';
import { useEffect, useState } from 'react';
import { ResourceManageAPI } from '~/api';
import { InterDataType, InterReqListType, PaginationProps } from '~/api/interface';
import { industryNewsListType } from '~/api/interface/resourceManageType';
//行业新闻返回类型
type industryNewsType = InterDataType<industryNewsListType>['list'];
//行业新闻列表参数类型
type industryNewsParameters = InterReqListType<industryNewsListType>;
const IndustryNews = () => {
const searchColumnsData: searchColumns[] = [
{
label: '文章名称',
type: 'input',
name: 'newsTitle',
placeholder: '请输入文章名称',
},
];
const tableColumns: ColumnsType<industryNewsType[0]> = [
{
title: '序号',
align: 'center',
render: (_text: string, _record, index: number) =>
(pagination.pageNo - 1) * pagination.pageSize + index + 1,
},
{
title: '文章名称',
align: 'center',
dataIndex: 'newsTitle',
width: '20%',
},
{
title: '发布时间',
align: 'center',
dataIndex: 'createTime',
width: '15%',
},
{
title: '来源',
align: 'center',
dataIndex: 'origin',
},
{
title: '作者',
align: 'center',
dataIndex: 'newsAuthor',
},
{
title: '封图片',
align: 'center',
dataIndex: 'surfaceImg',
render: (text: string) => <Image src={text} width={50} height={50} />,
},
{
title: '操作',
align: 'center',
width: '20%',
render: (_text: string, record) => (
<>
<Button type='link' onClick={() => addOrEditIndustryNewsClick(record)}>
编辑
</Button>
<Button type='link' onClick={() => previewClick(record)}>
预览
</Button>
<Button type='link' danger onClick={() => deleteIndustryNews(record)}>
删除
</Button>
</>
),
},
];
const [tableData, setTableData] = useState<industryNewsType>([]);
const [loading, setLoading] = useState<boolean>(false);
const [currentIndustryNews, setCurrentIndustryNews] = useState<industryNewsType[0]>();
const [addOrEditNewsModalShow, setAddOrEditNewsModalShow] = useState<boolean>(false);
const [previewNewsModalShow, setPreviewNewsModalShow] = useState<boolean>(false);
const [query, setQuery] = useState<industryNewsParameters>();
const [pagination, setPagination] = useState<PaginationProps & { totalCount: number }>({
pageNo: 1,
pageSize: 10,
totalCount: 0,
});
//获取行业新闻-列表
const getIndustryNewsList = (query?: industryNewsParameters) => {
setLoading(true);
ResourceManageAPI.getIndustryNewsList({
pageNo: pagination.pageNo,
pageSize: pagination.pageSize,
...query,
}).then(({ result }) => {
setLoading(false);
setTableData(result.list || []);
pagination.totalCount = result.totalCount;
setPagination(pagination);
});
};
//分页
const paginationChange = (pageNo: number, pageSize: number) => {
pagination.pageNo = pageNo;
pagination.pageSize = pageSize;
getIndustryNewsList(query);
};
//筛选
const searchSuccessEvent = (value?: industryNewsParameters) => {
pagination.pageNo = 1;
pagination.pageSize = 10;
setQuery(value);
getIndustryNewsList(value);
};
//新增、编辑
const addOrEditIndustryNewsClick = (record?: industryNewsType[0]) => {
setCurrentIndustryNews(record ? { ...record } : undefined);
setAddOrEditNewsModalShow(true);
};
const addOrEditNewsModalCancel = () => {
setAddOrEditNewsModalShow(false);
};
const addOrEditNewsModalOk = () => {
getIndustryNewsList();
setAddOrEditNewsModalShow(false);
};
//预览
const previewClick = (record: industryNewsType[0]) => {
setCurrentIndustryNews({ ...record });
setPreviewNewsModalShow(true);
};
const previewNewsModalCancel = () => {
setPreviewNewsModalShow(false);
};
//删除
const deleteIndustryNews = (record: industryNewsType[0]) => {
Modal.confirm({
title: '行业新闻删除',
content: '确认删除该行业新闻?',
onOk: () => {
ResourceManageAPI.removeIndustryNews({ id: record.id }).then(({ code }) => {
if (code === '200') {
message.success('删除成功');
if (pagination.pageNo !== 1 && tableData.length === 1) {
pagination.pageNo -= 1;
}
getIndustryNewsList(query);
}
});
},
});
};
useEffect(() => {
getIndustryNewsList();
}, []);
return (
<div className='industry-news'>
<SearchBox
search={searchColumnsData}
child={
<Button
type='primary'
icon={<PlusOutlined />}
onClick={() => addOrEditIndustryNewsClick()}
>
新建
</Button>
}
searchData={searchSuccessEvent}
/>
<Table
bordered
columns={tableColumns}
dataSource={tableData}
loading={loading}
rowKey='id'
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} 条数据`,
}}
/>
<AddOrEditNewsModal
open={addOrEditNewsModalShow}
onCancel={addOrEditNewsModalCancel}
handleOk={addOrEditNewsModalOk}
currentIndustryNews={currentIndustryNews}
/>
<PreviewNewsModal
open={previewNewsModalShow}
onCancel={previewNewsModalCancel}
currentIndustryNews={currentIndustryNews}
/>
</div>
);
};
export default IndustryNews;
import React, { useEffect, useState } from 'react';
import { Form, Input, message, Modal, Select } from 'antd';
import { DatePicker, Form, Input, message, Modal, Select, Space } from 'antd';
import { InterListType, InterReqType } from '~/api/interface';
import { insertBannerInfo, listBannerInfoPage } from '~/api/interface/commonType';
import { CommonAPI } from '~/api';
import { PlusOutlined } from '@ant-design/icons';
import { Uploader } from '~/components/uploader';
import RichText from '~/components/richText';
import dayjs from 'dayjs';
// 列表的类型
type TableType = InterListType<listBannerInfoPage>;
......@@ -45,6 +46,8 @@ const AddEditModal: React.FC<propType> = (props) => {
const [form] = Form.useForm<ReqType>();
// 上传图片
const [bannerTypeValue, setBannerTypeValue] = useState(0);
// 是否有效
const [validTime, setValidTime] = useState<number>(0);
// 关闭弹窗
const handleCancel = () => {
setBannerTypeValue(0);
......@@ -56,7 +59,7 @@ const AddEditModal: React.FC<propType> = (props) => {
form
.validateFields()
.then(async (values) => {
await handleSubmit(values);
await handleSubmit(values as ReqType & { timeRange: string[] });
})
.catch((err) => {
message
......@@ -67,9 +70,15 @@ const AddEditModal: React.FC<propType> = (props) => {
});
};
// 提交事件
const handleSubmit = async (values: ReqType) => {
const handleSubmit = async (values: ReqType & { timeRange: string[] }) => {
const res = await CommonAPI[data?.id ? 'updateBannerInfo' : 'insertBannerInfo']({
...values,
startTime: values.timeRange
? dayjs(values.timeRange[0]).format('YYYY-MM-DD HH:mm:ss')
: undefined,
endTime: values.timeRange
? dayjs(values.timeRange[1]).format('YYYY-MM-DD HH:mm:ss')
: undefined,
moduleId,
id: data?.id,
});
......@@ -84,6 +93,11 @@ const AddEditModal: React.FC<propType> = (props) => {
if (!data) return;
form.setFieldsValue(data);
setBannerTypeValue(data?.bannerType);
if (data?.endTime && data?.startTime) {
setValidTime(1);
form.setFieldValue('validTime', 1);
form.setFieldValue('timeRange', [dayjs(data?.startTime), dayjs(data?.endTime)]);
}
// console.log('data --->', data);
}, [open]);
return (
......@@ -110,8 +124,50 @@ const AddEditModal: React.FC<propType> = (props) => {
{ label: '下架', value: 0 },
]}
allowClear
onChange={(e) => {
if (e === 1) {
form.setFieldValue('timeRange', undefined);
}
}}
/>
</Form.Item>
<Form.Item label='有效时间' required wrapperCol={{ span: 18 }}>
<Space.Compact>
<Form.Item
name={'validTime'}
noStyle
rules={[{ required: true, message: '请选择是否有效' }]}
initialValue={0}
>
<Select
placeholder='请选择是否有效'
options={[
{ label: '永久有效', value: 0 },
{ label: '有效期限', value: 1 },
]}
style={{ width: '30%' }}
value={validTime}
onChange={(e) => {
setValidTime(e);
if (e === 0) {
form.setFieldValue('timeRange', undefined);
}
}}
/>
</Form.Item>
<Form.Item
name={'timeRange'}
noStyle
rules={[{ required: validTime === 1, message: '请选择有效期限' }]}
>
<DatePicker.RangePicker
showTime={{ format: 'HH:mm:ss' }}
format='YYYY-MM-DD HH:mm:ss'
disabled={validTime === 0}
/>
</Form.Item>
</Space.Compact>
</Form.Item>
<Form.Item
label='封面图'
name='bannerImg'
......@@ -207,7 +263,10 @@ const AddEditModal: React.FC<propType> = (props) => {
<Form.Item
label='链接地址'
name='bannerUrl'
rules={[{ required: true, message: '请输入链接地址' }]}
rules={[
{ required: true, message: '请输入链接地址' },
{ pattern: /^[^\s]*$/, message: '地址不能包含空格' },
]}
>
<Input placeholder={'请输入链接地址'} maxLength={100} allowClear />
</Form.Item>
......
......@@ -17,10 +17,11 @@ interface propType {
}
// 所属产品
const moduleType = [
{ label: '云享飞', value: 0 },
{ label: '云飞手', value: 1 },
{ label: '云仓', value: 2 },
{ label: '无人机城', value: 3 },
{ label: '云享飞Pro', value: 0 },
{ label: '云享飞Web', value: 1 },
// { label: '云飞手', value: 1 },
// { label: '云仓', value: 2 },
// { label: '无人机城', value: 3 },
];
const AddModuleModal: React.FC<propType> = (props) => {
......
......@@ -17,10 +17,11 @@ type ReqType = InterReqListType<listBannerInfoPage>;
let query: ReqType = {};
// 所属产品
const moduleType = [
{ label: '云享飞', value: '0' },
{ label: '云飞手', value: '1' },
{ label: '云仓', value: '2' },
{ label: '无人机城', value: '3' },
{ label: '云享飞Pro', value: '0' },
{ label: '云享飞Web', value: '1' },
// { label: '云飞手', value: '1' },
// { label: '云仓', value: '2' },
// { label: '无人机城', value: '3' },
];
// 详情类型
const bannerType = [
......@@ -37,6 +38,8 @@ const bannerType = [
{ label: '链接', value: 8 },
{ label: '富文本', value: 11 },
];
// 全部数据
// let tableDataAll: TableType = [];
const MaterielManageDetail = () => {
const { confirm } = Modal;
......@@ -120,6 +123,7 @@ const MaterielManageDetail = () => {
if (res && res.code === '200') {
const { list } = res.result; // 解构
setTableDataAll(list || []);
// tableDataAll = list || [];
}
};
// 切换排序
......@@ -147,24 +151,30 @@ const MaterielManageDetail = () => {
setSortBtnDisabled(true);
// 转换位置
const res = await CommonAPI.exchangeBannerInfo(
from === 'up' ? [tableDataAll[index - 1], item] : [tableDataAll[index + 1], item],
from === 'up'
? [tableDataAll[index - 1], tableDataAll[index]]
: [tableDataAll[index + 1], tableDataAll[index]],
);
if (res && res.code === '200') {
message.success('操作成功').then();
setSortBtnDisabled(false);
// setSelectedRows(from === 'up' ? [tableDataAll[index - 1]] : [tableDataAll[index + 1]]);
// 如果是当前页的第一条数据
if (tableIndex === 0 && from === 'up') {
paginationChange(pagination.current - 1, pagination.pageSize);
await getAllData();
await setSortBtnDisabled(false);
return;
}
// 如果是当前页的最后一条数据
if (tableIndex === tableData.length - 1 && from === 'down') {
paginationChange(pagination.current + 1, pagination.pageSize);
await getAllData();
await setSortBtnDisabled(false);
return;
}
paginationChange(pagination.current, pagination.pageSize);
getAllData().then();
await getAllData();
await setSortBtnDisabled(false);
}
};
// 修改提交数据
......@@ -208,6 +218,13 @@ const MaterielManageDetail = () => {
width: '50px',
render: (_text, _record, index) => (pagination.current - 1) * pagination.pageSize + index + 1,
},
// {
// title: 'sort',
// dataIndex: 'sort',
// align: 'center',
// width: '100px',
// ellipsis: true,
// },
{
title: '名称',
dataIndex: 'bannerName',
......@@ -254,6 +271,23 @@ const MaterielManageDetail = () => {
render: (text) => (text === 1 ? '上架' : '下架'),
},
{
title: '有效时间',
dataIndex: 'createTime',
align: 'center',
width: '120px',
ellipsis: true,
render: (_text, record) =>
record.startTime && record.endTime ? (
<>
<div>{record?.startTime}</div>
<div></div>
<div>{record?.endTime}</div>
</>
) : (
'永久'
),
},
{
title: '操作',
dataIndex: 'action',
align: 'center',
......@@ -393,6 +427,7 @@ const MaterielManageDetail = () => {
setAddModalVisible(false);
setEditData(undefined);
paginationChange(pagination.current, pagination.pageSize);
getAllData().then();
}}
moduleId={Number(qs.parse(location.search).id)}
/>
......
......@@ -19,10 +19,10 @@ type ReqType = InterReqListType<listModuleInfoPage>;
let query: ReqType = {};
// 所属产品
const moduleType = [
{ label: '云享飞', value: 0 },
{ label: '云飞手', value: 1 },
{ label: '云仓', value: 2 },
{ label: '无人机城', value: 3 },
{ label: '云享飞Pro', value: 0 },
{ label: '云享飞Web', value: 1 },
// { label: '云仓', value: 2 },
// { label: '无人机城', value: 3 },
];
const MaterielManageView = () => {
......@@ -184,7 +184,7 @@ const MaterielManageView = () => {
search={[
{
label: '模块名称',
name: 'keyword',
name: 'moduleName',
type: 'input',
placeholder: '请输入模块名称',
},
......
.require-description{
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
cursor: pointer;
}
import SearchBox, { searchColumns } from '~/components/search-box';
import { useEffect, useState } from 'react';
import { Button, message, Modal, Table, Tooltip } from 'antd';
import { ColumnsType } from 'antd/es/table';
import { ResourceManageAPI } from '~/api';
import { InterDataType, InterReqType, PaginationProps } from '~/api/interface';
import './index.scss';
import { listPublishPageType } from '~/api/interface/resourceManageType';
//需求列表返回类型
type requirementsType = InterDataType<listPublishPageType>['list'];
type requirementsParameter = Omit<InterReqType<listPublishPageType>, 'pageSize' | 'pageNo'>;
const RequirementsGathering = () => {
const [searchColumnsData, setSearchColumnsData] = useState<searchColumns[]>([
{
label: '需求类型',
type: 'select',
placeholder: '请选择需求类型',
name: 'requirementTypeId',
options: [],
},
{
label: '需求发起人',
type: 'input',
placeholder: '输入姓名/手机号搜索',
name: 'keyword',
},
]);
const tableColumn: ColumnsType<requirementsType[0]> = [
{
title: '需求类型',
align: 'center',
dataIndex: 'requirementTypeName',
},
{
title: '姓名',
align: 'center',
dataIndex: 'publishName',
},
{
title: '手机号',
align: 'center',
dataIndex: 'publishPhone',
},
{
title: '需求描述',
align: 'center',
dataIndex: 'requireDescription',
width: '20%',
ellipsis: true,
render: (text: string) => (
<Tooltip placement='top' title={text}>
<div className='require-description'>{text}</div>
</Tooltip>
),
},
{
title: '操作',
align: 'center',
render: (_text: string, record) => (
<>
<Button type='link' danger onClick={() => deleteRequirements(record)}>
强制删除
</Button>
<Button type='link'>联系客户</Button>
</>
),
},
];
const [tableData, setTableData] = useState<requirementsType>([]);
const [loading, setLoading] = useState<boolean>(false);
const [pagination, setPagination] = useState<PaginationProps & { totalCount: number }>({
pageNo: 1,
pageSize: 10,
totalCount: 0,
});
const [query, setQuery] = useState<requirementsParameter>();
//筛选
const searchSuccessEvent = (value: any) => {
pagination.pageSize = 10;
pagination.pageNo = 1;
setQuery(value);
getRequirementsList(value);
};
//分页
const paginationChange = (pageNo: number, pageSize: number) => {
pagination.pageNo = pageNo;
pagination.pageSize = pageSize;
getRequirementsList(query);
};
//需求列表
const getRequirementsList = (query?: requirementsParameter) => {
setLoading(true);
ResourceManageAPI.getListPublishPage({
pageSize: pagination.pageSize,
pageNo: pagination.pageNo,
...query,
}).then(({ result }) => {
setLoading(false);
setTableData(result.list || []);
pagination.totalCount = result.totalCount;
setPagination(pagination);
});
};
//需求类型列表
const getRequirementsTypeList = () => {
ResourceManageAPI.getRequirementTypeList().then(({ result }) => {
searchColumnsData[0].options = result.map((v) => ({ id: v.id, name: v.typeName }));
setSearchColumnsData([...searchColumnsData]);
});
};
//需求删除
const deleteRequirements = (record: requirementsType[0]) => {
Modal.confirm({
title: '需求删除',
content: '确认删除该需求?',
onOk: () => {
ResourceManageAPI.deleteRequirement({ requirementsInfoId: record.id }).then(({ code }) => {
if (code === '200') {
message.success('删除成功');
if (pagination.pageNo !== 1 && tableData.length === 1) {
pagination.pageNo -= 1;
}
getRequirementsList(query);
}
});
},
});
};
useEffect(() => {
getRequirementsList();
getRequirementsTypeList();
}, []);
return (
<div className='requirements-gathering'>
<SearchBox search={searchColumnsData} searchData={searchSuccessEvent} />
<Table
bordered
columns={tableColumn}
dataSource={tableData}
rowKey='id'
loading={loading}
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} 条数据`,
}}
/>
</div>
);
};
export default RequirementsGathering;
import { FC } from 'react';
import { Form, Input, Modal, ModalProps, Select } from 'antd';
import { Uploader } from '~/components/uploader';
import { UploadOutlined } from '@ant-design/icons';
interface selfProps {}
const AddOrEditTagModal: FC<ModalProps & selfProps> = ({ open, onCancel }) => {
return (
<Modal open={open} onCancel={onCancel} title='新建标签'>
<Form labelCol={{ span: 4 }} wrapperCol={{ span: 16 }}>
<Form.Item label='标签名称'>
<Input placeholder='请输入标签名称' />
</Form.Item>
<Form.Item label='标签类型'>
<Select placeholder='请选择标签类型'>
<Select.Option>1111</Select.Option>
</Select>
</Form.Item>
<Form.Item label='标签等级图标'>
<Uploader fileUpload listType='picture-card'>
<UploadOutlined />
</Uploader>
</Form.Item>
</Form>
</Modal>
);
};
export default AddOrEditTagModal;
import SearchBox, { searchColumns } from '~/components/search-box';
import { Button, Table } from 'antd';
import { PlusOutlined } from '@ant-design/icons';
import { ColumnsType } from 'antd/es/table';
import { useState } from 'react';
import AddOrEditTagModal from './components/addOrEditTagModal';
//行业新闻
const TagManage = () => {
const searchColumnsData: searchColumns[] = [
{
label: '标签名称',
placeholder: '请输入标签名称',
name: '',
type: 'input',
},
];
const tableColumns: ColumnsType<any> = [
{
title: '序号',
align: 'center',
},
{
title: '标签名称',
align: 'center',
},
{
title: '标签类型',
align: 'center',
},
{
title: '标签等级图标',
align: 'center',
},
{
title: '操作',
align: 'center',
render: () => (
<>
<Button type='link'>编辑</Button>
<Button type='link'>删除</Button>
</>
),
},
];
const [tableData, setTableData] = useState<any>([{ id: 1 }]);
const [addOrEditTagModalShow, setAddOrEditTagModalShow] = useState<boolean>(false);
const addOrEditTagClick = () => {
setAddOrEditTagModalShow(true);
};
const addOrEditTagModalCancel = () => {
setAddOrEditTagModalShow(false);
};
return (
<div className='tag-manage'>
<SearchBox
search={searchColumnsData}
child={
<Button type='primary' icon={<PlusOutlined />} onClick={addOrEditTagClick}>
新建
</Button>
}
/>
<Table bordered columns={tableColumns} dataSource={tableData} rowKey='id'></Table>
<AddOrEditTagModal open={addOrEditTagModalShow} onCancel={addOrEditTagModalCancel} />
</div>
);
};
export default TagManage;
import React, { useEffect } from 'react';
import { Form, Input, message, Modal } from 'antd';
import { InterListType, InterReqType } from '~/api/interface';
import {
releaseTenderNewsInfoUpdate,
releaseTenderNewsInfo,
} from '~/api/interface/resourceManageType';
import { ResourceManageAPI } from '~/api';
import RichText from '~/components/richText';
// 列表的类型
type TableType = InterListType<releaseTenderNewsInfo>;
// 请求的表单类型
type ReqType = InterReqType<releaseTenderNewsInfoUpdate>;
// 传参类型
interface propType {
title: string;
open: boolean;
closed: any;
data?: TableType[0];
}
const AddEditDetailModal: React.FC<propType> = (props) => {
AddEditDetailModal.defaultProps = {
data: undefined,
};
// 参数
const { title, open, closed, data } = props;
// 表单钩子
const [form] = Form.useForm<ReqType>();
// 关闭弹窗
const handleCancel = () => {
form.resetFields();
closed();
};
// 确认事件
const handleOk = () => {
form
.validateFields()
.then(async (values) => {
await handleSubmit(values as ReqType & { file: any[] });
})
.catch((err) => {
message
.warning({
content: err.errorFields[0].errors[0],
})
.then();
});
};
// 提交事件
const handleSubmit = async (values: ReqType) => {
const res = await ResourceManageAPI.releaseTenderNewsInfoUpdate({
...values,
id: Number(data?.id),
});
if (res && res.code === '200') {
message.success('操作成功');
handleCancel();
}
};
// componentDidMount
useEffect(() => {
if (!open) return;
if (!data) return;
form.setFieldsValue(data);
// console.log('data --->', data);
}, [open]);
return (
<Modal
open={open}
title={title}
onCancel={handleCancel}
onOk={handleOk}
destroyOnClose
width={768}
>
<Form
name='Form'
form={form}
labelAlign='right'
labelCol={{ span: 2 }}
wrapperCol={{ span: 21 }}
>
<Form.Item
label='标题'
name='tenderTitle'
rules={[{ required: true, message: '请输入标题' }]}
>
<Input placeholder={'请输入标题'} maxLength={50} allowClear />
</Form.Item>
<Form.Item
label='价格'
name='tenderPrice'
rules={[
{ required: true, message: '请输入价格' },
() => ({
validator(_, value) {
if (value && value.length > 10) {
return Promise.reject('金额不能超过十位数');
}
return Promise.resolve();
},
}),
]}
>
<Input
type={'number'}
placeholder={'请输入价格'}
maxLength={10}
allowClear
suffix={'万元'}
/>
</Form.Item>
<Form.Item
label='详情'
name='tenderContent'
rules={[{ required: true, message: '请输入详情' }]}
>
<RichText
value={form.getFieldValue('tenderContent')}
onChange={(e) => form.setFieldValue('tenderContent', e)}
height={250}
/>
</Form.Item>
</Form>
</Modal>
);
};
export default AddEditDetailModal;
import React, { useEffect } from 'react';
import { Button, Form, Input, message, Modal, Select } from 'antd';
import { InterListType, InterReqType } from '~/api/interface';
import { releaseTenderNewsUpdate, releaseTenderNews } from '~/api/interface/resourceManageType';
import { ResourceManageAPI } from '~/api';
import { Uploader } from '~/components/uploader';
import { UploadOutlined } from '@ant-design/icons';
// 列表的类型
type TableType = InterListType<releaseTenderNews>;
// 请求的表单类型
type ReqType = InterReqType<releaseTenderNewsUpdate>;
// 传参类型
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 [form] = Form.useForm<ReqType>();
// 关闭弹窗
const handleCancel = () => {
form.resetFields();
closed();
};
// 确认事件
const handleOk = () => {
form
.validateFields()
.then(async (values) => {
await handleSubmit(values as ReqType & { file: any[] });
})
.catch((err) => {
message
.warning({
content: err.errorFields[0].errors[0],
})
.then();
});
};
// 提交事件
const handleSubmit = async (values: ReqType & { file: any[] }) => {
const formData = new FormData();
formData.append('file', values?.file?.at(-1));
const blob = new Blob([JSON.stringify({ ...values, id: data?.id ? data?.id : null })], {
type: 'application/json',
});
formData.append('tenderNewsVO', blob);
const res = await ResourceManageAPI[
data?.id ? 'releaseTenderNewsUpdate' : 'releaseTenderNewsAdd'
](formData);
if (res && res.code === '200') {
message.success('操作成功');
handleCancel();
}
};
// componentDidMount
useEffect(() => {
if (!open) return;
if (!data) return;
form.setFieldsValue(data);
// console.log('data --->', data);
}, [open]);
return (
<Modal open={open} title={title} onCancel={handleCancel} onOk={handleOk} destroyOnClose>
<Form
name='Form'
form={form}
labelAlign='right'
labelCol={{ span: 5 }}
wrapperCol={{ span: 10 }}
>
<Form.Item
label='招标快讯名称'
name='tenderName'
rules={[{ required: true, message: '请输入名称' }]}
>
<Input placeholder={'请输入名称'} maxLength={20} allowClear />
</Form.Item>
<Form.Item
label='状态'
name='using'
rules={[{ required: true, message: '请选择状态' }]}
initialValue={1}
>
<Select
placeholder={'请选择状态'}
options={[
{ label: '上架', value: 1 },
{ label: '下架', value: 0 },
]}
allowClear
/>
</Form.Item>
<Form.Item
label='上传内容'
name='file'
rules={[{ required: !data?.id, message: '请上传内容' }]}
>
<Uploader
listType={'text'}
fileUpload={false}
fileType={[
'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
'application/vnd.ms-excel',
]}
onChange={(e) => {
form.setFieldValue('file', e);
}}
>
<Button icon={<UploadOutlined />} type={'primary'}>
上传
</Button>
</Uploader>
</Form.Item>
</Form>
</Modal>
);
};
export default AddEditModal;
import { useEffect, useState } from 'react';
import { useLocation, useNavigate } from 'react-router-dom';
import SearchBox from '~/components/search-box';
import { Button, Table, Tooltip } from 'antd';
import { ArrowLeftOutlined } from '@ant-design/icons';
import qs from 'query-string';
import { InterListType } from '~/api/interface';
import { releaseTenderNewsInfo } from '~/api/interface/resourceManageType';
import { ResourceManageAPI } from '~/api';
import { ColumnsType } from 'antd/es/table';
import AddEditDetailModal from '~/pages/resourceManage/tenderManage/comp/addEditDetailModal';
// 列表类型
type TableType = InterListType<releaseTenderNewsInfo>;
const TenderManageDetail = () => {
// 路由钩子
const location = useLocation();
// 导航钩子
const navigate = useNavigate();
// 返回上一页
const handleBack = () => {
navigate(-1);
};
// 新增修改弹窗是否开启
const [addModalVisible, setAddModalVisible] = useState(false);
// 需要编辑的数据
const [editData, setEditData] = useState<TableType[0]>();
// 表格数据
const [tableData, setTableData] = useState<TableType>([]);
// 表格分页配置
const [pagination, setPagination] = useState({
total: 0,
pageSize: 10,
current: 1,
totalPage: 0,
});
// 加载列表
const getTableList = async (value = {}) => {
// 只需要修改这个地方的接口即可
const res = await ResourceManageAPI.releaseTenderNewsInfo({
pageNo: pagination.current,
pageSize: pagination.pageSize,
...value,
tenderNewsId: Number(qs.parse(location.search)?.id),
});
if (res && res.code === '200') {
const { list, pageNo, totalCount, pageSize, totalPage } = res.result; // 解构
setPagination({
total: totalCount,
current: pageNo,
pageSize,
totalPage,
});
setTableData(list || []);
}
};
// 翻页
const paginationChange = (pageNo: number, pageSize: number) => {
getTableList({ pageNo, pageSize }).then();
};
// componentDidMount
useEffect(() => {
getTableList().then();
}, []);
// 表格结构
const columns: ColumnsType<TableType[0]> = [
{
title: '序号',
dataIndex: 'accountNo',
align: 'center',
width: '50px',
render: (_text, _record, index) => (pagination.current - 1) * pagination.pageSize + index + 1,
},
{
title: '标题',
dataIndex: 'tenderTitle',
align: 'center',
width: '200px',
ellipsis: true,
},
{
title: '详情',
dataIndex: 'tenderContent',
align: 'center',
width: '300px',
ellipsis: true,
render: (text) =>
text && (
<Tooltip
placement='top'
title={
<div
dangerouslySetInnerHTML={{ __html: text.replace(/<img(?:(?!\/>).|\n)*?\/>/gm, '') }}
/>
}
>
<div
style={{
height: '20px',
overflow: 'hidden',
textOverflow: 'ellipsis',
whiteSpace: 'nowrap',
wordBreak: 'break-all',
}}
dangerouslySetInnerHTML={{ __html: text }}
/>
</Tooltip>
),
},
{
title: '价格(万元)',
dataIndex: 'tenderPrice',
align: 'center',
width: '100px',
ellipsis: true,
render: (text) => text?.toLocaleString(),
},
{
title: '操作',
dataIndex: 'action',
align: 'center',
width: '100px',
fixed: 'right',
render: (_text, record) => (
<Button
type={'link'}
onClick={() => {
setEditData(JSON.parse(JSON.stringify(record)));
setAddModalVisible(true);
}}
>
编辑
</Button>
),
},
];
return (
<>
<SearchBox
child={
<>
<Button type={'primary'} icon={<ArrowLeftOutlined />} onClick={handleBack}>
返回
</Button>
</>
}
/>
<Table
size='small'
dataSource={tableData}
columns={columns}
rowKey='id'
// scroll={{ x: 1500 }}
bordered
pagination={{
total: pagination.total,
pageSize: pagination.pageSize,
current: pagination.current,
showSizeChanger: true,
showQuickJumper: true,
onChange: (page: number, pageSize: number) => paginationChange(page, pageSize),
showTotal: (total, range) => `当前 ${range[0]}-${range[1]} 条记录 / 共 ${total} 条数据`,
}}
/>
<AddEditDetailModal
open={addModalVisible}
title={editData?.id ? '编辑' : '新增'}
data={editData}
closed={() => {
setAddModalVisible(false);
setEditData(undefined);
paginationChange(pagination.current, pagination.pageSize);
}}
/>
</>
);
};
export default TenderManageDetail;
import { useEffect, useState } from 'react';
import SearchBox from '~/components/search-box';
import { ResourceManageAPI } from '~/api';
import qs from 'query-string';
import { useLocation, useNavigate } from 'react-router-dom';
import { Button, Table } from 'antd';
import { ArrowLeftOutlined } from '@ant-design/icons';
import {
releaseTenderNewsApplyList,
releaseTenderNewsInfo,
} from '~/api/interface/resourceManageType';
import { InterListType, InterReqListType } from '~/api/interface';
import { ColumnsType } from 'antd/es/table';
// 列表类型
type ListType = InterListType<releaseTenderNewsInfo>;
// 表格类型
type TableType = InterListType<releaseTenderNewsApplyList>;
// 请求的参数
type ReqType = InterReqListType<releaseTenderNewsApplyList>;
// 搜索表单的数据
let query: ReqType = {};
const TenderManageFeedback = () => {
// 路由钩子
const location = useLocation();
// 导航钩子
const navigate = useNavigate();
// 返回上一页
const handleBack = () => {
navigate(-1);
};
// 表格数据
const [tableData, setTableData] = useState<TableType>([]);
// 表格分页配置
const [pagination, setPagination] = useState({
total: 0,
pageSize: 10,
current: 1,
totalPage: 0,
});
// 快讯详情列表
const [tenderInfoList, setTenderInfoId] = useState<
{ value: number; label: string; data: ListType[0] }[]
>([]);
// 获取快讯详情列表
const getNewsInfoList = async () => {
const res = await ResourceManageAPI.releaseTenderNewsInfo({
pageNo: 1,
pageSize: 9999,
tenderNewsId: Number(qs.parse(location.search)?.id),
});
if (res && res.code === '200') {
const list = res.result?.list || [];
setTenderInfoId(
list?.map((i, j) => ({
value: i.id,
label: `${j + 1}${i.tenderTitle}`,
data: i,
})),
);
}
};
// 加载列表
const getTableList = async (value = {}) => {
// 只需要修改这个地方的接口即可
const res = await ResourceManageAPI.releaseTenderNewsApplyList({
pageNo: pagination.current,
pageSize: pagination.pageSize,
...value,
...query,
tenderNewsId: Number(qs.parse(location.search)?.id),
});
if (res && res.code === '200') {
const { list, pageNo, totalCount, pageSize, totalPage } = res.result; // 解构
setPagination({
total: totalCount,
current: pageNo,
pageSize,
totalPage,
});
setTableData(list);
}
};
// 翻页
const paginationChange = (pageNo: number, pageSize: number) => {
getTableList({ pageNo, pageSize }).then();
};
// 表单提交
const onFinish = (data: ReqType) => {
pagination.current = 1;
query = data;
getTableList(data).then();
};
// componentDidMount
useEffect(() => {
query = {};
getNewsInfoList().then();
getTableList().then();
}, []);
// 表格结构
const columns: ColumnsType<TableType[0]> = [
{
title: '编号',
dataIndex: 'tenderInfoNo',
align: 'center',
},
{
title: '标题',
dataIndex: 'tenderTitle',
align: 'center',
ellipsis: true,
},
{
title: '用户昵称',
dataIndex: 'nickName',
align: 'center',
},
{
title: '用户姓名',
dataIndex: 'userName',
align: 'center',
},
{
title: '电话号码',
dataIndex: 'phoneNum',
align: 'center',
},
];
return (
<>
<SearchBox
search={[
{
label: '项目编号',
name: 'tenderInfoId',
type: 'Select',
placeholder: '请选择编号',
options: tenderInfoList,
},
{ label: '用户姓名', name: 'userName', type: 'input', placeholder: '请输入用户姓名' },
]}
searchData={onFinish}
child={
<>
<Button type={'primary'} icon={<ArrowLeftOutlined />} onClick={handleBack}>
返回
</Button>
</>
}
/>
<Table
size='small'
dataSource={tableData}
columns={columns}
rowKey='id'
// scroll={{ x: 1500 }}
bordered
pagination={{
total: pagination.total,
pageSize: pagination.pageSize,
current: pagination.current,
showSizeChanger: true,
showQuickJumper: true,
onChange: (page: number, pageSize: number) => paginationChange(page, pageSize),
showTotal: (total, range) => `当前 ${range[0]}-${range[1]} 条记录 / 共 ${total} 条数据`,
}}
/>
</>
);
};
export default TenderManageFeedback;
import { useEffect, useState } from 'react';
import SearchBox from '~/components/search-box';
import { Button, message, Modal, Table } from 'antd';
import { PlusOutlined, DownloadOutlined } from '@ant-design/icons';
import { ColumnsType } from 'antd/es/table';
import { ResourceManageAPI } from '~/api';
import { InterListType, InterReqListType } from '~/api/interface';
import { releaseTenderNews } from '~/api/interface/resourceManageType';
import AddEditModal from './comp/addEditModal';
import qs from 'query-string';
import { useNavigate } from 'react-router-dom';
import saveAs from 'file-saver';
// 列表类型
type TableType = InterListType<releaseTenderNews>;
// 请求的参数
type ReqType = InterReqListType<releaseTenderNews>;
// 搜索表单的数据
let query: ReqType = {};
const TenderManageView = () => {
const { confirm } = Modal;
// 路由钩子
const navigate = useNavigate();
// 新增弹窗
const [addModalVisible, setAddModalVisible] = useState<boolean>(false);
// 需要编辑的数据
const [editData, setEditData] = useState<TableType[0]>();
// 表格数据
const [tableData, setTableData] = useState<TableType>([]);
// 表格分页配置
const [pagination, setPagination] = useState({
total: 0,
pageSize: 10,
current: 1,
totalPage: 0,
});
// 加载列表
const getTableList = async (value = {}) => {
// 只需要修改这个地方的接口即可
const res = await ResourceManageAPI.releaseTenderNews({
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);
}
};
// 翻页
const paginationChange = (pageNo: number, pageSize: number) => {
getTableList({ pageNo, pageSize }).then();
};
// 表单提交
const onFinish = (data: ReqType & { rangeTime: string[] }) => {
pagination.current = 1;
query = {
startTime: data.rangeTime ? data.rangeTime[0] : undefined,
endTime: data.rangeTime ? data.rangeTime[1] : undefined,
tenderName: data.tenderName,
using: data.using,
};
getTableList(query).then();
};
// 删除数据
const handleDelete = (record: TableType[0]) => {
confirm({
title: '提示',
content: '是否删除该记录?',
onOk: async () => {
const res = await ResourceManageAPI.releaseTenderNewsDelete({ id: record.id });
if (res && res.code === '200') {
message.success('删除成功');
paginationChange(
tableData.length === 1 ? pagination.current - 1 : pagination.current,
pagination.pageSize,
);
}
},
});
};
// 跳转详情
const handleDetail = (record: TableType[0]) => {
const search = {
id: record.id,
};
navigate(`/resourceManage/tenderManage/detail?${qs.stringify(search)}`);
};
// 跳转反馈
const handleFeedback = (record: TableType[0]) => {
const search = {
id: record.id,
};
navigate(`/resourceManage/tenderManage/feedback?${qs.stringify(search)}`);
};
// componentDidMount
useEffect(() => {
query = {};
getTableList().then();
}, []);
// 表格结构
const columns: ColumnsType<TableType[0]> = [
{
title: '招标快讯名称',
dataIndex: 'tenderName',
align: 'center',
ellipsis: true,
},
{
title: '发布时间',
dataIndex: 'createTime',
align: 'center',
},
{
title: '状态',
dataIndex: 'using',
align: 'center',
render: (text) => (text === 1 ? '上架' : '下架'),
},
{
title: '操作',
dataIndex: 'action',
align: 'center',
width: '200px',
fixed: 'right',
render: (_text, record) => (
<>
<Button type={'link'} onClick={() => handleDetail(record)}>
详情
</Button>
<Button
type={'link'}
onClick={() => {
setEditData(JSON.parse(JSON.stringify(record)));
setAddModalVisible(true);
}}
>
编辑
</Button>
<Button type={'link'} onClick={() => handleFeedback(record)}>
用户反馈
</Button>
<Button type={'link'} danger onClick={() => handleDelete(record)}>
删除
</Button>
</>
),
},
];
return (
<>
<SearchBox
search={[
{ name: 'tenderName', label: '名称', type: 'input', placeholder: '请输入招标快讯名称' },
{
name: 'rangeTime',
label: '发布时间',
type: 'rangePicker',
placeholder: '请选择开始时间和结束时间',
},
]}
searchData={onFinish}
child={
<>
<Button
type={'primary'}
icon={<PlusOutlined />}
onClick={() => {
setAddModalVisible(true);
}}
>
新增
</Button>
</>
}
otherChild={
<>
<Button
type={'primary'}
icon={<DownloadOutlined />}
onClick={() => {
saveAs(
'https://pad-video-x.oss-cn-shenzhen.aliyuncs.com/doc/tender-news-template.xlsx',
`招标快讯模板_${new Date().getTime()}.xlsx`,
);
}}
>
下载模板
</Button>
</>
}
/>
<Table
size='small'
dataSource={tableData}
columns={columns}
rowKey='id'
// scroll={{ x: 1500 }}
bordered
pagination={{
total: pagination.total,
pageSize: pagination.pageSize,
current: pagination.current,
showSizeChanger: true,
showQuickJumper: true,
onChange: (page: number, pageSize: number) => paginationChange(page, pageSize),
showTotal: (total, range) => `当前 ${range[0]}-${range[1]} 条记录 / 共 ${total} 条数据`,
}}
/>
<AddEditModal
open={addModalVisible}
title={editData?.id ? '编辑' : '新增'}
data={editData}
closed={() => {
setAddModalVisible(false);
setEditData(undefined);
paginationChange(pagination.current, pagination.pageSize);
}}
/>
</>
);
};
export default TenderManageView;
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论