ylj20011123 f651d3c91b update
2026-02-28 18:56:16 +08:00

472 lines
19 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
* @Author: cclue
* @Date: 2021-12-13 11:01:23
* @LastEditTime: 2024-12-16 11:03:30
* @LastEditors: cclu 1106109051@qq.com
* @Description: 经营项目列表页面
* @FilePath: \cloud-platform\src\pages\BussinessProject\list.tsx
*/
// 经营项目管理
import React from "react";
import Draggable from "react-draggable";
import SubMenu from "antd/lib/menu/SubMenu";
import ProTable from "@ant-design/pro-table";
import useRequest from "@ahooksjs/use-request";
import { useRef, useState } from "react";
import { PlusOutlined } from "@ant-design/icons";
import { PageContainer } from "@ant-design/pro-layout";
import { Button, Col, Drawer, Menu, message, Modal, Popconfirm, Row, Spin, Typography } from "antd";
import type { ActionType, ProColumns } from "@ant-design/pro-table";
import type { FormInstance } from 'antd';
import type { BusinessProjectModel } from "./data";
import type { ProFormInstance } from "@ant-design/pro-form";
import type { ServerpartTree } from "@/services/options";
import type { ContractListModel } from "../contract/data";
import type { ServerpartShopModel } from "../basicManage/ServerpartShop/data";
import { delProject, getProjectDetail, getProjectList, updateProject } from "./service";
import { getFieldEnum, getServerpartTree } from "@/services/options";
import { getList as getContractList } from "@/pages/contract/service";
import { getList as getServerpartShopList } from "@/pages/basicManage/ServerpartShop/service"
import { contractType } from "../contract/emun";
import ProjectEditor from './editor'
import ProjectDetail from './detail'
import './style.less'
import session from "@/utils/session";
import moment from "moment";
import PageTitleBox from "@/components/PageTitleBox";
import { CurrentUser } from "umi";
// 经营项目管理列表
// 列表数据删除功能;函数返回值为布尔型,表示成功或失败
const handelDelete = async (registerCompactId: number): Promise<boolean> => {
// 提示正在执行删除消息
const hide = message.loading('正在删除...');
try {
// 同步请求删除数据,等待返回值
const result = await delProject(registerCompactId);
// 关闭 提示正在执行删除的消息
hide();
// 根据返回值提示用户是否删除成功 并返回对应的布尔值
if (result.Result_Code !== 100) {
message.error(`${result.Result_Desc}`);
return false;
}
message.success('删除成功!');
return true;
} catch (error) { // 捕获请求异常,若执行则返回失败
hide();
message.error('删除失败');
return false;
}
};
// 提交新增或编辑的项目数据;函数返回值为布尔型,表示成功或失败
/**
* @description: 生成服务区左侧菜单
* @param {ServerpartTree[]} data 菜单数据源
* @param {Function} callback 点击菜单回调函数
* @return {JSX.Element[]} 返回jsx数据节点集
*/
function getMenuDom(data: ServerpartTree[], callback?: Function) {
// 遍历菜单数据源并返回相应的菜单子父级节点
return (
data.map((element: any) => {
// 判断数据是否为父级菜单 是则返回父级菜单容器并生成包含的子菜单
if (element.type === 0) {
return (
<SubMenu // 父级菜单andt组件
title={element.label}
key={`${element.value}`}
onTitleClick={(item) => { // 点击父级菜单标题方法 执行传入的回调方法
callback?.call(callback, item);
item.domEvent.stopPropagation();
}}
>
{/* 父级菜单有子级存在,则遍历子级数据生成子菜单 */}
{element.children && element.children.length > 0 && getMenuDom(element.children, callback)}
</SubMenu>
);
}
// 返回子菜单
return (
<Menu.Item key={`${element.value}`}>{element.label}</Menu.Item>); // 子级菜单andt组件
})
);
}
// 项目页面主体
// const ProjecetTable: React.FC = () => {
const ProjecetTable: React.FC<{ currentUser?: CurrentUser }> = (props) => {
const serverpartObj = session.get('serverpartObj')
const { currentUser } = props
// props
// useState 为umi封装的hooks方法
const [currentRow, setCurrentRow] = useState<BusinessProjectModel | any>(undefined) // 选中的当前行
const [showDetail, setShowDetail] = useState<boolean>(false) // 是否显示详情
const [modalVisible, handleModalVisible] = useState<boolean>(false) // 是否显示编辑
// 经营模式
const [businessType, setBusinessType] = useState<any>()
const actionRef = useRef<ActionType>() // 项目列表对象
const formRef = useRef<FormInstance>() // 项目列表查询对象
const SETTLEMENTMODESOBJ = session.get('SETTLEMENT_MODESObj')
const [showLoading, setShowLoading] = useState<boolean>(false)
// 项目列表 列数据配置
const columns: ProColumns<BusinessProjectModel>[] = [
{
title: '查询项目',
dataIndex: 'searchKey',
hideInTable: true,
hideInDescriptions: true,
fieldProps: {
placeholder: "请输入项目/备注/商户名称/门店"
}
},
{
title: '项目名称',
dataIndex: 'BUSINESSPROJECT_NAME',
ellipsis: true,
hideInDescriptions: true,
width: '24%',
render: (_, record) => {
return <a onClick={() => { // 点击项目名称时 打开抽屉 展示项目详情
setCurrentRow(record)
setShowDetail(true)
}}>{record.BUSINESSPROJECT_NAME}</a>
},
hideInSearch: true,
sorter: true,
},
{
title: '经营模式',
dataIndex: 'BUSINESS_TYPE',
valueType: 'select',
valueEnum: contractType,
width: 110,
align: "center",
// hideInSearch: true,
},
{
dataIndex: 'SETTLEMENT_MODES',
title: '结算模式',
valueType: 'select',
align: 'center',
width: 160,
request: async () => {
return await getFieldEnum({ FieldExplainField: 'SETTLEMENT_MODES' });
},
render: (_, record) => {
return record?.SWITCH_MODES ? `${SETTLEMENTMODESOBJ[record?.SETTLEMENT_MODES]}-->${SETTLEMENTMODESOBJ[record?.SWITCH_MODES]}` : SETTLEMENTMODESOBJ[record?.SETTLEMENT_MODES]
}
},
{
dataIndex: 'Period_Count',
hideInSearch: true,
title: '项目期数',
width: 100,
align: 'right',
},
{
dataIndex: 'Period_AvgAmount',
hideInSearch: true,
align: 'right',
title: '单期均值',
width: 100,
},
{
title: '项目金额',
dataIndex: 'GUARANTEE_PRICE',
valueType: "digit",
align: 'right',
sorter: true,
width: 130,
hideInSearch: true,
render: (_) => {
return <span style={{ paddingRight: 20 }}>{_}</span>
},
},
{
title: '经营商户',
dataIndex: 'MERCHANTS_NAME',
ellipsis: true,
width: '22%',
hideInSearch: true,
sorter: true,
},
{
title: '经营门店',
dataIndex: 'SERVERPARTSHOP_NAME',
width: 200,
hideInSearch: true,
ellipsis: true,
},
{
title: '开始日期',
hideInSearch: true,
dataIndex: 'PROJECT_STARTDATE',
valueType: 'date',
align: 'center',
width: 120,
sorter: true,
// defaultSortOrder: 'descend',
},
{
title: '结束日期',
hideInSearch: true,
dataIndex: 'PROJECT_ENDDATE',
valueType: 'date',
align: 'center',
width: 120,
sorter: true,
},
{
title: '项目周期(天)',
dataIndex: 'PROJECT_DAYS',
ellipsis: true,
hideInSearch: true,
width: '10%',
hideInTable: true
},
{
dataIndex: 'BUSINESSPROJECT_DESC',
title: '项目备注',
width: '20%',
ellipsis: true,
hideInSearch: true,
hideInDescriptions: true
},
{
title: '项目状态',
dataIndex: 'PROJECT_VALID',
valueType: 'select',
initialValue: "1",
// hideInSearch: true,
hideInTable: true,
valueEnum: {
'0': { text: '无效', status: 'error' },
'1': { text: '有效', status: 'success' },
'-1': { text: '待补充', status: 'process' }
},
},
{
title: '项目到期',
dataIndex: 'ProjectStateSearch',
hideInTable: true,
valueType: 'select',
valueEnum: {
"0": "已过期项目",
"1": "在营项目",
"2": "三个月到期",
"3": "半年到期",
}
},
{
title: '项目类型',
dataIndex: 'ProjectTypeSearch',
hideInTable: true,
valueType: 'select',
valueEnum: {
"1": "商铺租赁(有门店)",
"2": "经营资产(无门店)",
},
initialValue: '1'
},
{
title: '服务区',
dataIndex: "SERVERPART_IDS",
hideInTable: true,
valueType: 'select',
valueEnum: serverpartObj,
fieldProps: {
showSearch: true, // 支持输入文字搜索
filterOption: (input, option) => (option?.label ?? '').toLowerCase().includes(input.toLowerCase()),
}
},
{
title: '操作人',
dataIndex: 'STAFF_NAME',
hideInSearch: true,
hideInTable: true
},
{
dataIndex: 'OPERATE_DATE',
title: '更新时间',
hideInSearch: true,
hideInTable: true
},
{
title: '操作',
dataIndex: 'option',
valueType: 'option',
hideInDescriptions: true,
hideInSearch: true,
width: 90,
render: (_, record) => {
return [
<a onClick={async () => { // 点击编辑 存储当前行数据 并打开编辑弹出框
// 存在选中行且选中行数据有项目id 则 请求项目详情接口 并赋值给表单
setShowLoading(true)
if (record && record.BUSINESSPROJECT_ID) {
const data = await getProjectDetail(record?.BUSINESSPROJECT_ID)
/**
* serverpartId选择门店弹出框中查询服务区的参数
* SERVERPART_IDS服务区内码数组用在编辑页面显示服务区
* serverpartShopIds门店内码数组
*/
const current = {
...data,
serverpartId: data?.SERVERPART_IDS,
SERVERPART_IDS: data?.SERVERPART_IDS ? data?.SERVERPART_IDS.split(',').map(Number) : [],
serverpartShopIds: data?.SERVERPARTSHOP_ID ? data?.SERVERPARTSHOP_ID.split(',').map(Number) : [],
projectRangeDate: [record?.PROJECT_STARTDATE, record?.PROJECT_ENDDATE]
}
formRef.current?.setFieldsValue(current)
setCurrentRow(current)
}
else {
setCurrentRow(record)
// 否则 给表单数据赋初始值
formRef.current?.setFieldsValue({ PROJECT_VALID: 1, MULTIPROJECT_STATE: 0, SEGMENTED_MODE: 1 })
}
handleModalVisible(true)
setShowLoading(false)
}}></a>,
<Popconfirm // 删除按钮功能
title="确认删除该项目记录吗?"
onConfirm={async () => {
const sucesse = await handelDelete(record.BUSINESSPROJECT_ID); // 调用删除数据的方法
// 判断返回值 返回值若为true 则刷新项目数据
if (sucesse && actionRef.current) {
actionRef.current.reload();
}
}}
>
<a></a>
</Popconfirm>
]
}
}
];
return (
<PageContainer
header={{
title: '',
breadcrumb: {},
}}>
{
showLoading ?
<div
style={{
width: '100%',
height: '100%',
background: 'rgba(0,0,0,0.1)',
position: 'fixed',
zIndex: 2,
display: 'flex',
alignItems: 'center',
justifyContent: 'center'
}}
>
<div style={{
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
padding: '15px 20px 10px',
background: '#fff',
borderRadius: '8px',
width: '150px'
}}>
<Spin />
<span style={{ marginLeft: '5px' }}>...</span>
</div>
</div> : ''
}
{/* 项目页面 表格主体 */}
<ProTable<BusinessProjectModel>
headerTitle={<PageTitleBox props={props} />}
rowKey="BUSINESSPROJECT_ID"
request={async (params, sorter) => { // 请求项目表格数据 params 查询对象键值对sorter 排序对象键值对
if (params.BUSINESS_TYPE) {
setBusinessType(params.BUSINESS_TYPE)
} else {
setBusinessType('')
}
// 排序对象键值对 有值 则调整成后台接口需要的数据格式
const sortstr = Object.keys(sorter).map(n => {
const value = sorter[n]
return value ? `${n} ${value.replace('end', '')}` : ''
})
console.log('params', params)
// 发起请求return 请求返回的数据
const list = await getProjectList({
...params,
SERVERPART_IDS: params?.SERVERPART_IDS || "",
sortstr: sortstr.length ? sortstr.toString() : params?.sortstr,
keyWord: params.searchKey ? { key: "BUSINESSPROJECT_NAME,BUSINESSPROJECT_DESC,MERCHANTS_NAME,SERVERPARTSHOP_NAME", value: params.searchKey } : null, // 关键词查询
pagesize: params.pageSize,
ProjectStateSearch: params.ProjectStateSearch === "0" || params.ProjectStateSearch === "1" ? params.ProjectStateSearch : '',
DueDate_End: params.ProjectStateSearch === "2" ? moment().add(3, 'month').format('YYYY-MM-DD') : params.ProjectStateSearch === "3" ? moment().add(6, 'month').format('YYYY-MM-DD') : ''
})
console.log('list', list)
return list
}}
actionRef={actionRef} // 表格操作对象
search={{ span: 6 }} // 查询栏布局配置按照24/6=4份来分割
columns={columns} // 表格列数据配置
toolbar={{
actions: [ // 表格右上角工具栏配置
<Typography.Text type="secondary"></Typography.Text>,
<Button
key="new"
icon={<PlusOutlined />}
type="primary"
onClick={() => {
handleModalVisible(true)
const current = {
PROJECT_VALID: 1,
MULTIPROJECT_STATE: 0,
SEGMENTED_MODE: 1
}
formRef.current?.setFieldsValue(current)
setCurrentRow(current)
}}
>
</Button>,
],
}}
pagination={{ defaultPageSize: 10 }} // 翻页默认10条分页
/>
{/* 项目数据编辑弹出框 */}
<ProjectEditor parentTableRef={actionRef} currentRecord={currentRow} modalVisible={modalVisible} handleModalVisible={handleModalVisible} />
{/* 查看项目详情 右侧弹出的抽屉 */}
<Drawer
width="80%"
className="project-drawer"
visible={showDetail} // 抽屉弹框是否显示状态
onClose={() => { // 关闭抽屉 则在清空选中行数据 并 设置抽屉状态为关闭
setCurrentRow(undefined);
setShowDetail(false);
}}
bodyStyle={{ backgroundColor: "#f9f9f9", padding: 0 }}
closable={false}
>
{/* 抽屉打开时 加载项目详情组件 */}
{showDetail && <ProjectDetail id={currentRow?.BUSINESSPROJECT_ID} businessType={businessType} showType={'edit'}></ProjectDetail>}
</Drawer>
</PageContainer>
);
}
export default ProjecetTable;