fanzherong_v 2 月之前
父节点
当前提交
3e64b16a2a
共有 15 个文件被更改,包括 988 次插入15 次删除
  1. 6 0
      snowy-admin-web/src/api/biz/consumptionRecordApi.js
  2. 3 3
      snowy-admin-web/src/views/biz/rechargerecord/form.vue
  3. 2 1
      snowy-admin-web/src/views/biz/rechargerecord/index.vue
  4. 699 0
      snowy-admin-web/src/views/biz/statisty/recharge.vue
  5. 18 0
      snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/consumptionrecord/controller/ConsumptionRecordController.java
  6. 5 0
      snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/consumptionrecord/mapper/ConsumptionRecordMapper.java
  7. 50 0
      snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/consumptionrecord/mapper/mapping/ConsumptionRecordMapper.xml
  8. 4 0
      snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/consumptionrecord/service/ConsumptionRecordService.java
  9. 72 0
      snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/consumptionrecord/service/impl/ConsumptionRecordServiceImpl.java
  10. 28 0
      snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/rechargerecord/controller/BizRechargeRecordController.java
  11. 1 1
      snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/rechargerecord/entity/BizRechargeRecord.java
  12. 21 0
      snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/rechargerecord/param/BizRechargePay.java
  13. 5 4
      snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/rechargerecord/service/BizRechargeRecordService.java
  14. 72 4
      snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/rechargerecord/service/impl/BizRechargeRecordServiceImpl.java
  15. 2 2
      snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/wx/WxPayNotifyController.java

+ 6 - 0
snowy-admin-web/src/api/biz/consumptionRecordApi.js

@@ -29,6 +29,9 @@ export default {
 	queryRecordTotal(data){
 		return request('queryRecordTotal',data,'get')
 	},
+	queryRechargeTotal(data){
+		return request('queryRechargeTotal',data,'get')
+	},
 	//获取账户余额&会员数统计
 	queryBalanceTotal(data){
 		return request('queryBalanceTotal',data,'get')
@@ -37,6 +40,9 @@ export default {
 	queryConsumptionChart(data){
 		return request('queryConsumptionChart',data,'get')
 	},
+	queryRechargeChar(data){
+		return request('queryRechargeChar',data,'get')
+	},
 	queryEachStore(data){
 		return request('queryEachStore',data,'get')
 	},

+ 3 - 3
snowy-admin-web/src/views/biz/rechargerecord/form.vue

@@ -15,16 +15,16 @@
 					formData.couponNum
 				}}</a-descriptions-item>
 				<a-descriptions-item label="订单号">{{ formData.orderNo }}</a-descriptions-item>
-				<a-descriptions-item label="是否支付">{{ formData.isPay == true?'已支付':'待支付' }}</a-descriptions-item>
+				<a-descriptions-item label="是否支付">{{ formData.isPay == '0'?'待支付': formData.isPay == '1'?'已支付':'已取消' }}</a-descriptions-item>
 				<a-descriptions-item label="充值方案说明:" v-if="formData.rechargePlanId != null">{{
 					formData.rechargePlanDescribe
 				}}</a-descriptions-item>
 			</a-descriptions>
 		</a-form>
-		<template #footer>
+<!--		<template #footer>
 			<a-button style="margin-right: 8px" @click="onClose">关闭</a-button>
 			<a-button type="primary" @click="onSubmit" :loading="submitLoading">保存</a-button>
-		</template>
+		</template>-->
 	</xn-form-container>
 </template>
 

+ 2 - 1
snowy-admin-web/src/views/biz/rechargerecord/index.vue

@@ -26,7 +26,8 @@
 					{{ index + 1 }}
 				</template>
 				<template v-if="column.dataIndex === 'isPay'">
-					<a-tag v-if="record.isPay === true" color="blue">已支付</a-tag>
+					<a-tag v-if="record.isPay === '1'" color="blue">已支付</a-tag>
+					<a-tag v-else-if="record.isPay === '2'" color="purple">已取消</a-tag>
 					<a-tag v-else color="pink">待支付</a-tag>
 				</template>
 				<template v-if="column.dataIndex === 'action'">

+ 699 - 0
snowy-admin-web/src/views/biz/statisty/recharge.vue

@@ -0,0 +1,699 @@
+<template>
+	<a-card :bordered="false" :body-style="{ 'padding-bottom': '20px' }" class="mb-2">
+		<a-form ref="searchFormRef" name="advanced_search" :model="searchFormState" class="ant-advanced-search-form">
+			<a-row :gutter="24">
+				<a-col :span="6">
+					<a-form-item label="日期" name="consumptionTime">
+						<a-date-picker
+							style="width: 100%;"
+							v-model:value="searchFormState.consumptionTime"
+							show-date
+							format="YYYY-MM-DD"
+							placeholder="请选择日期"
+
+						/>
+<!--@change="onRangeChange"-->
+					</a-form-item>
+				</a-col>
+
+				<a-col :span="6">
+					<a-button type="primary" html-type="submit" @click="refresh()">查询</a-button>
+					<a-button style="margin: 0 8px" @click="reset">重置</a-button>
+<!--					<a-button @click="exportTotal">
+						<template #icon>
+							<export-outlined/>
+						</template>
+						导出
+					</a-button>-->
+				</a-col>
+			</a-row>
+		</a-form>
+	</a-card>
+	<a-row>
+		<a-col :span="8" style="margin-bottom: 10px;">
+			<a-card style="height: 180px">
+				<a-statistic title="当日充值金额" :value="payMoney"/>
+			</a-card>
+		</a-col>
+		<a-col :span="8" style="margin-bottom: 10px; margin-left: 20px">
+			<a-card style="height: 180px">
+				<a-statistic title="当日订单数" :value="payCount"/>
+			</a-card>
+		</a-col>
+		<a-col :span="7" style="margin-bottom: 10px; margin-left: 20px;">
+			<a-card style="height: 180px">
+				<a-statistic title="充值金额较上日" :value-style="{ color: '#3f8600' }" :value="compareMoney" v-if="payMoneyFlag=='up'">
+					<template #suffix>
+						<arrow-up-outlined/>
+					</template>
+				</a-statistic>
+				<a-statistic title="充值金额较上日" :value-style="{ color: '#cf1322' }" :value="compareMoney" v-else>
+					<template #suffix>
+						<arrow-down-outlined />
+					</template>
+				</a-statistic>
+				<a-statistic title="订单数较上日" :value-style="{ color: '#3f8600' }" :value="compareOrder" v-if="payOrderFlag=='up'">
+					<template #suffix>
+						<arrow-up-outlined/>
+					</template>
+				</a-statistic>
+				<a-statistic title="订单数较上日" :value-style="{ color: '#cf1322' }" :value="compareOrder" v-else>
+					<template #suffix>
+						<arrow-down-outlined/>
+					</template>
+				</a-statistic>
+			</a-card>
+		</a-col>
+	</a-row>
+
+	<a-card :bordered="false">
+
+		<div style="display:flex;justify-content:space-between" id="totalDiv">
+			<span id="totalSpan">
+				<left-outlined :style="{fontSize:'13px',color:'#C9C9C9',cursor:'pointer'}" @click="prePage" v-show="leftFlag"/>
+			</span>
+			<span>
+				<right-outlined style="width:1.5em;height:1.5em;color:#C9C9C9;cursor:pointer" @click="nextPage" v-show="rightFlag"/>
+			</span>
+		</div>
+
+
+	</a-card>
+
+	<a-card :bordered="false" :body-style="{ 'padding-bottom': '20px' }" class="mb-2">
+		<div id="main2" style="height: 340px"></div>
+	</a-card>
+
+</template>
+
+<script setup name="customerinfo">
+	import bizOrgApi from '@/api/biz/bizOrgApi'
+	import downloadUtil from '@/utils/downloadUtil'
+	import consumptionRecordApi from '@/api/biz/consumptionRecordApi'
+	import bizCouponRecordApi from '@/api/biz/bizCouponRecordApi'
+	import bizUserApi from '@/api/biz/bizUserApi'
+	import { onMounted } from 'vue'
+	import orgApi from '@/api/biz/bizOrgApi'
+	import * as echarts from 'echarts'
+	import dayjs from 'dayjs'
+
+	//消费
+	const consumerCount = ref(0)
+	const consumerOrderCount = ref(0)
+	//充值统计数量
+	const rechargeCount = ref(0)
+	const rechargeOrderCount = ref(0)
+	//会员
+	const userCount = ref(0)
+	//账户余额&代金券余额
+	const accountBalance = ref(0)
+	const voucherBalance = ref(0)
+	const payMoneyFlag = ref()
+	const payOrderFlag = ref()
+
+	const payMoney = ref(0)
+	const payCount = ref(0)
+	const compareMoney = ref(0)
+	const compareOrder = ref(0)
+
+	const treeData = ref([])
+	const activeKey = ref('1');
+
+	const searchFormRef = ref()
+	let searchFormState = reactive({})
+
+	const data1 = ref([])
+	const data2 = ref([])
+	const data3 = ref([])
+	const data4 = ref([])
+	const data5 = ref([])
+
+	const dayTime = ref()
+	const zhibiao = ref()
+	const fuhe = ref()
+	const typeTitle = ref()
+
+	//三条数据一页
+	const echartsPage = ref(7)
+	//当前显示页数
+	const currentPage = ref(1)
+	// 共有多少页
+	const totalPage = ref(0)
+
+	const leftFlag = ref(false)
+	const rightFlag = ref(false)
+
+
+
+
+	onMounted(() => {
+		//金额汇总
+		loadData1();
+		/*loadData3();
+		clickTab()*/
+		// 获取机构树并加入顶级
+		bizOrgApi.orgTreeSelector().then((res) => {
+			treeData.value = res
+		})
+		//折线图
+		customer();
+		//各个门店消费统计
+		loadData4()
+	})
+
+	const onRangeChange = (value, dateString) => {
+		console.log('Formatted Selected Time: ', dateString);
+		searchFormState.startTime = dateString[0]
+		searchFormState.endTime = dateString[1]
+		delete searchFormState.times
+	};
+
+	const table = ref()
+	const formRef = ref()
+	const toolConfig = { refresh: true, height: true, columnSetting: true, striped: false }
+	const columns1 = [
+		{
+			title: '会员姓名',
+			dataIndex: 'userName',
+			align: 'center',
+		},
+		{
+			title: '会员手机号',
+			dataIndex: 'phone',
+			align: 'center',
+		},
+		{
+			title: '消费操作',
+			dataIndex: 'consumptionOperate',
+			align: 'center'
+		},
+		{
+			title: '消费金额',
+			dataIndex: 'consumptionMoney',
+			align: 'center'
+		},
+		{
+			title: '账户糕点',
+			dataIndex: 'newAccountBalance',
+			align: 'center'
+		},
+		{
+			title: '账户积分',
+			dataIndex: 'newVoucherBalance',
+			align: 'center'
+		},
+		{
+			title: '消费时间',
+			dataIndex: 'consumptionTime',
+			align: 'center'
+		},
+		{
+			title: '会员编码',
+			dataIndex: 'userCode',
+			align: 'center'
+		},
+		{
+			title: '消费门店',
+			dataIndex: 'orgName',
+			align: 'center'
+		},
+	]
+
+	const columns2 = [
+		{
+			title: '优惠券编码',
+			dataIndex: 'couponNo',
+			align: 'center',
+		},
+		{
+			title: '优惠券生成时间',
+			dataIndex: 'time',
+			align: 'center',
+		},
+		{
+			title: '是否核销',
+			dataIndex: 'couponStatus',
+			align: 'center'
+		},
+		{
+			title: '有效期开始时间',
+			dataIndex: 'startTime',
+			align: 'center'
+		},
+		{
+			title: '有效期截止时间',
+			dataIndex: 'endTime',
+			align: 'center'
+		},
+		{
+			title: '核销人',
+			dataIndex: 'destroyUserName',
+			align: 'center'
+		},
+		{
+			title: '核销时间',
+			dataIndex: 'destroyTime',
+			align: 'center'
+		},
+		{
+			title: '核销门店',
+			dataIndex: 'destroyOrgName',
+			align: 'center'
+		},
+	]
+
+
+	const columns3 = [
+		{
+			title: '会员编码',
+			dataIndex: 'userReferralCode',
+			align: 'center',
+		},
+		{
+			title: '手机号',
+			dataIndex: 'phone',
+			align: 'center',
+		},
+		{
+			title: '姓名',
+			dataIndex: 'name',
+			align: 'center',
+		},
+		{
+			title: '账户糕点',
+			dataIndex: 'accountBalance',
+			align: 'center',
+		},
+		{
+			title: '账户积分',
+			dataIndex: 'voucherBalance',
+			align: 'center',
+		},
+		{
+			title: '注册时间',
+			dataIndex: 'createTime',
+			align: 'center',
+		},
+		/*{
+			title: '门店',
+			dataIndex: 'orgName',
+			align: 'center',
+		},*/
+	]
+
+
+	const columns4 = [
+		{
+			title: '门店名称',
+			dataIndex: 'name',
+			align: 'center'
+		},
+		{
+			title: '门店编码',
+			dataIndex: 'code',
+			align: 'center'
+		},
+		{
+			title: '消费',
+			children: [
+				{
+					title: '订单数',
+					dataIndex: 'orderCount',
+					align: 'center',
+				},
+				{
+					title: '账户消费糕点',
+					dataIndex: 'accountMoney',
+					align: 'center',
+				},
+				{
+					title: '账户消费积分',
+					dataIndex: 'voucherMoney',
+					align: 'center',
+				},
+			]
+		},
+		/*{
+			title: '注册会员数',
+			dataIndex: 'userCount',
+			align: 'center'
+		},*/
+
+	]
+
+
+	const selectedRowKeys = ref([])
+	// 列表选择配置
+	const options = {
+		// columns数字类型字段加入 needTotal: true 可以勾选自动算账
+		alert: {
+			show: true,
+			clear: () => {
+				selectedRowKeys.value = ref([])
+			}
+		},
+		rowSelection: {
+			onChange: (selectedRowKey, selectedRows) => {
+				selectedRowKeys.value = selectedRowKey
+			}
+		}
+	}
+
+	const totalMoney = ref(0)
+
+	//各个门店消费记录
+	const loadData4 = () => {
+		const orgId = ref('')
+		if(searchFormState.orgId == null || searchFormState.orgId== '' || searchFormState.orgId== 'undefined' ){
+
+		}else{
+			for(let i = 0;i<searchFormState.orgId.length;i++){
+				orgId.value = orgId.value + searchFormState.orgId[i]+","
+			}
+			orgId.value = orgId.value.slice(0,orgId.value.length-1)
+		}
+		const param = {
+			"orgId":orgId.value,
+			"consumptionTimeBegin":searchFormState.startTime,
+			"consumptionTimeEnd":searchFormState.endTime
+		}
+		consumptionRecordApi.queryEachStore(param).then((data)=>{
+			data4.value = data.dataList
+		})
+	}
+
+
+	//导出
+	const exportTotal = () => {
+		const orgId = ref('')
+		if(searchFormState.orgId == null || searchFormState.orgId== '' || searchFormState.orgId== 'undefined' ){
+
+		}else{
+			for(let i = 0;i<searchFormState.orgId.length;i++){
+				orgId.value = orgId.value + searchFormState.orgId[i]+","
+			}
+			orgId.value = orgId.value.slice(0,orgId.value.length-1)
+		}
+		const param = {
+			"orgId":orgId.value,
+			"consumptionTimeBegin":searchFormState.startTime,
+			"consumptionTimeEnd":searchFormState.endTime
+		}
+		consumptionRecordApi.exportRecord(param).then((res)=>{
+			downloadUtil.resultDownload(res)
+		})
+	}
+
+	//会员折线图
+	const customer = () => {
+		const orgId = ref('')
+		if(searchFormState.orgId == null || searchFormState.orgId== '' || searchFormState.orgId== 'undefined' ){
+
+		}else{
+			for(let i = 0;i<searchFormState.orgId.length;i++){
+				orgId.value = orgId.value + searchFormState.orgId[i]+","
+			}
+			orgId.value = orgId.value.slice(0,orgId.value.length-1)
+		}
+		const param = {
+			"orgId":orgId.value,
+			"customerName":searchFormState.customerName,
+			"startTime":searchFormState.startTime,
+			"endTime":searchFormState.endTime
+		}
+		consumptionRecordApi.queryRechargeChar(param).then((res)=>{
+			const xAxis = res.dateTime
+
+			let series = [
+				{
+					name: '充值金额',
+					type: 'line',
+					//stack: '总量',
+					showSymbol: false,
+					itemStyle: {
+					normal: {
+						color: '#00FF00', //折线点自定义
+						lineStyle: {
+						color: '#00FF00'
+						}
+					}
+					},
+					data: res.payMoney
+				},
+				{
+					name: '订单数',
+					type: 'line',
+					//stack: '总量',
+					showSymbol: false,
+					data: res.payCount
+				},
+
+			]
+			drow("main2",xAxis, series)
+		})
+	}
+
+	const drow = (id, xAxis, series) => {
+	let myChart = echarts.init(document.getElementById(id))
+
+	let option = {
+		color: ['#1890FF', '#52C41A'],
+		title: {
+		//text: '会话量',
+		},
+		tooltip: {
+		trigger: 'axis',
+		},
+		grid: {
+		left: '40px',
+		right: '40px',
+		top: '50px',
+		bottom: '30px'
+		},
+		legend: {
+		itemWidth: 20, // 图例图形宽度
+		itemHeight: 4,
+		icon: 'roundRect',
+		},
+		xAxis: {
+		type: 'category',
+		boundaryGap: false, //x轴两边不留空白
+		axisLabel: {
+			color: 'rgba(0, 0, 0, 0.65)',
+		},
+		axisLine: {
+			lineStyle: {
+			color: '#D9D9D9',
+			},
+		},
+		axisTick: {
+			lineStyle: {
+			color: '#D9D9D9',
+			},
+		},
+		data: xAxis,
+		},
+		yAxis: {
+		axisLine: {
+			show: false,
+			lineStyle: {
+			color: 'rgba(0, 0, 0, 0.65)',
+			},
+		},
+		splitLine: {
+			lineStyle: {
+			color: ['#E8E8E8'],
+			type: 'dashed',
+			},
+		},
+		axisLabel: {
+			color: 'rgba(0, 0, 0, 0.65)',
+		},
+		axisTick: {
+			show: false,
+			lineStyle: { color: 'rgb(150,150,150)' }, //y轴坐标刻度颜色(与axisLabel.textStyle是相同的效果)
+		},
+		type: 'value',
+		},
+		series: series
+	}
+	myChart.setOption(option)
+	}
+
+	//消费金额值统计
+	const loadData1 = () => {
+		const orgId = ref('')
+		if(searchFormState.orgId == null || searchFormState.orgId== '' || searchFormState.orgId== 'undefined' ){
+
+		}else{
+			for(let i = 0;i<searchFormState.orgId.length;i++){
+				orgId.value = orgId.value + searchFormState.orgId[i]+","
+			}
+			orgId.value = orgId.value.slice(0,orgId.value.length-1)
+		}
+		const param = {
+			"consumptionTime": dayjs(searchFormState.consumptionTime).format('YYYY-MM-DD')
+		}
+		consumptionRecordApi.queryRechargeTotal(param).then((data) => {
+			payMoney.value = '¥ ' + data.payMoney
+			payCount.value = data.payCount
+
+			compareMoney.value = data.compareMoney
+			compareOrder.value = data.compareOrder
+
+			payMoneyFlag.value = data.payMoneyFlag
+			payOrderFlag.value = data.payOrderFlag
+
+		})
+	}
+
+	//账户余额值统计
+	const loadData3 = () => {
+		const orgId = ref('')
+		if(searchFormState.orgId == null || searchFormState.orgId== '' || searchFormState.orgId== 'undefined' ){
+
+		}else{
+			for(let i = 0;i<searchFormState.orgId.length;i++){
+				orgId.value = orgId.value + searchFormState.orgId[i]+","
+			}
+			orgId.value = orgId.value.slice(0,orgId.value.length-1)
+		}
+		const param = {
+			"orgId":orgId.value,
+			"consumptionTimeBegin":searchFormState.startTime,
+			"consumptionTimeEnd":searchFormState.endTime
+		}
+		consumptionRecordApi.queryBalanceTotal(param).then((data)=>{
+			userCount.value = data.userCount
+			accountBalance.value = data.accountBalance
+			voucherBalance.value = data.voucherBalance
+		})
+	}
+
+
+	//切换
+	const clickTab = () => {
+		consumptionPage()
+		userPage()
+		couponPage()
+	}
+
+	const consumptionPage = () =>{
+		const orgId = ref('')
+		if(searchFormState.orgId == null || searchFormState.orgId== '' || searchFormState.orgId== 'undefined' ){
+
+		}else{
+			for(let i = 0;i<searchFormState.orgId.length;i++){
+				orgId.value = orgId.value + searchFormState.orgId[i]+","
+			}
+			orgId.value = orgId.value.slice(0,orgId.value.length-1)
+		}
+		const param = {
+			"orgId":orgId.value,
+			"consumptionTimeBegin":searchFormState.startTime,
+			"consumptionTimeEnd":searchFormState.endTime,
+			"consumptionOperate":'3,4'
+		}
+		consumptionRecordApi.consumptionRecordPage(param).then((data) => {
+			data1.value = data.records
+		})
+	}
+
+	//会员列表
+	const userPage = () => {
+		const orgId = ref('')
+		if(searchFormState.orgId == null || searchFormState.orgId== '' || searchFormState.orgId== 'undefined' ){
+
+		}else{
+			for(let i = 0;i<searchFormState.orgId.length;i++){
+				orgId.value = orgId.value + searchFormState.orgId[i]+","
+			}
+			orgId.value = orgId.value.slice(0,orgId.value.length-1)
+		}
+		const param = {
+			"orgId":orgId.value,
+			"beginTime":searchFormState.startTime,
+			"endTime":searchFormState.endTime
+		}
+		bizUserApi.memberPage(param).then((res) => {
+			data3.value = res.records
+		})
+	}
+
+
+	//优惠券列表
+	const couponPage = () => {
+		const orgId = ref('')
+		if(searchFormState.orgId == null || searchFormState.orgId== '' || searchFormState.orgId== 'undefined' ){
+
+		}else{
+			for(let i = 0;i<searchFormState.orgId.length;i++){
+				orgId.value = orgId.value + searchFormState.orgId[i]+","
+			}
+			orgId.value = orgId.value.slice(0,orgId.value.length-1)
+		}
+		const param = {
+			"orgId":orgId.value,
+			"beginTime":searchFormState.startTime,
+			"endTime":searchFormState.endTime
+		}
+		bizCouponRecordApi.bizCouponRecordPage(param).then((data) => {
+			data2.value = data.records
+		})
+	}
+
+
+	//查询
+	const refresh = () => {
+		loadData1();
+		loadData3();
+		clickTab()
+		loadData4()
+	}
+
+	//导出
+	const exportReport = () => {
+		if(activeKey.value == '1'){
+			searchFormState.queryFlag = '1'
+			console.log("searchFormState.queryFlag:"+searchFormState.queryFlag)
+			reportApi.exportReport(searchFormState).then((res) => {
+				downloadUtil.resultDownload(res)
+			})
+
+		}
+	}
+
+	// 重置
+	const reset = () => {
+		searchFormRef.value.resetFields()
+		searchFormState.times = []
+		searchFormState.startTime = null
+		searchFormState.endTime = null
+		searchFormState.orgId = []
+	}
+
+</script>
+
+<style lang="less" scoped>
+.ant-table-thead > tr > th {
+    text-align: center;
+}
+
+.dashboard-analysis-iconGroup {
+  i {
+    margin-left: 16px;
+    color: rgba(0, 0, 0, .45);
+    cursor: pointer;
+    transition: color .32s;
+    color: black;
+	height: 20px;
+  }
+}
+
+#totalDiv #totalSpan{
+	svg{
+		width: 1.5em;
+		height: 1.5em;
+	}
+}
+</style>

+ 18 - 0
snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/consumptionrecord/controller/ConsumptionRecordController.java

@@ -187,6 +187,24 @@ public class ConsumptionRecordController {
         return CommonResult.data(consumptionRecordService.queryConsumptionChart(consumptionRecordPageParam));
     }
 
+    /**
+     * 后台充值金额订单数折线图
+     * @return
+     */
+    @Operation(summary = "后台充值金额订单数折线图")
+    @SaCheckPermission("/biz/consumptionrecord/queryRechargeChar")
+    @GetMapping("/biz/consumptionrecord/queryRechargeChar")
+    public CommonResult<Map<String,Object>> queryRechargeChar(ConsumptionRecordPageParam consumptionRecordPageParam) {
+        return CommonResult.data(consumptionRecordService.queryRechargeChar(consumptionRecordPageParam));
+    }
+
+    @Operation(summary = "后台充值金额统计")
+    @SaCheckPermission("/biz/consumptionrecord/queryRechargeTotal")
+    @GetMapping("/biz/consumptionrecord/queryRechargeTotal")
+    public CommonResult<Map<String,Object>> queryRechargeTotal(ConsumptionRecordPageParam consumptionRecordPageParam) {
+        return CommonResult.data(consumptionRecordService.queryRechargeTotal(consumptionRecordPageParam));
+    }
+
     /**
      * 各个门店消费记录
      * @return

+ 5 - 0
snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/consumptionrecord/mapper/ConsumptionRecordMapper.java

@@ -38,10 +38,15 @@ public interface ConsumptionRecordMapper extends BaseMapper<ConsumptionRecord> {
 
     ConsumptionResult getRecordTotal(@Param("ew") QueryWrapper<ConsumptionRecord> ew);
 
+    ConsumptionResult getRechargeTotal(@Param("ew") QueryWrapper<ConsumptionRecord> ew);
+
     UserBalanceResult queryBalanceTotal(@Param("ew") QueryWrapper<ConsumptionRecord> ew);
 
     List<Map<String,Object>> queryConsumptionChart(@Param("ew") QueryWrapper<ConsumptionRecord> ew);
 
+    List<Map<String,Object>> queryRechargeChar(@Param("ew") QueryWrapper<ConsumptionRecord> ew);
+
+
     List<Map<String,Object>> queryEachStore(@Param("orgIds") List<String> orgIds,@Param("startTime") String startTime, @Param("endTime") String endTime);
 
 

+ 50 - 0
snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/consumptionrecord/mapper/mapping/ConsumptionRecordMapper.xml

@@ -192,4 +192,54 @@
         </where>
     </select>
 
+    <select id="queryRechargeChar" resultType="java.util.Map">
+        SELECT
+            DATE_FORMAT( t1.dateTime, '%m-%d' ) dateTime,
+            IFNULL( t2.payMoney, 0 ) AS payMoney,
+            IFNULL( t2.payCount, 0 ) payCount
+        FROM
+            (
+                SELECT
+                    CURDATE( ) AS dateTime UNION ALL
+                SELECT
+                    DATE_SUB( CURDATE( ), INTERVAL 1 DAY ) AS dateTime UNION ALL
+                SELECT
+                    DATE_SUB( CURDATE( ), INTERVAL 2 DAY ) AS dateTime UNION ALL
+                SELECT
+                    DATE_SUB( CURDATE( ), INTERVAL 3 DAY ) AS dateTime UNION ALL
+                SELECT
+                    DATE_SUB( CURDATE( ), INTERVAL 4 DAY ) AS dateTime UNION ALL
+                SELECT
+                    DATE_SUB( CURDATE( ), INTERVAL 5 DAY ) AS dateTime UNION ALL
+                SELECT
+                    DATE_SUB( CURDATE( ), INTERVAL 6 DAY ) AS dateTime
+            ) t1
+                LEFT JOIN (
+                SELECT LEFT
+                    ( brr.recharge_time, 10 ) AS dayTime,
+                    IFNULL( SUM( brr.wx_pay_amount ), 0 ) payMoney,
+                    count( * ) payCount
+                FROM
+                    biz_recharge_record brr
+                WHERE
+                    brr.delete_flag = 'NOT_DELETE'
+                  AND brr.is_pay = '1'
+                GROUP BY
+                    LEFT ( brr.recharge_time, 10 )
+                ORDER BY
+                    dayTime DESC
+            ) t2 ON t1.dateTime = t2.dayTime
+        ORDER BY t1.dateTime
+    </select>
+
+    <select id="getRechargeTotal"
+            resultType="vip.xiaonuo.biz.modular.consumptionrecord.param.ConsumptionResult">
+        SELECT
+            IFNULL( SUM( brr.wx_pay_amount ), 0 ) orderMoney,
+            count( * ) orderCount
+        FROM
+            biz_recharge_record brr
+        ${ew.customSqlSegment}
+    </select>
+
 </mapper>

+ 4 - 0
snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/consumptionrecord/service/ConsumptionRecordService.java

@@ -92,6 +92,10 @@ public interface ConsumptionRecordService extends IService<ConsumptionRecord> {
 
     Map<String,Object> queryConsumptionChart(ConsumptionRecordPageParam consumptionRecordPageParam);
 
+    Map<String,Object> queryRechargeChar(ConsumptionRecordPageParam consumptionRecordPageParam);
+
+    Map<String,Object> queryRechargeTotal(ConsumptionRecordPageParam consumptionRecordPageParam);
+
     Map<String,Object> queryEachStore(ConsumptionRecordPageParam consumptionRecordPageParam);
 
     Page<BizMemberUserResult> warnPage(ConsumptionRecordPageParam consumptionRecordPageParam);

+ 72 - 0
snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/consumptionrecord/service/impl/ConsumptionRecordServiceImpl.java

@@ -532,6 +532,78 @@ public class ConsumptionRecordServiceImpl extends ServiceImpl<ConsumptionRecordM
         return result;
     }
 
+    //查询仅七天充值折线图
+    @Override
+    public Map<String, Object> queryRechargeChar(ConsumptionRecordPageParam consumptionRecordPageParam) {
+        Map<String,Object> result = Maps.newHashMap();
+        List<BigDecimal> payMoneyList = Lists.newArrayList();
+        List<Integer> payCountList = Lists.newArrayList();
+        List<String> timeList = Lists.newArrayList();
+        QueryWrapper<ConsumptionRecord> queryWrapper = new QueryWrapper<>();
+        List<Map<String, Object>> mapList = this.getBaseMapper().queryRechargeChar(queryWrapper);
+        for(Map<String,Object> map: mapList){
+            timeList.add(MapUtils.getString(map,"dateTime"));
+            payMoneyList.add(new BigDecimal(MapUtils.getString(map,"payMoney")));
+            payCountList.add(MapUtils.getInteger(map,"payCount"));
+        }
+        result.put("dateTime",timeList);
+        result.put("payMoney",payMoneyList);
+        result.put("payCount",payCountList);
+        return result;
+    }
+
+
+    @Override
+    public Map<String, Object> queryRechargeTotal(ConsumptionRecordPageParam consumptionRecordPageParam) {
+        Map<String,Object> result = Maps.newHashMap();
+        QueryWrapper<ConsumptionRecord> queryWrapperToday = getRechargeQueryWrapper();
+        if(ObjectUtil.isEmpty(consumptionRecordPageParam.getConsumptionTime())){
+            String format = DateUtil.format(DateUtil.date(), "yyyy-MM-dd");
+            queryWrapperToday.between("brr.recharge_time",format+" 00:00:00", format+" 23:59:59");
+        }else{
+            queryWrapperToday.between("brr.recharge_time",consumptionRecordPageParam.getConsumptionTime()+" 00:00:00",
+                    consumptionRecordPageParam.getConsumptionTime()+" 23:59:59");
+        }
+
+        //查询当日充值金额和订单数
+        ConsumptionResult todayResult = this.getBaseMapper().getRechargeTotal(queryWrapperToday);
+        result.put("payMoney",todayResult.getOrderMoney());
+        result.put("payCount",todayResult.getOrderCount());
+        //查询昨日充值金额和订单数
+        String yesTime;
+        if(ObjectUtil.isEmpty(consumptionRecordPageParam.getConsumptionTime())){
+            yesTime = DateUtil.format(DateUtil.offsetDay(DateUtil.parseDate(DateUtil.format(DateUtil.date(), "yyyy-MM-dd")), -1), "yyyy-MM-dd");
+        }else{
+            yesTime = DateUtil.format(DateUtil.offsetDay(DateUtil.parseDate(consumptionRecordPageParam.getConsumptionTime()), -1), "yyyy-MM-dd");
+        }
+
+        QueryWrapper<ConsumptionRecord> yesWrapper = getRechargeQueryWrapper();
+        yesWrapper.between("brr.recharge_time",yesTime+" 00:00:00",yesTime+" 23:59:59");
+        ConsumptionResult yesResult = this.getBaseMapper().getRechargeTotal(yesWrapper);
+        if(todayResult.getOrderMoney().compareTo(yesResult.getOrderMoney()) >= 0){
+            result.put("payMoneyFlag","up");
+            result.put("compareMoney",todayResult.getOrderMoney().subtract(yesResult.getOrderMoney()));
+        }else{
+            result.put("payMoneyFlag","down");
+            result.put("compareMoney",yesResult.getOrderMoney().subtract(todayResult.getOrderMoney()));
+        }
+        if(todayResult.getOrderCount() >= yesResult.getOrderCount()){
+            result.put("payOrderFlag","up");
+            result.put("compareOrder",todayResult.getOrderCount() - yesResult.getOrderCount());
+        }else{
+            result.put("payOrderFlag","down");
+            result.put("compareOrder",yesResult.getOrderCount() - todayResult.getOrderCount());
+        }
+        return result;
+    }
+
+    public QueryWrapper<ConsumptionRecord> getRechargeQueryWrapper(){
+        QueryWrapper<ConsumptionRecord> queryWrapper = new QueryWrapper<>();
+        queryWrapper.eq("brr.delete_flag","NOT_DELETE");
+        queryWrapper.eq("brr.is_pay",'1');
+        return queryWrapper;
+    }
+
     @Override
     public Map<String, Object> queryEachStore(ConsumptionRecordPageParam consumptionRecordPageParam) {
         Map<String,Object> result = Maps.newHashMap();

+ 28 - 0
snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/rechargerecord/controller/BizRechargeRecordController.java

@@ -21,6 +21,7 @@ import org.springframework.web.bind.annotation.GetMapping;
 import org.springframework.web.bind.annotation.PostMapping;
 import org.springframework.web.bind.annotation.RequestBody;
 import org.springframework.web.bind.annotation.RestController;
+import vip.xiaonuo.biz.modular.rechargerecord.param.BizRechargePay;
 import vip.xiaonuo.common.annotation.CommonLog;
 import vip.xiaonuo.common.annotation.CommonNoRepeat;
 import vip.xiaonuo.common.pojo.CommonResult;
@@ -92,6 +93,20 @@ public class BizRechargeRecordController {
         return CommonResult.data(bizRechargeRecordService.add(bizRechargeRecordAddParam));
     }
 
+    /**
+     * 继续支付
+     *
+     * @author wulei
+     * @date 2025/02/06 17:41
+     */
+    @Operation(summary = "继续支付")
+    @CommonLog("继续支付")
+    @PostMapping("/biz/rechargerecord/retryPayment")
+    @CommonNoRepeat
+    public CommonResult<Map<String, Object>> retryPayment(@RequestBody @Valid BizRechargePay bizRechargePay) {
+        return CommonResult.data(bizRechargeRecordService.retryPayment(bizRechargePay));
+    }
+
 //    /**
 //     * 编辑充值记录表
 //     *
@@ -133,4 +148,17 @@ public class BizRechargeRecordController {
     public CommonResult<BizRechargeRecord> detail(@Valid BizRechargeRecordIdParam bizRechargeRecordIdParam) {
         return CommonResult.data(bizRechargeRecordService.detail(bizRechargeRecordIdParam));
     }
+
+    /**
+     * 取消订单
+     *
+     * @author wulei
+     * @date 2025/02/06 17:41
+     */
+    @Operation(summary = "取消订单")
+    @GetMapping("/biz/rechargerecord/cancelOrder")
+    public CommonResult<String> cancelOrder(@Valid BizRechargeRecordIdParam bizRechargeRecordIdParam) {
+        bizRechargeRecordService.cancelOrder(bizRechargeRecordIdParam);
+        return CommonResult.ok();
+    }
 }

+ 1 - 1
snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/rechargerecord/entity/BizRechargeRecord.java

@@ -108,7 +108,7 @@ public class BizRechargeRecord extends CommonEntity {
 
     /** 是否支付 0.未支付 1.已支付 */
     @Schema(description = "是否支付 0.未支付 1.已支付")
-    private Boolean isPay;
+    private String isPay;
 
     /** 支付时间 */
     @Schema(description = "支付时间")

+ 21 - 0
snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/rechargerecord/param/BizRechargePay.java

@@ -0,0 +1,21 @@
+package vip.xiaonuo.biz.modular.rechargerecord.param;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import jakarta.validation.constraints.NotNull;
+import lombok.Data;
+
+import java.math.BigDecimal;
+
+@Data
+public class BizRechargePay {
+
+    /** 充值金额 */
+    @Schema(description = "充值金额")
+    @NotNull(message = "充值金额不能为空")
+    private BigDecimal rechargeAmount;
+
+    /** 充值记录id */
+    @Schema(description = "充值记录id")
+    @NotNull(message = "充值记录id不能为空")
+    private String rechargeId;
+}

+ 5 - 4
snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/rechargerecord/service/BizRechargeRecordService.java

@@ -15,10 +15,7 @@ package vip.xiaonuo.biz.modular.rechargerecord.service;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.baomidou.mybatisplus.extension.service.IService;
 import vip.xiaonuo.biz.modular.rechargerecord.entity.BizRechargeRecord;
-import vip.xiaonuo.biz.modular.rechargerecord.param.BizRechargeRecordAddParam;
-import vip.xiaonuo.biz.modular.rechargerecord.param.BizRechargeRecordEditParam;
-import vip.xiaonuo.biz.modular.rechargerecord.param.BizRechargeRecordIdParam;
-import vip.xiaonuo.biz.modular.rechargerecord.param.BizRechargeRecordPageParam;
+import vip.xiaonuo.biz.modular.rechargerecord.param.*;
 
 import java.util.List;
 import java.util.Map;
@@ -55,6 +52,8 @@ public interface BizRechargeRecordService extends IService<BizRechargeRecord> {
      */
     Map<String, Object> add(BizRechargeRecordAddParam bizRechargeRecordAddParam);
 
+    Map<String,Object> retryPayment(BizRechargePay bizRechargePay);
+
 //    /**
 //     * 编辑充值记录表
 //     *
@@ -86,4 +85,6 @@ public interface BizRechargeRecordService extends IService<BizRechargeRecord> {
      * @date 2025/02/06 17:41
      **/
     BizRechargeRecord queryEntity(String id);
+
+    void cancelOrder(BizRechargeRecordIdParam bizRechargeRecordIdParam);
 }

+ 72 - 4
snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/rechargerecord/service/impl/BizRechargeRecordServiceImpl.java

@@ -40,6 +40,7 @@ import org.springframework.transaction.annotation.Transactional;
 import vip.xiaonuo.auth.core.util.StpLoginUserUtil;
 import vip.xiaonuo.biz.modular.rechargeplanconfig.entity.BizRechargePlanConfig;
 import vip.xiaonuo.biz.modular.rechargeplanconfig.mapper.BizRechargePlanConfigMapper;
+import vip.xiaonuo.biz.modular.rechargerecord.param.*;
 import vip.xiaonuo.biz.modular.user.entity.BizUser;
 import vip.xiaonuo.biz.modular.user.mapper.BizUserMapper;
 import vip.xiaonuo.common.enums.CommonDeleteFlagEnum;
@@ -48,10 +49,6 @@ import vip.xiaonuo.common.exception.CommonException;
 import vip.xiaonuo.common.page.CommonPageRequest;
 import vip.xiaonuo.biz.modular.rechargerecord.entity.BizRechargeRecord;
 import vip.xiaonuo.biz.modular.rechargerecord.mapper.BizRechargeRecordMapper;
-import vip.xiaonuo.biz.modular.rechargerecord.param.BizRechargeRecordAddParam;
-import vip.xiaonuo.biz.modular.rechargerecord.param.BizRechargeRecordEditParam;
-import vip.xiaonuo.biz.modular.rechargerecord.param.BizRechargeRecordIdParam;
-import vip.xiaonuo.biz.modular.rechargerecord.param.BizRechargeRecordPageParam;
 import vip.xiaonuo.biz.modular.rechargerecord.service.BizRechargeRecordService;
 import vip.xiaonuo.common.pojo.CommonEntity;
 import vip.xiaonuo.common.util.CommonCryptogramUtil;
@@ -250,6 +247,69 @@ public class BizRechargeRecordServiceImpl extends ServiceImpl<BizRechargeRecordM
         return resultMap;
     }
 
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public Map<String, Object> retryPayment(BizRechargePay bizRechargePay) {
+        Map<String, Object> resultMap = new HashMap<>(5);
+        //转换金额为分
+        Integer totalFee = bizRechargePay.getRechargeAmount().multiply(new BigDecimal("100")).intValue();
+
+        BizRechargeRecord rechargeRecord = this.getById(bizRechargePay.getRechargeId());
+        // 本系统订单号
+        String orderNumber = "BBT" + DateUtil.format(DateUtil.date(), DatePattern.PURE_DATETIME_MS_PATTERN) + RandomUtil.randomNumbers(3);
+        rechargeRecord.setOrderNo(orderNumber);
+        this.updateById(rechargeRecord);
+
+        BizUser bizUser = bizUserMapper.selectById(StpLoginUserUtil.getLoginUser().getId());
+        String openId = bizUser.getOpenId();
+
+        //请求微信支付相关配置
+        JsapiServiceExtension service =
+                new JsapiServiceExtension.Builder()
+                        .config(rsaAutoCertificateConfig)
+                        .signType("RSA") // 不填默认为RSA
+                        .build();
+        PrepayWithRequestPaymentResponse response;
+        try {
+            PrepayRequest request = new PrepayRequest();
+            request.setAppid(wxPayConfig.getAppId());
+            request.setMchid(wxPayConfig.getMerchantId());
+            request.setDescription("爸爸糖手工吐司会员账户充值");
+            request.setOutTradeNo(orderNumber);
+            request.setNotifyUrl(wxPayConfig.getPayNotifyUrl());
+            Amount amount = new Amount();
+            amount.setTotal(totalFee);
+            request.setAmount(amount);
+            Payer payer = new Payer();
+            payer.setOpenid(openId);
+            request.setPayer(payer);
+            log.info("请求生成订单,请求参数:{}", JSONObject.toJSONString(request));
+            // 调用预下单接口
+            response = service.prepayWithRequestPayment(request);
+            resultMap.put("package", response.getPackageVal());
+            resultMap.put("nonceStr", response.getNonceStr());
+            resultMap.put("signType", response.getSignType());
+            resultMap.put("timeStamp", response.getTimeStamp());
+            resultMap.put("paySign", response.getPaySign());
+            resultMap.put("dataId", rechargeRecord.getId());
+            log.info("订单【{}】生成订单成功,返回信息:{}", orderNumber, response);
+        } catch (HttpException e) {
+            // 发送HTTP请求失败
+            log.error("微信下单发送HTTP请求失败,错误信息:{}", e.getMessage());
+            throw new CommonException("微信下单失败,请联系管理员");
+        } catch (ServiceException e) {
+            // 服务返回状态小于200或大于等于300,例如500
+            log.error("微信下单服务状态错误,错误信息:{}", e.getErrorMessage());
+            throw new CommonException("微信下单失败,请联系管理员");
+        } catch (MalformedMessageException e) {
+            // 服务返回成功,返回体类型不合法,或者解析返回体失败
+            log.error("服务返回成功,返回体类型不合法,或者解析返回体失败,错误信息:{}", e.getMessage());
+            throw new CommonException("微信下单失败,请联系管理员");
+        }
+        //3. 返回微信订单参数,方便小程序唤起支付
+        return resultMap;
+    }
+
 //    @Transactional(rollbackFor = Exception.class)
 //    @Override
 //    public void edit(BizRechargeRecordEditParam bizRechargeRecordEditParam) {
@@ -278,4 +338,12 @@ public class BizRechargeRecordServiceImpl extends ServiceImpl<BizRechargeRecordM
         }
         return bizRechargeRecord;
     }
+
+    //取消订单
+    @Override
+    public void cancelOrder(BizRechargeRecordIdParam bizRechargeRecordIdParam) {
+        BizRechargeRecord bizRechargeRecord = this.queryEntity(bizRechargeRecordIdParam.getId());
+        bizRechargeRecord.setIsPay("2");
+        this.updateById(bizRechargeRecord);
+    }
 }

+ 2 - 2
snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/wx/WxPayNotifyController.java

@@ -139,7 +139,7 @@ public class WxPayNotifyController {
                 return JSONObject.toJSONString(returnMap);
             }
             //如果已经成功无需再次更新
-            if (bizRechargeRecord.getIsPay()) {
+            if (StringUtils.equals(bizRechargeRecord.getIsPay(),"1")) {
                 returnMap.put("code", "SUCCESS");
                 returnMap.put("message", "成功");
                 return JSONObject.toJSONString(returnMap);
@@ -184,7 +184,7 @@ public class WxPayNotifyController {
             log.info("=========== 更新充值记录 ========");
             bizRechargeRecord.setNewAccountBalance(bizUser.getAccountBalance());
             bizRechargeRecord.setPayTime(DateUtil.parse(transaction.getSuccessTime()));
-            bizRechargeRecord.setIsPay(Boolean.TRUE);
+            bizRechargeRecord.setIsPay("1");
             bizRechargeRecord.setWxOrderNo(transaction.getTransactionId());
             bizRechargeRecord.setWxPayAmount(realPayAmount);
             bizRechargeRecordService.updateById(bizRechargeRecord);