7 Commits

Author SHA1 Message Date
2a457fc076 fix(报表): 修复全年日历报表中金额计算逻辑错误
修复 getAmount 函数中 d.val 为 "other" 时的匹配逻辑,正确结果为支付方式为空或为"其他"的和。
2026-02-03 16:38:45 +08:00
7943cf2cb5 feat(商品管理/报表): 新增微信支付商户选择功能并优化实物报表
- 在商品添加/编辑页面增加微信支付商户选择(众妙之门/灵枢教育科技)
- 优化实物报表组件,支持按支付商户类型筛选和导出数据
- 修复报表组件中数据可能为空的显示问题
- 调整商品重量输入框的样式布局
2026-02-03 09:22:39 +08:00
86dc894f2f 修复:批量开课上传数据错误一直loading 2025-12-16 10:01:02 +08:00
c4102e572b Merge branch 'master' of https://gitee.com/wjl2008_admin/nuttyreading-master-html 2025-12-02 16:30:02 +08:00
8af1e3ac1c 更新:增加中西汇通vip查询和显示 2025-12-02 16:29:59 +08:00
9509e67074 修复:解决中西汇通vip未显示 2025-11-19 09:49:15 +08:00
b1090ba20d 更新:报表增加天医币后台、购买vip商品统计 2025-11-19 09:48:52 +08:00
9 changed files with 139 additions and 100 deletions

View File

@@ -175,6 +175,11 @@ export default {
val: "kecheng2", val: "kecheng2",
realTitle: "购买商品实物、课程" realTitle: "购买商品实物、课程"
}, },
{
title: "购买VIP商品",
val: "vip",
realTitle: "购买商品VIP"
},
{title:'报名培训班',val:'train',realTitle: "购买商品培训班"}, {title:'报名培训班',val:'train',realTitle: "购买商品培训班"},
// {title:'报名VIP',val:'vip'}, // {title:'报名VIP',val:'vip'},
{ title: "后台扣费", val: "deduction" } { title: "后台扣费", val: "deduction" }
@@ -207,25 +212,36 @@ export default {
}, },
methods: { methods: {
getAmount(d, index, month) { getAmount(d, index, month) {
if (!month || !month.total || !Array.isArray(month.total)) {
return "0";
}
if (d.val === "other") {
const list = month.total.filter(item => {
return (
item.type === d.realTitle &&
(item.payMethod === "" || item.payMethod === "其他")
);
});
if (!list.length) {
return "0";
}
return list.reduce((sum, item) => {
const val = Number(item.amount || 0);
return sum + (isNaN(val) ? 0 : val);
}, 0);
}
// 定义所有可能的匹配规则
const matchRules = [ const matchRules = [
item => {
// 例如:当类型是特定值时,启用特殊匹配
if (d.val == "other" && item.payMethod == "") {
return `${item.type}` === d.realTitle;
}
return false;
},
item => item.type === d.title, item => item.type === d.title,
item => item.type === d.realTitle, item => item.type === d.realTitle,
item => `${item.payMethod}${item.type}` === d.realTitle, item => `${item.payMethod}${item.type}` === d.realTitle,
item => `${item.type}${item.payMethod}` === d.realTitle, item => `${item.type}${item.payMethod}` === d.realTitle,
item => `${item.type}${item.goodsType}` === d.realTitle item => `${item.type}${item.goodsType}` === d.realTitle
// 更复杂的条件组合
]; ];
// 依次检查每个规则,返回第一个匹配项
for (const rule of matchRules) { for (const rule of matchRules) {
const matchedItem = month.total.find(rule); const matchedItem = month.total.find(rule);
if (matchedItem) { if (matchedItem) {
@@ -233,7 +249,6 @@ export default {
} }
} }
// 没有匹配项时返回空字符串
return "0"; return "0";
}, },
async handleExportAll() { async handleExportAll() {

View File

@@ -66,14 +66,11 @@
<span style="margin-left: 10px;color: #333;letter-spacing: 0.5px;" v-if="index==0" :style="{ <span style="margin-left: 10px;color: #333;letter-spacing: 0.5px;" v-if="index==0" :style="{
color: getAmount(item, index, month) == 0 ? '#888' : '#333' color: getAmount(item, index, month) == 0 ? '#888' : '#333'
}"> }">
{{ getAmount(item,index,month) }}
{{ getAmount(item,index,month) }} </span>
</span>
<span style="margin-left: 10px;color: #333;letter-spacing: 0.5px;" v-if="index==1"> <span style="margin-left: 10px;color: #333;letter-spacing: 0.5px;" v-if="index==1">
{{ month.total[0][item.val] }}
{{ month.total[0][item.val] }} </span>
</span>
</li> </li>
</div> </div>
@@ -136,31 +133,28 @@ export default {
showCurrentMonthDate: "", showCurrentMonthDate: "",
allMonthData: [], allMonthData: [],
list: [ list: [
{ title: "收入", val: "jing",bg:'#1bff000a', {
list: [ title: "收入", val: "jing",bg:'#1bff000a',
{ title: "后台微信", val: "weixin", realTitle: "后台微信" }, list: [
{ title: "后台支付宝", val: "alipay", realTitle: "后台支付宝" }, { title: "后台微信", val: "weixin", realTitle: "后台微信" },
{ title: "后台海外", val: "haiwai", realTitle: "后台海外支付" }, { title: "后台支付宝", val: "alipay", realTitle: "后台支付" },
{ title: "后台银行转账", val: "", realTitle: "后台银行支付" }, { title: "后台海外", val: "haiwai", realTitle: "后台海外支付" },
{ title: "后台其他", val: "other", realTitle: "后台其他" }, { title: "后台银行转账", val: "", realTitle: "后台银行支付" },
{ title: "App微信", val: "appweixin", realTitle: "微信" }, { title: "后台其他", val: "other", realTitle: "后台其他" },
{ { title: "后台天医币", val: "", realTitle: "后台天医币" },
title: "App支付宝", { title: "App微信", val: "appweixin", realTitle: "微信" },
val: "appalipay", { title: "App支付宝", val: "appalipay", realTitle: "支付宝" },
realTitle: "支付宝" { title: "App天医币", val: "appapple", realTitle: "天医币" }
},
{ title: "App天医币", val: "appapple", realTitle: "天医币" }
] ]
},
}, { title: "摊销", val: "chu",bg:'#ffc1070f',
{ title: "摊销", val: "chu",bg:'#ffc1070f',list:[ list:[
{title:'金额',val:'fee'}, {title:'金额',val:'fee'},
{title:'已摊销',val:'alreadyTanxiao'}, {title:'已摊销',val:'alreadyTanxiao'},
{title:'月摊销',val:'currentTanxiao'}, {title:'月摊销',val:'currentTanxiao'},
{title:'剩余摊销',val:'surplusTanxiao'}, {title:'剩余摊销',val:'surplusTanxiao'},
]
] }, },
], ],
weekDays: ["Mo", "Tu", "We", "Th", "Fr", "Sa", "Su"], weekDays: ["Mo", "Tu", "We", "Th", "Fr", "Sa", "Su"],
monthNames: [ monthNames: [

View File

@@ -5,7 +5,7 @@
> >
<div v-if="allMonthData.length>0" <div v-if="allMonthData.length>0"
@click="handleExportAll()" @click="handleExportAll()"
style="position: absolute;left: 360px;top:30px;cursor: pointer;color: #006699;font-size: 14px;" style="position: absolute;left: 360px;top:85px;cursor: pointer;color: #006699;font-size: 14px;"
> >
<i class="el-icon-download"></i>下载 {{ selectYear }} 年全部实物报表 <i class="el-icon-download"></i>下载 {{ selectYear }} 年全部实物报表
</div> </div>
@@ -67,7 +67,9 @@
>共计{{ >共计{{
allMonthData[mIndex].total.filter( allMonthData[mIndex].total.filter(
item => item.payType == d.title item => item.payType == d.title
)[0].count )[0] ? allMonthData[mIndex].total.filter(
item => item.payType == d.title
)[0].count : 0
}}</span }}</span
> >
@@ -75,7 +77,9 @@
>{{ >{{
allMonthData[mIndex].total.filter( allMonthData[mIndex].total.filter(
item => item.payType == d.title item => item.payType == d.title
)[0].totalPrice )[0] ? allMonthData[mIndex].total.filter(
item => item.payType == d.title
)[0].totalPrice : 0
}} }}
</span> </span>
</div> </div>
@@ -119,7 +123,11 @@ export default {
urlList: { urlList: {
type: Object, type: Object,
default: () => ({}) default: () => ({})
} },
merchantType: {
type: String,
default: '0'
},
}, },
data() { data() {
return { return {
@@ -156,8 +164,8 @@ export default {
}, },
async created() { async created() {
await this.getMonthsByYear(this.selectYear); // await this.getMonthsByYear(this.selectYear);
await this.fetchAllMonthData(); // await this.fetchAllMonthData();
}, },
methods: { methods: {
async handleExportAll() { async handleExportAll() {
@@ -175,7 +183,7 @@ export default {
return this.$http({ return this.$http({
url: this.$http.adornUrl(this.urlList.export), url: this.$http.adornUrl(this.urlList.export),
method: "post", method: "post",
data: this.$http.adornData({ date:this.$commonJS.getDate(this.selectYear,m) }), data: this.$http.adornData({ date:this.$commonJS.getDate(this.selectYear,m), orderType: this.merchantType }),
responseType: "blob" responseType: "blob"
}) })
.then(res => { .then(res => {
@@ -235,7 +243,8 @@ export default {
url: this.$http.adornUrl(this.urlList.export), url: this.$http.adornUrl(this.urlList.export),
method: "post", method: "post",
data: this.$http.adornData({ data: this.$http.adornData({
date:this.$commonJS.getDate(this.selectYear,this.pad(mIndex)) date:this.$commonJS.getDate(this.selectYear,this.pad(mIndex)),
orderType: this.merchantType
}), }),
responseType: "blob" // ⚡⚡⚡一定要加上 responseType: "blob" // ⚡⚡⚡一定要加上
}).then(res => { }).then(res => {
@@ -292,7 +301,7 @@ export default {
return this.$http({ return this.$http({
url: this.$http.adornUrl(this.urlList.list), url: this.$http.adornUrl(this.urlList.list),
method: "post", method: "post",
data: this.$http.adornData({ date: this.$commonJS.getDate(year,m) }) data: this.$http.adornData({ date: this.$commonJS.getDate(year,m), orderType: this.merchantType })
}) })
.then(res => { .then(res => {
if (res.data && res.data.code === 0) { if (res.data && res.data.code === 0) {

View File

@@ -1,41 +1,35 @@
<template> <template>
<div class="mod-config"> <div class="mod-config">
<el-tabs v-model="merchantType" type="card" @tab-click="changeTab">
<el-tab-pane label="众妙之门" name="order" />
<el-tab-pane label="灵枢教育科技" name="lsorder" />
</el-tabs>
<el-form <el-form
:inline="true" :inline="true"
:model="dataForm" :model="dataForm"
@keyup.enter.native="getDataList()" @keyup.enter.native="getDataList()"
> >
<el-form-item> <el-form-item>
<div class="block"> <div class="block">
<el-date-picker
v-model="currentYear"
<el-date-picker type="year"
v-model="currentYear" format="yyyy"
type="year" value-format="yyyy" :picker-options="pickerOptions"
format="yyyy" placeholder="选择年份"
value-format="yyyy" :picker-options="pickerOptions" @change="handleYearChange"
placeholder="选择年份" />
@change="handleYearChange" </div>
/>
</div>
</el-form-item> </el-form-item>
<el-button <el-button
type="primary" type="primary"
size="small" size="small"
@click=" @click=" handleYearChange()"
>刷新</el-button>
handleYearChange();
"
>刷新</el-button
>
</el-form> </el-form>
<FullYearCalendar :urlList="urlList" ref="refCalendar" :selectYear="Number(currentYear)" :marks="markedDates" v-if="currentYear" /> <FullYearCalendar :urlList="urlList" ref="refCalendar" :selectYear="Number(currentYear)" :marks="markedDates" :merchantType="orderType" v-if="currentYear" />
</div> </div>
</template> </template>
@@ -45,29 +39,31 @@
data() { data() {
return { return {
urlList:{ urlList:{
list:'/master/statistics/getPhysicalBuyOrderInfoTotal', list:'/master/statistics/getPhysicalBuyOrderInfoTotal',
export:'/master/statistics/exportPhysicalBuyOrderInfo', export:'/master/statistics/exportPhysicalBuyOrderInfo',
}, },
currentYear: '', currentYear: '',
merchantType:'order',
orderType:'order',
dataForm:{}, dataForm:{},
pickerOptions: { pickerOptions: {
disabledDate(time) { disabledDate(time) {
// 禁用今年以后的年份 // 禁用今年以后的年份
return time.getFullYear() > new Date().getFullYear() return time.getFullYear() > new Date().getFullYear()
} }
}, },
markedDates: { markedDates: {
"2019-01-01": "red", "2019-01-01": "red",
"2019-02-14": "blue", "2019-02-14": "blue",
"2019-03-12": "yellow", "2019-03-12": "yellow",
"2019-05-20": "blue", "2019-05-20": "blue",
"2019-06-10": "yellow" "2019-06-10": "yellow"
} }
}; };
}, },
components: { FullYearCalendar }, components: { FullYearCalendar },
activated() { activated() {
this.currentYear = new Date().getFullYear().toString(); this.currentYear = new Date().getFullYear().toString();
this.handleYearChange(); this.handleYearChange();
}, },
@@ -77,7 +73,13 @@ export:'/master/statistics/exportPhysicalBuyOrderInfo',
this.$refs.refCalendar.init(); this.$refs.refCalendar.init();
}) })
}, },
changeTab(tab) {
if (tab.name === this.orderType) {
return;
}
this.orderType = tab.name;
this.handleYearChange();
}
} }

View File

@@ -174,6 +174,12 @@
<el-radio :label="0"></el-radio> <el-radio :label="0"></el-radio>
</el-radio-group> </el-radio-group>
</el-form-item> </el-form-item>
<el-form-item label="微信支付商户" prop="payMerchant">
<el-radio-group v-model="dataForm.payMerchant">
<el-radio :label="0">众妙之门</el-radio>
<el-radio :label="1">灵枢教育科技</el-radio>
</el-radio-group>
</el-form-item>
</div> </div>
<el-form-item label="商品详情" prop="productDetails"> <el-form-item label="商品详情" prop="productDetails">
<el-upload <el-upload
@@ -282,6 +288,7 @@ export default {
// format: '', // 开本 // format: '', // 开本
isFreeMail: 1, // 是否包邮 isFreeMail: 1, // 是否包邮
isVipPrice: 1, //是否vip isVipPrice: 1, //是否vip
payMerchant: 0, // 微信支付商户
// pageNum: '', // pageNum: '',
// quality: '', // 内文用纸 // quality: '', // 内文用纸
isNew: 0, isNew: 0,

View File

@@ -160,7 +160,7 @@
v-model="dataForm.weight" v-model="dataForm.weight"
placeholder="商品重量" placeholder="商品重量"
></el-input ></el-input
><span style="display: inline-block; float: right; width: 10%;" ><span style="float: right; width: 10%;"
></span ></span
> >
</el-form-item> </el-form-item>
@@ -224,6 +224,12 @@
<el-radio :label="0"></el-radio> <el-radio :label="0"></el-radio>
</el-radio-group> </el-radio-group>
</el-form-item> </el-form-item>
<el-form-item label="微信支付商户" prop="payMerchant">
<el-radio-group v-model="dataForm.payMerchant">
<el-radio :label="0">众妙之门</el-radio>
<el-radio :label="1">灵枢教育科技</el-radio>
</el-radio-group>
</el-form-item>
</div> </div>
<el-form-item label="商品详情" prop="productDetails"> <el-form-item label="商品详情" prop="productDetails">
<el-upload <el-upload
@@ -326,6 +332,7 @@ export default {
// format: '', // 开本 // format: '', // 开本
isFreeMail: 1, // 是否包邮 isFreeMail: 1, // 是否包邮
isVipPrice: 0, //是否vip isVipPrice: 0, //是否vip
payMerchant: 0, // 微信支付商户
// pageNum: '', // pageNum: '',
// quality: '', // 内文用纸 // quality: '', // 内文用纸
isNew: 0, isNew: 0,
@@ -517,6 +524,7 @@ export default {
// this.dataForm.format = data.shopProduct.format // this.dataForm.format = data.shopProduct.format
this.dataForm.isFreeMail = data.shopProduct.isFreeMail; this.dataForm.isFreeMail = data.shopProduct.isFreeMail;
this.dataForm.isNew = data.shopProduct.isNew; this.dataForm.isNew = data.shopProduct.isNew;
this.dataForm.payMerchant = data.shopProduct.payMerchant;
this.dataForm.productDetails = data.shopProduct.productDetails; this.dataForm.productDetails = data.shopProduct.productDetails;
this.dataForm.poids = data.shopProduct.poids; this.dataForm.poids = data.shopProduct.poids;
this.dataForm.productStock = data.shopProduct.productStock; this.dataForm.productStock = data.shopProduct.productStock;
@@ -633,6 +641,7 @@ export default {
isFreeMail: this.dataForm.isFreeMail, isFreeMail: this.dataForm.isFreeMail,
isVipPrice: this.dataForm.isVipPrice, isVipPrice: this.dataForm.isVipPrice,
isNew: this.dataForm.isNew, isNew: this.dataForm.isNew,
payMerchant: this.dataForm.payMerchant, // 微信支付商户
// 'pageNum': this.dataForm.pageNum, // 'pageNum': this.dataForm.pageNum,
// 'quality': this.dataForm.quality, // 内文用纸 // 'quality': this.dataForm.quality, // 内文用纸
productStock: this.dataForm.productStock, // 库存 productStock: this.dataForm.productStock, // 库存

View File

@@ -267,15 +267,16 @@
file: this.dataForm.file file: this.dataForm.file
}) })
}).then(({ data }) => { }).then(({ data }) => {
this.dataListLoading = false;
if (data && data.code === 0) { if (data && data.code === 0) {
if(data.result&&data.result.has.length>0){ if(data.result&&data.result.has.length>0){
this.resultStatus = true; this.resultStatus = true;
this.resultData = data.result; this.resultData = data.result;
this.dataListLoading = false; } else {
this.$message.warning(`没有有效的数据,请检查核对文件模板和数据后重新上传`);
} }
}else{ }else{
this.$message.error('文件解析有误'); this.$message.error('文件解析有误');
this.dataListLoading = false;
} }
}); });
}, },

View File

@@ -26,6 +26,7 @@
<el-option label="中医VIP" value="4"></el-option> <el-option label="中医VIP" value="4"></el-option>
<el-option label="针灸VIP" value="5"></el-option> <el-option label="针灸VIP" value="5"></el-option>
<el-option label="肿瘤VIP" value="6"></el-option> <el-option label="肿瘤VIP" value="6"></el-option>
<el-option label="中西汇通VIP" value="9"></el-option>
<el-option label="国学VIP" value="7"></el-option> <el-option label="国学VIP" value="7"></el-option>
<el-option label="心理学VIP" value="8"></el-option> <el-option label="心理学VIP" value="8"></el-option>
</el-select> </el-select>
@@ -696,7 +697,8 @@ export default {
5: "针灸VIP", 5: "针灸VIP",
6: "肿瘤VIP", 6: "肿瘤VIP",
7: "国学VIP", 7: "国学VIP",
8: "心理学VIP" 8: "心理学VIP",
9: "中西汇通VIP"
}; };
// 将 userVips 转为数组形式,以便处理(如果是数字则转为数字数组) // 将 userVips 转为数组形式,以便处理(如果是数字则转为数字数组)
@@ -709,8 +711,8 @@ export default {
vipTypes = userVips.map(vip => vip.type); // 如果是对象数组,获取每个对象的 type vipTypes = userVips.map(vip => vip.type); // 如果是对象数组,获取每个对象的 type
} }
// 判断是否同时包含 4、5、6医学SVIP // 判断是否同时包含 4、5、6、9医学SVIP
const hasMedicalSVip = [4, 5, 6].every(type => vipTypes.includes(type)); const hasMedicalSVip = [4, 5, 6, 9].every(type => vipTypes.includes(type));
// 判断是否同时包含 7、8心理学SVIP // 判断是否同时包含 7、8心理学SVIP
const hasPsychologySVip = [7, 8].every(type => vipTypes.includes(type)); const hasPsychologySVip = [7, 8].every(type => vipTypes.includes(type));
@@ -737,7 +739,7 @@ export default {
vipMap[type] && vipMap[type] &&
!( !(
( (
(hasMedicalSVip && [4, 5, 6].includes(type)) || // 医学SVIP已显示排除 4、5、6 (hasMedicalSVip && [4, 5, 6, 9].includes(type)) || // 医学SVIP已显示排除 4、5、6、9
(hasPsychologySVip && [7, 8].includes(type)) (hasPsychologySVip && [7, 8].includes(type))
) // 心理学SVIP已显示排除 7、8 ) // 心理学SVIP已显示排除 7、8
) )

View File

@@ -6,7 +6,7 @@
// api接口请求地址 // api接口请求地址
// window.SITE_CONFIG['baseUrl'] = 'https://api.nuttyreading.com'; // 线上正式环境 // window.SITE_CONFIG['baseUrl'] = 'https://api.nuttyreading.com'; // 线上正式环境
window.SITE_CONFIG['baseUrl'] = 'http://192.168.110.100:9200/pb'; //川 window.SITE_CONFIG['baseUrl'] = 'http://192.168.110.100:9200/pb'; //
// cdn地址 = 域名 + 版本号 // cdn地址 = 域名 + 版本号
window.SITE_CONFIG['domain'] = './'; // 域名 window.SITE_CONFIG['domain'] = './'; // 域名