This commit is contained in:
ylj20011123 2025-09-23 19:14:35 +08:00
parent d0c4edded6
commit cee81d5037
17 changed files with 907 additions and 239 deletions

View File

@ -1,6 +1,6 @@
{ {
"name": "ant-design-pro", "name": "ant-design-pro",
"version": "4.5.61", "version": "4.5.62",
"private": true, "private": true,
"description": "An out-of-box UI solution for enterprise applications", "description": "An out-of-box UI solution for enterprise applications",
"scripts": { "scripts": {

View File

@ -51,6 +51,9 @@ const Model: LoginModelType = {
// 登录方法 // 登录方法
* login({ payload }, { call, put }) { * login({ payload }, { call, put }) {
const response = yield call(accountLogin, payload); const response = yield call(accountLogin, payload);
console.log('responseresponseresponseresponse', response);
yield put({ yield put({
type: 'changeLoginStatus', type: 'changeLoginStatus',
payload: response, payload: response,
@ -58,8 +61,16 @@ const Model: LoginModelType = {
// Login successfully // Login successfully
if (response.status === 'ok') { if (response.status === 'ok') {
// yield put({ type: 'global/getMenuData', payload: response.currentUser.ID }); // 生成左侧菜单 // yield put({ type: 'global/getMenuData', payload: response.currentUser.ID }); // 生成左侧菜单
yield put({ type: 'user/saveCurrentUser', payload: { ...response.currentUser } }); // 存储用户信息 // 这里拿一下用户信息 顺便判断一下 当前用户 是不是密码等级过低
if (!response?.passwordRes) {
message.error('密码过于简单,请重新设置密码!')
history.push('/user/forgetPassword');
return
}
yield put({ type: 'user/saveCurrentUser', payload: { ...response.currentUser } }); // 存储用户信息
message.success('🎉 🎉 🎉 登录成功!'); message.success('🎉 🎉 🎉 登录成功!');
if (!history) return; if (!history) return;

View File

@ -39,12 +39,12 @@ const handelResetPassWord = async (item: CloudChangePassword) => {
const ForgetPasswordContent: React.FC = () => { const ForgetPasswordContent: React.FC = () => {
const [submitting, setSubmitting] = useState<boolean>() const [submitting, setSubmitting] = useState<boolean>()
const newPasswordForm = useRef<FormInstance>() const newPasswordForm = useRef<FormInstance>()
const [step, setStep] = useState<1 | 2 >(1) // 1填写信息 2 修改成功 const [step, setStep] = useState<1 | 2>(1) // 1填写信息 2 修改成功
return ( return (
<div> <div>
<Typography.Title level={2} style={{ textAlign: 'center', paddingTop: 60, paddingBottom: 30 }}> {step === 1 ? '驿商云忘记密码' : ''}</Typography.Title> <Typography.Title level={2} style={{ textAlign: 'center', paddingTop: 60, paddingBottom: 30 }}> {step === 1 ? '驿商云重置密码' : ''}</Typography.Title>
<Card bordered={false} style={{ width: 910, margin: 'auto',height: 560 }} bodyStyle={{ padding: 80 }}> <Card bordered={false} style={{ width: 910, margin: 'auto', height: 560 }} bodyStyle={{ padding: 80 }}>
{step === 1 && {step === 1 &&
<ProForm <ProForm
style={{ width: 425, margin: '0 auto' }} style={{ width: 425, margin: '0 auto' }}
@ -69,22 +69,22 @@ const ForgetPasswordContent: React.FC = () => {
setSubmitting(true) setSubmitting(true)
const newValue = { ...values, DataType: 2000 } const newValue = { ...values, DataType: 2000 }
let success = null let success = null
delete newValue.ComfirmPassword delete newValue.ComfirmPassword
success = await handelResetPassWord( {...newValue } ) success = await handelResetPassWord({ ...newValue })
setSubmitting(false) setSubmitting(false)
if (success) { if (success) {
setStep(2) setStep(2)
return true return true
} }
return false return false
}} }}
> >
<ProFormText <ProFormText
fieldProps={{ fieldProps={{
size: 'large', size: 'large',
@ -147,11 +147,39 @@ const ForgetPasswordContent: React.FC = () => {
rules={[ rules={[
{ {
required: true, required: true,
message: '' message: '请输入新密码'
},
{
min: 8,
message: '密码长度至少8位'
},
{
validator: (_, value) => {
if (!value) return Promise.resolve();
// 检查密码复杂度数字、大小写字母、特殊字符中的2种以上组成
const hasNumber = /\d/.test(value);
const hasLowercase = /[a-z]/.test(value);
const hasUppercase = /[A-Z]/.test(value);
const hasSpecialChar = /[!@#$%^&*()_+\-=\[\]{};':"\\|,.<>\/?]/.test(value);
const typeCount = [hasNumber, hasLowercase, hasUppercase, hasSpecialChar].filter(Boolean).length;
if (typeCount < 2) {
return Promise.reject(new Error('密码不符合安全要求请设置长度8位以上由数字、大小写字母、特殊字符中的2种以上组成'));
}
return Promise.resolve();
}
} }
]} ]}
placeholder="" placeholder=""
hasFeedback hasFeedback
extra={
<Typography.Text type="secondary" style={{ fontSize: '12px' }}>
82
</Typography.Text>
}
/> />
<ProFormText.Password <ProFormText.Password
dependencies={['NewPassword']} dependencies={['NewPassword']}
@ -183,20 +211,20 @@ const ForgetPasswordContent: React.FC = () => {
/> />
</ProForm> </ProForm>
} }
{step === 2 && <> {step === 2 && <>
<Result <Result
status="success" status="success"
title="密码重置成功" title="密码重置成功"
extra={<Button type="default" onClick={() => history.push('/user/login')}> </Button>}/> extra={<Button type="default" onClick={() => history.push('/user/login')}> </Button>} />
</>} </>}
</Card> </Card>
</div> </div>
); );

View File

@ -1,6 +1,5 @@
// 营收汇总报表 // 营收汇总报表
import moment from 'moment'; import moment from 'moment';
import numeral from 'numeral'; import numeral from 'numeral';
import { connect, history } from 'umi'; import { connect, history } from 'umi';
@ -35,6 +34,8 @@ import rectification from '@/assets/rectification.png'
import codeIcon from '@/assets/DataVerification/code.png' import codeIcon from '@/assets/DataVerification/code.png'
import interfaceIcon from '@/assets/DataVerification/interface.png' import interfaceIcon from '@/assets/DataVerification/interface.png'
import PageTitleBox from '@/components/PageTitleBox'; import PageTitleBox from '@/components/PageTitleBox';
import { formatTreeData, sortTreeData } from '@/utils/format';
import { exportXlsxFromProColumnsExcelJS } from '@/utils/exportExcelFun';
const { Text } = Typography; const { Text } = Typography;
@ -82,6 +83,7 @@ const RevenueSummaryTable: React.FC<{ currentUser?: CurrentUser }> = (props) =>
MERCHANTS_NAME: { show: false }, MERCHANTS_NAME: { show: false },
ShopTrade: { show: false }, ShopTrade: { show: false },
}) })
const SHOPTRADEObj = session.get('SHOPTRADEObj')
// 显示每日流水抽屉 // 显示每日流水抽屉
const [showDailyDrawer, setShowDailyDrawer] = useState<boolean>(false) const [showDailyDrawer, setShowDailyDrawer] = useState<boolean>(false)
const [currentRow, setCurrentRow] = useState<any>() const [currentRow, setCurrentRow] = useState<any>()
@ -384,11 +386,12 @@ const RevenueSummaryTable: React.FC<{ currentUser?: CurrentUser }> = (props) =>
width: 120, width: 120,
valueType: 'select', valueType: 'select',
hideInSearch: true, hideInSearch: true,
request: async () => { valueEnum: SHOPTRADEObj
// 这里要手动添加枚举字段(从下面这些字典中选择一个):商品业态[BUSINESSTYPE] // request: async () => {
const options = await getFieldEnum({ FieldExplainField: 'BUSINESSTYPE' }); // // 这里要手动添加枚举字段(从下面这些字典中选择一个):商品业态[BUSINESSTYPE]
return options; // const options = await getFieldEnum({ FieldExplainField: 'BUSINESSTYPE' });
}, // return options;
// },
}, },
] ]
}, },
@ -764,18 +767,22 @@ const RevenueSummaryTable: React.FC<{ currentUser?: CurrentUser }> = (props) =>
span: 6, span: 6,
defaultCollapsed: false, defaultCollapsed: false,
}} }}
request={async (params) => { request={async (params, sorter) => {
const sortstr = Object.keys(sorter).map(n => {
const value = sorter[n]
return value ? `${n} ${value.replace('end', '')}` : ''
})
console.log('sortstrsortstrsortstr', sortstr);
params.ServerpartIds = selectedId || '0' params.ServerpartIds = selectedId || '0'
if (params?.StartDate === params?.EndDate) { if (params?.StartDate === params?.EndDate) {
setIsSameDay(true) setIsSameDay(true)
} else { } else {
setIsSameDay(false) setIsSameDay(false)
} }
const req: RevenueStatisticsParams = { const req: RevenueStatisticsParams = {
...params, ...params,
DataType: activeKey || '1', DataType: activeKey || '1',
DataSourceType: DataSourceType || '1', DataSourceType: DataSourceType || '1',
ShowShop: params.ShowShop === '1', ShowShop: params.ShowShop === '1',
@ -789,6 +796,11 @@ const RevenueSummaryTable: React.FC<{ currentUser?: CurrentUser }> = (props) =>
const data = await getRevenueReport(req); const data = await getRevenueReport(req);
setSearchParamsTime(params) setSearchParamsTime(params)
setSearchTime([params.StartDate, params.EndDate]) setSearchTime([params.StartDate, params.EndDate])
let filterList: any = sortTreeData(data.data, sortstr.toString())
console.log('filterList', filterList);
setReqDetailList(data.data); setReqDetailList(data.data);
setPrintOut(undefined); setPrintOut(undefined);
const list = data.data const list = data.data
@ -805,7 +817,6 @@ const RevenueSummaryTable: React.FC<{ currentUser?: CurrentUser }> = (props) =>
isOneService = true isOneService = true
} }
let result: any = [] let result: any = []
if (list && list.length > 0) { if (list && list.length > 0) {
list.forEach((item: any, index: number) => { list.forEach((item: any, index: number) => {
@ -869,21 +880,30 @@ const RevenueSummaryTable: React.FC<{ currentUser?: CurrentUser }> = (props) =>
} }
} }
// if (list && list.length>0){ let fieldData: any = [
// list.forEach((item: any)=>{ 'TotalRevenue.Revenue_Amount',
// if (item.children && item.children.length>0){ 'TotalRevenue.MobilePay_Amount',
// // item.SPRegionType_Name = item.Serverpart_Name 'TotalRevenue.CashPay_Amount',
// // item.Serverpart_Name = '' 'TotalRevenue.Mobile_Correct',
// 'TotalRevenue.Cash_Correct',
// item.children.forEach((subItem: any)=>{ 'RegionARevenue.Revenue_Amount',
// subItem.SPRegionType_Name = subItem.Serverpart_Name 'RegionARevenue.MobilePay_Amount',
// subItem.Serverpart_Name = '' 'RegionARevenue.CashPay_Amount',
// }) 'RegionARevenue.Mobile_Correct',
// } 'RegionARevenue.Cash_Correct',
// }) 'RegionBRevenue.Revenue_Amount',
// } 'RegionBRevenue.MobilePay_Amount',
'RegionBRevenue.CashPay_Amount',
'RegionBRevenue.Mobile_Correct',
'RegionBRevenue.Cash_Correct',
]
let enumList: any = ['ShopTrade']
setReqDetailList(result); // 处理一下导出数据
let newPrintData: any = formatTreeData(result, fieldData, enumList, SHOPTRADEObj, [])
console.log('newPrintDatanewPrintDatanewPrintData', newPrintData);
setReqDetailList(newPrintData);
if (result) { if (result) {
return { data: result, success: true }; return { data: result, success: true };
} }
@ -926,15 +946,15 @@ const RevenueSummaryTable: React.FC<{ currentUser?: CurrentUser }> = (props) =>
headerTitle={<PageTitleBox props={props} />} headerTitle={<PageTitleBox props={props} />}
toolbar={{ toolbar={{
actions: [ actions: [
<span style={{ visibility: 'hidden' }}> // <span style={{ visibility: 'hidden' }}>
<ReactHTMLTableToExcel // <ReactHTMLTableToExcel
buttonText={'导出excel'} // buttonText={'导出excel'}
ref={downloadBtnRef} // ref={downloadBtnRef}
table="table-to-xls-RevenueReport" // table="table-to-xls-RevenueReport"
filename={`门店经营报表(${moment(searchTime[0] || '').format('YYYY/MM/DD')}-${moment(searchTime[1] || '').format('YYYY/MM/DD')}`} // filename={`门店经营报表(${moment(searchTime[0] || '').format('YYYY/MM/DD')}-${moment(searchTime[1] || '').format('YYYY/MM/DD')}`}
sheet="sheet1" // sheet="sheet1"
/> // />
</span>, // </span>,
<ReactToPrint <ReactToPrint
trigger={() => ( trigger={() => (
<Button key="printout" type="default" onClick={() => { <Button key="printout" type="default" onClick={() => {
@ -962,16 +982,29 @@ const RevenueSummaryTable: React.FC<{ currentUser?: CurrentUser }> = (props) =>
type="primary" type="primary"
onClick={async (e) => { onClick={async (e) => {
if (reqDetailList && reqDetailList.length > 0) { if (reqDetailList && reqDetailList.length > 0) {
setShowLoading(true) // 尝试一下 导出新方法
setTimeout(() => { exportXlsxFromProColumnsExcelJS(columns,
setShowExportTable(true) reqDetailList,
setTimeout(() => { `营收汇总报表${searchParamsTime?.StartDate}-${searchParamsTime?.EndDate}`,
exportTable(e, true) {
}, 100) // topTitle: `营收汇总报表`, // 顶部大标题
}, 100) }
)
} else { } else {
message.error('暂无数据可导出!') message.error('暂无数据可导出!')
} }
// if (reqDetailList && reqDetailList.length > 0) {
// setShowLoading(true)
// setTimeout(() => {
// setShowExportTable(true)
// setTimeout(() => {
// exportTable(e, true)
// }, 100)
// }, 100)
// } else {
// message.error('暂无数据可导出!')
// }
}} }}
> >
excel excel

View File

@ -15,8 +15,9 @@ import LeftSelectTree from "@/pages/reports/settlementAccount/component/leftSele
import moment from 'moment' import moment from 'moment'
import session from "@/utils/session"; import session from "@/utils/session";
import { handleCorrectShopCigarette, handleGetCigaretteReport } from "../../Finance/service"; import { handleCorrectShopCigarette, handleGetCigaretteReport } from "../../Finance/service";
import { handleGetSumRow } from "@/utils/format"; import { formatTreeData, handleGetSumRow } from "@/utils/format";
import PageTitleBox from "@/components/PageTitleBox"; import PageTitleBox from "@/components/PageTitleBox";
import { exportXlsxFromProColumnsExcelJS } from "@/utils/exportExcelFun";
const cigaretteReport: React.FC<{ currentUser: CurrentUser }> = (props) => { const cigaretteReport: React.FC<{ currentUser: CurrentUser }> = (props) => {
@ -418,22 +419,47 @@ const cigaretteReport: React.FC<{ currentUser: CurrentUser }> = (props) => {
res.push(item) res.push(item)
}) })
let result: any = handleGetSumRow(res, ['sumRevenue_Amount', 'sumCigarette_Amount', 'sumDifferent_Price_More', 'sumDifferent_Price_Less', 'sumCashPay_Amount', 'sumMobilePay_Amount', 'ARevenue_Amount', 'ACigarette_Amount', 'ADifferent_Price_More', 'ADifferent_Price_Less', 'ACashPay_Amount', 'AMobilePay_Amount', 'BRevenue_Amount', 'BCigarette_Amount', 'BDifferent_Price_More', 'BDifferent_Price_Less', 'BCashPay_Amount', 'BMobilePay_Amount'], 'Statistics_Date') let result: any = handleGetSumRow(res, ['sumRevenue_Amount', 'sumCigarette_Amount', 'sumDifferent_Price_More', 'sumDifferent_Price_Less', 'sumCashPay_Amount', 'sumMobilePay_Amount', 'ARevenue_Amount', 'ACigarette_Amount', 'ADifferent_Price_More', 'ADifferent_Price_Less', 'ACashPay_Amount', 'AMobilePay_Amount', 'BRevenue_Amount', 'BCigarette_Amount', 'BDifferent_Price_More', 'BDifferent_Price_Less', 'BCashPay_Amount', 'BMobilePay_Amount'], 'Statistics_Date')
setReqDetailList(result)
let fieldData: any = [
"sumRevenue_Amount",
"sumCigarette_Amount",
"sumDifferent_Price_More",
"sumDifferent_Price_Less",
"sumCashPay_Amount",
"sumMobilePay_Amount",
"ARevenue_Amount",
"ACigarette_Amount",
"ADifferent_Price_More",
"ADifferent_Price_Less",
"ACashPay_Amount",
"AMobilePay_Amount",
"BRevenue_Amount",
"BCigarette_Amount",
"BDifferent_Price_More",
"BDifferent_Price_Less",
"BCashPay_Amount",
"BMobilePay_Amount",
]
let enumList: any = []
let newPrintData: any = formatTreeData(JSON.parse(JSON.stringify(result)), fieldData, enumList, [], [])
setReqDetailList(newPrintData)
return { data: result, success: true } return { data: result, success: true }
} }
setReqDetailList([])
return { data: [], success: true } return { data: [], success: true }
}} }}
toolbar={{ toolbar={{
actions: [ actions: [
<span style={{ visibility: 'hidden' }}> // <span style={{ visibility: 'hidden' }}>
<ReactHTMLTableToExcel // <ReactHTMLTableToExcel
buttonText={'导出excel'} // buttonText={'导出excel'}
ref={downloadBtnRef} // ref={downloadBtnRef}
table="table-to-xls-cigaretteReport" // table="table-to-xls-cigaretteReport"
filename={`香烟报表${searchParams?.StartDate}-${searchParams?.EndDate}`} // filename={`香烟报表${searchParams?.StartDate}-${searchParams?.EndDate}`}
sheet="sheet1" // sheet="sheet1"
/> // />
</span>, // </span>,
<Button type="primary" loading={btnLoading} onClick={async (e) => { <Button type="primary" loading={btnLoading} onClick={async (e) => {
if (!searchParams?.ServerpartIds) { if (!searchParams?.ServerpartIds) {
message.error('请选择服务区!') message.error('请选择服务区!')
@ -468,17 +494,31 @@ const cigaretteReport: React.FC<{ currentUser: CurrentUser }> = (props) => {
key="new" key="new"
type="primary" type="primary"
onClick={(e) => { onClick={(e) => {
if (reqDetailList && reqDetailList.length > 0) { if (reqDetailList && reqDetailList.length > 0) {
setShowLoading(true) // 尝试一下 导出新方法
setTimeout(() => { exportXlsxFromProColumnsExcelJS(columns,
setShowExportTable(true) reqDetailList,
setTimeout(() => { `香烟营收报表${searchParams?.StartDate}-${searchParams?.EndDate}`,
exportTable(e) // {
}, 100) // topTitle: `单品销售排行统计`, // 顶部大标题
}, 100) // }
)
} else { } else {
message.error('暂无数据可导出!') message.error('暂无数据可导出!')
} }
// if (reqDetailList && reqDetailList.length > 0) {
// setShowLoading(true)
// setTimeout(() => {
// setShowExportTable(true)
// setTimeout(() => {
// exportTable(e)
// }, 100)
// }, 100)
// } else {
// message.error('暂无数据可导出!')
// }
}} }}
> >
excel excel

View File

@ -19,6 +19,8 @@ import numeral from "numeral";
import { contractType } from "@/pages/contract/emun"; import { contractType } from "@/pages/contract/emun";
import { handleGetShopShortNamesGet } from "@/pages/reports/BusinessAnalysis/transactionAnalysis/service"; import { handleGetShopShortNamesGet } from "@/pages/reports/BusinessAnalysis/transactionAnalysis/service";
import PageTitleBox from "@/components/PageTitleBox"; import PageTitleBox from "@/components/PageTitleBox";
import { exportXlsxFromProColumnsExcelJS } from "@/utils/exportExcelFun";
import { formatTreeData } from "@/utils/format";
const personSellReport: React.FC<{ currentUser: CurrentUser }> = (props) => { const personSellReport: React.FC<{ currentUser: CurrentUser }> = (props) => {
@ -49,6 +51,8 @@ const personSellReport: React.FC<{ currentUser: CurrentUser }> = (props) => {
const [showExportTable, setShowExportTable] = useState<boolean>(false) const [showExportTable, setShowExportTable] = useState<boolean>(false)
// 自营业态的选择列表 // 自营业态的选择列表
const [shopNamesList, setShopNamesList] = useState<any>() const [shopNamesList, setShopNamesList] = useState<any>()
// 表格数据
const [tableData, setTableData] = useState<any>()
// 自营业态的选择的列表方法 // 自营业态的选择的列表方法
const handleGetShopNamesList = async (id: any) => { const handleGetShopNamesList = async (id: any) => {
const req: any = { const req: any = {
@ -361,10 +365,10 @@ const personSellReport: React.FC<{ currentUser: CurrentUser }> = (props) => {
formRef={formRef} formRef={formRef}
columns={columns} columns={columns}
bordered bordered
scroll={{ x: '100%', y: 'calc(100vh - 520px)' }} scroll={{ x: '100%', y: 'calc(100vh - 560px)' }}
// pagination={false} // pagination={false}
headerTitle={<PageTitleBox props={props} />} headerTitle={<PageTitleBox props={props} />}
search={{ span: 8 }} search={{ span: 8, defaultCollapsed: false }}
request={async (params) => { request={async (params) => {
if (!selectedId) { if (!selectedId) {
return return
@ -392,37 +396,69 @@ const personSellReport: React.FC<{ currentUser: CurrentUser }> = (props) => {
SERVERPART_NAME: '合计' SERVERPART_NAME: '合计'
}) })
console.log('list', list) console.log('list', list)
setReqDetailList(list)
let fieldData: any = [
"TICKETCOUNT",
"TOTALCOUNT",
"TOTALOFFAMOUNT",
"RealActualCashpay",
"TOTALSELLAMOUNT",
"CASHPAY",
"CASH",
"DIFFERENT_PRICE",
"MobilyPay",
]
let enumList: any = []
let newPrintData: any = formatTreeData(JSON.parse(JSON.stringify(list)), fieldData, enumList, [], [])
setReqDetailList(newPrintData)
setTableData(list)
return { data: list, success: true } return { data: list, success: true }
} }
setReqDetailList([])
setTableData([])
return { data: [], success: true } return { data: [], success: true }
}} }}
toolbar={{ toolbar={{
actions: [ actions: [
<span style={{ visibility: 'hidden' }}> // <span style={{ visibility: 'hidden' }}>
<ReactHTMLTableToExcel // <ReactHTMLTableToExcel
buttonText={'导出excel'} // buttonText={'导出excel'}
ref={downloadBtnRef} // ref={downloadBtnRef}
table="table-to-xls-personSellReport" // table="table-to-xls-personSellReport"
filename={`服务区收银员报表${searchParams?.SELL_ENDDATE_Start}-${searchParams?.SELL_ENDDATE_End}`} // filename={`服务区收银员报表${searchParams?.SELL_ENDDATE_Start}-${searchParams?.SELL_ENDDATE_End}`}
sheet="sheet1" // sheet="sheet1"
/> // />
</span>, // </span>,
<Button <Button
key="new" key="new"
type="primary" type="primary"
onClick={(e) => { onClick={(e) => {
if (reqDetailList && reqDetailList.length > 0) { if (reqDetailList && reqDetailList.length > 0) {
setShowLoading(true) // 尝试一下 导出新方法
setTimeout(() => { exportXlsxFromProColumnsExcelJS(columns,
setShowExportTable(true) reqDetailList,
setTimeout(() => { `服务区收银员报表${searchParams?.SELL_ENDDATE_Start}-${searchParams?.SELL_ENDDATE_End}`,
exportTable(e) // {
}, 100) // topTitle: `单品销售排行统计`, // 顶部大标题
}, 100) // }
)
} else { } else {
message.error('暂无数据可导出!') message.error('暂无数据可导出!')
} }
// if (reqDetailList && reqDetailList.length > 0) {
// setShowLoading(true)
// setTimeout(() => {
// setShowExportTable(true)
// setTimeout(() => {
// exportTable(e)
// }, 100)
// }, 100)
// } else {
// message.error('暂无数据可导出!')
// }
}} }}
> >
excel excel
@ -430,7 +466,7 @@ const personSellReport: React.FC<{ currentUser: CurrentUser }> = (props) => {
] ]
}} }}
tableExtraRender={() => { tableExtraRender={() => {
if (reqDetailList && reqDetailList.length > 0) { if (tableData && tableData.length > 0) {
let TICKETCOUNTSum: number = 0 let TICKETCOUNTSum: number = 0
let TOTALCOUNTSum: number = 0 let TOTALCOUNTSum: number = 0
let TOTALOFFAMOUNTSum: number = 0 let TOTALOFFAMOUNTSum: number = 0
@ -441,7 +477,7 @@ const personSellReport: React.FC<{ currentUser: CurrentUser }> = (props) => {
let DIFFERENT_PRICESum: number = 0 let DIFFERENT_PRICESum: number = 0
let MobilyPaySum: number = 0 let MobilyPaySum: number = 0
reqDetailList.forEach((item: any) => { tableData.forEach((item: any) => {
TICKETCOUNTSum += item.TICKETCOUNT TICKETCOUNTSum += item.TICKETCOUNT
TOTALCOUNTSum += item.TOTALCOUNT TOTALCOUNTSum += item.TOTALCOUNT
TOTALOFFAMOUNTSum += item.TOTALOFFAMOUNT TOTALOFFAMOUNTSum += item.TOTALOFFAMOUNT

View File

@ -28,6 +28,7 @@ import AccountChildren from '../../Finance/components/accountChildren';
import { handleGetSumRow } from '@/utils/format'; import { handleGetSumRow } from '@/utils/format';
import FlowDrawerSC from '@/pages/merchantManagement/mobilePayment/bankArrival/components/flowDrawerSC'; import FlowDrawerSC from '@/pages/merchantManagement/mobilePayment/bankArrival/components/flowDrawerSC';
import PageTitleBox from '@/components/PageTitleBox'; import PageTitleBox from '@/components/PageTitleBox';
import { exportXlsxFromProColumnsExcelJS } from '@/utils/exportExcelFun';
const { Text } = Typography; const { Text } = Typography;
@ -957,28 +958,40 @@ const revenueDistributionReport: React.FC<{ currentUser?: CurrentUser }> = (prop
}} }}
toolbar={{ toolbar={{
actions: [ actions: [
<span style={{ visibility: 'hidden' }}> // <span style={{ visibility: 'hidden' }}>
<ReactHTMLTableToExcel // <ReactHTMLTableToExcel
buttonText={'导出excel'} // buttonText={'导出excel'}
ref={downloadBtnRef} // ref={downloadBtnRef}
table="table-to-xls-revenueDistributionReport" // table="table-to-xls-revenueDistributionReport"
filename={`合作商户资金到账汇总表${searchDate && searchDate.length > 0 ? `${moment(searchDate[0]).format('YYYY-MM-DD')}-${moment(searchDate[1]).format('YYYY-MM-DD')}` : ''}`} // filename={`合作商户资金到账汇总表${searchDate && searchDate.length > 0 ? `${moment(searchDate[0]).format('YYYY-MM-DD')}-${moment(searchDate[1]).format('YYYY-MM-DD')}` : ''}`}
sheet="sheet1" // sheet="sheet1"
/> // />
</span>, // </span>,
<Typography.Text type="secondary"></Typography.Text>, <Typography.Text type="secondary"></Typography.Text>,
<Button <Button
key="new" key="new"
type="primary" type="primary"
onClick={(e) => { onClick={(e) => {
// if (reqDetailList && reqDetailList.length > 0) {
// setShowLoading(true)
// setTimeout(() => {
// setShowExportTable(true)
// setTimeout(() => {
// exportTable(e)
// }, 100)
// }, 100)
// } else {
// message.error('暂无数据可导出!')
// }
if (reqDetailList && reqDetailList.length > 0) { if (reqDetailList && reqDetailList.length > 0) {
setShowLoading(true) // 尝试一下 导出新方法
setTimeout(() => { exportXlsxFromProColumnsExcelJS(columns,
setShowExportTable(true) reqDetailList,
setTimeout(() => { `合作商户资金到账汇总表${searchDate && searchDate.length > 0 ? `${moment(searchDate[0]).format('YYYY-MM-DD')}-${moment(searchDate[1]).format('YYYY-MM-DD')}` : ''}`,
exportTable(e) // {
}, 100) // topTitle: `单品销售排行统计`, // 顶部大标题
}, 100) // }
)
} else { } else {
message.error('暂无数据可导出!') message.error('暂无数据可导出!')
} }

View File

@ -32,6 +32,8 @@ import './salesFlow.less'
import FlowDetail from "@/pages/merchantManagement/reports/SalesFlow/components/FlowDetail"; import FlowDetail from "@/pages/merchantManagement/reports/SalesFlow/components/FlowDetail";
import SubMenu from "antd/lib/menu/SubMenu"; import SubMenu from "antd/lib/menu/SubMenu";
import PageTitleBox from '@/components/PageTitleBox'; import PageTitleBox from '@/components/PageTitleBox';
import { exportXlsxFromProColumnsExcelJS } from '@/utils/exportExcelFun';
import { formatTreeData } from '@/utils/format';
const { Text } = Typography; const { Text } = Typography;
@ -75,7 +77,7 @@ const saleFlow: React.FC<{ currentUser: CurrentUser | undefined }> = (props) =>
const [showExportTable, setShowExportTable] = useState<boolean>(false) const [showExportTable, setShowExportTable] = useState<boolean>(false)
const columns: ProColumns<YSSELLMASTERModel>[] = [ const columns: any = [
{ {
dataIndex: 'index', dataIndex: 'index',
title: '序号', title: '序号',
@ -317,11 +319,21 @@ const saleFlow: React.FC<{ currentUser: CurrentUser | undefined }> = (props) =>
console.log('data1', data); console.log('data1', data);
if (data.List && data.List.length > 0) { if (data.List && data.List.length > 0) {
const list: any = JSON.parse(JSON.stringify(data.List)) const list: any = JSON.parse(JSON.stringify(data.List))
setReqDetailList(list);
let fieldData: any = [
"SELLMASTER_COUNT",
"SELLMASTER_AMOUNT",
"SELLMASTER_OFFPRICE"
]
let enumList: any = []
let newPrintData: any = formatTreeData(JSON.parse(JSON.stringify(list)), fieldData, enumList, [], [])
setReqDetailList(newPrintData);
console.log('data.otherData', data.otherData) console.log('data.otherData', data.otherData)
setOtherData(data.OtherData) setOtherData(data.OtherData)
return { data: list, success: true } return { data: list, success: true }
} }
setReqDetailList([]);
return { data: [], success: true } return { data: [], success: true }
} }
@ -331,31 +343,44 @@ const saleFlow: React.FC<{ currentUser: CurrentUser | undefined }> = (props) =>
columns={columns} columns={columns}
toolbar={{ toolbar={{
actions: [ actions: [
<span style={{ visibility: 'hidden' }}> // <span style={{ visibility: 'hidden' }}>
<ReactHTMLTableToExcel // <ReactHTMLTableToExcel
buttonText={'导出excel'} // buttonText={'导出excel'}
ref={downloadBtnRef} // ref={downloadBtnRef}
table="table-to-xls-saleRankReport" // table="table-to-xls-saleRankReport"
filename={`销售流水统计${searchParams?.SELLMASTER_DATE}`} // filename={`销售流水统计${searchParams?.SELLMASTER_DATE}`}
sheet="sheet1" // sheet="sheet1"
/> // />
</span>, // </span>,
<Button <Button
key="new" key="new"
type="primary" type="primary"
onClick={async (e) => { onClick={async (e) => {
// if (reqDetailList && reqDetailList.length > 0) {
// setShowLoading(true)
// setTimeout(() => {
// setShowExportTable(true)
// setTimeout(() => {
// exportTable(e)
// }, 100)
// }, 100)
// } else {
// message.error('暂无数据可导出!')
// }
if (reqDetailList && reqDetailList.length > 0) { if (reqDetailList && reqDetailList.length > 0) {
setShowLoading(true) // 尝试一下 导出新方法
setTimeout(() => { exportXlsxFromProColumnsExcelJS(columns,
setShowExportTable(true) reqDetailList,
setTimeout(() => { `销售流水查询${searchParams?.SELLMASTER_DATE}`,
exportTable(e) // {
}, 100) // topTitle: `单品销售排行统计`, // 顶部大标题
}, 100) // }
)
} else { } else {
message.error('暂无数据可导出!') message.error('暂无数据可导出!')
} }
// const success = await exportExcel( // const success = await exportExcel(
// columns.slice(2), // columns.slice(2),
// reqDetailList || [], // reqDetailList || [],

View File

@ -23,6 +23,7 @@ import ProDescriptions from "@ant-design/pro-descriptions";
import numeral from "numeral"; import numeral from "numeral";
import PageTitleBox from "@/components/PageTitleBox"; import PageTitleBox from "@/components/PageTitleBox";
import { exportXlsxFromProColumnsExcelJS } from "@/utils/exportExcelFun"; import { exportXlsxFromProColumnsExcelJS } from "@/utils/exportExcelFun";
import { formatTreeData } from "@/utils/format";
const saleHisReport: React.FC<{ currentUser: CurrentUser }> = (props) => { const saleHisReport: React.FC<{ currentUser: CurrentUser }> = (props) => {
@ -54,6 +55,8 @@ const saleHisReport: React.FC<{ currentUser: CurrentUser }> = (props) => {
const [showExportTable, setShowExportTable] = useState<boolean>(false) const [showExportTable, setShowExportTable] = useState<boolean>(false)
const businessTypeObj = session.get("BUSINESSTYPEObj") const businessTypeObj = session.get("BUSINESSTYPEObj")
const [printIndex, setPrintIndex] = useState<number>(new Date().getTime()) const [printIndex, setPrintIndex] = useState<number>(new Date().getTime())
// 表格数据
const [tableData, setTableData] = useState<any>()
// 商品业态列表 // 商品业态列表
const [commodityFormatsObj, setCommodityFormatsObj] = useState<any>() const [commodityFormatsObj, setCommodityFormatsObj] = useState<any>()
@ -329,8 +332,8 @@ const saleHisReport: React.FC<{ currentUser: CurrentUser }> = (props) => {
columns={columns} columns={columns}
bordered bordered
headerTitle={<PageTitleBox props={props} />} headerTitle={<PageTitleBox props={props} />}
scroll={{ y: 'calc(100vh - 540px)' }} scroll={{ y: 'calc(100vh - 570px)' }}
search={{ span: 6 }} search={{ span: 6, defaultCollapsed: false }}
pagination={{ pageSize: 100 }} pagination={{ pageSize: 100 }}
request={async (params) => { request={async (params) => {
@ -362,20 +365,32 @@ const saleHisReport: React.FC<{ currentUser: CurrentUser }> = (props) => {
}) })
list = data list = data
} }
setReqDetailList(list)
let fieldData: any = [
"Commodity_RetailPrice",
"Total_Count",
"Total_OffAmount",
"Total_SellAmount",
"Commodity_PurchasePrice",
]
let enumList: any = []
let newPrintData: any = formatTreeData(JSON.parse(JSON.stringify(list)), fieldData, enumList, [], ["Total_SellAmountRate"])
setReqDetailList(newPrintData)
setTableData(list)
return { data: list, success: true } return { data: list, success: true }
}} }}
toolbar={{ toolbar={{
actions: [ actions: [
<span style={{ visibility: 'hidden' }}> // <span style={{ visibility: 'hidden' }}>
<ReactHTMLTableToExcel // <ReactHTMLTableToExcel
buttonText={'导出excel'} // buttonText={'导出excel'}
ref={downloadBtnRef} // ref={downloadBtnRef}
table="table-to-xls-saleHisReport" // table="table-to-xls-saleHisReport"
filename={`单品统计报表${searchParams?.StartTime}-${searchParams?.EndTime}`} // filename={`单品统计报表${searchParams?.StartTime}-${searchParams?.EndTime}`}
sheet="sheet1" // sheet="sheet1"
/> // />
</span>, // </span>,
<Button <Button
key="new" key="new"
type="primary" type="primary"
@ -411,12 +426,12 @@ const saleHisReport: React.FC<{ currentUser: CurrentUser }> = (props) => {
] ]
}} }}
tableExtraRender={() => { tableExtraRender={() => {
if (reqDetailList && reqDetailList.length > 0) { if (tableData && tableData.length > 0) {
let Total_CountSum: number = 0 let Total_CountSum: number = 0
let Total_OffAmountSum: number = 0 let Total_OffAmountSum: number = 0
let Total_SellAmountSum: number = 0 let Total_SellAmountSum: number = 0
reqDetailList.forEach((item: any) => { tableData.forEach((item: any) => {
Total_CountSum += item.Total_Count Total_CountSum += item.Total_Count
Total_OffAmountSum += item.Total_OffAmount Total_OffAmountSum += item.Total_OffAmount
Total_SellAmountSum += item.Total_SellAmount Total_SellAmountSum += item.Total_SellAmount

View File

@ -21,6 +21,7 @@ import { contractType } from "@/pages/contract/emun";
import { handleGetShopShortNamesGet } from "@/pages/reports/BusinessAnalysis/transactionAnalysis/service"; import { handleGetShopShortNamesGet } from "@/pages/reports/BusinessAnalysis/transactionAnalysis/service";
import PageTitleBox from "@/components/PageTitleBox"; import PageTitleBox from "@/components/PageTitleBox";
import { exportXlsxFromProColumnsExcelJS } from "@/utils/exportExcelFun"; import { exportXlsxFromProColumnsExcelJS } from "@/utils/exportExcelFun";
import { formatTreeData } from "@/utils/format";
const saleRankReport: React.FC<{ currentUser: CurrentUser }> = (props) => { const saleRankReport: React.FC<{ currentUser: CurrentUser }> = (props) => {
@ -56,6 +57,9 @@ const saleRankReport: React.FC<{ currentUser: CurrentUser }> = (props) => {
const [commodityTypeList, setCommodityTypeList] = useState<any>() const [commodityTypeList, setCommodityTypeList] = useState<any>()
// 商品类别的选择值 // 商品类别的选择值
const [commodityTypeValue, setCommodityTypeValue] = useState<any>() const [commodityTypeValue, setCommodityTypeValue] = useState<any>()
// 表格数据
const [tableData, setTableData] = useState<any>()
const { loading: nestLoading, data: nestList } = useRequest(async () => { const { loading: nestLoading, data: nestList } = useRequest(async () => {
const req = { const req = {
PROVINCE_CODE: currentUser?.ProvinceCode, PROVINCE_CODE: currentUser?.ProvinceCode,
@ -355,8 +359,8 @@ const saleRankReport: React.FC<{ currentUser: CurrentUser }> = (props) => {
columns={columns} columns={columns}
bordered bordered
headerTitle={<PageTitleBox props={props} />} headerTitle={<PageTitleBox props={props} />}
search={{ span: 6 }} search={{ span: 6, defaultCollapsed: false }}
scroll={{ x: "100%", y: 'calc(100vh - 420px)' }} scroll={{ x: "100%", y: 'calc(100vh - 480px)' }}
pagination={false} pagination={false}
request={async (params) => { request={async (params) => {
if (!selectShopId) { if (!selectShopId) {
@ -373,22 +377,31 @@ const saleRankReport: React.FC<{ currentUser: CurrentUser }> = (props) => {
const data = await handleGetSaleRank(req) const data = await handleGetSaleRank(req)
console.log('data', data) console.log('data', data)
if (data && data.length > 0) { if (data && data.length > 0) {
setReqDetailList(data) let fieldData: any = [
"Total_Count",
"Total_SellAmount",
]
let enumList: any = []
let newPrintData: any = formatTreeData(JSON.parse(JSON.stringify(data)), fieldData, enumList, [], [])
setReqDetailList(newPrintData)
setTableData(data)
return { data, success: true } return { data, success: true }
} }
setReqDetailList([])
setTableData([])
return { data: [], success: true } return { data: [], success: true }
}} }}
toolbar={{ toolbar={{
actions: [ actions: [
<span style={{ visibility: 'hidden' }}> // <span style={{ visibility: 'hidden' }}>
<ReactHTMLTableToExcel // <ReactHTMLTableToExcel
buttonText={'导出excel'} // buttonText={'导出excel'}
ref={downloadBtnRef} // ref={downloadBtnRef}
table="table-to-xls-saleRankReport" // table="table-to-xls-saleRankReport"
filename={`单品销售排行统计${searchParams?.startDate}-${searchParams?.endDate}`} // filename={`单品销售排行统计${searchParams?.startDate}-${searchParams?.endDate}`}
sheet="sheet1" // sheet="sheet1"
/> // />
</span>, // </span>,
<Button <Button
key="new" key="new"
type="primary" type="primary"
@ -397,10 +410,10 @@ const saleRankReport: React.FC<{ currentUser: CurrentUser }> = (props) => {
// 尝试一下 导出新方法 // 尝试一下 导出新方法
exportXlsxFromProColumnsExcelJS(columns, exportXlsxFromProColumnsExcelJS(columns,
reqDetailList, reqDetailList,
`单品销售排行统计${searchParams?.startDate}-${searchParams?.endDate}`, `商品销售排名${searchParams?.startDate}-${searchParams?.endDate}`,
{ // {
topTitle: `单品销售排行统计`, // 顶部大标题 // topTitle: `单品销售排行统计`, // 顶部大标题
} // }
) )
} else { } else {
message.error('暂无数据可导出!') message.error('暂无数据可导出!')
@ -425,11 +438,11 @@ const saleRankReport: React.FC<{ currentUser: CurrentUser }> = (props) => {
] ]
}} }}
tableExtraRender={() => { tableExtraRender={() => {
if (reqDetailList && reqDetailList.length > 0) { if (tableData && tableData.length > 0) {
let Total_CountSum: number = 0 let Total_CountSum: number = 0
let Total_SellAmountSum: number = 0 let Total_SellAmountSum: number = 0
reqDetailList.forEach((item: any) => { tableData.forEach((item: any) => {
Total_CountSum += item.Total_Count Total_CountSum += item.Total_Count
Total_SellAmountSum += item.Total_SellAmount Total_SellAmountSum += item.Total_SellAmount
}) })

View File

@ -21,7 +21,8 @@ import ProTable from "@ant-design/pro-table";
import ReactHTMLTableToExcel from "react-html-table-to-excel"; import ReactHTMLTableToExcel from "react-html-table-to-excel";
import { import {
handleGetBusinessTrades, handleGetBusinessTrades,
handleGetCommoditySaleSummary handleGetCommoditySaleSummary,
handleGetDailyCommoditySaleList
} from "@/pages/reports/BusinessAnalysis/saleReport/service"; } from "@/pages/reports/BusinessAnalysis/saleReport/service";
import moment from "moment/moment"; import moment from "moment/moment";
import session from "@/utils/session"; import session from "@/utils/session";
@ -31,6 +32,7 @@ import { handleGetShopShortNamesGet } from "@/pages/reports/BusinessAnalysis/tra
import PageTitleBox from "@/components/PageTitleBox"; import PageTitleBox from "@/components/PageTitleBox";
import center from "@/pages/account/center"; import center from "@/pages/account/center";
import { exportXlsxFromProColumnsExcelJS } from "@/utils/exportExcelFun"; import { exportXlsxFromProColumnsExcelJS } from "@/utils/exportExcelFun";
import { formatTreeData, sortTreeData } from "@/utils/format";
const saleReport: React.FC<{ currentUser: CurrentUser }> = (props) => { const saleReport: React.FC<{ currentUser: CurrentUser }> = (props) => {
@ -90,8 +92,19 @@ const saleReport: React.FC<{ currentUser: CurrentUser }> = (props) => {
setShopNamesList(obj) setShopNamesList(obj)
} }
} }
// 表格数据
const [tableData, setTableData] = useState<any>()
const columns: any = [ const columns: any = [
{
title: "数据类型",
dataIndex: "statisticalType",
valueType: 'select',
hideInTable: true,
fieldProps: {
options: [{ label: "按账期统计", value: 1 }, { label: "按自然日统计", value: 2 }]
},
initialValue: 1
},
{ {
title: '统计时间', title: '统计时间',
dataIndex: 'search_date', dataIndex: 'search_date',
@ -189,6 +202,15 @@ const saleReport: React.FC<{ currentUser: CurrentUser }> = (props) => {
ellipsis: true, ellipsis: true,
align: 'center' align: 'center'
}, },
{
width: 120,
title: <div style={{ textAlign: 'center' }}></div>,
dataIndex: 'Commodity_Code',
hideInSearch: true,
hideInTable: currentUser?.ProvinceCode !== '734100',
ellipsis: true,
align: 'center'
},
{ {
dataIndex: 'Commodity_Name', dataIndex: 'Commodity_Name',
title: <div style={{ textAlign: 'center' }}></div>, title: <div style={{ textAlign: 'center' }}></div>,
@ -385,16 +407,50 @@ const saleReport: React.FC<{ currentUser: CurrentUser }> = (props) => {
handleCallLogs() handleCallLogs()
console.log('params', params) console.log('params', params)
setSearchParams(params) setSearchParams(params)
const req = {
...params, const sortstr = Object.keys(sorter).map(n => {
DataType: 1, const value = sorter[n]
ServerpartShopIds: selectedId, return value ? `${n} ${value.replace('end', '')}` : ''
SearchKeyName: "Commodity_Name,Commodity_Barcode", })
let data: any = []
console.log('sortstrsortstr', sortstr);
if (params?.statisticalType === 1) {
const req = {
...params,
DataType: 1,
ServerpartShopIds: selectedId,
SearchKeyName: "Commodity_Name,Commodity_Barcode",
}
console.log('reqreqreq', req);
data = await handleGetCommoditySaleSummary(req)
} else {
// 等有了新接口 换上去
const req = {
SearchKeyValue: params?.SearchKeyValue || "",
StartDate: params?.StartTime || "",
EndDate: params?.EndTime || "",
ServerpartShopId: selectedId,
SearchKeyName: "Commodity_Name,Commodity_Barcode",
SortStr: sortstr.toString()
}
console.log('reqreqreq', req);
data = await handleGetDailyCommoditySaleList(req)
} }
const data = await handleGetCommoditySaleSummary(req)
console.log('data', data) console.log('data', data)
if (data && data.length > 0) { if (data && data.length > 0) {
setReqDetailList(data) let newData: any = sortTreeData(JSON.parse(JSON.stringify(data)), sortstr.toString())
let fieldData: any = [
"Total_SellAmount",
"Commodity_RetailPrice",
"Total_OffAmount",
]
let enumList: any = []
let newPrintData: any = formatTreeData(newData, fieldData, enumList, [], ['Total_SellAmountRate'])
setReqDetailList(newPrintData)
setTableData(data)
return { data, success: true } return { data, success: true }
} }
return { data: [], success: true } return { data: [], success: true }
@ -446,12 +502,12 @@ const saleReport: React.FC<{ currentUser: CurrentUser }> = (props) => {
] ]
}} }}
tableExtraRender={() => { tableExtraRender={() => {
if (reqDetailList && reqDetailList.length > 0) { if (tableData && tableData.length > 0) {
let Total_CountSum: number = 0 let Total_CountSum: number = 0
let Total_OffAmountSum: number = 0 let Total_OffAmountSum: number = 0
let Total_SellAmountSum: number = 0 let Total_SellAmountSum: number = 0
reqDetailList.forEach((item: any) => { tableData.forEach((item: any) => {
Total_CountSum += item.Total_Count Total_CountSum += item.Total_Count
Total_OffAmountSum += item.Total_OffAmount Total_OffAmountSum += item.Total_OffAmount
Total_SellAmountSum += item.Total_SellAmount Total_SellAmountSum += item.Total_SellAmount
@ -460,7 +516,7 @@ const saleReport: React.FC<{ currentUser: CurrentUser }> = (props) => {
<ProDescriptions column={4} className="commity-sale-description" labelStyle={{ color: "#00000073" }}> <ProDescriptions column={4} className="commity-sale-description" labelStyle={{ color: "#00000073" }}>
<ProDescriptions.Item label="销售数量" contentStyle={{ color: 'orangered' }}>{Total_CountSum ? numeral(Total_CountSum).format('0,0.00') : '0'}</ProDescriptions.Item> <ProDescriptions.Item label="销售数量" contentStyle={{ color: 'orangered' }}>{Total_CountSum ? numeral(Total_CountSum).format('0,0.00') : '0'}</ProDescriptions.Item>
<ProDescriptions.Item label="优惠金额" valueType="money" contentStyle={{ color: 'orangered' }}>{Total_OffAmountSum || '0.00'}</ProDescriptions.Item> <ProDescriptions.Item label="优惠金额" valueType="money" contentStyle={{ color: 'orangered' }}>{Total_OffAmountSum || '0.00'}</ProDescriptions.Item>
<ProDescriptions.Item label="对客营收" valueType="money" contentStyle={{ color: 'orangered' }}>{Total_SellAmountSum}</ProDescriptions.Item> <ProDescriptions.Item label="对客营收" valueType="money" contentStyle={{ color: 'orangered' }}>{Total_SellAmountSum || '0.00'}</ProDescriptions.Item>
{/* <ProDescriptions.Item label="毛利率" contentStyle={{ color: 'orangered' }}></ProDescriptions.Item> */} {/* <ProDescriptions.Item label="毛利率" contentStyle={{ color: 'orangered' }}></ProDescriptions.Item> */}
</ProDescriptions> </ProDescriptions>
<ProDescriptions column={4} className="commity-sale-description" labelStyle={{ color: "#00000073" }}> <ProDescriptions column={4} className="commity-sale-description" labelStyle={{ color: "#00000073" }}>

View File

@ -1,26 +1,39 @@
import request from '@/utils/request'; import request from '@/utils/request';
import requestEncryption from '@/utils/requestEncryption';
// 获取销售同环比 // 获取销售同环比
export async function handleGetCommoditySaleSummary(params: any) { export async function handleGetCommoditySaleSummary(params: any) {
const data = await request('/Sales/GetCommoditySaleSummary', { const data = await request('/Sales/GetCommoditySaleSummary', {
method: 'GET', method: 'GET',
params params
}) })
if (data.Result_Code !== 100) { if (data.Result_Code !== 100) {
return { return {
data: [], data: [],
otherData: '', otherData: '',
current: 1, current: 1,
pageSize: 20, pageSize: 20,
total: 0, total: 0,
success: true, success: true,
}; };
} }
return data.Result_Data.List return data.Result_Data.List
} }
// 获取自然日单品销售数据
export async function handleGetDailyCommoditySaleList(params: any) {
const data = await requestEncryption('/Revenue/GetDailyCommoditySaleList', {
method: 'POST',
data: {
...params,
requestEncryption: true
}
})
return data.Result_Data.List
}
// 获取商品业态 // 获取商品业态
export async function handleGetBusinessTrades(params: any) { export async function handleGetBusinessTrades(params: any) {
const data = await request('/BaseInfo/GetBusinessTrades', { const data = await request('/BaseInfo/GetBusinessTrades', {

View File

@ -1,3 +1,6 @@
// 历史销售类别报表
import { connect } from "umi"; import { connect } from "umi";
import type { CurrentUser } from "umi"; import type { CurrentUser } from "umi";
import type { ConnectState } from "@/models/connect"; import type { ConnectState } from "@/models/connect";
@ -19,6 +22,8 @@ import { handleGetNestingCOMMODITYTYPETree } from "@/pages/reports/BusinessAnaly
import ProDescriptions from "@ant-design/pro-descriptions"; import ProDescriptions from "@ant-design/pro-descriptions";
import numeral from "numeral"; import numeral from "numeral";
import PageTitleBox from "@/components/PageTitleBox"; import PageTitleBox from "@/components/PageTitleBox";
import { exportXlsxFromProColumnsExcelJS } from "@/utils/exportExcelFun";
import { formatTreeData } from "@/utils/format";
const saleTypeHisReport: React.FC<{ currentUser: CurrentUser }> = (props) => { const saleTypeHisReport: React.FC<{ currentUser: CurrentUser }> = (props) => {
@ -67,6 +72,8 @@ const saleTypeHisReport: React.FC<{ currentUser: CurrentUser }> = (props) => {
setCommodityTypeList(data) setCommodityTypeList(data)
}) })
const [printIndex, setPrintIndex] = useState<number>(new Date().getTime()) const [printIndex, setPrintIndex] = useState<number>(new Date().getTime())
// 表格数据
const [tableData, setTableData] = useState<any>()
const columns: any = [ const columns: any = [
{ {
@ -331,35 +338,58 @@ const saleTypeHisReport: React.FC<{ currentUser: CurrentUser }> = (props) => {
}) })
list = data list = data
} }
setReqDetailList(list) let fieldData: any = [
"Total_Count",
"Total_OffAmount",
"Total_SellAmount",
]
let enumList: any = []
let newPrintData: any = formatTreeData(JSON.parse(JSON.stringify(list)), fieldData, enumList, [], ["Total_SellAmountRate"])
setReqDetailList(newPrintData)
setTableData(list)
return { data: list, success: true } return { data: list, success: true }
}} }}
toolbar={{ toolbar={{
actions: [ actions: [
<span style={{ visibility: 'hidden' }}> // <span style={{ visibility: 'hidden' }}>
<ReactHTMLTableToExcel // <ReactHTMLTableToExcel
buttonText={'导出excel'} // buttonText={'导出excel'}
ref={downloadBtnRef} // ref={downloadBtnRef}
table="table-to-xls-saleReport" // table="table-to-xls-saleReport"
filename={`类别统计报表${searchParams?.startDate}-${searchParams?.endDate}`} // filename={`类别统计报表${searchParams?.startDate}-${searchParams?.endDate}`}
sheet="sheet1" // sheet="sheet1"
/> // />
</span>, // </span>,
<Button <Button
key="new" key="new"
type="primary" type="primary"
onClick={(e) => { onClick={(e) => {
if (reqDetailList && reqDetailList.length > 0) { if (reqDetailList && reqDetailList.length > 0) {
setShowLoading(true) // 尝试一下 导出新方法
setTimeout(() => { exportXlsxFromProColumnsExcelJS(columns,
setShowExportTable(true) reqDetailList,
setTimeout(() => { `类别统计报表${searchParams?.startDate}-${searchParams?.endDate}`,
exportTable(e) // {
}, 100) // topTitle: `历史销售单品报表`, // 顶部大标题
}, 100) // }
)
} else { } else {
message.error('暂无数据可导出!') message.error('暂无数据可导出!')
} }
// if (reqDetailList && reqDetailList.length > 0) {
// setShowLoading(true)
// setTimeout(() => {
// setShowExportTable(true)
// setTimeout(() => {
// exportTable(e)
// }, 100)
// }, 100)
// } else {
// message.error('暂无数据可导出!')
// }
}} }}
> >
excel excel
@ -367,12 +397,12 @@ const saleTypeHisReport: React.FC<{ currentUser: CurrentUser }> = (props) => {
] ]
}} }}
tableExtraRender={() => { tableExtraRender={() => {
if (reqDetailList && reqDetailList.length > 0) { if (tableData && tableData.length > 0) {
let Total_CountSum: number = 0 let Total_CountSum: number = 0
let Total_OffAmountSum: number = 0 let Total_OffAmountSum: number = 0
let Total_SellAmountSum: number = 0 let Total_SellAmountSum: number = 0
reqDetailList.forEach((item: any) => { tableData.forEach((item: any) => {
Total_CountSum += item.Total_Count Total_CountSum += item.Total_Count
Total_OffAmountSum += item.Total_OffAmount Total_OffAmountSum += item.Total_OffAmount
Total_SellAmountSum += item.Total_SellAmount Total_SellAmountSum += item.Total_SellAmount

View File

@ -22,6 +22,8 @@ import { handleGetBusinessTrades } from "./service";
import ProDescriptions from "@ant-design/pro-descriptions"; import ProDescriptions from "@ant-design/pro-descriptions";
import numeral from "numeral"; import numeral from "numeral";
import PageTitleBox from "@/components/PageTitleBox"; import PageTitleBox from "@/components/PageTitleBox";
import { exportXlsxFromProColumnsExcelJS } from "@/utils/exportExcelFun";
import { formatTreeData } from "@/utils/format";
const saleReport: React.FC<{ currentUser: CurrentUser }> = (props) => { const saleReport: React.FC<{ currentUser: CurrentUser }> = (props) => {
@ -62,6 +64,8 @@ const saleReport: React.FC<{ currentUser: CurrentUser }> = (props) => {
// 商品业态列表 // 商品业态列表
const [commodityFormatsObj, setCommodityFormatsObj] = useState<any>() const [commodityFormatsObj, setCommodityFormatsObj] = useState<any>()
// 表格数据
const [tableData, setTableData] = useState<any>()
const { loading: nestLoading, data: nestList } = useRequest(async () => { const { loading: nestLoading, data: nestList } = useRequest(async () => {
@ -312,9 +316,9 @@ const saleReport: React.FC<{ currentUser: CurrentUser }> = (props) => {
columns={columns} columns={columns}
bordered bordered
headerTitle={<PageTitleBox props={props} />} headerTitle={<PageTitleBox props={props} />}
search={{ span: 6 }} search={{ span: 6, defaultCollapsed: false }}
pagination={false} pagination={false}
scroll={{ y: 'calc(100vh - 470px)' }} scroll={{ y: 'calc(100vh - 520px)' }}
request={async (params) => { request={async (params) => {
if (isFirst) { if (isFirst) {
setIsFirst(false) setIsFirst(false)
@ -341,35 +345,58 @@ const saleReport: React.FC<{ currentUser: CurrentUser }> = (props) => {
}) })
list = data list = data
} }
setReqDetailList(list)
let fieldData: any = [
"Total_Count",
"Total_OffAmount",
"Total_SellAmount",
]
let enumList: any = []
let newPrintData: any = formatTreeData(list, fieldData, enumList, [], ['Total_SellAmountRate'])
setReqDetailList(newPrintData)
setTableData(list)
return { data: list, success: true } return { data: list, success: true }
}} }}
toolbar={{ toolbar={{
actions: [ actions: [
<span style={{ visibility: 'hidden' }}> // <span style={{ visibility: 'hidden' }}>
<ReactHTMLTableToExcel // <ReactHTMLTableToExcel
buttonText={'导出excel'} // buttonText={'导出excel'}
ref={downloadBtnRef} // ref={downloadBtnRef}
table="table-to-xls-saleTypeReport" // table="table-to-xls-saleTypeReport"
filename={`类别统计报表${searchParams?.startDate}-${searchParams?.endDate}`} // filename={`类别统计报表${searchParams?.startDate}-${searchParams?.endDate}`}
sheet="sheet1" // sheet="sheet1"
/> // />
</span>, // </span>,
<Button <Button
key="new" key="new"
type="primary" type="primary"
onClick={(e) => { onClick={(e) => {
if (reqDetailList && reqDetailList.length > 0) { if (reqDetailList && reqDetailList.length > 0) {
setShowLoading(true) // 尝试一下 导出新方法
setTimeout(() => { exportXlsxFromProColumnsExcelJS(columns,
setShowExportTable(true) reqDetailList,
setTimeout(() => { `销售类别报表${searchParams?.startDate}-${searchParams?.endDate}`,
exportTable(e) {
}, 100)
}, 100) // topTitle: `营收汇总报表`, // 顶部大标题
}
)
} else { } else {
message.error('暂无数据可导出!') message.error('暂无数据可导出!')
} }
// if (reqDetailList && reqDetailList.length > 0) {
// setShowLoading(true)
// setTimeout(() => {
// setShowExportTable(true)
// setTimeout(() => {
// exportTable(e)
// }, 100)
// }, 100)
// } else {
// message.error('暂无数据可导出!')
// }
}} }}
> >
excel excel
@ -377,12 +404,12 @@ const saleReport: React.FC<{ currentUser: CurrentUser }> = (props) => {
] ]
}} }}
tableExtraRender={() => { tableExtraRender={() => {
if (reqDetailList && reqDetailList.length > 0) { if (tableData && tableData.length > 0) {
let Total_CountSum: number = 0 let Total_CountSum: number = 0
let Total_OffAmountSum: number = 0 let Total_OffAmountSum: number = 0
let Total_SellAmountSum: number = 0 let Total_SellAmountSum: number = 0
reqDetailList.forEach((item: any) => { tableData.forEach((item: any) => {
Total_CountSum += item.Total_Count Total_CountSum += item.Total_Count
Total_OffAmountSum += item.Total_OffAmount Total_OffAmountSum += item.Total_OffAmount
Total_SellAmountSum += item.Total_SellAmount Total_SellAmountSum += item.Total_SellAmount

View File

@ -11,6 +11,7 @@
import request from '@/utils/request'; import request from '@/utils/request';
import CryptoJs from 'crypto-js'; import CryptoJs from 'crypto-js';
import type { CurrentUser } from '@/models/user'; import type { CurrentUser } from '@/models/user';
import { validatePassword } from '@/utils/format';
export type LoginParamsType = { export type LoginParamsType = {
UserPassport: string; UserPassport: string;
@ -23,9 +24,14 @@ export type LoginResult = {
currentAuthority: string; currentAuthority: string;
status: string; status: string;
currentUser?: CurrentUser; currentUser?: CurrentUser;
passwordRes?: any
}; };
export async function accountLogin(params: LoginParamsType): Promise<LoginResult> { export async function accountLogin(params: LoginParamsType): Promise<LoginResult> {
let realParams: any = JSON.parse(JSON.stringify(params))
let passwordRes: any = validatePassword(realParams.UserPassWord)
params.UserPassWord = CryptoJs.MD5(params.UserPassWord + params.UserPassport).toString(); params.UserPassWord = CryptoJs.MD5(params.UserPassWord + params.UserPassport).toString();
const data = await request(`/Logging/UserLogin`, { const data = await request(`/Logging/UserLogin`, {
method: 'POST', method: 'POST',
@ -46,6 +52,7 @@ export async function accountLogin(params: LoginParamsType): Promise<LoginResult
currentAuthority: 'admin',// data.Result_Data.UserName, currentAuthority: 'admin',// data.Result_Data.UserName,
status: 'ok', status: 'ok',
currentUser: user, currentUser: user,
passwordRes: passwordRes
}; };
// const resp = await request('/api/login/account', { // const resp = await request('/api/login/account', {
// method: 'POST', // method: 'POST',
@ -53,7 +60,7 @@ export async function accountLogin(params: LoginParamsType): Promise<LoginResult
// }); // });
// return resp; // return resp;
} }
// export async function getFakeCaptcha(mobile: string) { // export async function getFakeCaptcha(mobile: string) {
// return request(`/api/login/captcha?mobile=${mobile}`); // return request(`/api/login/captcha?mobile=${mobile}`);
// } // }

View File

@ -763,4 +763,325 @@ export function convertTreeFieldToNumber(tree: any[], key: string): any[] {
} }
return newNode; return newNode;
}); });
}
// 登录密码的正则校验 判断是否符合规则
export function validatePassword(password: string) {
if (!password || password.length < 8) {
return false;
}
const hasDigit = /\d/.test(password);
const hasLower = /[a-z]/.test(password);
const hasUpper = /[A-Z]/.test(password);
const hasSpecial = /[!@#$%^&*(),.?":{}|<>_\-+=~`[\]\\;]/.test(password);
// 统计符合的种类
let count = 0;
if (hasDigit) count++;
if (hasLower || hasUpper) count++; // 大小写都算作字母
if (hasSpecial) count++;
return count >= 2;
}
/**
*
* @param data
* @param sortField : "字段名 排序方式" (: "Total_Count desc""TotalRevenue.Revenue_Amount asc")
* @param childrenKey key名称 'children'
* @returns
*/
export function sortTreeData(data: any[], sortField: string, childrenKey: string = 'children'): any[] {
if (!data || !Array.isArray(data) || data.length === 0 || !sortField) {
return data;
}
const parts = sortField.trim().split(/\s+/);
if (parts.length !== 2) {
console.warn('排序字段格式错误,应为: "字段名 排序方式",如: "Total_Count desc" 或 "TotalRevenue.Revenue_Amount asc"');
return data;
}
const [fieldPath, sortOrder] = parts;
const isDesc = sortOrder.toLowerCase() === 'desc';
/**
*
* @param obj
* @param path "TotalRevenue.Revenue_Amount"
* @returns
*/
function getNestedValue(obj: any, path: string): any {
if (!obj || typeof obj !== 'object') {
return null;
}
const keys = path.split('.');
let current = obj;
for (const key of keys) {
if (current === null || current === undefined) {
return null;
}
current = current[key];
}
return current;
}
function sortRecursive(nodes: any[]): any[] {
// 对当前层级进行排序
const sortedNodes = [...nodes].sort((a, b) => {
const aValue = getNestedValue(a, fieldPath);
const bValue = getNestedValue(b, fieldPath);
// 处理 null, undefined 的情况,将它们排到最后
if (aValue == null && bValue == null) return 0;
if (aValue == null) return 1;
if (bValue == null) return -1;
// 数值比较
if (typeof aValue === 'number' && typeof bValue === 'number') {
return isDesc ? bValue - aValue : aValue - bValue;
}
// 字符串比较(先尝试转换为数字)
const aNum = Number(aValue);
const bNum = Number(bValue);
if (!isNaN(aNum) && !isNaN(bNum)) {
return isDesc ? bNum - aNum : aNum - bNum;
}
// 字符串比较
const aStr = String(aValue);
const bStr = String(bValue);
if (isDesc) {
return bStr.localeCompare(aStr);
} else {
return aStr.localeCompare(bStr);
}
});
// 递归排序子节点
return sortedNodes.map(node => {
if (node[childrenKey] && Array.isArray(node[childrenKey]) && node[childrenKey].length > 0) {
return {
...node,
[childrenKey]: sortRecursive(node[childrenKey])
};
}
return node;
});
}
return sortRecursive(data);
}
/**
* -
* @param data
* @param formatFields ( "obj.fieldName")
* @param enumFields ()
* @param enumData enumFields
* @param childrenKey key名称 'children'
* @returns
*/
export function formatTreeData(
data: any[],
formatFields: string[] = [],
enumFields: string[] = [],
enumData: any[] = [],
percentFields: string[] = [],
childrenKey: string = 'children'
): any[] {
if (!data || !Array.isArray(data) || data.length === 0) {
return data;
}
/**
*
* @param obj
* @param path "obj.fieldName"
* @returns
*/
function getNestedValue(obj: any, path: string): any {
if (!obj || typeof obj !== 'object') {
return undefined;
}
const keys = path.split('.');
let current = obj;
for (const key of keys) {
if (current === null || current === undefined) {
return undefined;
}
current = current[key];
}
return current;
}
/**
*
* @param obj
* @param path "obj.fieldName"
* @param value
*/
function setNestedValue(obj: any, path: string, value: any): void {
if (!obj || typeof obj !== 'object') {
return;
}
const keys = path.split('.');
let current = obj;
for (let i = 0; i < keys.length - 1; i++) {
const key = keys[i];
if (current[key] === null || current[key] === undefined || typeof current[key] !== 'object') {
current[key] = {};
}
current = current[key];
}
current[keys[keys.length - 1]] = value;
}
/**
*
* @param value
* @returns
*/
function formatNumber(value: any): string {
if (value === null || value === undefined || value === '') {
return '';
}
const num = Number(value);
if (isNaN(num)) {
return String(value);
}
return num.toLocaleString();
}
/**
*
* @param value
* @param enumData {1000:"枚举1",2000:"枚举2"}
* @returns
*/
function parseEnumValue(value: any, enumData: any): any {
if (!enumData) {
return value;
}
// 支持对象格式 {1000:"枚举1",2000:"枚举2"}
if (typeof enumData === 'object' && !Array.isArray(enumData)) {
// 直接匹配
let enumValue = enumData[value];
if (enumValue !== undefined) {
return enumValue;
}
// 类型转换匹配:尝试字符串和数字的相互转换
const valueStr = String(value);
const valueNum = Number(value);
// 如果原值是数字,尝试用字符串匹配
if (!isNaN(valueNum)) {
enumValue = enumData[valueStr];
if (enumValue !== undefined) {
return enumValue;
}
}
// 如果原值是字符串,尝试用数字匹配
if (!isNaN(valueNum)) {
enumValue = enumData[valueNum];
if (enumValue !== undefined) {
return enumValue;
}
}
// 遍历所有键进行宽松匹配
for (const key in enumData) {
if (String(key) === String(value) || Number(key) === Number(value)) {
return enumData[key];
}
}
return value;
}
// 支持数组格式(保持向下兼容)
if (Array.isArray(enumData) && enumData.length > 0) {
const enumItem = enumData.find(item => {
// 支持多种匹配方式,包括类型转换
const itemValue = item.value || item.id || item.key || item.code;
return itemValue === value ||
String(itemValue) === String(value) ||
Number(itemValue) === Number(value);
});
if (enumItem) {
// 返回枚举项的显示文本
return enumItem.label || enumItem.name || enumItem.text || enumItem.title || value;
}
}
return value;
}
function formatRecursive(nodes: any[]): any[] {
return nodes.map(node => {
// 深拷贝节点,避免修改原数据
const newNode = JSON.parse(JSON.stringify(node));
// 处理格式化字段
formatFields.forEach(fieldPath => {
const value = getNestedValue(newNode, fieldPath);
if (value !== undefined) {
const formattedValue = formatNumber(value);
setNestedValue(newNode, fieldPath, formattedValue);
}
});
// 处理枚举字段
enumFields.forEach((fieldPath, index) => {
const value = getNestedValue(newNode, fieldPath);
if (value !== undefined && enumData[index]) {
const parsedValue = parseEnumValue(value, enumData[index]);
setNestedValue(newNode, fieldPath, parsedValue);
}
});
// 处理百分号字段
percentFields.forEach((fieldPath) => {
const value = getNestedValue(newNode, fieldPath);
if (value !== undefined) {
const currentValueStr = String(value);
// 如果值后面还没有百分号,则添加
if (!currentValueStr.endsWith('%')) {
const percentValue = currentValueStr + '%';
setNestedValue(newNode, fieldPath, percentValue);
}
}
});
// 递归处理子节点
if (newNode[childrenKey] && Array.isArray(newNode[childrenKey]) && newNode[childrenKey].length > 0) {
newNode[childrenKey] = formatRecursive(newNode[childrenKey]);
}
return newNode;
});
}
return formatRecursive(data);
} }

View File

@ -1,4 +1,4 @@
// 由 scripts/writeVersion.js 自动生成 // 由 scripts/writeVersion.js 自动生成
export const VERSION = "4.5.61"; export const VERSION = "4.5.62";
export const GIT_HASH = "c58125e"; export const GIT_HASH = "d0c4edd";
export const BUILD_TIME = "2025-09-22T02:36:17.457Z"; export const BUILD_TIME = "2025-09-23T05:40:18.538Z";