This commit is contained in:
ylj20011123 2025-08-05 18:56:06 +08:00
parent a14b50b7f6
commit 9900baf6a3
26 changed files with 2098 additions and 290 deletions

View File

@ -1,6 +1,6 @@
{
"name": "ant-design-pro",
"version": "4.5.13",
"version": "4.5.15",
"private": true,
"description": "An out-of-box UI solution for enterprise applications",
"scripts": {
@ -19,7 +19,7 @@
"lint:prettier": "prettier --check \"src/**/*\" --end-of-line auto",
"lint:style": "stylelint --fix \"src/**/*.less\" --syntax less",
"prettier": "prettier -c --write \"src/**/*\"",
"start": "cross-env NODE_OPTIONS=--max-old-space-size=8192 UMI_ENV=dev umi dev",
"start": "set NODE_OPTIONS=--max-old-space-size=8192 && umi dev",
"start:dev": "cross-env REACT_APP_ENV=dev MOCK=none UMI_ENV=dev umi dev",
"start:no-mock": "cross-env MOCK=none UMI_ENV=dev umi dev",
"start:no-ui": "cross-env UMI_UI=none UMI_ENV=dev umi dev",
@ -63,6 +63,7 @@
"@umijs/route-utils": "^1.0.33",
"ahooks": "^2.10.3",
"antd": "^4.17.0",
"aws-sdk": "^2.1692.0",
"classnames": "^2.2.6",
"compression-webpack-plugin": "^11.1.0",
"crypto-js": "^4.1.1",

BIN
src/assets/ai/editIcon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

View File

@ -1,12 +1,231 @@
// 卡券兑换统计
import { ConnectState } from "@/models/connect";
import { connect, CurrentUser } from "umi";
// 卡券领取统计
import { connect } from "umi";
import type { CurrentUser } from "umi";
import type { ConnectState } from "@/models/connect";
import React, { useRef, useState } from "react";
import { Drawer, Modal, type FormInstance } from "antd";
import type { ActionType } from "@ant-design/pro-table";
import ProTable from "@ant-design/pro-table";
import PageTitleBox from "@/components/PageTitleBox";
import { handeGetCouponStockList } from "@/pages/travelMember/service";
import moment from 'moment'
import CardVoucherSearch from "../CardVoucherSearch";
const CardHaveCollection: React.FC<{ currentUser: CurrentUser }> = (props) => {
const { currentUser } = props
const actionRef = useRef<ActionType>();
const formRef = useRef<FormInstance>();
const [reqDetailList, setReqDetailList] = useState<any>(); // 合计项数据源
const [printOut, setPrintOut] = useState<any>(); // 打印数据的内容
const [collapsible, setCollapsible] = useState<boolean>(false)
const [treeView, setTreeView] = useState<any>()
const [printIndex, setPrintIndex] = useState<number>(new Date().getTime())
// 树相关的属性和方法
const [selectedId, setSelectedId] = useState<string>()
// 导出的加载效果
const [showLoading, setShowLoading] = useState<boolean>(false)
// 是否显示打印的表格
const [showExportTable, setShowExportTable] = useState<boolean>(false)
// 查询的条件
const [searchParams, setSearchParams] = useState<any>()
// 点击行的数据
const [currentRow, setCurrentRow] = useState<any>()
// 显示详情
const [showDetial, setShowDetail] = useState<any>()
const columns: any = [
{
title: "卡券类型",
dataIndex: "COUPON_TYPE",
width: 120,
align: 'center',
ellipsis: true,
valueType: 'select',
valueEnum: {
"1000": "满减券",
"2000": "折扣券",
"3000": "抵扣券",
"4000": "兑换券",
"5000": "代金券",
"9000": "实物券"
}
},
{
title: '领取时间',
dataIndex: 'search_date',
valueType: 'dateRange',
hideInTable: true,
hideInDescriptions: true,
search: {
transform: (value) => {
return {
STARTDATE: value[0],
ENDDATE: value[1],
};
},
},
initialValue: [moment().startOf('M').format('YYYY-MM-DD'), moment().add(-1, 'day').format('YYYY-MM-DD')],
},
{
title: "卡券名称",
width: 250,
dataIndex: "COUPON_NAME",
align: 'center',
hideInSearch: true,
ellipsis: true,
},
{
title: "发放数量",
dataIndex: "COUPON_QUOTA",
width: 120,
align: 'center',
sorter: (a, b) => a.COUPON_QUOTA - b.COUPON_QUOTA,
hideInSearch: true,
ellipsis: true,
},
{
title: "领取数量",
dataIndex: "TAKE_COUNT",
width: 120,
align: 'center',
hideInSearch: true,
ellipsis: true,
sorter: (a, b) => a.TAKE_COUNT - b.TAKE_COUNT,
render: (_, record) => {
return record?.TAKE_COUNT ? <a onClick={() => {
setCurrentRow(record)
setShowDetail(true)
}}>{record?.TAKE_COUNT}</a> : "-"
}
},
{
title: "剩余数量",
dataIndex: "LAST_COUNT",
width: 120,
align: 'center',
hideInSearch: true,
ellipsis: true,
sorter: (a, b) => a.LAST_COUNT - b.LAST_COUNT,
},
{
title: "发放金额",
dataIndex: "QUOTA_AMOUNT",
width: 120,
align: 'center',
hideInSearch: true,
ellipsis: true,
sorter: (a, b) => a.QUOTA_AMOUNT - b.QUOTA_AMOUNT,
},
{
title: "领取金额",
dataIndex: "TAKE_AMOUNT",
width: 120,
align: 'center',
hideInSearch: true,
ellipsis: true,
sorter: (a, b) => a.TAKE_AMOUNT - b.TAKE_AMOUNT,
},
{
title: "活动开始时间",
dataIndex: "START_TIME",
width: 180,
align: 'center',
hideInSearch: true,
ellipsis: true,
render: (_, record) => {
return record?.START_TIME ? moment(record?.START_TIME).format('YYYY-MM-DD') : "-"
}
},
{
title: "活动结束时间",
dataIndex: "END_TIME",
width: 180,
align: 'center',
hideInSearch: true,
ellipsis: true,
render: (_, record) => {
return record?.END_TIME ? moment(record?.END_TIME).format('YYYY-MM-DD') : "-"
}
},
]
const CardHaveCollection: React.FC<{ currentUser: CurrentUser | undefined }> = (props) => {
return (
<div>
<div ref={(el) => {
// 打印报表
if (!reqDetailList || reqDetailList.length === 0) return;
setPrintOut(el);
}} >
<div style={{ backgroundColor: '#fff', display: 'flex' }}>
<div style={{
width: '100%',
paddingTop: 0,
paddingBottom: 0,
paddingRight: 0
}}>
<ProTable
actionRef={actionRef}
formRef={formRef}
columns={columns}
bordered
expandable={{
expandRowByClick: true
}}
scroll={{ y: 'calc(100vh - 430px)' }}
// headerTitle={<span style={{ color: "#1890ff", fontSize: 14, fontWeight: 600 }}>单品销售排行统计</span>}
headerTitle={<PageTitleBox props={props} />}
search={{ span: 6 }}
request={async (params) => {
const req: any = {
SearchParameter: {
COUPON_TYPES: params?.COUPON_TYPE || "",
TAKE_TIME_Start: params?.STARTDATE || "",// 开始时间
TAKE_TIME_End: params?.ENDDATE || "",// 结束时间
COUPON_ISVALID: 1
},
PageIndex: 1,
PageSize: 999999,
sortStr: "END_TIME desc"
}
setSearchParams(params)
const data = await handeGetCouponStockList(req)
console.log('datadatadatadatadata', data);
if (data.List && data.List.length > 0) {
return { data: data.List, success: true }
}
return { data: [], success: true }
</div>
}}
toolbar={{
actions: [
]
}}
/>
</div>
</div>
<Drawer
title={currentRow?.COUPON_NAME || ""}
destroyOnClose={true}
width={'80%'}
bodyStyle={{
height: '700px', // 你可以根据需要调整高度
overflowY: 'auto',
}}
visible={showDetial}
onClose={() => {
setCurrentRow(null)
setShowDetail(false)
}}
>
<CardVoucherSearch isComponent={true} parentRow={currentRow} />
</Drawer>
</div >
)
}

View File

@ -1,4 +1,4 @@
// 卡券库存管理
// 卡券库存管理 卡券库存查询
import { connect } from "umi";
import type { CurrentUser } from "umi";
import type { ConnectState } from "@/models/connect";
@ -44,6 +44,8 @@ const CardVoucherCollection: React.FC<{ currentUser: CurrentUser }> = (props) =>
"2000": "折扣券",
"3000": "抵扣券",
"4000": "兑换券",
"5000": "代金券",
"9000": "实物券"
}
},
{
@ -79,15 +81,6 @@ const CardVoucherCollection: React.FC<{ currentUser: CurrentUser }> = (props) =>
hideInSearch: true,
ellipsis: true,
},
{
title: "发放金额",
dataIndex: "QUOTA_AMOUNT",
width: 120,
align: 'center',
hideInSearch: true,
ellipsis: true,
sorter: (a, b) => a.QUOTA_AMOUNT - b.QUOTA_AMOUNT,
},
{
title: "领取数量",
dataIndex: "TAKE_COUNT",
@ -97,15 +90,6 @@ const CardVoucherCollection: React.FC<{ currentUser: CurrentUser }> = (props) =>
ellipsis: true,
sorter: (a, b) => a.TAKE_COUNT - b.TAKE_COUNT,
},
{
title: "领取金额",
dataIndex: "TAKE_AMOUNT",
width: 120,
align: 'center',
hideInSearch: true,
ellipsis: true,
sorter: (a, b) => a.TAKE_AMOUNT - b.TAKE_AMOUNT,
},
{
title: "剩余数量",
dataIndex: "LAST_COUNT",
@ -115,6 +99,24 @@ const CardVoucherCollection: React.FC<{ currentUser: CurrentUser }> = (props) =>
ellipsis: true,
sorter: (a, b) => a.LAST_COUNT - b.LAST_COUNT,
},
{
title: "发放金额",
dataIndex: "QUOTA_AMOUNT",
width: 120,
align: 'center',
hideInSearch: true,
ellipsis: true,
sorter: (a, b) => a.QUOTA_AMOUNT - b.QUOTA_AMOUNT,
},
{
title: "领取金额",
dataIndex: "TAKE_AMOUNT",
width: 120,
align: 'center',
hideInSearch: true,
ellipsis: true,
sorter: (a, b) => a.TAKE_AMOUNT - b.TAKE_AMOUNT,
},
{
title: "活动开始时间",
dataIndex: "START_TIME",
@ -122,6 +124,9 @@ const CardVoucherCollection: React.FC<{ currentUser: CurrentUser }> = (props) =>
align: 'center',
hideInSearch: true,
ellipsis: true,
render: (_, record) => {
return record?.START_TIME ? moment(record?.START_TIME).format('YYYY-MM-DD') : "-"
}
},
{
title: "活动结束时间",
@ -130,6 +135,9 @@ const CardVoucherCollection: React.FC<{ currentUser: CurrentUser }> = (props) =>
align: 'center',
hideInSearch: true,
ellipsis: true,
render: (_, record) => {
return record?.END_TIME ? moment(record?.END_TIME).format('YYYY-MM-DD') : "-"
}
},
]
@ -166,6 +174,7 @@ const CardVoucherCollection: React.FC<{ currentUser: CurrentUser }> = (props) =>
request={async (params) => {
const req: any = {
SearchParameter: {
OWNERUNIT_ID: currentUser?.OwnerUnitId,
COUPON_TYPES: params?.COUPON_TYPE || "",
END_TIME_Start: params?.STARTDATE || "",// 开始时间
START_TIME_End: params?.ENDDATE || "",// 结束时间
@ -173,6 +182,7 @@ const CardVoucherCollection: React.FC<{ currentUser: CurrentUser }> = (props) =>
},
PageIndex: 1,
PageSize: 999999,
sortStr: "END_TIME desc"
}
setSearchParams(params)
const data = await handeGetCouponStockList(req)

View File

@ -1,11 +1,169 @@
// 卡券领取统计
// 卡券发放统计 卡券兑换统计
import { ConnectState } from "@/models/connect";
import { connect, CurrentUser } from "umi";
import SelectCardVouch from "../CardVoucherSearch/components/selectCardVouch";
import { useRef, useState } from "react";
import ProTable, { ActionType } from "@ant-design/pro-table";
import PageTitleBox from "@/components/PageTitleBox";
import { FormInstance } from "antd";
import { handeGetCouponExchangeSummary } from "@/pages/travelMember/service";
import moment from 'moment'
const CardVoucherRedemption: React.FC<{ currentUser: CurrentUser | undefined }> = (props) => {
const { currentUser } = props
const actionRef = useRef<ActionType>();
const formRef = useRef<FormInstance>();
// 树相关的属性和方法
const [selectedId, setSelectedId] = useState<string>()
const [collapsible, setCollapsible] = useState<boolean>(false)
const columns: any = [
{
title: "卡券类型",
dataIndex: "CouponType",
width: 200,
align: 'center',
ellipsis: true,
valueType: 'select',
valueEnum: {
"1000": "满减券",
"2000": "折扣券",
"3000": "抵扣券",
"4000": "兑换券",
"5000": "代金券",
"9000": "实物券"
}
},
{
title: '统计时间',
dataIndex: 'search_date',
valueType: 'dateRange',
hideInTable: true,
hideInDescriptions: true,
search: {
transform: (value: any) => {
return {
STARTDATE: value[0],
ENDDATE: value[1],
};
},
},
initialValue: [moment().startOf('M').format('YYYY-MM-DD'), moment().add(-1, 'day').format('YYYY-MM-DD')],
},
{
title: "卡券名称",
width: 250,
dataIndex: "CouponName",
align: 'center',
hideInSearch: true,
ellipsis: true,
},
{
title: "服务区名称",
width: 250,
dataIndex: "Serverpart_Name",
align: 'center',
hideInSearch: true,
ellipsis: true,
},
{
title: "门店名称",
width: 250,
dataIndex: "ServerpartShop_Name",
align: 'center',
hideInSearch: true,
ellipsis: true,
},
{
title: "使用数量",
width: 150,
dataIndex: "UsedCount",
align: 'center',
hideInSearch: true,
ellipsis: true,
},
{
title: "订单金额",
width: 150,
dataIndex: "OrderAmount",
align: 'center',
hideInSearch: true,
ellipsis: true,
},
{
title: "优惠金额",
width: 150,
dataIndex: "CouponAmount",
align: 'center',
hideInSearch: true,
ellipsis: true,
},
{
title: "实付金额",
width: 150,
dataIndex: "PayAmount",
align: 'center',
hideInSearch: true,
ellipsis: true,
},
]
return (
<div>
<div style={{ backgroundColor: '#fff', display: 'flex' }}>
<SelectCardVouch setSelectedId={setSelectedId} setCollapsible={setCollapsible} collapsible={collapsible} />
<div style={{
width: !collapsible ? 'calc(100% - 300px)' : 'calc(100% - 60px)',
paddingTop: 0,
paddingBottom: 0,
paddingRight: 0
}}>
<ProTable
actionRef={actionRef}
formRef={formRef}
columns={columns}
rowKey={(record: any) => {
return `${record?.CouponId}-${record?.Serverpart_Id}-${record?.ServerpartShop_Id}`
}}
bordered
expandable={{
expandRowByClick: true
}}
scroll={{ x: "100%", y: "calc(100vh - 430px)" }}
headerTitle={<PageTitleBox props={props} />} // 列表表头
search={{ span: 6 }}
request={async (params) => {
if (!selectedId) {
return
}
let req: any = {
OwnerUnitId: currentUser?.OwnerUnitId,
ServerpartId: "",
StartDate: params?.STARTDATE || "",
EndDate: params?.ENDDATE || "",
CouponType: params?.CouponType || ""
}
let data: any = await handeGetCouponExchangeSummary(req)
if (data && data.length > 0) {
return { data: data, success: true }
}
return { data: [], success: true }
}}
toolbar={{
actions: [
]
}}
/>
</div>
</div>
</div>
)
}

View File

@ -68,13 +68,13 @@ const selectCardVouch = ({ setSelectedId, reload, actionRef, currentUser, width,
setTreeView([])
const list: any = []
resList.forEach((item: any) => {
if (item.label.indexOf(value) !== -1) {
if (item.COUPON_NAME.indexOf(value) !== -1) {
list.push(item)
} else {
if (item.children && item.children.length > 0) {
const childrenList: any = []
item.children.forEach((subItem: any) => {
if (subItem.label.indexOf(value) !== -1) {
if (subItem.COUPON_NAME.indexOf(value) !== -1) {
childrenList.push(subItem)
}
})

View File

@ -19,8 +19,8 @@ import { handeGetCOUPON_SENDList } from "@/pages/travelMember/service";
import moment from 'moment'
const CardVoucherSearch: React.FC<{ currentUser: CurrentUser }> = (props) => {
const { currentUser } = props
const CardVoucherSearch: React.FC<{ currentUser: CurrentUser, isComponent?: boolean, parentRow?: any }> = (props) => {
const { currentUser, isComponent, parentRow } = props
const downloadBtnRef = useRef<any>()
const actionRef = useRef<ActionType>();
const formRef = useRef<FormInstance>();
@ -176,10 +176,13 @@ const CardVoucherSearch: React.FC<{ currentUser: CurrentUser }> = (props) => {
<div style={{ backgroundColor: '#fff', display: 'flex' }}>
{
isComponent ? '' :
<SelectCardVouch setSelectedId={setSelectedId} setCollapsible={setCollapsible} collapsible={collapsible} />
}
{/* <LeftSelectTree setSelectedId={setSelectedId} setCollapsible={setCollapsible} collapsible={collapsible} /> */}
<SelectCardVouch setSelectedId={setSelectedId} setCollapsible={setCollapsible} collapsible={collapsible} />
<div style={{
width: !collapsible ? 'calc(100% - 300px)' : 'calc(100% - 60px)',
width: isComponent ? '100%' : !collapsible ? 'calc(100% - 300px)' : 'calc(100% - 60px)',
paddingTop: 0,
paddingBottom: 0,
paddingRight: 0
@ -194,31 +197,39 @@ const CardVoucherSearch: React.FC<{ currentUser: CurrentUser }> = (props) => {
}}
scroll={{ x: "100%", y: "calc(100vh - 410px)" }}
headerTitle={<PageTitleBox props={props} />} // 列表表头
search={{ span: 6 }}
search={isComponent ? false : { span: 6 }}
request={async (params) => {
console.log('selectedIdselectedIdselectedIdselectedId', selectedId);
if (!selectedId) {
if (!selectedId && !isComponent) {
return
}
const req: any = {
SearchParameter: {
COUPON_IDS: selectedId,
WECHATAPP_APPID: "wxee018fb96955552a",
// 领取时间
CREATE_DATE_Start: params?.searchType === '1' ? params?.STARTDATE : '',
CREATE_DATE_End: params?.searchType === '1' ? params?.ENDDATE : '',
// 核销时间
USED_DATE_Start: params?.searchType === '2' ? params?.STARTDATE : '',
USED_DATE_End: params?.searchType === '2' ? params?.ENDDATE : '',
COUPON_STATE: params?.COUPON_STATE || ""
},
PageIndex: 1,
PageSize: 999999,
// keyWord: {
// Key: "SELLER_NAME,MEMBERSHIP_NAME",
// Value: params?.searchText || ""
// },
// SortStr: "CREATE_DATE desc"
let req: any = {}
if (isComponent) {
parentRow
req = {
SearchParameter: {
COUPON_IDS: parentRow?.COUPON_ID,
WECHATAPP_APPID: "wxee018fb96955552a",
},
PageIndex: 1,
PageSize: 999999,
}
} else {
req = {
SearchParameter: {
COUPON_IDS: selectedId,
WECHATAPP_APPID: "wxee018fb96955552a",
// 领取时间
CREATE_DATE_Start: params?.searchType === '1' ? params?.STARTDATE : '',
CREATE_DATE_End: params?.searchType === '1' ? params?.ENDDATE : '',
// 核销时间
USED_DATE_Start: params?.searchType === '2' ? params?.STARTDATE : '',
USED_DATE_End: params?.searchType === '2' ? params?.ENDDATE : '',
COUPON_STATE: params?.COUPON_STATE || ""
},
PageIndex: 1,
PageSize: 999999,
}
}
setSearchParams(params)

View File

@ -6,7 +6,7 @@ import type { ConnectState } from "@/models/connect";
import { useState } from "react";
import ProCard from "@ant-design/pro-card";
import { MenuFoldOutlined } from "@ant-design/icons";
import type { FormInstance} from "antd";
import type { FormInstance } from "antd";
import { Modal, Popconfirm } from "antd";
import { Button, Drawer, message, Spin, Tree, Typography, Tooltip } from "antd";
import { getMoney, getServerpartTree } from "@/services/options";
@ -91,6 +91,7 @@ const revenueConfirmationDifference: React.FC<{ currentUser: CurrentUser }> = (p
const [defaultTableData, setDefaultTableData] = useState<any>()
// 判断是否有不一样的税率
const [differentRate, setDifferentRate] = useState<any>()
const [showDifference, setShowDifference] = useState<boolean>(false)
const columns: any = [
// {
@ -278,7 +279,7 @@ const revenueConfirmationDifference: React.FC<{ currentUser: CurrentUser }> = (p
width: 100,
hideInSearch: true,
render: (_, record) => {
const rightTaxRate = record?.errorTaxRate ? `${record?.errorTaxRate }%` : ''
const rightTaxRate = record?.errorTaxRate ? `${record?.errorTaxRate}%` : ''
return <div>
{
record?.isErrorTaxRate ?
@ -415,7 +416,33 @@ const revenueConfirmationDifference: React.FC<{ currentUser: CurrentUser }> = (p
align: 'right',
hideInSearch: true,
render: (_, record) => {
return numeral(record?.DiffRevenueAmount).format('0,0.00')
// return numeral(record?.DiffRevenueAmount).format('0,0.00')
return <a onClick={() => {
if (record?.SERVERPARTSHOP_ID) {
console.log('record', record);
const obj: any = {
...record,
}
let [monthStartTime, monthEndTime] = record?.IndexDesc.split('-')
monthStartTime = moment(monthStartTime).format('YYYY-MM-DD')
monthEndTime = moment(monthEndTime).format('YYYY-MM-DD')
const startDate: any = moment(searchParams?.MonthDate).startOf('months').format('YYYY-MM-DD')
const endDate: any = moment(searchParams?.MonthDate).endOf('months').format('YYYY-MM-DD')
obj.startTime = monthStartTime
obj.Id = record.SERVERPARTSHOP_ID
if (new Date(monthEndTime).getTime() < new Date(endDate).getTime()) {
obj.endTime = monthEndTime
} else {
obj.endTime = endDate
}
console.log('objobjobjobj', obj);
setCurrentRow(obj)
setShowDifference(true)
}
}} style={{ color: record?.SERVERPARTSHOP_ID ? '#0e9976' : '#000' }}>
{record?.DiffRevenueAmount ? numeral(getMoney(record?.DiffRevenueAmount)).format('0,0.00') : '0.00'}
</a>
}
},
{
@ -1012,6 +1039,151 @@ const revenueConfirmationDifference: React.FC<{ currentUser: CurrentUser }> = (p
}
setShowCompareDrawer(true)
}
// 要传递的columns
const childrenColumns: any = [
{
title: '累计营业额',
dataIndex: '',
hideInSearch: true,
children: [
{
title: <div style={{ textAlign: 'center' }}>{'项目拆分'}</div>,
dataIndex: 'TotalRevenueAmount',
width: 130,
valueType: 'digit',
align: 'right',
hideInSearch: true,
render: (_, record) => {
return record?.TotalRevenueAmount ?
record?.BUSINESSPROJECT_ID ?
<span>{numeral(getMoney(record?.TotalRevenueAmount || 0)).format('0,0.00')}</span> : <span>{numeral(getMoney(record?.TotalRevenueAmount || 0)).format('0,0.00')}</span>
:
'-'
}
},
{
title: <div style={{ textAlign: 'center' }}>{'自然日营收'}</div>,
dataIndex: 'DailyRevenueAmount',
width: 130,
valueType: 'digit',
align: 'right',
hideInSearch: true,
render: (_, record) => {
return numeral(getMoney(record?.DailyRevenueAmount || 0)).format('0,0.00')
}
},
{
title: <div style={{ textAlign: 'center' }}>{'营收差额'}</div>,
dataIndex: 'DiffRevenueAmount',
width: 130,
valueType: 'digit',
align: 'right',
hideInSearch: true,
render: (_, record) => {
return <a style={{ color: record?.DiffRevenueAmount > 0 ? '#0e9976' : record?.DiffRevenueAmount < 0 ? '#e83944' : '#000' }}>
{record?.DiffRevenueAmount ? numeral(getMoney(record?.DiffRevenueAmount)).format('0,0.00') : ''}
</a>
}
},
]
},
{
title: '已确认营业额',
hideInSearch: true,
children: [
{
title: '项目拆分',
width: 130,
valueType: 'digit',
align: 'right',
dataIndex: 'LastMonthRevenue',
hideInSearch: true,
render: (_, record) => {
return <span>
{numeral(getMoney(record?.LastMonthRevenue || 0)).format('0,0.00')}
</span>
}
},
{
title: '自然日',
width: 130,
valueType: 'digit',
align: 'right',
dataIndex: 'DailyLastMonthRevenue',
hideInSearch: true,
render: (_, record) => {
return <span>
{numeral(getMoney(record?.LastMonthRevenue || 0)).format('0,0.00')}
</span>
}
},
{
title: '差额',
width: 130,
valueType: 'digit',
align: 'right',
dataIndex: 'DiffLastMonthRevenue',
hideInSearch: true,
render: (_, record) => {
return <a onClick={() => {
}} style={{ color: record?.DiffLastMonthRevenue > 0 ? '#0e9976' : record?.DiffLastMonthRevenue < 0 ? '#e83944' : '#000' }}>
{record?.DiffLastMonthRevenue ? numeral(getMoney(record?.DiffLastMonthRevenue)).format('0,0.00') : ''}
</a>
}
}
]
},
{
title: '本月营业额',
hideInSearch: true,
children: [
{
title: '项目拆分',
width: 130,
valueType: 'digit',
align: 'right',
dataIndex: 'CurMonthRevenue',
hideInSearch: true,
render: (_, record) => {
return <span>
{numeral(getMoney(record?.CurMonthRevenue || 0)).format('0,0.00')}
</span>
}
},
{
title: '自然日',
width: 130,
valueType: 'digit',
align: 'right',
dataIndex: 'DailyCurMonthRevenue',
hideInSearch: true,
render: (_, record) => {
return <span>
{numeral(getMoney(record?.DailyCurMonthRevenue || 0)).format('0,0.00')}
</span>
}
},
{
title: '差额',
width: 130,
valueType: 'digit',
align: 'right',
dataIndex: 'DiffCurMonthRevenue',
hideInSearch: true,
render: (_, record) => {
return <a onClick={() => {
}} style={{ color: record?.DiffCurMonthRevenue > 0 ? '#0e9976' : record?.DiffCurMonthRevenue < 0 ? '#e83944' : '#000' }}>
{record?.DiffCurMonthRevenue ? numeral(getMoney(record?.DiffCurMonthRevenue)).format('0,0.00') : ''}
</a>
}
}
]
},
]
return (
<div ref={(el) => {
@ -1620,6 +1792,25 @@ const revenueConfirmationDifference: React.FC<{ currentUser: CurrentUser }> = (p
<CalibrationDifference currentObj={compareCurrent} onShow={showCalibration} parentRef={actionRef} />
</Drawer>
{/* 点击差额出现的抽屉 */}
<Drawer
width="85%"
className="project-drawer"
visible={showDifference} // 抽屉弹框是否显示状态
onClose={() => { // 关闭抽屉 则在清空选中行数据 并 设置抽屉状态为关闭
setCurrentRow(undefined);
setShowDifference(false);
}}
bodyStyle={{ backgroundColor: "#f9f9f9", padding: 0 }}
closable={false}
>
{showDifference && <CompareList type={'revenueConfirmation'}
setShowCompareDrawer={setShowDifference} fatherActionRef={actionRef} showCompareDrawer={showDifference}
compareCurrent={currentRow} onlyRead={true} monthTime={searchMonth} come={'ConfirmationDifference'} comeColumns={childrenColumns}
/>}
</Drawer>
</div >
)
}

View File

@ -1211,7 +1211,7 @@ const compareList: React.FC<{
console.log('data212', data)
// 已经发起申请了的 就不去请求下面表格的数据了
// 也不会显示 请求上面那个接口是因为要拿到顶部的详情数据
if (compareCurrent?.Approvalstate > 0) {
if (compareCurrent?.Approvalstate > 0 && come !== 'ConfirmationDifference') {
if (res) {
setTopProjectDetail(res.RevenueRecognition)
}
@ -1219,8 +1219,8 @@ const compareList: React.FC<{
let detailObj: any = {}
console.log('compareCurrent', compareCurrent)
let detail: any = {}
if (compareCurrent?.BUSINESSAPPROVAL_ID) {
detail = await handleGetBUSINESSAPPROVALDetail({ BUSINESSAPPROVALId: compareCurrent?.BUSINESSAPPROVAL_ID })
if (compareCurrent?.BUSINESSAPPROVAL_ID || compareCurrent?.BusinessApprovalId) {
detail = await handleGetBUSINESSAPPROVALDetail({ BUSINESSAPPROVALId: compareCurrent?.BUSINESSAPPROVAL_ID || compareCurrent?.BusinessApprovalId })
}
console.log('detail', detail);
if (detail?.BUSINESSPROCESS_ID) {
@ -1259,8 +1259,8 @@ const compareList: React.FC<{
let detailObj: any = {}
console.log('compareCurrent', compareCurrent)
let detail: any = {}
if (compareCurrent?.BUSINESSAPPROVAL_ID) {
detail = await handleGetBUSINESSAPPROVALDetail({ BUSINESSAPPROVALId: compareCurrent?.BUSINESSAPPROVAL_ID })
if (compareCurrent?.BUSINESSAPPROVAL_ID || compareCurrent?.BusinessApprovalId) {
detail = await handleGetBUSINESSAPPROVALDetail({ BUSINESSAPPROVALId: compareCurrent?.BUSINESSAPPROVAL_ID || compareCurrent?.BusinessApprovalId })
}
console.log('detail', detail);
if (detail?.BUSINESSPROCESS_ID) {
@ -1367,8 +1367,8 @@ const compareList: React.FC<{
let detailObj: any = {}
console.log('compareCurrent', compareCurrent)
let detail: any = {}
if (compareCurrent?.BUSINESSAPPROVAL_ID) {
detail = await handleGetBUSINESSAPPROVALDetail({ BUSINESSAPPROVALId: compareCurrent?.BUSINESSAPPROVAL_ID })
if (compareCurrent?.BUSINESSAPPROVAL_ID || compareCurrent?.BusinessApprovalId) {
detail = await handleGetBUSINESSAPPROVALDetail({ BUSINESSAPPROVALId: compareCurrent?.BUSINESSAPPROVAL_ID || compareCurrent?.BusinessApprovalId })
}
console.log('detail', detail);
if (detail?.BUSINESSPROCESS_ID) {
@ -1410,8 +1410,8 @@ const compareList: React.FC<{
let detailObj: any = {}
console.log('compareCurrent', compareCurrent)
let detail: any = {}
if (compareCurrent?.BUSINESSAPPROVAL_ID) {
detail = await handleGetBUSINESSAPPROVALDetail({ BUSINESSAPPROVALId: compareCurrent?.BUSINESSAPPROVAL_ID })
if (compareCurrent?.BUSINESSAPPROVAL_ID || compareCurrent?.BusinessApprovalId) {
detail = await handleGetBUSINESSAPPROVALDetail({ BUSINESSAPPROVALId: compareCurrent?.BUSINESSAPPROVAL_ID || compareCurrent?.BusinessApprovalId })
}
if (detail?.BUSINESSPROCESS_ID) {
const res = await handleGetBIZPSPLITMONTHDetail({ BIZPSPLITMONTHId: detail?.BUSINESSPROCESS_ID })
@ -2546,7 +2546,7 @@ const compareList: React.FC<{
setPrintData(res)
const reqProgress: any = {
BUSINESSAPPROVALId: compareCurrent?.BUSINESSAPPROVAL_ID
BUSINESSAPPROVALId: compareCurrent?.BUSINESSAPPROVAL_ID || compareCurrent?.BusinessApprovalId
}
const dataProgress = await handleGetGetBUSINESSAPPROVALDetail(reqProgress)
console.log('datahandleGetProcessProgress', dataProgress);
@ -2568,7 +2568,7 @@ const compareList: React.FC<{
confirmationName: '',// 商户确认签名
confirmationRealName: '',// 商户确认签名(只有人名)
developManagerName: dataProgress.STAFF_NAME,// 经发人签名
developManagerRealName: `${dataProgress.STAFF_NAME.split('【')[0]} ${data.BUSINESS_STARTDATE || ''}`,// 经发人签名(只有人名)
developManagerRealName: `${dataProgress.STAFF_NAME ? dataProgress.STAFF_NAME.split('【')[0] : ""} ${data.BUSINESS_STARTDATE || ''}`,// 经发人签名(只有人名)
}
if (dataProgress.approveList && dataProgress.approveList.length > 0) {
@ -2642,125 +2642,127 @@ const compareList: React.FC<{
{/* <div className={'titleBox'}>初始月度结算表</div> */}
{
showMoreBtn ?
<ProTable
columns={come === 'revenueDifference' ? comeColumns : defaultColumns}
bordered
style={{ background: '#fff', paddingTop: '10px' }}
// scroll={{x: 1100}}
scroll={{ x: 'max-content' }}
search={false}
// options={false}
pagination={false}
loading={tableSecondLoading}
dataSource={come === 'revenueDifference' ? [compareCurrent] : firstTableData}
columnsState={{
value: defaultColumnsStateMap,
onChange: setDefaultColumnsStateMap,
}}
tableExtraRender={(_, data) => {
return <div className={'extraRenderBox'} style={{ paddingLeft: 30, paddingBottom: 0, paddingTop: '15px', background: '#fff' }}>
<div style={{ width: '100%', display: 'flex', alignItems: 'center', justifyContent: 'space-between', boxSizing: 'border-box', paddingRight: '20%', marginBottom: '8px' }}>
<div style={{ fontSize: '20px', fontWeight: 600, marginBottom: '16px' }}>
{`${compareCurrent?.Serverpart_Name || compareCurrent?.SERVERPART_NAME || ''}-${topProjectDetail?.SERVERPARTSHOP_NAME || ''}-${compareCurrent?.STATISTICS_MONTH || monthTime || ''}月度结算`}
come !== 'ConfirmationDifference' ?
showMoreBtn ?
<ProTable
columns={come === 'revenueDifference' ? comeColumns : defaultColumns}
bordered
style={{ background: '#fff', paddingTop: '10px' }}
// scroll={{x: 1100}}
scroll={{ x: 'max-content' }}
search={false}
// options={false}
pagination={false}
loading={tableSecondLoading}
dataSource={come === 'revenueDifference' ? [compareCurrent] : firstTableData}
columnsState={{
value: defaultColumnsStateMap,
onChange: setDefaultColumnsStateMap,
}}
tableExtraRender={(_, data) => {
return <div className={'extraRenderBox'} style={{ paddingLeft: 30, paddingBottom: 0, paddingTop: '15px', background: '#fff' }}>
<div style={{ width: '100%', display: 'flex', alignItems: 'center', justifyContent: 'space-between', boxSizing: 'border-box', paddingRight: '20%', marginBottom: '8px' }}>
<div style={{ fontSize: '20px', fontWeight: 600, marginBottom: '16px' }}>
{`${compareCurrent?.Serverpart_Name || compareCurrent?.SERVERPART_NAME || ''}-${topProjectDetail?.SERVERPARTSHOP_NAME || ''}-${compareCurrent?.STATISTICS_MONTH || monthTime || ''}月度结算`}
</div>
<Button type="primary" onClick={() => {
setShowMoreBtn(false)
}}></Button>
</div>
<Button type="primary" onClick={() => {
setShowMoreBtn(false)
}}></Button>
</div>
<Row align="middle">
<Col span={14}>
<ProDescriptions column={3}>
{/* <ProDescriptions.Item label="经营商户">{topProjectDetail?.MERCHANTS_NAME}</ProDescriptions.Item> */}
{/* <ProDescriptions.Item label="合同起止日期">{`${topProjectDetail?.COMPACT_STARTDATE ? moment(topProjectDetail?.COMPACT_STARTDATE).format('YYYY/MM/DD') : ''}${topProjectDetail?.COMPACT_ENDDATE ? `-${moment(topProjectDetail?.COMPACT_ENDDATE).format('YYYY/MM/DD')}` : ''}`}</ProDescriptions.Item> */}
<ProDescriptions.Item label="开始日期">{`${topProjectDetail?.COMPACT_STARTDATE ? moment(topProjectDetail?.COMPACT_STARTDATE).format('YYYY/MM/DD') : ''}`}</ProDescriptions.Item>
<ProDescriptions.Item label="结束日期">{`${topProjectDetail?.COMPACT_ENDDATE ? moment(topProjectDetail?.COMPACT_ENDDATE).format('YYYY/MM/DD') : ''}`}</ProDescriptions.Item>
<ProDescriptions.Item label="结算模式">{SETTLEMENT_MODESObj[topProjectDetail?.SettlementModes]}</ProDescriptions.Item>
</ProDescriptions>
<ProDescriptions column={3}>
<ProDescriptions.Item label="项目期数">{topProjectDetail?.IndexStr}</ProDescriptions.Item>
<ProDescriptions.Item label="装修期">{topProjectDetail?.DecorateDesc}</ProDescriptions.Item>
<ProDescriptions.Item label="履约保证金"
>{topProjectDetail?.SECURITYDEPOSIT ? `${getMoney(topProjectDetail?.SECURITYDEPOSIT / 10000)}万元` : ''}</ProDescriptions.Item>
</ProDescriptions>
<ProDescriptions column={3}>
{/* <ProDescriptions.Item label="/"
<Row align="middle">
<Col span={14}>
<ProDescriptions column={3}>
{/* <ProDescriptions.Item label="经营商户">{topProjectDetail?.MERCHANTS_NAME}</ProDescriptions.Item> */}
{/* <ProDescriptions.Item label="合同起止日期">{`${topProjectDetail?.COMPACT_STARTDATE ? moment(topProjectDetail?.COMPACT_STARTDATE).format('YYYY/MM/DD') : ''}${topProjectDetail?.COMPACT_ENDDATE ? `-${moment(topProjectDetail?.COMPACT_ENDDATE).format('YYYY/MM/DD')}` : ''}`}</ProDescriptions.Item> */}
<ProDescriptions.Item label="开始日期">{`${topProjectDetail?.COMPACT_STARTDATE ? moment(topProjectDetail?.COMPACT_STARTDATE).format('YYYY/MM/DD') : ''}`}</ProDescriptions.Item>
<ProDescriptions.Item label="结束日期">{`${topProjectDetail?.COMPACT_ENDDATE ? moment(topProjectDetail?.COMPACT_ENDDATE).format('YYYY/MM/DD') : ''}`}</ProDescriptions.Item>
<ProDescriptions.Item label="结算模式">{SETTLEMENT_MODESObj[topProjectDetail?.SettlementModes]}</ProDescriptions.Item>
</ProDescriptions>
<ProDescriptions column={3}>
<ProDescriptions.Item label="项目期数">{topProjectDetail?.IndexStr}</ProDescriptions.Item>
<ProDescriptions.Item label="装修期">{topProjectDetail?.DecorateDesc}</ProDescriptions.Item>
<ProDescriptions.Item label="履约保证金"
>{topProjectDetail?.SECURITYDEPOSIT ? `${getMoney(topProjectDetail?.SECURITYDEPOSIT / 10000)}万元` : ''}</ProDescriptions.Item>
</ProDescriptions>
<ProDescriptions column={3}>
{/* <ProDescriptions.Item label="/"
>{topProjectDetail?.RENTFEE?`${getMoney(topProjectDetail?.RENTFEE / 10000)}万元`:''}</ProDescriptions.Item> */}
<ProDescriptions.Item label="提成比例">{topProjectDetail?.GUARANTEERATIO ? `${topProjectDetail?.GUARANTEERATIO}%` : '-'}</ProDescriptions.Item>
<ProDescriptions.Item label="税率">{topProjectDetail?.TaxRate ? `${topProjectDetail?.TaxRate}%` : '-'}</ProDescriptions.Item>
<ProDescriptions.Item label="期除税收入">{topProjectDetail?.MINTURNOVER ? `${getMoney(topProjectDetail?.MINTURNOVER / 10000)}万元` : ''}</ProDescriptions.Item>
</ProDescriptions>
{/* <ProDescriptions column={3}> */}
{/* <ProDescriptions.Item label="月收入" valueType="money">{topProjectDetail?.MonthlyIncome}</ProDescriptions.Item> */}
{/* <ProDescriptions.Item label="累计月数">{topProjectDetail?.MonthlyCount}</ProDescriptions.Item> */}
{/* <ProDescriptions.Item label="经营门店">{compareCurrent?.SERVERPARTSHOP_NAME}</ProDescriptions.Item> */}
<ProDescriptions.Item label="提成比例">{topProjectDetail?.GUARANTEERATIO ? `${topProjectDetail?.GUARANTEERATIO}%` : '-'}</ProDescriptions.Item>
<ProDescriptions.Item label="税率">{topProjectDetail?.TaxRate ? `${topProjectDetail?.TaxRate}%` : '-'}</ProDescriptions.Item>
<ProDescriptions.Item label="期除税收入">{topProjectDetail?.MINTURNOVER ? `${getMoney(topProjectDetail?.MINTURNOVER / 10000)}万元` : ''}</ProDescriptions.Item>
</ProDescriptions>
{/* <ProDescriptions column={3}> */}
{/* <ProDescriptions.Item label="月收入" valueType="money">{topProjectDetail?.MonthlyIncome}</ProDescriptions.Item> */}
{/* <ProDescriptions.Item label="累计月数">{topProjectDetail?.MonthlyCount}</ProDescriptions.Item> */}
{/* <ProDescriptions.Item label="经营门店">{compareCurrent?.SERVERPARTSHOP_NAME}</ProDescriptions.Item> */}
{/* </ProDescriptions> */}
{/* <ProDescriptions column={3}> */}
{/* <ProDescriptions.Item label="累计月收入" valueType="money">{topProjectDetail?.MonthlyTotalIncome}</ProDescriptions.Item> */}
{/* </ProDescriptions> */}
</Col>
{/* </ProDescriptions> */}
{/* <ProDescriptions column={3}> */}
{/* <ProDescriptions.Item label="累计月收入" valueType="money">{topProjectDetail?.MonthlyTotalIncome}</ProDescriptions.Item> */}
{/* </ProDescriptions> */}
</Col>
<Col span={3}>
<Statistic className="contract-static-card"
title={topProjectDetail?.RENTFEE ? amountDom(topProjectDetail?.RENTFEE / 10000) : <Text type="warning" style={{
fontSize: 36, lineHeight: 1,
fontFamily: "Bahnschrift Regular"
}}>-</Text>}
valueStyle={{ color: "#00000075", fontSize: 14 }}
value={'项目金额'}
/>
</Col>
<Col span={3}>
<Statistic className="contract-static-card"
title={topProjectDetail?.RENTFEE ? amountDom(topProjectDetail?.RENTFEE / 10000) : <Text type="warning" style={{
fontSize: 36, lineHeight: 1,
fontFamily: "Bahnschrift Regular"
}}>-</Text>}
valueStyle={{ color: "#00000075", fontSize: 14 }}
value={'项目金额'}
/>
</Col>
<Col span={7}>
<Statistic className="contract-static-card" title={<span style={{ fontSize: 20, color: "#262626" }}>{topProjectDetail?.MERCHANTS_NAME}</span>}
valueStyle={{ color: "#00000075", fontSize: 14, marginTop: 10 }}
value={"经营商户"}
/>
</Col>
{/* <Col>
<Col span={7}>
<Statistic className="contract-static-card" title={<span style={{ fontSize: 20, color: "#262626" }}>{topProjectDetail?.MERCHANTS_NAME}</span>}
valueStyle={{ color: "#00000075", fontSize: 14, marginTop: 10 }}
value={"经营商户"}
/>
</Col>
{/* <Col>
<Descriptions column={7}>
<Descriptions.Item label="备注说明">{topProjectDetail?.Remark}</Descriptions.Item>
</Descriptions>
</Col> */}
</Row>
{
noticeRowData ?
<div style={{ color: '#00000073' }}>
{noticeRowData?.CURMOBILEPAY_AMOUNT ? `${numeral(getMoney(noticeRowData?.CURMOBILEPAY_AMOUNT)).format('0,0.00')}` : ''}
{noticeRowData?.CURMOBILEPAY_AMOUNT > noticeRowData?.MobilePay_Amount ? '>' : noticeRowData?.CURMOBILEPAY_AMOUNT === noticeRowData?.MobilePay_Amount ? '=' : '<'}
{'自然日移动支付'}
{noticeRowData?.MobilePay_Amount ? `${numeral(getMoney(noticeRowData?.MobilePay_Amount)).format('0,0.00')}` : ''}
{noticeRowData?.CURMOBILEPAY_AMOUNT >= noticeRowData?.MobilePay_Amount ? '项目拆分移动支付' : '自然日拆分移动支付'}
{noticeRowData?.CashPay_Amount ? `${numeral(getMoney(noticeRowData?.CashPay_Amount)).format('0,0.00')}` : ''}
{noticeRowData?.CashPay_Amount > noticeRowData?.CURCASHPAY_AMOUNT ? '>' : noticeRowData?.CashPay_Amount === noticeRowData?.CURCASHPAY_AMOUNT ? '=' : '<'}
{'项目拆分现金支付'}
{noticeRowData?.CURCASHPAY_AMOUNT ? `${numeral(getMoney(noticeRowData?.CURCASHPAY_AMOUNT)).format('0,0.00')}` : ''}
{noticeRowData?.CashPay_Amount >= noticeRowData?.CURCASHPAY_AMOUNT ? '项目拆分现金支付' : '自然日现金支付'}
{noticeRowData?.CashPay_Amount && noticeRowData?.CURCASHPAY_AMOUNT && noticeRowData?.CashPay_Amount - noticeRowData?.CURCASHPAY_AMOUNT > 0 ? `建议现金冲正${numeral(getMoney(noticeRowData?.CashPay_Amount - noticeRowData?.CURCASHPAY_AMOUNT)).format('0,0.00')}` : ''}
</div> : ''
}
</Row>
{
noticeRowData ?
<div style={{ color: '#00000073' }}>
{noticeRowData?.CURMOBILEPAY_AMOUNT ? `${numeral(getMoney(noticeRowData?.CURMOBILEPAY_AMOUNT)).format('0,0.00')}` : ''}
{noticeRowData?.CURMOBILEPAY_AMOUNT > noticeRowData?.MobilePay_Amount ? '>' : noticeRowData?.CURMOBILEPAY_AMOUNT === noticeRowData?.MobilePay_Amount ? '=' : '<'}
{'自然日移动支付'}
{noticeRowData?.MobilePay_Amount ? `${numeral(getMoney(noticeRowData?.MobilePay_Amount)).format('0,0.00')}` : ''}
{noticeRowData?.CURMOBILEPAY_AMOUNT >= noticeRowData?.MobilePay_Amount ? '项目拆分移动支付' : '自然日拆分移动支付'}
{noticeRowData?.CashPay_Amount ? `${numeral(getMoney(noticeRowData?.CashPay_Amount)).format('0,0.00')}` : ''}
{noticeRowData?.CashPay_Amount > noticeRowData?.CURCASHPAY_AMOUNT ? '>' : noticeRowData?.CashPay_Amount === noticeRowData?.CURCASHPAY_AMOUNT ? '=' : '<'}
{'项目拆分现金支付'}
{noticeRowData?.CURCASHPAY_AMOUNT ? `${numeral(getMoney(noticeRowData?.CURCASHPAY_AMOUNT)).format('0,0.00')}` : ''}
{noticeRowData?.CashPay_Amount >= noticeRowData?.CURCASHPAY_AMOUNT ? '项目拆分现金支付' : '自然日现金支付'}
{noticeRowData?.CashPay_Amount && noticeRowData?.CURCASHPAY_AMOUNT && noticeRowData?.CashPay_Amount - noticeRowData?.CURCASHPAY_AMOUNT > 0 ? `建议现金冲正${numeral(getMoney(noticeRowData?.CashPay_Amount - noticeRowData?.CURCASHPAY_AMOUNT)).format('0,0.00')}` : ''}
</div> : ''
}
</div>
}}
/>
:
<div>
<div style={{ width: '100%', display: 'flex', alignItems: 'center', justifyContent: 'space-between', boxSizing: 'border-box', paddingTop: '16px', paddingLeft: '30px', paddingRight: '20%', marginBottom: '8px' }}>
<div style={{ fontSize: '20px', fontWeight: 600, marginBottom: '16px' }}>
{`${compareCurrent?.Serverpart_Name || compareCurrent?.SERVERPART_NAME || ''}-${topProjectDetail?.SERVERPARTSHOP_NAME || ''}-${compareCurrent?.STATISTICS_MONTH || monthTime || ''}月度结算`}
</div>
<Button type="primary" onClick={() => {
setShowMoreBtn(true)
}}></Button>
</div>
}}
/>
:
<div>
<div style={{ width: '100%', display: 'flex', alignItems: 'center', justifyContent: 'space-between', boxSizing: 'border-box', paddingTop: '16px', paddingLeft: '30px', paddingRight: '20%', marginBottom: '8px' }}>
<div style={{ fontSize: '20px', fontWeight: 600, marginBottom: '16px' }}>
{`${compareCurrent?.Serverpart_Name || compareCurrent?.SERVERPART_NAME || ''}-${topProjectDetail?.SERVERPARTSHOP_NAME || ''}-${compareCurrent?.STATISTICS_MONTH || monthTime || ''}月度结算`}
</div>
<Button type="primary" onClick={() => {
setShowMoreBtn(true)
}}></Button>
</div>
</div>
</div> : ""
}
{
@ -2779,8 +2781,11 @@ const compareList: React.FC<{
/> */}
<MonthSettlement onRef={MonthSettlementRef} detail={compareCurrent} noTitle={true} />
{
come !== 'ConfirmationDifference' ?
<MonthSettlement onRef={MonthSettlementRef} detail={compareCurrent} noTitle={true} />
: ""
}
@ -3028,7 +3033,7 @@ const compareList: React.FC<{
}}></Button> : ''
}
{
compareCurrent?.Approvalstate === 9 ?
compareCurrent?.Approvalstate === 9 && come !== 'ConfirmationDifference' ?
<Button key="new" style={{ marginLeft: '8px' }} onClick={() => {
console.log('compareCurrent', compareCurrent);
console.log('topProjectDetail', topProjectDetail);
@ -3144,7 +3149,7 @@ const compareList: React.FC<{
{/* dataSource={secondTableData} */}
{/* /> */}
{
compareCurrent?.Approvalstate > 0 ? '' :
compareCurrent?.Approvalstate > 0 && come !== 'ConfirmationDifference' ? '' :
<div className={'titleBox'} style={{ marginTop: '16px' }}>
<div className={'leftBox'}>
@ -3197,7 +3202,7 @@ const compareList: React.FC<{
}
<>
{
showBigTableDifference ?
showBigTableDifference || come === 'ConfirmationDifference' ?
<Button type="primary" onClick={() => {
console.log('tableAllData', tableAllData);
setShowBigTableDifference(false)
@ -3232,7 +3237,7 @@ const compareList: React.FC<{
{
compareCurrent?.Approvalstate > 0 ?
compareCurrent?.Approvalstate > 0 && come !== 'ConfirmationDifference' ?
<div style={{ width: '100%', boxSizing: 'border-box', padding: '0 30px' }}>
<ReviewProcess showReviewProcess={compareCurrent} compareCurrent={{
...compareCurrent,
@ -3855,11 +3860,11 @@ const compareList: React.FC<{
const data = await handleGetAPPROVALROUTEDetail(req)
const detailReq: any = {
BUSINESSAPPROVALId: compareCurrent?.BUSINESSAPPROVAL_ID
BUSINESSAPPROVALId: compareCurrent?.BUSINESSAPPROVAL_ID || compareCurrent?.BusinessApprovalId
}
console.log('req', req);
let detailData: any = []
if (compareCurrent?.BUSINESSAPPROVAL_ID) {
if (compareCurrent?.BUSINESSAPPROVAL_ID || compareCurrent?.BusinessApprovalId) {
detailData = await handleGetBUSINESSAPPROVALDetail(detailReq)
}

View File

@ -35,6 +35,8 @@ const ActiveMemberStatistics: React.FC<{ currentUser: CurrentUser | undefined }>
const [valueType, setValueType] = useState<any>()
// 显示加载效果
const [showLoading, setShowLoading] = useState<boolean>(false)
// 当前的搜索条件
const [searchParams, setSearchParams] = useState<any>()
let MEMBERSHIPLEVELYNObj = session.get('MEMBERSHIPLEVELYNObj')
let MEMBERSHIPLEVELYNList = session.get('MEMBERSHIPLEVELYNList')
@ -49,6 +51,18 @@ const ActiveMemberStatistics: React.FC<{ currentUser: CurrentUser | undefined }>
[start, end] = formData.searchTime
}
console.log('fkdsjfaks', {
...formData,
start: start,
end: end
});
setSearchParams({
...formData,
start: start,
end: end
})
const req: any = {
CalcType: 4, // 活跃会员
OwnerUnitId: currentUser?.OwnerUnitId,
@ -65,7 +79,10 @@ const ActiveMemberStatistics: React.FC<{ currentUser: CurrentUser | undefined }>
setShowLoading(false)
console.log('datadatadatadata', data);
setMembershipType(data.List)
let newList: any = data.List.filter((item: any) => item.label !== '1')
// setMembershipType(data.List)
setMembershipType(newList)
setMemberShipTotal(data.OtherData)
}
@ -74,12 +91,16 @@ const ActiveMemberStatistics: React.FC<{ currentUser: CurrentUser | undefined }>
// type 1 的话是 会员类型 2 的话是 会员等级 memberType 对应的枚举值
setCurrentDrawerTitle(`${type === 1 ? '会员类型' : type === 2 ? '会员等级' : ''}${type === 1 ? MEMBERSHIPTYPEYNObj && memberType ? MEMBERSHIPTYPEYNObj[memberType] : '' : type === 2 ? MEMBERSHIPLEVELYNObj && memberType ? MEMBERSHIPLEVELYNObj[memberType] : '' : ''}`)
setSearchType(type)
setSearchParams({
...searchParams,
MEMBERSHIP_LEVEL: memberType
})
setValueType(memberType)
setShowDetail(true)
}
useEffect(() => {
handleGetData()
handleGetData({ searchTime: [moment().startOf('M').format('YYYY-MM-DD'), moment().format('YYYY-MM-DD')] })
}, [])
return (
@ -137,7 +158,7 @@ const ActiveMemberStatistics: React.FC<{ currentUser: CurrentUser | undefined }>
label={"查询时间"}
name={"searchTime"}
// initialValue={[moment().startOf('M').format('YYYY-MM-DD'), moment().format('YYYY-MM-DD')]}
initialValue={[moment().startOf('M'), moment()]}
initialValue={[moment().startOf('M').format('YYYY-MM-DD'), moment().format('YYYY-MM-DD')]}
fieldProps={{
ranges: {
"本月": [moment().startOf('M'), moment()],
@ -201,7 +222,9 @@ const ActiveMemberStatistics: React.FC<{ currentUser: CurrentUser | undefined }>
<div className="ActiveMemberStatisticsItemOther">
{
membershipType.map((item: any) => {
return <div className="ActiveMemberStatisticsOtherItem">
return <div className="ActiveMemberStatisticsOtherItem" onClick={() => {
handleShowTableData(2, item.label)
}}>
<div className="otherItemTitle">{item.label === '0' ? '未授权用户' : MEMBERSHIPLEVELYNObj && item.label ? MEMBERSHIPLEVELYNObj[item.label] : ''}</div>
<div className="otherItemValue">{item.value}<span className="otherItemValueUnit"></span></div>
<div className="addLabel"></div>
@ -262,7 +285,7 @@ const ActiveMemberStatistics: React.FC<{ currentUser: CurrentUser | undefined }>
setShowDetail(false)
}}
>
<MemberInfor searchType={searchType} valueType={valueType} isComponent={true} />
<MemberInfor searchType={2} valueType={valueType} isComponent={true} come={'ActiveMemberStatistics'} comeParams={searchParams} noMemberLevel={true} />
</Drawer>
</div >
)

View File

@ -1,11 +1,102 @@
// 黑名单管理
import { ConnectState } from "@/models/connect";
import ProForm, { FormInstance, ProFormUploadButton } from "@ant-design/pro-form";
import { Button, Image } from "antd";
import { useRef, useState } from "react";
import { connect, CurrentUser } from "umi";
import AWS from 'aws-sdk'
import { handleMinIOPriview, handleMinIOUpload, handlePriview } from "@/utils/uploadFile";
const BlacklistManage: React.FC<{ currentUser: CurrentUser | undefined }> = (props) => {
const modalRef = useRef<FormInstance>();
// 图片
const [imgList, setImgList] = useState<any>([])
const [imagePreviewVisible, setImagePreviewVisible] = useState<boolean>(false) // 预览图片
const s3 = new AWS.S3({
endpoint: 'http://121.5.37.142:9000',
accessKeyId: 'admin',
secretAccessKey: 'minio123456',
region: 'us-east-1',
s3ForcePathStyle: true
});
const testUpload = async (file: any) => {
const result = await s3.upload({
Bucket: 'file-upload',
Key: file.name,
Body: file.originFileObj
}).promise();
console.log('上传成功:', result);
};
const testDelete = async (fileKey: string) => {
const result = await s3.deleteObject({
Bucket: 'file-upload', // 你的桶名
Key: '11.jpg', // 上传时的文件名(路径+文件名)
}).promise();
console.log('删除成功:', result);
}
const handleChangePreview = (val: any) => {
setImagePreviewVisible(val)
}
return (
<div>
{/* <ProForm
formRef={modalRef}
layout={'horizontal'}
labelCol={{ style: { width: 80 } }}
submitter={false}
>
<ProFormUploadButton
label={"上传附件"}
name={"file"}
/>
</ProForm>
<Button type={'primary'} onClick={() => {
modalRef.current?.validateFields().then(async (res: any) => {
console.log('resresresres', res);
// let fileObj: any = res.file[0]
// console.log('fileObjfileObjfileObj', fileObj);
// 批量上传图片
handleMinIOUpload(res.file)
// for (let i = 0; i < res.file.length; i++) {
// testUpload(res.file[i])
// }
})
}}></Button>
<Button danger onClick={() => {
testDelete('')
}}></Button>
<Button onClick={async () => {
let list = await handleMinIOPriview(['11.jpg'])
console.log('listlistlistlist', list);
setImgList(list)
}}></Button>
<Image.PreviewGroup
preview={{
visible: imagePreviewVisible,
onVisibleChange: vis => {
handleChangePreview(vis)
}
}}>
{
imgList.map((n) => <Image src={n.url} key={n.url} />)
}
</Image.PreviewGroup> */}
</div>
)
}

View File

@ -6,7 +6,7 @@ import ProTable, { ActionType } from "@ant-design/pro-table";
import PageTitleBox from "@/components/PageTitleBox";
import { Button, Col, FormInstance, message, Modal, Popconfirm, Row, Space } from "antd";
import { PlusOutlined } from "@ant-design/icons";
import { handeDeleteMERCHANTS, handeGetMERCHANTSList, handeGetSALEBILLDetail, handeGetSALEBILLList, handeGetSaleBillWholeList, handeGetSALEDETAILList, handeSynchroMERCHANTS } from "../service";
import { handeDeleteMERCHANTS, handeGetMERCHANTSList, handeGetNestingAUTOTYPEList, handeGetSALEBILLDetail, handeGetSALEBILLList, handeGetSaleBillWholeList, handeGetSALEDETAILList, handeSynchroMERCHANTS } from "../service";
import Draggable from "react-draggable";
import React from "react";
import ProForm, { ProFormSelect, ProFormText, ProFormTextArea } from "@ant-design/pro-form";
@ -154,6 +154,39 @@ const BookingMealOrder: React.FC<{ currentUser: CurrentUser | undefined }> = (pr
},
initialValue: "0"
},
{
title: '会员标签',
dataIndex: "MEMBERSHIP_TARGET",
valueType: 'treeSelect',
request: async () => {
const req = {
AUTOTYPE_TYPEID: '2000',
AUTOTYPE_PID: "",
OWNERUNIT_ID: currentUser?.OwnerUnitId,
AUTOTYPE_VALID: 1,
SearchKey: ""
}
const data = await handeGetNestingAUTOTYPEList(req);
console.log('datadatadatadatadata', data);
return data
},
hideInTable: true,
fieldProps: {
allowClear: true,
showSearch: true,
filterTreeNode: (input, node) => {
// ✅ 输入时根据 AUTOTYPE_NAME 模糊匹配
return node?.AUTOTYPE_NAME?.toLowerCase()?.includes(input.toLowerCase());
},
treeDefaultExpandAll: true,
fieldNames: {
label: 'AUTOTYPE_NAME',
value: 'AUTOTYPE_ID',
}
}
},
{
dataIndex: 'ORDER_AMOUNT',
title: '订单金额',
@ -306,7 +339,7 @@ const BookingMealOrder: React.FC<{ currentUser: CurrentUser | undefined }> = (pr
bordered
headerTitle={<PageTitleBox props={props} />} // 列表表头
actionRef={actionRef}
search={{ span: 6, labelWidth: 'auto' }}
search={{ span: 6, labelWidth: 'auto', defaultCollapsed: false }}
// 请求数据
request={async (params, sorter) => {
if (!selectedId) {
@ -319,7 +352,8 @@ const BookingMealOrder: React.FC<{ currentUser: CurrentUser | undefined }> = (pr
ORDER_DATE_Start: params?.ORDER_DATE_Start || "",
ORDER_DATE_End: params?.ORDER_DATE_End || "",
SALEBILL_STATES: params?.SALEBILL_STATE === "0" ? "1010,2000,3000" : params?.SALEBILL_STATE,
SearchKeyValue: params?.searchText || ""
SearchKeyValue: params?.searchText || "",
MEMBERSHIP_TARGET: params?.MEMBERSHIP_TARGET || ""
},
PageIndex: 1,
PageSize: 999999,

View File

@ -8,7 +8,7 @@ import type { ActionType } from "@ant-design/pro-table";
import ProTable from "@ant-design/pro-table";
import PageTitleBox from "@/components/PageTitleBox";
import moment from 'moment'
import { handeGetSALEBILLList, handeGetSaleBillWholeList, handeGetSALEDETAILList } from "../service";
import { handeGetMERCHANTSList, handeGetNestingAUTOTYPEList, handeGetSALEBILLList, handeGetSaleBillWholeList, handeGetSALEDETAILList } from "../service";
import './style.less'
import Draggable from "react-draggable";
import ProForm, { ProFormSelect, ProFormText } from "@ant-design/pro-form";
@ -290,7 +290,69 @@ const MallOrderManage: React.FC<{ currentUser: CurrentUser }> = (props) => {
ellipsis: true,
align: "center",
},
{
title: '会员标签',
dataIndex: "MEMBERSHIP_TARGET",
valueType: 'treeSelect',
request: async () => {
const req = {
AUTOTYPE_TYPEID: '2000',
AUTOTYPE_PID: "",
OWNERUNIT_ID: currentUser?.OwnerUnitId,
AUTOTYPE_VALID: 1,
SearchKey: ""
}
const data = await handeGetNestingAUTOTYPEList(req);
console.log('datadatadatadatadata', data);
return data
},
hideInTable: true,
fieldProps: {
allowClear: true,
showSearch: true,
filterTreeNode: (input, node) => {
// ✅ 输入时根据 AUTOTYPE_NAME 模糊匹配
return node?.AUTOTYPE_NAME?.toLowerCase()?.includes(input.toLowerCase());
},
treeDefaultExpandAll: true,
fieldNames: {
label: 'AUTOTYPE_NAME',
value: 'AUTOTYPE_ID',
}
}
},
{
title: '供应商',
dataIndex: "MERCHANTS_IDS",
valueType: 'select',
request: async () => {
const req = {
searchParameter: {
OWNERUNIT_ID: currentUser?.OwnerUnitId,
PROVINCE_CODE: currentUser?.ProvinceCode,
MERCHANTS_TYPE: ""
},
PageIndex: 1,
PageSize: 999999,
}
const data = await handeGetMERCHANTSList(req);
return data.List
},
hideInTable: true,
fieldProps: {
allowClear: true,
showSearch: true,
filterTreeNode: (input, node) => {
// ✅ 输入时根据 AUTOTYPE_NAME 模糊匹配
return node?.MERCHANTS_NAME?.toLowerCase()?.includes(input.toLowerCase());
},
treeDefaultExpandAll: true,
fieldNames: {
label: 'MERCHANTS_NAME',
value: 'MERCHANTS_ID',
}
}
},
// {
// title: "订单编号",
// dataIndex: "SALEBILL_CODE",
@ -390,7 +452,10 @@ const MallOrderManage: React.FC<{ currentUser: CurrentUser }> = (props) => {
}}
scroll={{ x: "100%", y: "calc(100vh - 410px)" }}
headerTitle={<PageTitleBox props={props} />} // 列表表头
search={{ span: 6 }}
search={{
span: 6,
defaultCollapsed: false
}}
request={async (params) => {
console.log('paramsparamsparams', params);
@ -403,7 +468,9 @@ const MallOrderManage: React.FC<{ currentUser: CurrentUser }> = (props) => {
ORDER_DATE_End: params?.ORDER_DATE_End || "",
SALEBILL_STATES: params?.orderStatus === "0" ? "1010,2010,3000" : params?.orderStatus,
CHANNEL_TYPE: params?.PAY_METHOD === "0" ? "" : params?.PAY_METHOD,
SearchKeyValue: params?.searchText || ""
SearchKeyValue: params?.searchText || "",
MERCHANTS_IDS: params?.MERCHANTS_IDS || "",
MEMBERSHIP_TARGET: params?.MEMBERSHIP_TARGET || ""
},
PageIndex: 1,
PageSize: 999999,

View File

@ -1,17 +1,17 @@
// 会员汇总统计
// 会员汇总统计 //会员积分报表
import { ConnectState } from "@/models/connect";
import { connect, CurrentUser } from "umi";
import './MemberSummaryStatistics.less'
import ProTable, { ActionType } from "@ant-design/pro-table";
import { useEffect, useRef, useState } from "react";
import { Button, Col, FormInstance, Row, Tooltip } from "antd";
import { handeGetPointGrowthSummary, handleGetMEMBERGROWTHList, handleGetPOINTRECORDList } from "../service";
import { handeGetNestingAUTOTYPEList, handeGetPointGrowthSummary, handleGetMEMBERGROWTHList, handleGetPOINTRECORDList } from "../service";
import moment from 'moment'
import addIcon from '@/assets/detail/addIcon.png'
import reduceIcon from '@/assets/detail/reduceIcon.png'
import staticSumTotalBg from '@/assets/detail/staticSumTotalBg.png'
import session from "@/utils/session";
import ProForm, { ProFormDateRangePicker } from "@ant-design/pro-form";
import ProForm, { ProFormDateRangePicker, ProFormTreeSelect } from "@ant-design/pro-form";
import { handleSetlogSave } from "@/utils/format";
import OrderDetailModal from "../BookingMealOrder/components/orderDetailModal";
import MemberDetail from "../memberInfor/component/memberDetail";
@ -354,7 +354,7 @@ const MemberSummaryStatistics: React.FC<{ currentUser: CurrentUser | undefined }
handleGetTopData()
}, [])
// 获取顶部的数据
const handleGetTopData = async (StartDate?: string, EndDate?: string) => {
const handleGetTopData = async (StartDate?: string, EndDate?: string, MEMBERSHIP_TARGET?: string) => {
const req: any = {
CalcType: 1, // 1 汇总 2 会员等级 3 会员类型
OwnerUnitId: currentUser?.OwnerUnitId,
@ -365,7 +365,7 @@ const MemberSummaryStatistics: React.FC<{ currentUser: CurrentUser | undefined }
MemberShipId: "",
MembershipType: "",
MembershipLevel: "",
MembershipTarget: ""
MembershipTarget: MEMBERSHIP_TARGET || ""
}
const data = await handeGetPointGrowthSummary(req)
console.log('datadatadatadatadata', data);
@ -385,7 +385,8 @@ const MemberSummaryStatistics: React.FC<{ currentUser: CurrentUser | undefined }
OPERATE_DATE_End: searchParams?.EndDate || "",
OWNERUNIT_ID: 911,
POINT_TYPE: value === 1 ? '' : value === 2 ? '1' : value === 3 ? '-1' : '',
POINT_SOURCE: ''
POINT_SOURCE: '',
MEMBERSHIP_TARGET: searchParams?.MEMBERSHIP_TARGET || ""
},
keyWord: {
Key: "MEMBERSHIP_NAME",
@ -404,7 +405,8 @@ const MemberSummaryStatistics: React.FC<{ currentUser: CurrentUser | undefined }
OWNERUNIT_ID: 911,
SCORESETTING_STATE: 1,
GROWTH_SOURCES: "",
GROWTH_TYPE: value === 4 ? '' : value === 5 ? '1' : value === 6 ? '-1' : ''
GROWTH_TYPE: value === 4 ? '' : value === 5 ? '1' : value === 6 ? '-1' : '',
MEMBERSHIP_TARGET: searchParams?.MEMBERSHIP_TARGET || ""
},
PageIndex: searchParams?.current,
PageSize: 20,
@ -450,7 +452,7 @@ const MemberSummaryStatistics: React.FC<{ currentUser: CurrentUser | undefined }
if (values.searchTime && values.searchTime.length > 0) {
[StartDate, EndDate] = values.searchTime
}
handleGetTopData(StartDate, EndDate)
handleGetTopData(StartDate, EndDate, values.MEMBERSHIP_TARGET)
setSearchParams({
StartDate: StartDate,
EndDate: EndDate
@ -459,19 +461,54 @@ const MemberSummaryStatistics: React.FC<{ currentUser: CurrentUser | undefined }
PointsRecordSearchRef.current?.actionRef?.current?.reload()
}}
>
<ProFormDateRangePicker
label={"查询时间"}
name={"searchTime"}
initialValue={[moment().startOf('M'), moment()]}
fieldProps={{
ranges: {
"本月": [moment().startOf('M'), moment()],
"上月": [moment().subtract(1, 'M').startOf('M'), moment().subtract(1, 'M').endOf('M')],
"近三月": [moment().subtract(3, 'M').startOf('M'), moment().endOf('M')],
"近半年": [moment().subtract(6, 'M').startOf('M'), moment().endOf('M')],
}
}}
/>
<Row gutter={8}>
<Col span={8}>
<ProFormDateRangePicker
label={"查询时间"}
name={"searchTime"}
initialValue={[moment().startOf('M'), moment()]}
fieldProps={{
ranges: {
"本月": [moment().startOf('M'), moment()],
"上月": [moment().subtract(1, 'M').startOf('M'), moment().subtract(1, 'M').endOf('M')],
"近三月": [moment().subtract(3, 'M').startOf('M'), moment().endOf('M')],
"近半年": [moment().subtract(6, 'M').startOf('M'), moment().endOf('M')],
}
}}
/>
</Col>
<Col span={8}>
<ProFormTreeSelect
label={"会员标签"}
name={"MEMBERSHIP_TARGET"}
request={async () => {
const req = {
AUTOTYPE_TYPEID: '2000',
AUTOTYPE_PID: "",
OWNERUNIT_ID: currentUser?.OwnerUnitId,
AUTOTYPE_VALID: 1,
SearchKey: ""
}
const data = await handeGetNestingAUTOTYPEList(req);
console.log('datadatadatadatadata', data);
return data
}}
fieldProps={{
allowClear: true,
showSearch: true,
filterTreeNode: (input, node) => {
// ✅ 输入时根据 AUTOTYPE_NAME 模糊匹配
return node?.AUTOTYPE_NAME?.toLowerCase()?.includes(input.toLowerCase());
},
treeDefaultExpandAll: true,
fieldNames: {
label: 'AUTOTYPE_NAME',
value: 'AUTOTYPE_ID',
}
}}
/>
</Col>
</Row>
</ProForm>
</Col>
<Col span={6}>

View File

@ -0,0 +1,238 @@
import { connect } from "umi";
import type { ConnectState } from "@/models/connect";
import ProCard from "@ant-design/pro-card";
import searchIcon from '@/assets/ai/searchIcon.png'
import { useRef, useState } from "react";
import { MenuFoldOutlined } from "@ant-design/icons";
import ProForm, { ProFormText } from "@ant-design/pro-form";
import { Button, Col, FormInstance, Row, Tree } from "antd";
import close from '@/assets/ai/close.png'
import { getServerpartTree } from "@/services/options";
import useRequest from "@ahooksjs/use-request";
import './style.less'
import { getMerchantShopTree } from "@/pages/Setting/Users/service";
import session from "@/utils/session";
import { handeGetNestingFIELDENUMList, handleGetCOOPSHOP_RULEList, handleGetCOUPONList } from "../../service";
type DetailProps = {
setSelectedId: any; // 把选择的服务区 可以带给外层
reload?: boolean; // 选择服务区 是否可以刷新组件之外的内容
actionRef?: any; // 和reload配合使用 确认要刷新的内容
currentUser: any; // 当前用户的信息
width?: number; // 组件的宽度
otherFun?: any; // 点击之后要进行的其他操作 多个操作可以写在一个方法里面传进来
setCollapsible: any; // 是否收缩组件
collapsible: boolean; // 收缩组件的判断依据
haveTest?: boolean;// 是否有测试服务区
handleGetLeftTreeData?: any // 拿到树数据的方法 必须要有输出值的
noWj?: any // 把万佳商贸隐藏
selectOnly?: boolean// 传入的时候 仅支持单选
}
const LeftSelectMemberLevel = ({ setSelectedId, reload, actionRef, currentUser, width, otherFun, setCollapsible, collapsible, haveTest, handleGetLeftTreeData, noWj, selectOnly }: DetailProps) => {
const searchTreeRef = useRef<FormInstance>();
// 默认的服务区树
const [allTreeViews, setAllTreeViews] = useState<any>()
// 是否要显示全部
const [isShowAllInTree, setIsShowAllInTree] = useState<boolean>(false)
// 加载服务区树
const { loading: treeLoading, data: treeViews } = useRequest(async () => {
const req = {
FIELDEXPLAIN_FIELD: 'MEMBERSHIP_LEVEL_YN',
FIELDEXPLAIN_ID: "",
FIELDENUM_PID: "",
FIELDENUM_STATUS: 1,
SearchKey: ""
}
const data = await handeGetNestingFIELDENUMList(req);
let list: any = data.filter((item: any) => item.FIELDENUM_VALUE !== '1')
setAllTreeViews(list)
setTreeView(list)
})
// 显示服务区树搜索框
const [showServiceSearchBox, setShowServiceSearchBox] = useState<boolean>(false)
// 实际显示在左侧的服务区树
const [treeView, setTreeView] = useState<any>()
// 树要展开的行
const [treeShowRow, setTreeShowRow] = useState<any>()
// 筛选左侧的服务区树
const handleFilterServiceTree = async (value?: string) => {
const resList: any = JSON.parse(JSON.stringify(allTreeViews))
setSelectedId('')
if (resList && resList.length > 0 && value) {
setTreeView([])
const list: any = []
resList.forEach((item: any) => {
if (item.FIELDENUM_NAME.indexOf(value) !== -1) {
list.push(item)
} else {
if (item.children && item.children.length > 0) {
const childrenList: any = []
item.children.forEach((subItem: any) => {
if (subItem.FIELDENUM_NAME.indexOf(value) !== -1) {
childrenList.push(subItem)
}
})
item.children = childrenList
if (childrenList && childrenList.length > 0) {
list.push(item)
}
}
}
})
if (list && list.length > 0) {
const keyList: any = ['0-0']
list.forEach((item: any) => {
keyList.push(item.key)
})
setTreeShowRow(keyList)
}
setTimeout(() => {
setTreeView(list)
}, 100)
} else {
setTreeView([])
setTreeShowRow([])
setTreeView(allTreeViews)
}
}
// 根据传入的服务区id筛选剔除掉这个服务区
const handleFilterList = (list: any, id: any) => {
let res: any = []
list.forEach((item: any) => {
if (item.value === id) {
} else {
res.push(item)
}
})
console.log('res', res);
return res
}
// 仅支持单选一个服务区的时候 调用的方法
const convertTreeForSelectOnly = (treeData: any[]): any[] => {
return treeData.map(item => {
const newItem = {
...item,
disabled: item.type !== 1,
};
if (item.children) {
newItem.children = convertTreeForSelectOnly(item.children);
}
return newItem;
});
};
return (
<div>
<ProCard
style={{ width: !collapsible ? width ? `${width}px` : "300px" : "60px" }}
className="pageTable-leftnav"
bodyStyle={{ padding: 0, paddingTop: 20, paddingLeft: 20, width: !collapsible ? width ? `${width}px` : "300px" : "60px" }}
extra={<div className="leftSelectBox">
<img className="searchIcon" src={searchIcon} onClick={() => {
setShowServiceSearchBox(true)
}} />
<MenuFoldOutlined onClick={() => {
setCollapsible(!collapsible);
}} />
<div className="fixedBox" style={{ display: showServiceSearchBox ? 'flex' : 'none', width: width ? `${width}px` : '275px' }}>
<ProForm
formRef={searchTreeRef}
layout={'horizontal'}
submitter={{
render: () => {
return []
}
}}
isKeyPressSubmit
onFinish={(values: any) => {
return handleFilterServiceTree(values?.searchValue || '')
}}
>
<Row>
<Col span={15} className={'noBottom'}>
<ProFormText
name={'searchValue'}
fieldProps={{
placeholder: '请输入服务区名称'
}}
allowClear
/>
</Col>
<Col span={2}></Col>
<Col span={5}>
<Button type={'primary'} onClick={() => {
searchTreeRef.current?.submit()
}}></Button>
</Col>
</Row>
</ProForm>
<img style={{ width: '20px', height: '20px', cursor: 'pointer', marginLeft: '5px' }} src={close} onClick={() => {
setShowServiceSearchBox(false)
}} />
</div>
</div>}
colSpan={!collapsible ? "300px" : "60px"}
title={!collapsible ? "请选择服务区" : ""}
headerBordered
collapsed={collapsible}
>
{treeView && treeView.length > 0 ? <Tree
checkable
treeData={[{
FIELDENUM_NAME: '全部',
FIELDENUM_VALUE: 0,
key: '0-0',
children: treeView
}]}
blockNode
defaultExpandAll={isShowAllInTree ? false : true}
defaultExpandedKeys={isShowAllInTree ? treeShowRow && treeShowRow.length > 0 ? treeShowRow : ['0-0'] : []}
onCheck={(checkedKeys: React.Key[] | any, info) => {
if (selectOnly) {
// 只允许单选且只允许type为1
const checked = Array.isArray(checkedKeys.checked) ? checkedKeys.checked : checkedKeys;
const node = info.node;
if (node.type === 1) {
setSelectedId(node.value);
if (reload) {
actionRef?.current?.reload();
}
if (otherFun) {
otherFun(info);
}
} else {
// 取消非type=1的勾选
setSelectedId('');
}
} else {
// 多选逻辑
const selectedIds = info.checkedNodes.filter((n: any) => n?.FIELDENUM_VALUE > 0)
setSelectedId(selectedIds.map((n: any) => n?.FIELDENUM_VALUE)?.toString() || '')
if (reload) {
actionRef?.current?.reload()
}
if (otherFun) {
otherFun(info)
}
}
}}
fieldNames={{
title: "FIELDENUM_NAME",
key: "FIELDENUM_VALUE"
}}
/> : ''}
</ProCard>
</div>
)
}
export default connect(({ user }: ConnectState) => ({
currentUser: user.currentUser,
}))(LeftSelectMemberLevel);

View File

@ -0,0 +1,29 @@
.pageTable-leftnav{
.leftSelectBox{
position: relative;
.searchIcon{
width: 20px;
height: 20px;
cursor: pointer;
margin-right: 15px;
}
.fixedBox{
position: absolute;
width: 275px;
background: #fff;
right: -10px;
box-shadow: 0 3px 6px -4px rgba(0, 0, 0, 0.12), 0 6px 16px 0 rgba(0, 0, 0, 0.08), 0 9px 28px 8px rgba(0, 0, 0, 0.05);
border-radius: 8px;
box-sizing: border-box;
padding: 12px;
z-index: 2;
display: flex;
align-items: center;
.noBottom{
.ant-form-item{
margin-bottom: 0!important;
}
}
}
}
}

View File

@ -1,11 +1,370 @@
// 会员等级分布
import { ConnectState } from "@/models/connect";
import { connect, CurrentUser } from "umi";
import LeftSelectMemberLevel from "./components/LeftSelectMemberLevel";
import { useRef, useState } from "react";
import ProTable, { ActionType } from "@ant-design/pro-table";
import { FormInstance } from "antd";
import PageTitleBox from "@/components/PageTitleBox";
import moment from 'moment'
import { handleSetlogSave } from "@/utils/format";
import session from "@/utils/session";
import { handleGetMEMBERSHIPList } from "../service";
const MembershipLevelDistribution: React.FC<{ currentUser: CurrentUser | undefined }> = (props) => {
const actionRef = useRef<ActionType>();
const formRef = useRef<FormInstance>();
// 树相关的属性和方法
const [selectedId, setSelectedId] = useState<string>()
const [collapsible, setCollapsible] = useState<boolean>(false)
// 当前行数据
const [currentRow, setCurrentRow] = useState<any>()
// 显示详情抽屉
const [showDetailDrawer, setShowDetailDrawer] = useState<boolean>(false)
let MEMBERSHIPTYPEYNObj = session.get('MEMBERSHIPTYPEYNObj');
let CONSUMPTIONRECORDTYPEObj = session.get('CONSUMPTIONRECORDTYPEObj')
let MEMBERSHIPLEVELYNObj = session.get('MEMBERSHIPLEVELYNObj')
const columns: any = [
{
title: "用户昵称",
width: 200,
dataIndex: "MEMBERSHIP_NAME",
ellipsis: true,
align: 'center',
fixed: 'left',
render: (_, record) => {
return <a onClick={() => {
setCurrentRow(record)
setShowDetailDrawer(true)
handleSetlogSave(`查看${record?.MEMBERSHIP_NAME}${record?.MEMBERSHIP_ID}】会员信息`)
}}>
{record?.MEMBERSHIP_NAME || ""}
</a>
},
fieldProps: {
placeholder: "请输入用户昵称/联系电话/证件号/车牌号"
}
},
{
title: "会员类型",
width: 120,
dataIndex: "MEMBERSHIP_TYPE",
ellipsis: true,
hideInTable: true,
align: 'center',
valueType: 'select',
// request: () => {
// let MEMBERSHIPTYPEYNList = session.get('MEMBERSHIPTYPEYNList')
// let newList: any = []
// if (MEMBERSHIPTYPEYNList && MEMBERSHIPTYPEYNList.length > 0) {
// MEMBERSHIPTYPEYNList.forEach((item: any) => {
// if (item.value !== 1) {
// // && item.value < 9000
// newList.push(item)
// }
// })
// }
// return newList
// }
valueEnum: {
...MEMBERSHIPTYPEYNObj,
},
initialValue: "1"
},
{
title: "会员类型",
width: 120,
dataIndex: "MEMBERSHIP_TYPE",
ellipsis: true,
hideInSearch: true,
align: 'center',
valueType: 'select',
valueEnum: {
...MEMBERSHIPTYPEYNObj,
},
},
{
title: "会员编码",
width: 120,
dataIndex: "MEMBERSHIP_CODE",
hideInSearch: true,
ellipsis: true,
align: 'center',
},
{
title: "会员性别",
width: 120,
dataIndex: "MEMBERSHIP_SEX",
hideInSearch: true,
ellipsis: true,
align: 'center',
valueType: 'select',
valueEnum: {
0: '男',
1: '女',
}
},
{
title: "联系电话",
width: 120,
dataIndex: "MEMBERSHIP_MOBILEPHONE",
hideInSearch: true,
ellipsis: true,
align: 'center',
},
{
title: "会员等级",
width: 120,
dataIndex: "MEMBERSHIP_LEVEL",
hideInSearch: true,
ellipsis: true,
align: 'center',
valueType: 'select',
valueEnum: MEMBERSHIPLEVELYNObj,
initialValue: "1"
// request: () => {
// let MEMBERSHIPLEVELYNList = session.get('MEMBERSHIPLEVELYNList')
// let newList: any = []
// if (MEMBERSHIPLEVELYNList && MEMBERSHIPLEVELYNList.length > 0) {
// MEMBERSHIPLEVELYNList.forEach((item: any) => {
// if (item.value !== '1') {
// // && item.value < 9000
// newList.push(item)
// }
// })
// }
// return newList
// }
},
{
title: "会员积分",
width: 120,
dataIndex: "MEMBERSHIP_POINT",
hideInSearch: true,
ellipsis: true,
sorter: true,
align: 'center',
},
{
title: "会员成长值",
width: 120,
dataIndex: "MEMBERGROWTH_VALUE",
hideInSearch: true,
ellipsis: true,
align: 'center',
},
{
title: "账户余额",
width: 120,
dataIndex: "ACCOUNT_BALANCE",
hideInSearch: true,
ellipsis: true,
sorter: true,
align: 'center',
},
{
title: "会员生日",
width: 150,
dataIndex: "MEMBERSHIP_BIRTHDAY",
hideInSearch: true,
ellipsis: true,
align: 'center',
render: (_, record) => {
return record?.MEMBERSHIP_BIRTHDAY ? moment(record?.MEMBERSHIP_BIRTHDAY).format('YYYY-MM-DD') : '-'
}
},
{
title: "证件号码",
width: 150,
dataIndex: "CERTIFICATE_NUMBER",
hideInSearch: true,
ellipsis: true,
align: 'center',
},
{
title: "会员卡号",
width: 120,
dataIndex: "MEMBERSHIP_CARD",
hideInSearch: true,
ellipsis: true,
align: 'center',
},
// {
// title: "会员头像",
// width: 120,
// dataIndex: "MEMBERSHIP_HEADIMAGEURL",
// hideInSearch: true,
// ellipsis: true,
// align: 'center',
// render: (_, record) => {
// return record?.MEMBERSHIP_HEADIMAGEURL ? <a onClick={() => {
// window.open(record?.MEMBERSHIP_HEADIMAGEURL)
// }}>点击查看</a> : ""
// }
// },
{
title: "联系地址",
width: 180,
dataIndex: "MEMBERSHIP_ADDRESS",
hideInSearch: true,
ellipsis: true,
align: 'center',
},
{
title: "车牌号",
width: 150,
dataIndex: "PLATE_NUMBER",
hideInSearch: true,
ellipsis: true,
align: 'center',
},
// {
// title: "付费会员",
// width: 120,
// dataIndex: "ISPLUS",
// hideInSearch: true,
// ellipsis: true,
// align: 'center',
// valueType: 'select',
// valueEnum: {
// 0: "否",
// 1: "是"
// }
// },
{
title: "付费有效期",
width: 120,
dataIndex: "PLUS_EXPIRYDATE",
hideInSearch: true,
ellipsis: true,
align: 'center',
},
{
title: "推荐人",
width: 120,
dataIndex: "RECOMMEND_NAME",
hideInSearch: true,
ellipsis: true,
align: 'center',
},
// {
// title: "会员状态",
// width: 120,
// dataIndex: "MEMBERSHIP_STATE",
// ellipsis: true,
// align: 'center',
// valueType: 'select',
// valueEnum: COMPANY_STATEObj,
// initialValue: "1000"
// },
{
title: "最后活跃时间",
width: 150,
// BEHAVIORRECORD_TIME 用于排序 ACTIVE_LASTTIME 用于显示
dataIndex: "BEHAVIORRECORD_TIME",
align: 'center',
hideInSearch: true,
ellipsis: true,
sorter: true,
// defaultSortOrder: 'descend',
render: (_, record) => {
return record?.ACTIVE_LASTTIME ? moment(record?.ACTIVE_LASTTIME).format('YYYY-MM-DD HH:mm:ss') : '-'
}
},
{
title: "注册时间",
width: 150,
dataIndex: "ADDTIME",
align: 'center',
hideInSearch: true,
ellipsis: true,
sorter: true,
// sorter: (a, b) => {
// const timeA = new Date(a.ADDTIME).getTime();
// const timeB = new Date(b.ADDTIME).getTime();
// return timeB - timeA; // 倒序排序
// },
// 默认排序配置
// defaultSortOrder: 'descend',
render: (_, record) => {
return record?.ADDTIME ? moment(record?.ADDTIME).format('YYYY-MM-DD HH:mm:ss') : '-'
}
},
{
title: "备注",
width: 120,
dataIndex: "MEMBERSHIP_DESC",
hideInSearch: true,
ellipsis: true,
},
]
return (
<div>
<div style={{ backgroundColor: '#fff', display: 'flex' }}>
<LeftSelectMemberLevel setSelectedId={setSelectedId} setCollapsible={setCollapsible} collapsible={collapsible} />
<div style={{
width: !collapsible ? 'calc(100% - 300px)' : 'calc(100% - 60px)',
paddingTop: 0,
paddingBottom: 0,
paddingRight: 0
}}>
<ProTable
actionRef={actionRef}
formRef={formRef}
columns={columns}
bordered
expandable={{
expandRowByClick: true
}}
scroll={{ x: "100%", y: "calc(100vh - 410px)" }}
headerTitle={<PageTitleBox props={props} />} // 列表表头
search={{ span: 6 }}
request={async (params, sorter) => {
if (!selectedId) {
return
}
const sortstr = Object.keys(sorter).map(n => {
const value = sorter[n]
return value ? `${n} ${value.replace('end', '')}` : ''
})
console.log('selectedIdselectedIdselectedId', selectedId);
const req: any = {
SearchParameter: {
OWNERUNIT_ID: 911,
MEMBERSHIP_LEVELS: selectedId,
MEMBERSHIP_STATE: params?.MEMBERSHIP_STATE,
},
keyWord: {
Key: "MEMBERSHIP_NAME,MEMBERSHIP_MOBILEPHONE,CERTIFICATE_NUMBER,MEMBERSHIP_CARD,MEMBERSHIP_ADDRESS,PLATE_NUMBER",
value: params?.MEMBERSHIP_NAME || ""
},
PageIndex: params.current || 1,
PageSize: params?.pageSize,
sortstr: sortstr.length ? sortstr.toString() === "MEMBERGROWTH_VALUE asc" || sortstr.toString() === "MEMBERGROWTH_VALUE desc" ? "" : sortstr.toString() : "",
}
handleSetlogSave(`查看了会员账户管理列表`)
const data = await handleGetMEMBERSHIPList(req)
if (data.List && data.List.length > 0) {
return { data: data.List, success: true, total: data.TotalCount }
}
return { data: [], success: true }
}}
toolbar={{
actions: [
]
}}
/>
</div>
</div>
</div>
)
}

View File

@ -1,16 +1,16 @@
// 会员汇总统计
// 会员汇总统计 // 会员等级统计
import { ConnectState } from "@/models/connect";
import { connect, CurrentUser } from "umi";
import './MembershipLevelStatistics.less'
import ProTable, { ActionType } from "@ant-design/pro-table";
import { useEffect, useRef, useState } from "react";
import { Button, Col, Drawer, FormInstance, Row, Spin, Tabs, Tooltip } from "antd";
import { handeGetPointGrowthSummary, handleGetMEMBERGROWTHList, handleGetPOINTRECORDList } from "../service";
import { handeGetNestingAUTOTYPEList, handeGetPointGrowthSummary, handleGetMEMBERGROWTHList, handleGetPOINTRECORDList } from "../service";
import moment from 'moment'
import addIcon from '@/assets/detail/addIcon.png'
import reduceIcon from '@/assets/detail/reduceIcon.png'
import session from "@/utils/session";
import ProForm, { ProFormDateRangePicker } from "@ant-design/pro-form";
import ProForm, { ProFormDateRangePicker, ProFormTreeSelect } from "@ant-design/pro-form";
import { handleSetlogSave } from "@/utils/format";
import PointsRecordSearch from "../PointsRecordSearch";
import GrowthValueRecordSearch from "../GrowthValueRecordSearch";
@ -289,7 +289,7 @@ const MembershipLevelStatistics: React.FC<{ currentUser: CurrentUser | undefined
}, [])
// 获取顶部的数据
const handleGetTopData = async (StartDate?: string, EndDate?: string) => {
const handleGetTopData = async (StartDate?: string, EndDate?: string, MEMBERSHIP_TARGET?: string) => {
const req: any = {
CalcType: 2, // 1 汇总 2 会员等级 3 会员类型
OwnerUnitId: currentUser?.OwnerUnitId,
@ -300,7 +300,7 @@ const MembershipLevelStatistics: React.FC<{ currentUser: CurrentUser | undefined
MemberShipId: "",
MembershipType: "",
MembershipLevel: "",
MembershipTarget: ""
MembershipTarget: MEMBERSHIP_TARGET || ""
}
setTopLoading(true)
const data = await handeGetPointGrowthSummary(req)
@ -458,7 +458,7 @@ const MembershipLevelStatistics: React.FC<{ currentUser: CurrentUser | undefined
if (values.searchTime && values.searchTime.length > 0) {
[StartDate, EndDate] = values.searchTime
}
handleGetTopData(StartDate, EndDate)
handleGetTopData(StartDate, EndDate, values.MEMBERSHIP_TARGET)
setSearchParams({
StartDate: StartDate,
EndDate: EndDate
@ -466,19 +466,55 @@ const MembershipLevelStatistics: React.FC<{ currentUser: CurrentUser | undefined
actionRef.current?.reload()
}}
>
<ProFormDateRangePicker
label={"查询时间"}
name={"searchTime"}
initialValue={[moment().startOf('M'), moment()]}
fieldProps={{
ranges: {
"本月": [moment().startOf('M'), moment()],
"上月": [moment().subtract(1, 'M').startOf('M'), moment().subtract(1, 'M').endOf('M')],
"近三月": [moment().subtract(3, 'M').startOf('M'), moment().endOf('M')],
"近半年": [moment().subtract(6, 'M').startOf('M'), moment().endOf('M')],
}
}}
/>
<Row gutter={8}>
<Col span={8}>
<ProFormDateRangePicker
label={"查询时间"}
name={"searchTime"}
initialValue={[moment().startOf('M'), moment()]}
fieldProps={{
ranges: {
"本月": [moment().startOf('M'), moment()],
"上月": [moment().subtract(1, 'M').startOf('M'), moment().subtract(1, 'M').endOf('M')],
"近三月": [moment().subtract(3, 'M').startOf('M'), moment().endOf('M')],
"近半年": [moment().subtract(6, 'M').startOf('M'), moment().endOf('M')],
}
}}
/>
</Col>
<Col span={8}>
<ProFormTreeSelect
label={"会员标签"}
name={"MEMBERSHIP_TARGET"}
request={async () => {
const req = {
AUTOTYPE_TYPEID: '2000',
AUTOTYPE_PID: "",
OWNERUNIT_ID: currentUser?.OwnerUnitId,
AUTOTYPE_VALID: 1,
SearchKey: ""
}
const data = await handeGetNestingAUTOTYPEList(req);
console.log('datadatadatadatadata', data);
return data
}}
fieldProps={{
allowClear: true,
showSearch: true,
filterTreeNode: (input, node) => {
// ✅ 输入时根据 AUTOTYPE_NAME 模糊匹配
return node?.AUTOTYPE_NAME?.toLowerCase()?.includes(input.toLowerCase());
},
treeDefaultExpandAll: true,
fieldNames: {
label: 'AUTOTYPE_NAME',
value: 'AUTOTYPE_ID',
}
}}
/>
</Col>
</Row>
</ProForm>
</Col>
<Col span={6}>

View File

@ -1,16 +1,16 @@
// 会员汇总统计
// 会员汇总统计 // 会员类型统计
import { ConnectState } from "@/models/connect";
import { connect, CurrentUser } from "umi";
import './MembershipTypeStatistics.less'
import ProTable, { ActionType } from "@ant-design/pro-table";
import { useEffect, useRef, useState } from "react";
import { Button, Col, Drawer, FormInstance, Row, Spin, Tabs, Tooltip } from "antd";
import { handeGetPointGrowthSummary, handleGetMEMBERGROWTHList, handleGetPOINTRECORDList } from "../service";
import { handeGetNestingAUTOTYPEList, handeGetPointGrowthSummary, handleGetMEMBERGROWTHList, handleGetPOINTRECORDList } from "../service";
import moment from 'moment'
import addIcon from '@/assets/detail/addIcon.png'
import reduceIcon from '@/assets/detail/reduceIcon.png'
import session from "@/utils/session";
import ProForm, { ProFormDateRangePicker } from "@ant-design/pro-form";
import ProForm, { ProFormDateRangePicker, ProFormTreeSelect } from "@ant-design/pro-form";
import { handleSetlogSave } from "@/utils/format";
import PointsRecordSearch from "../PointsRecordSearch";
import GrowthValueRecordSearch from "../GrowthValueRecordSearch";
@ -375,7 +375,7 @@ const MembershipTypeStatistics: React.FC<{ currentUser: CurrentUser | undefined
initData();
}, [])
// 获取顶部的数据
const handleGetTopData = async (StartDate?: string, EndDate?: string) => {
const handleGetTopData = async (StartDate?: string, EndDate?: string, MEMBERSHIP_TARGET?: string) => {
const req: any = {
CalcType: 3, // 1 汇总 2 会员等级 3 会员类型
OwnerUnitId: currentUser?.OwnerUnitId,
@ -386,7 +386,7 @@ const MembershipTypeStatistics: React.FC<{ currentUser: CurrentUser | undefined
MemberShipId: "",
MembershipType: "",
MembershipLevel: "",
MembershipTarget: ""
MembershipTarget: MEMBERSHIP_TARGET || ""
}
setTopLoading(true)
const data = await handeGetPointGrowthSummary(req)
@ -542,7 +542,7 @@ const MembershipTypeStatistics: React.FC<{ currentUser: CurrentUser | undefined
if (values.searchTime && values.searchTime.length > 0) {
[StartDate, EndDate] = values.searchTime
}
handleGetTopData(StartDate, EndDate)
handleGetTopData(StartDate, EndDate, values.MEMBERSHIP_TARGET)
setSearchParams({
StartDate: StartDate,
EndDate: EndDate
@ -550,19 +550,55 @@ const MembershipTypeStatistics: React.FC<{ currentUser: CurrentUser | undefined
actionRef.current?.reload()
}}
>
<ProFormDateRangePicker
label={"查询时间"}
name={"searchTime"}
initialValue={[moment().startOf('M'), moment()]}
fieldProps={{
ranges: {
"本月": [moment().startOf('M'), moment()],
"上月": [moment().subtract(1, 'M').startOf('M'), moment().subtract(1, 'M').endOf('M')],
"近三月": [moment().subtract(3, 'M').startOf('M'), moment().endOf('M')],
"近半年": [moment().subtract(6, 'M').startOf('M'), moment().endOf('M')],
}
}}
/>
<Row gutter={8}>
<Col span={8}>
<ProFormDateRangePicker
label={"查询时间"}
name={"searchTime"}
initialValue={[moment().startOf('M'), moment()]}
fieldProps={{
ranges: {
"本月": [moment().startOf('M'), moment()],
"上月": [moment().subtract(1, 'M').startOf('M'), moment().subtract(1, 'M').endOf('M')],
"近三月": [moment().subtract(3, 'M').startOf('M'), moment().endOf('M')],
"近半年": [moment().subtract(6, 'M').startOf('M'), moment().endOf('M')],
}
}}
/>
</Col>
<Col span={8}>
<ProFormTreeSelect
label={"会员标签"}
name={"MEMBERSHIP_TARGET"}
request={async () => {
const req = {
AUTOTYPE_TYPEID: '2000',
AUTOTYPE_PID: "",
OWNERUNIT_ID: currentUser?.OwnerUnitId,
AUTOTYPE_VALID: 1,
SearchKey: ""
}
const data = await handeGetNestingAUTOTYPEList(req);
console.log('datadatadatadatadata', data);
return data
}}
fieldProps={{
allowClear: true,
showSearch: true,
filterTreeNode: (input, node) => {
// ✅ 输入时根据 AUTOTYPE_NAME 模糊匹配
return node?.AUTOTYPE_NAME?.toLowerCase()?.includes(input.toLowerCase());
},
treeDefaultExpandAll: true,
fieldNames: {
label: 'AUTOTYPE_NAME',
value: 'AUTOTYPE_ID',
}
}}
/>
</Col>
</Row>
</ProForm>
</Col>
<Col span={6}>

View File

@ -2,9 +2,9 @@
import { ConnectState } from "@/models/connect";
import { useEffect, useRef, useState } from "react";
import { connect, CurrentUser } from "umi";
import { handeGetGetOnlineOrderSummary, handeGetSaleBillWholeList } from "../service";
import { handeGetGetOnlineOrderSummary, handeGetNestingAUTOTYPEList, handeGetSaleBillWholeList } from "../service";
import { Button, Col, FormInstance, Row, Tooltip } from "antd";
import ProForm, { ProFormDateRangePicker } from "@ant-design/pro-form";
import ProForm, { ProFormDateRangePicker, ProFormTreeSelect } from "@ant-design/pro-form";
import ProTable, { ActionType } from "@ant-design/pro-table";
import moment from 'moment'
import './SummaryOfReservation.less'
@ -260,25 +260,62 @@ const SummaryOfReservation: React.FC<{ currentUser: CurrentUser | undefined }> =
handleGetTopData(StartDate, EndDate)
setSearchParams({
StartDate: StartDate,
EndDate: EndDate
EndDate: EndDate,
MEMBERSHIP_TARGET: values.MEMBERSHIP_TARGET || ""
})
actionRef.current?.reload()
}}
>
<ProFormDateRangePicker
label={"查询时间"}
name={"searchTime"}
// initialValue={[moment().startOf('M').format('YYYY-MM-DD'), moment().format('YYYY-MM-DD')]}
initialValue={[moment().startOf('M'), moment()]}
fieldProps={{
ranges: {
"本月": [moment().startOf('M'), moment()],
"上月": [moment().subtract(1, 'M').startOf('M'), moment().subtract(1, 'M').endOf('M')],
"近三月": [moment().subtract(3, 'M').startOf('M'), moment().endOf('M')],
"近半年": [moment().subtract(6, 'M').startOf('M'), moment().endOf('M')],
}
}}
/>
<Row gutter={8}>
<Col span={8}>
<ProFormDateRangePicker
label={"查询时间"}
name={"searchTime"}
// initialValue={[moment().startOf('M').format('YYYY-MM-DD'), moment().format('YYYY-MM-DD')]}
initialValue={[moment().startOf('M'), moment()]}
fieldProps={{
ranges: {
"本月": [moment().startOf('M'), moment()],
"上月": [moment().subtract(1, 'M').startOf('M'), moment().subtract(1, 'M').endOf('M')],
"近三月": [moment().subtract(3, 'M').startOf('M'), moment().endOf('M')],
"近半年": [moment().subtract(6, 'M').startOf('M'), moment().endOf('M')],
}
}}
/>
</Col>
<Col span={8}>
<ProFormTreeSelect
label={"会员标签"}
name={"MEMBERSHIP_TARGET"}
request={async () => {
const req = {
AUTOTYPE_TYPEID: '2000',
AUTOTYPE_PID: "",
OWNERUNIT_ID: currentUser?.OwnerUnitId,
AUTOTYPE_VALID: 1,
SearchKey: ""
}
const data = await handeGetNestingAUTOTYPEList(req);
console.log('datadatadatadatadata', data);
return data
}}
fieldProps={{
allowClear: true,
showSearch: true,
filterTreeNode: (input, node) => {
// ✅ 输入时根据 AUTOTYPE_NAME 模糊匹配
return node?.AUTOTYPE_NAME?.toLowerCase()?.includes(input.toLowerCase());
},
treeDefaultExpandAll: true,
fieldNames: {
label: 'AUTOTYPE_NAME',
value: 'AUTOTYPE_ID',
}
}}
/>
</Col>
</Row>
</ProForm>
</Col>
<Col span={6}>
@ -567,7 +604,8 @@ const SummaryOfReservation: React.FC<{ currentUser: CurrentUser | undefined }> =
selectTab == 8 ? '' :
selectTab == 9 ? '' :
selectTab == 10 ? '' : '',
SearchKeyValue: params?.searchText || ""
SearchKeyValue: params?.searchText || "",
MEMBERSHIP_TARGET: searchParams?.MEMBERSHIP_TARGET || "",
},
PageIndex: 1,
PageSize: 999999,

View File

@ -1,7 +1,7 @@
// 会员详情组件
import { connect } from "umi";
import { connect, useRequest } from "umi";
import type { ConnectState } from "@/models/connect";
import { Button, Col, FormInstance, message, Modal, Row } from "antd";
import { Button, Col, FormInstance, message, Modal, Row, Select, TreeSelect } from "antd";
import { useEffect, useRef, useState } from "react";
import Draggable from "react-draggable";
import React from "react";
@ -12,7 +12,7 @@ import closeIcon from '@/assets/detail/closeIcon.png'
import session from "@/utils/session";
import memberDetailIcon from '@/assets/detail/memberDetailIcon.png'
import ProTable from "@ant-design/pro-table";
import { handeDeleteMembershipRecord, handeGetMEMBERSHIPDetail, handleGetCONSUMPTIONRECORDList, handleGetMEMBERGROWTHList, handleGetPOINTRECORDList } from "../../service";
import { handeDeleteMembershipRecord, handeGetMEMBERSHIPDetail, handeGetNestingAUTOTYPEList, handeGetSynchroMEMBERSHIP, handleGetCONSUMPTIONRECORDList, handleGetMEMBERGROWTHList, handleGetPOINTRECORDList } from "../../service";
import AddressDetail from "../../MemberAddress/components/addressDetail";
import './style.less'
import ConsumptionRecordSearch from "../../ConsumptionRecordSearch";
@ -25,6 +25,7 @@ import CollectProducts from "./CollectProducts";
import MerchantEvaluationManage from "../../MerchantEvaluationManage";
import MallEvaluationManage from "../../MallEvaluationManage";
import { handleSetlogSave } from "@/utils/format";
import editIcon from '@/assets/ai/editIcon.png'
type DetailProps = {
@ -48,11 +49,49 @@ const MemberDetail = ({ showDetailDrawer, currentRow, handleCloseModal, currentU
let SCORETYPETree = session.get('SCORETYPETree')
let CONSUMPTIONRECORDTYPEObj = session.get('CONSUMPTIONRECORDTYPEObj')
// 把树形的数据 全部层级的value 和label都匹配上
const flattenGrowthType = (list: any[], nameKey: string, valueKey: any) => {
const result: Record<string, string> = {}
function traverse(items: any[]) {
items.forEach(item => {
result[item[valueKey]] = item[nameKey]
if (Array.isArray(item.children) && item.children.length > 0) {
traverse(item.children)
}
})
}
traverse(list)
return result
}
// 会员详情信息
const [userDetailInfo, setUserDetailInfo] = useState<any>({})
// 当前选中在详情里面要查看的内容
const [selectTab, setSelectTab] = useState<number>(1)
// 会员标签枚举
const [labelConfig, setLabelConfig] = useState<any>()
const [labelConfigTreeList, setLabelConfigTreeList] = useState<any>()
// 选择的会员标签
const [selectUserLabel, setSelectUserLabel] = useState<any>()
// 变得可以编辑
const [showEdit, setShowEdit] = useState<boolean>(false)
const { loading: headerTitleLoading, data: tableHeaderObj } = useRequest(async () => {
const req = {
AUTOTYPE_TYPEID: '2000',
AUTOTYPE_PID: "",
OWNERUNIT_ID: currentUser?.OwnerUnitId,
AUTOTYPE_VALID: 1,
SearchKey: ""
}
const data = await handeGetNestingAUTOTYPEList(req);
console.log('datadatadatadatadata', data);
setLabelConfigTreeList(data)
let obj: any = flattenGrowthType(data, 'AUTOTYPE_NAME', 'AUTOTYPE_ID')
setLabelConfig(obj)
})
const onDraggaleStart = (event, uiData) => {
const { clientWidth, clientHeight } = window.document.documentElement;
@ -297,9 +336,28 @@ const MemberDetail = ({ showDetailDrawer, currentRow, handleCloseModal, currentU
useEffect(() => {
if (showDetailDrawer) {
setSelectTab(1)
} else {
setShowEdit(false)
}
}, [showDetailDrawer])
// 保存标签
const handleSaveLabelConfig = async () => {
const req: any = {
...userDetailInfo,
MEMBERSHIP_TARGET: selectUserLabel
}
const data = await handeGetSynchroMEMBERSHIP(req)
if (data.Result_Code === 100) {
message.success('同步成功!')
setShowEdit(false)
setUserDetailInfo(data.Result_Data)
} else {
message.error(data.Result_Desc)
setSelectUserLabel(null)
}
}
return (
<Modal
className="memberInfoDetailModal"
@ -356,6 +414,7 @@ const MemberDetail = ({ showDetailDrawer, currentRow, handleCloseModal, currentU
ADDTIME: data.ADDTIME ? moment(data.ADDTIME).format('YYYY-MM-DD HH:mm:ss') : '',
MEMBERSHIP_BIRTHDAY: currentRow?.MEMBERSHIP_BIRTHDAY ? moment(currentRow?.MEMBERSHIP_BIRTHDAY).format('YYYY-MM-DD') : '',
}
setSelectUserLabel(obj.MEMBERSHIP_TARGET)
setUserDetailInfo(obj)
return obj
} else {
@ -397,6 +456,46 @@ const MemberDetail = ({ showDetailDrawer, currentRow, handleCloseModal, currentU
<span className="memberType" style={{ marginLeft: '8px' }}>{MEMBERSHIPLEVELYNObj[userDetailInfo?.MEMBERSHIP_LEVEL]}</span> : ""
}
{
showEdit ?
<div style={{ marginLeft: '8px' }}>
<TreeSelect
showSearch
style={{ width: '150px' }}
value={selectUserLabel}
dropdownStyle={{ maxHeight: 400, overflow: 'auto' }}
placeholder="Please select"
allowClear
treeDefaultExpandAll
onChange={(e: any) => {
console.log('eeee', e);
setSelectUserLabel(e)
}}
treeData={labelConfigTreeList}
fieldNames={{
label: 'AUTOTYPE_NAME',
value: 'AUTOTYPE_ID',
}}
/>
</div> : userDetailInfo?.MEMBERSHIP_TARGET && labelConfig && labelConfig[userDetailInfo?.MEMBERSHIP_TARGET] ?
<div style={{ display: 'inline-block' }}>
<span className="memberType" style={{ marginLeft: '8px' }}>{labelConfig[userDetailInfo?.MEMBERSHIP_TARGET]}</span>
</div>
: ""
}
{
showEdit ?
<div style={{ marginLeft: '8px' }}>
<Button type={"primary"} onClick={() => {
handleSaveLabelConfig()
}}></Button>
</div> :
<img src={editIcon} style={{ cursor: 'pointer', width: '20px', height: '20px', marginLeft: '8px' }} onClick={() => {
setShowEdit(!showEdit)
}} />
}
</div>
<div className="topDetailItem">

View File

@ -83,6 +83,10 @@
padding: 8px 0;
.topDetailRightTop {
display: flex;
align-items: center;
height: 28px;
.detailName {
font-family: PingFangSC, PingFang SC;
font-weight: 600;
@ -108,12 +112,14 @@
font-family: PingFangSC, PingFang SC;
font-size: 14px;
color: #fff;
line-height: 14px;
line-height: 24px;
text-align: left;
font-style: normal;
padding: 2px 8px;
background: linear-gradient(0deg, #A13B00 0%, #D7AB0E 100%);
border-radius: 4px;
height: 100%;
box-sizing: border-box;
}
}

View File

@ -33,9 +33,11 @@ import { request } from "express";
// isComponent 判断是不是以组件形式
// noMemberType 判断是否隐藏 会员类型得筛选条件
// noMemberLevel 判断是否隐藏 会员等级得筛选条件
// come 具体来自哪个页面
// comeParams 来自哪个页面 可能需要带上那个页面的查询参数
const memberInfor: React.FC<{ currentUser: CurrentUser, searchType?: any, valueType?: any, isComponent?: boolean, noMemberType?: boolean, noMemberLevel?: boolean }> = (props) => {
const { currentUser, searchType, valueType, isComponent, noMemberType, noMemberLevel } = props
const memberInfor: React.FC<{ currentUser: CurrentUser, searchType?: any, valueType?: any, isComponent?: boolean, noMemberType?: boolean, noMemberLevel?: boolean, come?: string, comeParams?: any }> = (props) => {
const { currentUser, searchType, valueType, isComponent, noMemberType, noMemberLevel, come, comeParams } = props
const downloadBtnRef = useRef<any>()
const draggleRef = React.createRef<any>()
const actionRef = useRef<ActionType>();
@ -337,6 +339,20 @@ const memberInfor: React.FC<{ currentUser: CurrentUser, searchType?: any, valueT
// valueEnum: COMPANY_STATEObj,
// initialValue: "1000"
// },
{
title: "最后活跃时间",
width: 150,
// BEHAVIORRECORD_TIME 用于排序 ACTIVE_LASTTIME 用于显示
dataIndex: "BEHAVIORRECORD_TIME",
align: 'center',
hideInSearch: true,
ellipsis: true,
sorter: true,
// defaultSortOrder: 'descend',
render: (_, record) => {
return record?.ACTIVE_LASTTIME ? moment(record?.ACTIVE_LASTTIME).format('YYYY-MM-DD HH:mm:ss') : '-'
}
},
{
title: "注册时间",
width: 150,
@ -351,9 +367,9 @@ const memberInfor: React.FC<{ currentUser: CurrentUser, searchType?: any, valueT
// return timeB - timeA; // 倒序排序
// },
// 默认排序配置
defaultSortOrder: 'descend',
// defaultSortOrder: 'descend',
render: (_, record) => {
return record?.ADDTIME ? moment(record?.ADDTIME).format('YYYY-MM-DD') : '-'
return record?.ADDTIME ? moment(record?.ADDTIME).format('YYYY-MM-DD HH:mm:ss') : '-'
}
},
{
@ -706,6 +722,7 @@ const memberInfor: React.FC<{ currentUser: CurrentUser, searchType?: any, valueT
search={{ span: 6 }}
request={async (params, sorter) => {
console.log('paramsparamsparams', params);
console.log('searchTypesearchTypesearchType', searchType);
console.log('sortersortersortersorter', sorter);
const sortstr = Object.keys(sorter).map(n => {
@ -720,8 +737,10 @@ const memberInfor: React.FC<{ currentUser: CurrentUser, searchType?: any, valueT
// PROVINCE_CODE: currentUser?.ProvinceCode || "",
OWNERUNIT_ID: 911,
MEMBERSHIP_TYPE: searchType === 1 ? valueType : '',
MEMBERSHIP_LEVEL: searchType === 2 ? valueType : '',
MEMBERSHIP_STATE: 1000
MEMBERSHIP_LEVEL: come === 'ActiveMemberStatistics' ? comeParams?.MEMBERSHIP_LEVEL || '' : searchType === 2 ? valueType : '',
MEMBERSHIP_STATE: 1000,
ACTIVE_DATE_Start: come === 'ActiveMemberStatistics' ? comeParams?.start || '' : '',
ACTIVE_DATE_End: come === 'ActiveMemberStatistics' ? comeParams?.end || '' : '',
},
keyWord: {
// PLATE_NUMBER

View File

@ -1220,3 +1220,29 @@ export async function handeSynchroSUGGESTION(params: any) {
}
return data
}
// 查询卡券兑换统计表
export async function handeGetCouponExchangeSummary(params: any) {
const data = await requestEncryption(`/Coupon/GetCouponExchangeSummary`, {
method: 'POST',
data: { ...params, requestEncryption: true }
})
if (data.Result_Code !== 100) {
return data
}
return wrapTreeNode(data.Result_Data.List)
}
// 同步会员信息表
export async function handeGetSynchroMEMBERSHIP(params: any) {
const data = await requestEncryption(`/Member/SynchroMEMBERSHIP`, {
method: 'POST',
data: { ...params, requestEncryption: true }
})
if (data.Result_Code !== 100) {
return data
}
return data
}

75
src/utils/uploadFile.ts Normal file
View File

@ -0,0 +1,75 @@
// 封装上传文件的方法 http://121.5.37.142:9001/browser/file-upload 后台查看的网址
import AWS from 'aws-sdk'
// 地址路径
let endpoint: string = 'http://121.5.37.142:9000'
// 账号
let accessKeyId: string = 'admin'
// 密码
let secretAccessKey: string = 'minio123456'
// 上传文件的基础配置
const s3 = new AWS.S3({
endpoint: endpoint,
accessKeyId: accessKeyId,
secretAccessKey: secretAccessKey,
region: 'us-east-1', // 写死就行
s3ForcePathStyle: true
});
// 上传图片的方法
// 传入的 肯定是一个 proform 的 上传图片的数组格式
export async function handleMinIOUpload(fileList: any) {
let fileRes: any = []
for (let i = 0; i < fileList.length; i++) {
let file: any = fileList[i]
const key = `${new Date().getTime()} ${file.name.toString()}`;
const result = await s3.upload({
Bucket: 'file-upload',
Key: key,
Body: file.originFileObj,
}).promise();
console.log('上传成功:', result);
fileRes.push({
name: file.name.toString(),
key: key,
url: result.Location
})
}
return fileRes
};
// 删除图片的方法
export async function handleMinIODelete(fileKey: string) {
// 文件的key名称
const result = await s3.deleteObject({
Bucket: 'file-upload', // 你的桶名
Key: fileKey, // 上传时的文件名(路径+文件名)
}).promise();
return result
}
// 读取文件
export async function handleMinIOPriview(fileName: string[]) {
let resultList = []
for (let i = 0; i < fileName.length; i++) {
const url = await s3.getSignedUrlPromise('getObject', {
Bucket: 'file-upload',
Key: fileName[i],
Expires: 3600
});
resultList.push({
url: url,
name: fileName[i]
})
}
return resultList
// window.open(url);
}

View File

@ -1,4 +1,4 @@
// 由 scripts/writeVersion.js 自动生成
export const VERSION = "4.5.13";
export const GIT_HASH = "524c0ab";
export const BUILD_TIME = "2025-08-04T10:43:20.278Z";
export const VERSION = "4.5.15";
export const GIT_HASH = "a14b50b";
export const BUILD_TIME = "2025-08-05T03:04:59.319Z";