Merge remote-tracking branch 'origin/master' into allinone-lite-mysql-redis

This commit is contained in:
Chopper711
2026-06-13 11:50:04 +08:00
19 changed files with 3709 additions and 44 deletions

View File

@@ -50,7 +50,7 @@
"style-resources-loader": "^1.3.2",
"uglifyjs-webpack-plugin": "^2.2.0",
"vue-cli-plugin-style-resources-loader": "^0.1.4",
"vue-template-compiler": "^2.6.10"
"vue-template-compiler": "2.6.14"
},
"resolutions": {
"minimatch": "^3.1.2",

View File

@@ -3,7 +3,8 @@ import {
getRequest,
postRequest,
putRequest,
deleteRequest
deleteRequest,
importRequest
} from "@/libs/axios";
// 获取秒杀活动申请列表
@@ -280,4 +281,72 @@ export const deletePointsGoodsCategoryById = id => {
// 获取优惠券领取记录
export const getCouponReceiveList = (params) => {
return getRequest("/promotion/coupon/received", params);
};
// 现金礼品卡活动分页
export const getGiftCardCashActivityPage = (params) => {
return getRequest("/promotion/giftCardCash/activity", params);
};
// 新建礼品卡活动
export const saveGiftCardCashActivity = (params) => {
return postRequest("/promotion/giftCardCash/activity", params, {
"Content-type": "application/json",
});
};
// 礼品卡活动详情
export const getGiftCardCashActivity = (id) => {
return getRequest(`/promotion/giftCardCash/activity/${id}`);
};
// 更新礼品卡活动
export const updateGiftCardCashActivity = (id, params) => {
return putRequest(`/promotion/giftCardCash/activity/${id}`, params, {
"Content-type": "application/json",
});
};
// 活动下批量制卡
export const giftCardCashBatchCreate = (activityId, params) => {
return postRequest(
`/promotion/giftCardCash/activity/${activityId}/batchCreate`,
params,
{
"Content-type": "application/json",
}
);
};
// 下载批量发卡 Excel 模板
export const downloadGiftCardCashIssueTemplate = () => {
return getRequest("/promotion/giftCardCash/issue/template", {}, "blob");
};
// 按活动上传 Excel 批量发卡multipartfile
export const giftCardCashIssueImportByActivity = (activityId, formData) => {
return importRequest(
`/promotion/giftCardCash/activity/${activityId}/issueImport`,
formData
);
};
// 制卡批次分页
export const getGiftCardCashCreateBatchPage = (params) => {
return getRequest("/promotion/giftCardCash/createBatch", params);
};
// 发卡/发送记录分页
export const getGiftCardCashIssueBatchPage = (params) => {
return getRequest("/promotion/giftCardCash/issueBatch", params);
};
// 礼品卡使用记录分页
export const getGiftCardCashUsageRecordPage = (params) => {
return getRequest("/promotion/giftCardCash/usageRecord", params);
};
// 卡密凭证分页(平台库存+会员资产)
export const getGiftCardCashCredentialPage = (params) => {
return getRequest("/promotion/giftCardCash/credential", params);
};

View File

@@ -224,6 +224,41 @@ export const otherRouter = {
name: "manager-coupon",
component: () => import("@/views/promotions/coupon/coupon.vue")
},
{
path: "promotions/gift-card-cash",
title: "礼品卡",
name: "manager-gift-card-cash",
component: () =>
import("@/views/promotions/gift-card-cash/gift-card-cash-activity.vue")
},
{
path: "promotions/add-gift-card-cash-activity",
title: "添加礼品卡",
name: "add-gift-card-cash-activity",
component: () =>
import("@/views/promotions/gift-card-cash/gift-card-cash-activity-add.vue")
},
{
path: "promotions/edit-gift-card-cash-activity",
title: "编辑礼品卡",
name: "edit-gift-card-cash-activity",
component: () =>
import("@/views/promotions/gift-card-cash/gift-card-cash-activity-add.vue")
},
{
path: "promotions/gift-card-cash-records",
title: "礼品卡记录",
name: "gift-card-cash-records",
component: () =>
import("@/views/promotions/gift-card-cash/gift-card-cash-records.vue")
},
{
path: "promotions/gift-card-cash-batch-credentials",
title: "制卡批次卡密",
name: "gift-card-cash-batch-credentials",
component: () =>
import("@/views/promotions/gift-card-cash/gift-card-cash-batch-credentials.vue")
},
{
path: "promotions/coupon-receive",
title: "优惠券领取记录",

View File

@@ -6,10 +6,11 @@
<Form-item label="会员名称" prop="memberName">
<Input type="text" v-model="searchForm.memberName" placeholder="请输入会员名称" clearable style="width: 240px" />
</Form-item>
<Form-item label="审核状态" prop="applyStatus">
<Form-item label="提现状态" prop="applyStatus">
<Select v-model="searchForm.applyStatus" clearable style="width: 240px">
<Option value="APPLY">申请中</Option>
<Option value="VIA_AUDITING">审核通过</Option>
<Option value="WAIT_USER_CONFIRM">用户确认</Option>
<Option value="FAIL_AUDITING">审核拒绝</Option>
<Option value="SUCCESS">提现成功</Option>
<Option value="ERROR">提现失败</Option>
@@ -165,6 +166,8 @@ export default {
return h("Tag", { props: { color: "volcano" } }, "申请中");
} else if (params.row.applyStatus == "VIA_AUDITING") {
return h("Tag", { props: { color: "green" } }, "审核通过");
} else if (params.row.applyStatus == "WAIT_USER_CONFIRM") {
return h("Tag", { props: { color: "gold" } }, "用户确认");
} else if (params.row.applyStatus == "SUCCESS") {
return h("Tag", { props: { color: "blue" } }, "提现成功");
} else if (params.row.applyStatus == "ERROR") {
@@ -251,8 +254,12 @@ export default {
return "申请中";
} else if (val === "VIA_AUDITING") {
return "审核通过(提现成功)";
} else if (val === "WAIT_USER_CONFIRM") {
return "用户确认";
} else if (val === "FAIL_AUDITING") {
return "审核拒绝";
} else if (val === "SUCCESS") {
return "提现成功";
} else if (val === "ERROR") {
return "提现失败";
} else {
@@ -270,14 +277,22 @@ export default {
this.$Message.error("审核备注不能为空");
return;
}
withdrawApply(params).then((res) => {
this.loading = false;
if (res == true) {
this.$Message.success("操作成功");
this.roleModalVisible = false;
this.getDataList();
}
});
this.submitLoading = true;
withdrawApply(params)
.then((result) => {
const success = result === true || (result && result.success === true);
if (success) {
this.$Message.success("操作成功");
this.roleModalVisible = false;
this.queryModalVisible = false;
this.audit = "";
this.showList = {};
this.getDataList();
}
})
.finally(() => {
this.submitLoading = false;
});
},
init() {
this.getDataList();

View File

@@ -288,7 +288,9 @@ export default {
key: "paymentMethod",
width: 120,
render: (h, params) => {
if (params.row.paymentMethod == "WECHAT") {
if (params.row.paymentMethod == "NOT_ACTUALLY_PAID") {
return h("div", {}, "-");
} else if (params.row.paymentMethod == "WECHAT") {
return h("div", {}, "微信支付");
} else if (params.row.paymentMethod == "ALIPAY") {
return h("div", {}, "支付宝");

View File

@@ -0,0 +1,401 @@
<template>
<div>
<Card :loading="detailLoading">
<Form ref="form" :model="form" :label-width="130" :rules="onlyView ? {} : formRule">
<div class="base-info-item">
<h4>{{ pageTitle }}</h4>
<div class="form-item-view gift-card-activity-form">
<FormItem label="礼品卡名称" prop="giftCardName">
<Input
v-model="form.giftCardName"
type="text"
placeholder="请输入礼品卡名称"
clearable
maxlength="64"
show-word-limit
style="width: 360px"
:disabled="onlyView"
/>
</FormItem>
<FormItem label="礼品卡类型" prop="cardType" class="gift-card-type-form-item">
<RadioGroup v-model="form.cardType" class="gift-card-type-group">
<Radio label="CASH" :disabled="onlyView">现金卡</Radio>
<Radio label="PICKUP" disabled>提货卡</Radio>
</RadioGroup>
</FormItem>
<FormItem label="面值" prop="faceValue">
<Input
v-model="form.faceValue"
type="text"
placeholder="面值"
clearable
style="width: 200px"
:disabled="onlyView"
/>
</FormItem>
<FormItem label="总库存" prop="stockTotal">
<InputNumber
v-model="form.stockTotal"
:min="1"
:precision="0"
placeholder="最多可制发凭证张数"
style="width: 200px"
:disabled="onlyView"
/>
</FormItem>
<FormItem prop="validityType" :label-width="0" class="gift-card-validity-form-item">
<div class="gift-card-validity-outer">
<div class="gift-card-validity-label-col">
<span v-if="!onlyView" class="gift-card-validity-required">*</span>
<span>有效期</span>
</div>
<div class="gift-card-validity-radios">
<RadioGroup v-model="form.validityType" vertical class="gift-card-validity-group">
<Radio label="LONG_TERM" class="gift-card-validity-row" :disabled="onlyView"
>长期有效</Radio
>
<Radio label="AFTER_ACTIVATE_MONTHS" class="gift-card-validity-row" :disabled="onlyView">
<span>自激活后</span>
<InputNumber
v-model="form.validMonthsAfterActivate"
:min="1"
:max="99"
:precision="0"
placeholder="请输入1-99的整数"
:disabled="onlyView || form.validityType !== 'AFTER_ACTIVATE_MONTHS'"
class="gift-card-validity-input-gap"
/>
<span>月内有效</span>
</Radio>
<Radio label="FIXED_UNTIL" class="gift-card-validity-row" :disabled="onlyView">
<span>指定有效期至</span>
<DatePicker
v-model="form.validEndTime"
type="datetime"
format="yyyy-MM-dd HH:mm:ss"
placeholder="选择结束时间"
clearable
transfer
:disabled="onlyView || form.validityType !== 'FIXED_UNTIL'"
class="gift-card-validity-date-gap"
style="width: 220px"
/>
</Radio>
</RadioGroup>
</div>
</div>
</FormItem>
</div>
<div class="foot-btn">
<Button style="margin-right: 8px" @click="closeCurrentPage">返回</Button>
<Button
v-if="!onlyView"
type="primary"
:loading="submitLoading"
@click="handleSubmit"
>提交</Button
>
</div>
</div>
</Form>
</Card>
</div>
</template>
<script>
import {
saveGiftCardCashActivity,
getGiftCardCashActivity,
updateGiftCardCashActivity,
} from "@/api/promotion";
import { regular } from "@/utils";
export default {
name: "addGiftCardCashActivity",
data() {
const checkFaceValue = (rule, value, callback) => {
if (!value && value !== 0) {
return callback(new Error("面额不能为空"));
}
if (!regular.money.test(value)) {
callback(new Error("请输入正整数或者两位小数"));
} else if (parseFloat(value) > 99999999) {
callback(new Error("面额设置超过上限值"));
} else if (parseFloat(value) < 0.01) {
callback(new Error("面值必须大于 0"));
} else {
callback();
}
};
const validateStock = (rule, value, callback) => {
if (value === null || value === undefined || value === "") {
callback(new Error("请填写总库存"));
return;
}
if (Number(value) < 1) {
callback(new Error("活动库存至少为 1"));
return;
}
callback();
};
return {
detailLoading: false,
submitLoading: false,
form: {
giftCardName: "",
cardType: "CASH",
faceValue: "",
stockTotal: null,
validityType: "LONG_TERM",
validEndTime: null,
validMonthsAfterActivate: null,
},
formRule: {
giftCardName: [
{ required: true, message: "活动名称不能为空", trigger: "blur" },
{ type: "string", max: 64, message: "活动名称过长", trigger: "blur" },
],
faceValue: [{ required: true, message: "请输入面额" }, { validator: checkFaceValue }],
stockTotal: [{ required: true, validator: validateStock, trigger: "blur" }],
},
};
},
computed: {
onlyView() {
const q = this.$route.query.onlyView;
return q === "true" || q === true;
},
isEditMode() {
return !!this.$route.query.id && !this.onlyView;
},
pageTitle() {
if (this.onlyView) {
return "查看礼品卡";
}
if (this.isEditMode) {
return "编辑礼品卡";
}
return "添加礼品卡";
},
},
mounted() {
if (this.$route.query.id) {
this.loadDetail(this.$route.query.id);
}
},
watch: {
"form.validityType"(v) {
if (v !== "FIXED_UNTIL") {
this.form.validEndTime = null;
}
if (v !== "AFTER_ACTIVATE_MONTHS") {
this.form.validMonthsAfterActivate = null;
}
},
"$route.query.id"(id) {
if (id) {
this.loadDetail(id);
}
},
},
methods: {
parseDetailDate(val) {
if (!val) {
return null;
}
if (val instanceof Date) {
return val;
}
const d = new Date(val);
return Number.isNaN(d.getTime()) ? null : d;
},
loadDetail(id) {
this.detailLoading = true;
getGiftCardCashActivity(id)
.then((res) => {
this.detailLoading = false;
if (!res.success || !res.result) {
return;
}
const d = res.result;
this.form.giftCardName = d.giftCardName || "";
this.form.cardType = d.cardType || "CASH";
this.form.faceValue =
d.faceValue !== null && d.faceValue !== undefined ? String(d.faceValue) : "";
this.form.stockTotal =
d.stockTotal !== null && d.stockTotal !== undefined ? d.stockTotal : null;
this.form.validityType = d.validityType || "LONG_TERM";
this.form.validEndTime = this.parseDetailDate(d.validEndTime);
this.form.validMonthsAfterActivate =
d.validMonthsAfterActivate !== null &&
d.validMonthsAfterActivate !== undefined &&
d.validMonthsAfterActivate !== ""
? d.validMonthsAfterActivate
: null;
})
.catch(() => {
this.detailLoading = false;
});
},
closeCurrentPage() {
const name = this.$route.name;
if (name) {
this.$store.commit("removeTag", name);
}
localStorage.pageOpenedList = JSON.stringify(this.$store.state.app.pageOpenedList);
this.$router.go(-1);
},
validateByValidityType() {
const t = this.form.validityType;
if (t === "FIXED_UNTIL") {
if (!this.form.validEndTime) {
this.$Message.warning("请选择结束时间");
return false;
}
}
if (t === "AFTER_ACTIVATE_MONTHS") {
const m = this.form.validMonthsAfterActivate;
if (m === null || m === undefined || m === "" || Number(m) < 1 || Number(m) > 99) {
this.$Message.warning("请输入1-99的整数");
return false;
}
}
return true;
},
buildPayload() {
const payload = {
giftCardName: (this.form.giftCardName || "").trim(),
cardType: this.form.cardType || "CASH",
faceValue: parseFloat(this.form.faceValue),
validityType: this.form.validityType || "LONG_TERM",
stockTotal: this.form.stockTotal,
};
if (payload.validityType === "FIXED_UNTIL") {
payload.validEndTime = this.form.validEndTime;
}
if (payload.validityType === "AFTER_ACTIVATE_MONTHS") {
payload.validMonthsAfterActivate = this.form.validMonthsAfterActivate;
}
return payload;
},
handleSubmit() {
if (this.onlyView) {
return;
}
this.$refs.form.validate((valid) => {
if (!valid) {
return;
}
if (!this.validateByValidityType()) {
return;
}
this.submitLoading = true;
const req = this.isEditMode
? updateGiftCardCashActivity(this.$route.query.id, this.buildPayload())
: saveGiftCardCashActivity(this.buildPayload());
req
.then((res) => {
this.submitLoading = false;
if (res.success) {
this.$Message.success(
this.isEditMode ? "礼品卡活动已更新" : "礼品卡活动创建成功"
);
this.closeCurrentPage();
}
})
.catch(() => {
this.submitLoading = false;
});
});
},
},
};
</script>
<style scoped>
.gift-card-activity-form >>> .ivu-form-item {
margin-bottom: 26px;
}
.gift-card-type-form-item >>> .ivu-form-item-label {
line-height: 32px;
padding-top: 1px;
}
.gift-card-type-form-item >>> .ivu-form-item-content {
display: flex;
align-items: center;
min-height: 32px;
}
.gift-card-type-group >>> .ivu-radio-wrapper {
margin-right: 32px;
line-height: 32px;
display: inline-flex !important;
align-items: center;
vertical-align: middle;
}
.gift-card-validity-form-item >>> .ivu-form-item-content {
margin-left: 0 !important;
}
.gift-card-validity-outer {
display: flex;
align-items: flex-start;
width: 100%;
}
.gift-card-validity-label-col {
flex: 0 0 130px;
width: 130px;
padding-right: 12px;
box-sizing: border-box;
text-align: right;
line-height: 32px;
min-height: 32px;
display: flex;
align-items: center;
justify-content: flex-end;
padding-top: 1px;
}
.gift-card-validity-required {
color: #ed4014;
margin-right: 4px;
font-family: SimSun, serif;
}
.gift-card-validity-radios {
flex: 1;
min-width: 0;
padding-top: 1px;
}
.gift-card-validity-group {
padding-top: 0;
padding-bottom: 0;
}
.gift-card-type-group >>> .ivu-radio {
display: inline-flex;
align-items: center;
line-height: 1;
}
.gift-card-validity-group >>> .ivu-radio {
display: inline-flex;
align-items: center;
line-height: 1;
}
.gift-card-validity-group >>> .ivu-radio-wrapper:first-child {
margin-top: 0;
}
.gift-card-validity-group >>> .ivu-radio-wrapper {
display: flex;
flex-wrap: wrap;
align-items: center;
margin-bottom: 10px;
line-height: 32px;
min-height: 32px;
}
.gift-card-validity-group >>> .ivu-radio-wrapper:last-child {
margin-bottom: 0;
}
.gift-card-validity-input-gap {
width: 168px;
margin: 0 10px;
}
.gift-card-validity-date-gap {
margin-left: 10px;
}
</style>

View File

@@ -0,0 +1,712 @@
<template>
<div class="search">
<Card>
<Form
ref="searchForm"
:model="searchForm"
inline
:label-width="80"
class="search-form mb_10"
>
<Form-item label="礼品卡名称" prop="giftCardName">
<Input
v-model="searchForm.giftCardName"
type="text"
placeholder="模糊搜索礼品卡名称"
clearable
style="width: 260px"
/>
</Form-item>
<Button type="primary" icon="ios-search" class="search-btn" @click="handleSearch"
>搜索</Button
>
</Form>
</Card>
<Card>
<Row class="operation padding-row">
<Button type="primary" @click="addActivity">添加礼品卡</Button>
</Row>
<Table :loading="loading" :columns="columns" :data="data" ref="table">
<template slot-scope="{ row }" slot="action">
<template v-if="canEdit(row)">
<a :style="linkStyle" @click.prevent="goEdit(row)">编辑</a>
<span :style="sepStyle">|</span>
</template>
<a :style="linkStyle" @click.prevent="goView(row)">查看</a>
<template v-if="canBatchCreate(row)">
<span :style="sepStyle">|</span>
<a :style="linkStyle" @click.prevent="openBatchCreate(row)">批量制卡</a>
</template>
<template v-if="canBatchIssue(row)">
<span :style="sepStyle">|</span>
<a :style="linkStyle" @click.prevent="openBatchIssue(row)">批量发卡</a>
</template>
<span :style="sepStyle">|</span>
<a :style="linkStyle" @click.prevent="goRecords(row)">查看记录</a>
</template>
</Table>
<Row type="flex" justify="end" class="mt_10">
<Page
:current="searchForm.pageNumber"
:total="total"
:page-size="searchForm.pageSize"
:page-size-opts="[20, 50, 100]"
size="small"
show-total
show-elevator
show-sizer
@on-change="changePage"
@on-page-size-change="changePageSize"
/>
</Row>
</Card>
<Modal
v-model="batchCreateVisible"
title="批量制卡"
:mask-closable="false"
width="520"
@on-visible-change="onBatchCreateVisible"
>
<Form ref="batchForm" :model="batchForm" :rules="batchFormRule" :label-width="100">
<FormItem label="礼品卡名称">
<span>{{ batchCtx.giftCardName || "-" }}</span>
</FormItem>
<FormItem label="面值">
<template v-if="batchCtx.faceValue != null && batchCtx.faceValue !== ''">
<priceColorScheme
:value="batchCtx.faceValue"
:color="$mainColor"
></priceColorScheme>
</template>
<span v-else>-</span>
</FormItem>
<FormItem label="当前库存">
<span>{{ fmtInt(batchCtx.headroom) }}</span>
</FormItem>
<FormItem label="制卡张数" prop="quantity">
<InputNumber
v-model="batchForm.quantity"
:min="1"
:max="batchQuantityMax"
:precision="0"
placeholder="请输入制卡张数"
style="width: 220px"
/>
</FormItem>
<FormItem label="本批备注" prop="batchRemark">
<Input
v-model="batchForm.batchRemark"
type="textarea"
:rows="2"
maxlength="64"
show-word-limit
placeholder="选填最多64字"
style="width: 100%"
/>
</FormItem>
</Form>
<div slot="footer">
<Button @click="batchCreateVisible = false">取消</Button>
<Button type="primary" :loading="batchCreateSubmitting" @click="submitBatchCreate"
>确定</Button
>
</div>
</Modal>
<Modal
v-model="batchIssueVisible"
title="批量发卡"
:mask-closable="false"
width="560"
@on-visible-change="onBatchIssueVisible"
>
<div class="gcc-batch-issue-body">
<Form :label-width="100">
<FormItem label="礼品卡名称">
<span>{{ issueCtx.giftCardName || "-" }}</span>
</FormItem>
</Form>
<Alert type="info" show-icon class="mb_10">
请先下载模板按列填写<strong>手机号</strong><strong>发卡数量</strong>后上传发卡不区分制卡批次
</Alert>
<div class="gcc-batch-issue-actions">
<Button
type="primary"
ghost
icon="md-download"
:loading="issueTemplateDownloading"
@click="downloadIssueTemplate"
>
下载 Excel 模板
</Button>
</div>
<div class="gcc-batch-issue-upload">
<span class="gcc-batch-issue-upload-label">上传已填写的 Excel</span>
<Upload
:before-upload="onIssueImportBeforeUpload"
accept=".xls,.xlsx,application/vnd.ms-excel,application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
:show-upload-list="false"
>
<Button type="dashed" icon="ios-cloud-upload-outline">选择文件</Button>
</Upload>
<span v-if="issueFileName" class="gcc-batch-issue-filename">{{ issueFileName }}</span>
</div>
</div>
<div slot="footer">
<Button @click="batchIssueVisible = false">取消</Button>
<Button type="primary" :loading="issueImportSubmitting" @click="submitIssueImport"
>开始发卡</Button
>
</div>
</Modal>
</div>
</template>
<script>
import {
getGiftCardCashActivityPage,
giftCardCashBatchCreate,
downloadGiftCardCashIssueTemplate,
giftCardCashIssueImportByActivity,
} from "@/api/promotion";
export default {
name: "GiftCardCashActivity",
data() {
return {
loading: false,
searchForm: {
pageNumber: 1,
pageSize: 20,
sort: "createTime",
order: "desc",
giftCardName: "",
},
columns: [
{
title: "礼品卡名称",
key: "giftCardName",
minWidth: 100,
tooltip: true,
},
{
title: "礼品卡类型",
key: "cardType",
width: 200,
render: (h, params) => {
const t = params.row.cardType;
const map = { CASH: "现金卡", PICKUP: "提货卡" };
return h("span", map[t] || t || "-");
},
},
{
title: "面值",
key: "faceValue",
width: 200,
align: "right",
render: (h, params) => {
const v = params.row.faceValue;
if (v === null || v === undefined || v === "") {
return h("span", "-");
}
return h("priceColorScheme", {
props: { value: v, color: this.$mainColor },
});
},
},
{
title: "有效期",
key: "validityType",
width: 200,
render: (h, params) => {
return h("span", this.formatValidity(params.row));
},
},
{
title: "总库存",
key: "stockTotal",
width: 200,
align: "center",
render: (h, params) =>
h("span", this.fmtInt(params.row.stockTotal)),
},
{
title: "批量制卡数",
key: "producedQuantity",
width: 200,
align: "center",
render: (h, params) =>
h("span", this.fmtInt(params.row.producedQuantity)),
},
{
title: "批量发卡数",
key: "issuedCardQuantity",
width: 200,
align: "center",
render: (h, params) =>
h("span", this.fmtInt(params.row.issuedCardQuantity)),
},
{
title: "剩余库存",
key: "remainingStock",
width: 200,
align: "center",
render: (h, params) =>
h("span", this.fmtInt(params.row.remainingStock)),
},
{
title: "状态",
key: "status",
width: 200,
render: (h, params) => {
if (this.isFixedValidityExpired(params.row)) {
return h("div", [
h(
"Tag",
{
props: { color: "red" },
},
"已过期"
),
]);
}
return h("div", [
h(
"Tag",
{
props: { color: "green" },
},
"正常"
),
]);
},
},
{
title: "创建时间",
key: "createTime",
width: 200,
},
{
title: "操作",
slot: "action",
align: "right",
width: 380,
},
],
data: [],
total: 0,
linkStyle: {
color: "#2d8cf0",
cursor: "pointer",
textDecoration: "none",
},
disabledLinkStyle: {
color: "#c5c8ce",
cursor: "not-allowed",
},
sepStyle: { margin: "0 8px", color: "#dcdee2" },
batchCreateVisible: false,
batchCreateSubmitting: false,
batchCtx: {
id: "",
giftCardName: "",
faceValue: null,
remainingStock: null,
headroom: null,
},
batchForm: {
quantity: null,
batchRemark: "",
},
batchFormRule: {},
batchIssueVisible: false,
issueTemplateDownloading: false,
issueImportSubmitting: false,
issueCtx: {
id: "",
giftCardName: "",
},
issueFile: null,
issueFileName: "",
};
},
computed: {
batchQuantityMax() {
const cap = 10000;
const h = this.batchCtx.headroom;
if (h !== null && h !== undefined && h !== "" && Number(h) >= 1) {
return Math.min(cap, Number(h));
}
return cap;
},
},
created() {
this.batchFormRule = {
quantity: [{ validator: this.validateBatchQuantity, trigger: "change" }],
batchRemark: [{ type: "string", max: 64, message: "备注过长", trigger: "blur" }],
};
},
mounted() {
this.getDataList();
},
methods: {
validateBatchQuantity(rule, value, callback) {
if (value === null || value === undefined || value === "") {
callback(new Error("请填写制卡张数"));
return;
}
const n = Number(value);
if (Number.isNaN(n) || n < 1) {
callback(new Error("制卡张数至少为 1"));
return;
}
const maxQ = this.batchQuantityMax;
if (n > maxQ) {
callback(new Error(`制卡张数不能超过 ${maxQ}(可制卡上限与单次上限)`));
return;
}
if (n > 10000) {
callback(new Error("单次制卡不超过 10000 张"));
return;
}
callback();
},
fmtInt(n) {
if (n === null || n === undefined || n === "") {
return "-";
}
return n;
},
/** 固定到期类有效期且到期时间早于当前时间,列表状态展示为「已过期」 */
isFixedValidityExpired(row) {
if (!row || !row.validityType || row.validEndTime == null || row.validEndTime === "") {
return false;
}
const type = String(row.validityType).toUpperCase();
const fixedEndTypes = [
"FIXED_UNTIL",
"FIXED_END",
"FIXED",
"BY_END_TIME",
"FIXED_DATE",
];
if (!fixedEndTypes.includes(type)) {
return false;
}
const end = new Date(row.validEndTime);
if (Number.isNaN(end.getTime())) {
return false;
}
return end.getTime() < Date.now();
},
formatValidity(row) {
if (!row || !row.validityType) {
return "-";
}
const type = String(row.validityType).toUpperCase();
if (type === "LONG_TERM") {
return "长期有效";
}
if (type === "FIXED_UNTIL") {
return row.validEndTime ? String(row.validEndTime) : "固定到期";
}
if (type === "AFTER_ACTIVATE_MONTHS") {
const m = row.validMonthsAfterActivate;
return m != null && m !== "" ? `激活后${m}个月有效` : "激活后按月";
}
if (
type === "FIXED_END" ||
type === "FIXED" ||
type === "BY_END_TIME" ||
type === "FIXED_DATE"
) {
return row.validEndTime ? String(row.validEndTime) : type;
}
if (
type === "AFTER_ACTIVATE" ||
type === "MONTHS_AFTER_ACTIVATE" ||
type === "RELATIVE"
) {
const m = row.validMonthsAfterActivate;
return m != null && m !== "" ? `激活后${m}个月有效` : type;
}
const parts = [row.validityType];
if (row.validEndTime) {
parts.push(String(row.validEndTime));
}
if (row.validMonthsAfterActivate != null && row.validMonthsAfterActivate !== "") {
parts.push(`激活后${row.validMonthsAfterActivate}个月`);
}
return parts.join(" ");
},
addActivity() {
this.$router.push({ name: "add-gift-card-cash-activity" });
},
goEdit(row) {
if (!this.canEdit(row)) {
return;
}
this.$router.push({
name: "edit-gift-card-cash-activity",
query: { id: row.id },
});
},
goView(row) {
this.$router.push({
name: "edit-gift-card-cash-activity",
query: { id: row.id, onlyView: "true" },
});
},
goRecords(row) {
this.$router.push({
name: "gift-card-cash-records",
query: {
activityId: row.id,
giftCardName: row.giftCardName || "",
},
});
},
getRemainingStock(row) {
if (!row || row.remainingStock === null || row.remainingStock === undefined || row.remainingStock === "") {
return 0;
}
const n = Number(row.remainingStock);
if (Number.isNaN(n)) {
return 0;
}
return Math.max(0, Math.floor(n));
},
hasRemainingStock(row) {
return this.getRemainingStock(row) >= 1;
},
canEdit(row) {
return this.hasRemainingStock(row);
},
/** 本次批量制卡允许的最大张数:以剩余库存为准 */
getBatchCreateHeadroom(row) {
return this.getRemainingStock(row);
},
canBatchCreate(row) {
return this.hasRemainingStock(row);
},
/** 可发卡余量:与制卡独立,以剩余库存为准 */
getBatchIssuePool(row) {
return this.getRemainingStock(row);
},
canBatchIssue(row) {
if (this.isFixedValidityExpired(row)) {
return false;
}
return this.hasRemainingStock(row);
},
openBatchIssue(row) {
if (!this.canBatchIssue(row)) {
return;
}
this.issueCtx = {
id: row.id,
giftCardName: row.giftCardName,
};
this.issueFile = null;
this.issueFileName = "";
this.batchIssueVisible = true;
},
onBatchIssueVisible(open) {
if (!open) {
this.issueFile = null;
this.issueFileName = "";
}
},
downloadIssueTemplate() {
this.issueTemplateDownloading = true;
downloadGiftCardCashIssueTemplate()
.then((res) => {
this.issueTemplateDownloading = false;
if (!res) {
return;
}
if (res instanceof Blob && res.type && res.type.indexOf("json") !== -1) {
const reader = new FileReader();
reader.onload = () => {
try {
const j = JSON.parse(reader.result);
if (j && j.message) {
this.$Message.error(j.message);
} else {
this.$Message.error("模板下载失败");
}
} catch (e) {
this.$Message.error("模板下载失败");
}
};
reader.readAsText(res);
return;
}
const blob =
res instanceof Blob
? res
: new Blob([res], {
type:
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8",
});
const name = "批量发卡模板.xlsx";
if ("download" in document.createElement("a")) {
const link = document.createElement("a");
link.download = name;
link.style.display = "none";
link.href = URL.createObjectURL(blob);
document.body.appendChild(link);
link.click();
URL.revokeObjectURL(link.href);
document.body.removeChild(link);
} else if (navigator.msSaveBlob) {
navigator.msSaveBlob(blob, name);
}
this.$Message.success("模板已开始下载");
})
.catch(() => {
this.issueTemplateDownloading = false;
});
},
onIssueImportBeforeUpload(file) {
this.issueFile = file;
this.issueFileName = file.name;
return false;
},
submitIssueImport() {
if (!this.issueCtx.id) {
return;
}
if (!this.issueFile) {
this.$Message.warning("请先选择要上传的 Excel 文件");
return;
}
const fd = new FormData();
fd.append("file", this.issueFile);
this.issueImportSubmitting = true;
giftCardCashIssueImportByActivity(this.issueCtx.id, fd)
.then((res) => {
this.issueImportSubmitting = false;
if (res && res.success) {
this.$Message.success(
res.result ? `发卡任务已提交,发卡批次号:${res.result}` : "发卡任务已提交"
);
this.batchIssueVisible = false;
this.issueFile = null;
this.issueFileName = "";
this.getDataList();
}
})
.catch(() => {
this.issueImportSubmitting = false;
});
},
openBatchCreate(row) {
if (!this.canBatchCreate(row)) {
return;
}
const headroom = this.getBatchCreateHeadroom(row);
this.batchCtx = {
id: row.id,
giftCardName: row.giftCardName,
faceValue: row.faceValue,
remainingStock: row.remainingStock,
headroom,
};
this.batchForm.quantity = null;
this.batchForm.batchRemark = "";
this.batchCreateVisible = true;
},
onBatchCreateVisible(open) {
if (!open && this.$refs.batchForm && typeof this.$refs.batchForm.resetFields === "function") {
this.$refs.batchForm.resetFields();
}
},
submitBatchCreate() {
if (!this.$refs.batchForm) {
return;
}
this.$refs.batchForm.validate((valid) => {
if (!valid) {
return;
}
const q = this.batchForm.quantity;
const payload = { quantity: q };
const remark = (this.batchForm.batchRemark || "").trim();
if (remark) {
payload.batchRemark = remark;
}
this.batchCreateSubmitting = true;
giftCardCashBatchCreate(this.batchCtx.id, payload)
.then((res) => {
this.batchCreateSubmitting = false;
if (res.success) {
this.$Message.success(
res.result ? `制卡成功,批次号:${res.result}` : "制卡成功"
);
this.batchCreateVisible = false;
this.getDataList();
}
})
.catch(() => {
this.batchCreateSubmitting = false;
});
});
},
changePage(v) {
this.searchForm.pageNumber = v;
this.getDataList();
},
changePageSize(v) {
this.searchForm.pageNumber = 1;
this.searchForm.pageSize = v;
this.getDataList();
},
handleSearch() {
this.searchForm.pageNumber = 1;
this.getDataList();
},
getDataList() {
this.loading = true;
const params = { ...this.searchForm };
if (!params.giftCardName) {
delete params.giftCardName;
}
getGiftCardCashActivityPage(params)
.then((res) => {
this.loading = false;
if (res.success && res.result) {
this.data = res.result.records || [];
this.total = res.result.total || 0;
}
})
.catch(() => {
this.loading = false;
});
},
},
};
</script>
<style scoped>
.gcc-batch-issue-body {
padding: 0 4px;
}
.gcc-batch-issue-actions {
margin-bottom: 20px;
}
.gcc-batch-issue-upload {
display: flex;
flex-wrap: wrap;
align-items: center;
gap: 12px;
}
.gcc-batch-issue-upload-label {
color: #515a6e;
font-size: 14px;
}
.gcc-batch-issue-filename {
color: #2d8cf0;
font-size: 13px;
word-break: break-all;
}
</style>

View File

@@ -0,0 +1,531 @@
<template>
<div class="search gcc-batch-credentials">
<Card>
<div class="gcc-records-toolbar">
<Button type="primary" class="gcc-records-back" @click="closePage">
返回
</Button>
</div>
<div v-if="giftCardName" class="gcc-records-meta mb_10">
<strong>礼品卡</strong>{{ giftCardName }}
</div>
<div class="gcc-records-meta mb_10">
<strong>{{ batchTypeLabel }}</strong>{{ batchIdDisplay || "—" }}
<span v-if="batchRemark" style="margin-left: 12px"><strong>本批备注</strong>{{ batchRemark }}</span>
</div>
<Alert v-if="!activityId || !hasBatchId" type="warning">
缺少活动或批次参数请从{{ batchSourceLabel }}进入
</Alert>
<template v-else>
<div class="gcc-status-tabs">
<span
v-for="t in statusTabList"
:key="t.key"
:class="{ active: lifecycleTab === t.key }"
@click="onLifecycleTab(t.key)"
>{{ t.label }}</span
>
</div>
<Form ref="searchForm" :model="searchForm" inline class="search-form mb_10 gcc-filter-form">
<FormItem label="卡号" prop="cardNo" :label-width="60">
<Input v-model="searchForm.cardNo" placeholder="请输入卡号" clearable style="width: 160px" />
</FormItem>
<FormItem :label-width="0" class="gcc-combo-item">
<span class="gcc-combo-label">兑换会员</span>
<Select v-model="searchForm.redeemMemberField" style="width: 130px">
<Option value="nickName">兑换会员昵称</Option>
<Option value="mobile">兑换会员手机</Option>
</Select>
<Input
v-model="searchForm.redeemMemberKeyword"
placeholder="请输入"
clearable
style="width: 140px; margin-left: 4px"
/>
</FormItem>
<FormItem label="兑换时间" prop="redeemDateRange" :label-width="72">
<DatePicker
v-model="redeemDateRange"
type="daterange"
clearable
format="yyyy-MM-dd"
placeholder="开始日期"
style="width: 240px"
/>
</FormItem>
<FormItem :label-width="0" class="gcc-combo-item">
<span class="gcc-combo-label">激活会员</span>
<Select v-model="searchForm.activateMemberField" style="width: 130px">
<Option value="nickName">激活会员昵称</Option>
<Option value="mobile">激活会员手机</Option>
</Select>
<Input
v-model="searchForm.activateMemberKeyword"
placeholder="请输入"
clearable
style="width: 140px; margin-left: 4px"
/>
</FormItem>
<FormItem label="激活时间" prop="activateDateRange" :label-width="72">
<DatePicker
v-model="activateDateRange"
type="daterange"
clearable
format="yyyy-MM-dd"
placeholder="开始日期"
style="width: 240px"
/>
</FormItem>
<Button type="primary" icon="ios-search" class="search-btn" @click="handleSearch">搜索</Button>
</Form>
<Table :loading="loading" :columns="tableColumns" :data="data" />
<Row type="flex" justify="end" class="mt_10">
<Page
:current="searchForm.pageNumber"
:total="total"
:page-size="searchForm.pageSize"
:page-size-opts="[20, 50, 100]"
size="small"
show-total
show-elevator
show-sizer
@on-change="changePage"
@on-page-size-change="changePageSize"
/>
</Row>
</template>
</Card>
</div>
</template>
<script>
import { getGiftCardCashCredentialPage } from "@/api/promotion";
const STATUS_LABEL = {
UNISSUED: "未兑换",
UNREDEEMED: "未兑换",
UNACTIVATED: "未激活",
BOUND: "已激活",
ACTIVATED: "已激活",
VOIDED: "已销卡",
EXPIRED: "已过期",
};
const ISSUE_STATUS_LABEL = {
ISSUED: "已发卡",
UNISSUED: "未发卡",
PENDING: "待处理",
PENDING_ACTIVATION: "待激活",
ACTIVATED: "已激活",
FAILED: "发卡失败",
SUCCESS: "发卡成功",
};
export default {
name: "GiftCardCashBatchCredentials",
data() {
return {
activityId: "",
createBatchId: "",
issueBatchId: "",
giftCardName: "",
batchRemark: "",
lifecycleTab: "all",
statusTabList: [
{ key: "all", label: "全部", status: "" },
{ key: "unredeemed", label: "未兑换", status: "UNISSUED" },
{ key: "unactivated", label: "未激活", status: "UNACTIVATED" },
{ key: "activated", label: "已激活", status: "BOUND" },
{ key: "cancelled", label: "已销卡", status: "VOIDED" },
{ key: "expired", label: "已过期", status: "EXPIRED" },
],
redeemDateRange: [],
activateDateRange: [],
loading: false,
total: 0,
data: [],
searchForm: {
pageNumber: 1,
pageSize: 20,
sort: "createTime",
order: "desc",
cardNo: "",
redeemMemberField: "nickName",
redeemMemberKeyword: "",
activateMemberField: "nickName",
activateMemberKeyword: "",
},
};
},
computed: {
isIssueBatchMode() {
return !!this.issueBatchId;
},
hasBatchId() {
return !!(this.createBatchId || this.issueBatchId);
},
batchTypeLabel() {
return this.isIssueBatchMode ? "发卡批次" : "制卡批次";
},
batchSourceLabel() {
return this.isIssueBatchMode ? "发卡记录" : "制卡记录";
},
batchIdDisplay() {
return this.isIssueBatchMode ? this.issueBatchId : this.createBatchId;
},
createBatchColumns() {
return [
{ title: "卡号", key: "cardNo", minWidth: 140, tooltip: true },
{ title: "卡密", key: "cardSecret", minWidth: 120, tooltip: true },
{ title: "面额", key: "faceValue", width: 90, align: "right" },
{ title: "余额", key: "balance", width: 90, align: "right" },
{
title: "状态",
key: "status",
width: 90,
align: "center",
render: (h, params) => {
const s = params.row.status;
return h("span", STATUS_LABEL[s] || s || "—");
},
},
{ title: "会员手机", key: "memberMobile", width: 120, tooltip: true },
{ title: "会员昵称", key: "memberNickName", minWidth: 100, tooltip: true },
{ title: "绑定时间", key: "bindTime", width: 165 },
{ title: "到期时间", key: "expireTime", width: 165 },
{ title: "创建时间", key: "createTime", width: 165 },
];
},
issueBatchColumns() {
return [
{ title: "卡号", key: "cardNo", minWidth: 140, tooltip: true },
{
title: "发卡批次ID",
key: "issueBatchId",
minWidth: 160,
tooltip: true,
render: (h, params) => {
const id = params.row.issueBatchId ?? this.issueBatchId;
return h("span", id != null && id !== "" ? String(id) : "—");
},
},
{
title: "发卡会员",
key: "issueMember",
minWidth: 150,
render: (h, params) => h("span", this.formatIssueMember(params.row)),
},
{
title: "发卡状态",
key: "issueStatus",
width: 110,
align: "center",
render: (h, params) => {
const s = params.row.issueStatus;
return h("span", ISSUE_STATUS_LABEL[s] || s || "—");
},
},
{
title: "激活会员",
key: "activationMember",
minWidth: 150,
render: (h, params) => h("span", this.formatActivationMember(params.row)),
},
{
title: "激活时间",
key: "activationTime",
width: 165,
render: (h, params) => {
const t =
params.row.activationTime ||
params.row.activateTime ||
params.row.bindTime;
return h("span", t != null && t !== "" ? String(t) : "—");
},
},
{
title: "状态",
key: "status",
width: 90,
align: "center",
render: (h, params) => {
const s = params.row.status;
return h("span", STATUS_LABEL[s] || s || "—");
},
},
];
},
tableColumns() {
return this.isIssueBatchMode ? this.issueBatchColumns : this.createBatchColumns;
},
},
mounted() {
this.initFromRoute();
if (this.activityId && this.hasBatchId) {
this.loadList();
}
},
watch: {
"$route.query.createBatchId"() {
this.onRouteQueryChange();
},
"$route.query.issueBatchId"() {
this.onRouteQueryChange();
},
"$route.query.activityId"() {
this.onRouteQueryChange();
},
},
methods: {
onRouteQueryChange() {
this.initFromRoute();
if (this.activityId && this.hasBatchId) {
this.searchForm.pageNumber = 1;
this.loadList();
}
},
initFromRoute() {
const q = this.$route.query || {};
this.activityId = (q.activityId && String(q.activityId)) || "";
this.createBatchId = (q.createBatchId && String(q.createBatchId)) || "";
this.issueBatchId = (q.issueBatchId && String(q.issueBatchId)) || "";
this.giftCardName = (q.giftCardName && String(q.giftCardName)) || "";
this.batchRemark = (q.batchRemark && String(q.batchRemark)) || "";
},
closePage() {
this.$store.commit("removeTag", "gift-card-cash-batch-credentials");
localStorage.pageOpenedList = JSON.stringify(this.$store.state.app.pageOpenedList);
this.$router.go(-1);
},
formatMemberText(name, mobile) {
const n = name != null && name !== "" ? String(name) : "";
const m = mobile != null && mobile !== "" ? String(mobile) : "";
if (n && m) {
return `${n} / ${m}`;
}
return n || m || "—";
},
formatIssueMember(row) {
return this.formatMemberText(
row.issueMemberNickName ||
row.issueMemberName ||
row.exchangeMemberNickName ||
row.exchangeMemberName ||
row.memberNickName,
row.issueMemberMobile || row.exchangeMemberMobile || row.memberMobile
);
},
formatActivationMember(row) {
return this.formatMemberText(
row.activationMemberNickName ||
row.activationMemberName ||
row.activateMemberNickName ||
row.activateMemberName,
row.activationMemberMobile || row.activateMemberMobile
);
},
onLifecycleTab(key) {
if (this.lifecycleTab === key) {
return;
}
this.lifecycleTab = key;
this.searchForm.pageNumber = 1;
this.loadList();
},
handleSearch() {
this.searchForm.pageNumber = 1;
this.loadList();
},
changePage(v) {
this.searchForm.pageNumber = v;
this.loadList();
},
changePageSize(v) {
this.searchForm.pageNumber = 1;
this.searchForm.pageSize = v;
this.loadList();
},
formatDayStart(d) {
if (!d) {
return "";
}
const x = d instanceof Date ? d : new Date(d);
if (Number.isNaN(x.getTime())) {
return "";
}
const y = x.getFullYear();
const m = String(x.getMonth() + 1).padStart(2, "0");
const day = String(x.getDate()).padStart(2, "0");
return `${y}-${m}-${day} 00:00:00`;
},
formatDayEnd(d) {
if (!d) {
return "";
}
const x = d instanceof Date ? d : new Date(d);
if (Number.isNaN(x.getTime())) {
return "";
}
const y = x.getFullYear();
const m = String(x.getMonth() + 1).padStart(2, "0");
const day = String(x.getDate()).padStart(2, "0");
return `${y}-${m}-${day} 23:59:59`;
},
appendMemberSearch(params, kind, field, keyword) {
const kw = (keyword || "").trim();
if (!kw) {
return;
}
if (kind === "exchange") {
if (field === "mobile") {
params.exchangeMemberMobile = kw;
} else {
params.exchangeMemberNickName = kw;
}
} else {
if (field === "mobile") {
params.activationMemberMobile = kw;
} else {
params.activationMemberNickName = kw;
}
}
},
appendDateRange(params, kind, range) {
if (!range || !range[0] || !range[1]) {
return;
}
const start = this.formatDayStart(range[0]);
const end = this.formatDayEnd(range[1]);
if (kind === "exchange") {
if (start) {
params.exchangeTimeStart = start;
}
if (end) {
params.exchangeTimeEnd = end;
}
} else {
if (start) {
params.activationTimeStart = start;
}
if (end) {
params.activationTimeEnd = end;
}
}
},
loadList() {
if (!this.activityId || !this.hasBatchId) {
return;
}
this.loading = true;
const params = {
activityId: this.activityId,
pageNumber: this.searchForm.pageNumber,
pageSize: this.searchForm.pageSize,
sort: this.searchForm.sort,
order: this.searchForm.order,
};
if (this.isIssueBatchMode) {
params.issueBatchId = this.issueBatchId;
} else {
params.createBatchId = this.createBatchId;
}
const tabCfg = this.statusTabList.find((t) => t.key === this.lifecycleTab);
if (tabCfg && tabCfg.status) {
params.status = tabCfg.status;
}
const cardNo = (this.searchForm.cardNo || "").trim();
if (cardNo) {
params.cardNo = cardNo;
}
this.appendMemberSearch(
params,
"exchange",
this.searchForm.redeemMemberField,
this.searchForm.redeemMemberKeyword
);
this.appendMemberSearch(
params,
"activation",
this.searchForm.activateMemberField,
this.searchForm.activateMemberKeyword
);
this.appendDateRange(params, "exchange", this.redeemDateRange);
this.appendDateRange(params, "activation", this.activateDateRange);
getGiftCardCashCredentialPage(params)
.then((res) => {
this.loading = false;
if (res.success && res.result) {
this.data = res.result.records || [];
this.total = res.result.total || 0;
}
})
.catch(() => {
this.loading = false;
});
},
},
};
</script>
<style scoped>
.gcc-batch-credentials .gcc-records-toolbar {
margin-bottom: 22px;
padding-bottom: 16px;
border-bottom: 1px solid #e8eaec;
}
.gcc-batch-credentials .gcc-records-back {
font-weight: 500;
}
.gcc-batch-credentials .gcc-records-meta {
line-height: 1.6;
color: #515a6e;
}
.gcc-batch-credentials .gcc-status-tabs {
display: flex;
flex-wrap: wrap;
align-items: center;
border-bottom: 1px solid #e8eaec;
margin-bottom: 16px;
gap: 4px 8px;
}
.gcc-batch-credentials .gcc-status-tabs span {
padding: 10px 14px 12px;
cursor: pointer;
color: #808695;
font-size: 14px;
position: relative;
user-select: none;
}
.gcc-batch-credentials .gcc-status-tabs span:hover {
color: #515a6e;
}
.gcc-batch-credentials .gcc-status-tabs span.active {
color: #ff6600;
font-weight: 500;
}
.gcc-batch-credentials .gcc-status-tabs span.active::after {
content: "";
position: absolute;
left: 10px;
right: 10px;
bottom: 0;
height: 3px;
background: #ff6600;
border-radius: 2px 2px 0 0;
}
.gcc-batch-credentials .gcc-filter-form {
display: flex;
flex-wrap: wrap;
align-items: flex-end;
}
.gcc-batch-credentials .gcc-combo-item {
margin-right: 12px;
}
.gcc-batch-credentials .gcc-combo-label {
display: inline-block;
margin-right: 6px;
color: #515a6e;
font-size: 14px;
vertical-align: middle;
}
</style>

View File

@@ -0,0 +1,952 @@
<template>
<div class="search">
<Card>
<div class="gcc-records-toolbar">
<Button type="primary" class="gcc-records-back" @click="closePage">
返回
</Button>
</div>
<div v-if="giftCardName" class="gcc-records-meta mb_10">
<strong>礼品卡</strong>{{ giftCardName }}
</div>
<div v-else-if="activityId" class="gcc-records-meta mb_10">
<strong>活动ID</strong>{{ activityId }}
</div>
<Alert v-if="!activityId" type="warning">缺少活动参数请从礼品卡列表进入</Alert>
<Tabs v-else v-model="activeTab" @on-click="onTabClick">
<TabPane label="制卡记录" name="createBatch">
<Card :bordered="false" dis-hover>
<Form
ref="createFilterForm"
:model="createSearchForm"
inline
label-position="left"
class="search-form mb_10 gcc-create-batch-search"
:label-width="100"
>
<FormItem label="卡号" prop="cardNo">
<Input
v-model="createSearchForm.cardNo"
clearable
style="width: 150px"
/>
</FormItem>
<FormItem label="制卡批次ID" prop="createBatchId">
<Input
v-model="createSearchForm.createBatchId"
clearable
style="width: 170px"
/>
</FormItem>
<FormItem label="卡名称" prop="giftCardName">
<Input
v-model="createSearchForm.giftCardName"
clearable
style="width: 160px"
/>
</FormItem>
<FormItem label="制卡人名称" prop="createUserName">
<Input
v-model="createSearchForm.createUserName"
clearable
style="width: 140px"
/>
</FormItem>
<FormItem label="制卡时间" prop="createTimeRange">
<DatePicker
v-model="createSearchForm.createTimeRange"
type="daterange"
clearable
format="yyyy-MM-dd"
style="width: 220px"
/>
</FormItem>
<FormItem label="过期时间" prop="expireTimeRange">
<DatePicker
v-model="createSearchForm.expireTimeRange"
type="daterange"
clearable
format="yyyy-MM-dd"
style="width: 220px"
/>
</FormItem>
<FormItem :label-width="0">
<Button type="primary" icon="ios-search" class="search-btn" @click="handleCreateSearch">
搜索
</Button>
</FormItem>
</Form>
<Table :loading="createLoading" :columns="createColumns" :data="createData" />
<Row type="flex" justify="end" class="mt_10">
<Page
:current="createSearchForm.pageNumber"
:total="createTotal"
:page-size="createSearchForm.pageSize"
:page-size-opts="[20, 50, 100]"
size="small"
show-total
show-elevator
show-sizer
@on-change="createChangePage"
@on-page-size-change="createChangePageSize"
/>
</Row>
</Card>
</TabPane>
<TabPane label="发卡记录" name="issue">
<Card :bordered="false" dis-hover>
<Form
ref="issueFilterForm"
:model="issueSearchForm"
inline
label-position="left"
class="search-form mb_10 gcc-create-batch-search"
:label-width="100"
>
<FormItem label="卡号" prop="cardNo">
<Input
v-model="issueSearchForm.cardNo"
clearable
style="width: 150px"
/>
</FormItem>
<FormItem label="发卡批次ID" prop="issueBatchId">
<Input
v-model="issueSearchForm.issueBatchId"
clearable
style="width: 170px"
/>
</FormItem>
<FormItem label="现金卡名称" prop="giftCardName">
<Input
v-model="issueSearchForm.giftCardName"
clearable
style="width: 160px"
/>
</FormItem>
<FormItem label="发卡人名称" prop="issueUserName">
<Input
v-model="issueSearchForm.issueUserName"
clearable
style="width: 140px"
/>
</FormItem>
<FormItem label="发卡时间" prop="createTimeRange">
<DatePicker
v-model="issueSearchForm.createTimeRange"
type="daterange"
clearable
format="yyyy-MM-dd"
style="width: 220px"
/>
</FormItem>
<FormItem label="过期时间" prop="expireTimeRange">
<DatePicker
v-model="issueSearchForm.expireTimeRange"
type="daterange"
clearable
format="yyyy-MM-dd"
style="width: 220px"
/>
</FormItem>
<FormItem :label-width="0">
<Button type="primary" icon="ios-search" class="search-btn" @click="handleIssueSearch">
搜索
</Button>
</FormItem>
</Form>
<Table :loading="issueLoading" :columns="issueColumns" :data="issueData" />
<Row type="flex" justify="end" class="mt_10">
<Page
:current="issueSearchForm.pageNumber"
:total="issueTotal"
:page-size="issueSearchForm.pageSize"
:page-size-opts="[20, 50, 100]"
size="small"
show-total
show-elevator
show-sizer
@on-change="issueChangePage"
@on-page-size-change="issueChangePageSize"
/>
</Row>
</Card>
</TabPane>
<TabPane label="使用记录" name="usage">
<Card :bordered="false" dis-hover>
<Form
ref="usageFilterForm"
:model="usageSearchForm"
inline
label-position="left"
class="search-form mb_10 gcc-create-batch-search"
:label-width="90"
>
<FormItem label="订单号" prop="orderSn">
<Input
v-model="usageSearchForm.orderSn"
clearable
style="width: 160px"
/>
</FormItem>
<FormItem label="客户名称" prop="memberName">
<Input
v-model="usageSearchForm.memberName"
clearable
style="width: 150px"
/>
</FormItem>
<FormItem label="卡号" prop="cardNo">
<Input
v-model="usageSearchForm.cardNo"
clearable
style="width: 150px"
/>
</FormItem>
<FormItem label="交易时间" prop="transactionTimeRange">
<DatePicker
v-model="usageSearchForm.transactionTimeRange"
type="daterange"
clearable
format="yyyy-MM-dd"
style="width: 220px"
/>
</FormItem>
<FormItem label="交易类型" prop="transactionType">
<Select
v-model="usageSearchForm.transactionType"
clearable
style="width: 150px"
>
<Option value="ORDER_DEDUCT">订单抵扣</Option>
<Option value="ORDER_REFUND">订单退款</Option>
<Option value="ORDER_CANCEL">订单取消</Option>
</Select>
</FormItem>
<FormItem :label-width="0">
<Button type="primary" icon="ios-search" class="search-btn" @click="handleUsageSearch">
搜索
</Button>
</FormItem>
</Form>
<Table :loading="usageLoading" :columns="usageColumns" :data="usageData" />
<Row type="flex" justify="end" class="mt_10">
<Page
:current="usageSearchForm.pageNumber"
:total="usageTotal"
:page-size="usageSearchForm.pageSize"
:page-size-opts="[20, 50, 100]"
size="small"
show-total
show-elevator
show-sizer
@on-change="usageChangePage"
@on-page-size-change="usageChangePageSize"
/>
</Row>
</Card>
</TabPane>
</Tabs>
</Card>
</div>
</template>
<script>
import {
getGiftCardCashCreateBatchPage,
getGiftCardCashIssueBatchPage,
getGiftCardCashUsageRecordPage,
} from "@/api/promotion";
export default {
name: "GiftCardCashRecords",
data() {
return {
activeTab: "createBatch",
activityId: "",
giftCardName: "",
createLoading: false,
createTotal: 0,
createData: [],
createSearchForm: {
pageNumber: 1,
pageSize: 20,
sort: "createTime",
order: "desc",
cardNo: "",
createBatchId: "",
giftCardName: "",
createUserName: "",
createTimeRange: [],
expireTimeRange: [],
},
issueLoading: false,
issueTotal: 0,
issueData: [],
issueSearchForm: {
pageNumber: 1,
pageSize: 20,
sort: "createTime",
order: "desc",
cardNo: "",
issueBatchId: "",
giftCardName: "",
issueUserName: "",
createTimeRange: [],
expireTimeRange: [],
},
usageLoading: false,
usageTotal: 0,
usageData: [],
usageSearchForm: {
pageNumber: 1,
pageSize: 20,
sort: "createTime",
order: "desc",
orderSn: "",
memberName: "",
cardNo: "",
transactionType: "",
transactionTimeRange: [],
},
};
},
computed: {
createColumns() {
return [
{
title: "制卡批次ID",
key: "createBatchId",
minWidth: 100,
tooltip: true,
align: "left",
render: (h, p) => {
const id = p.row.createBatchId ?? p.row.id;
return h("span", id != null && id !== "" ? String(id) : "-");
},
},
{
title: "卡号范围",
key: "cardNoRange",
minWidth: 160,
tooltip: true,
align: "left",
render: (h, p) => {
const t = p.row.cardNoRange;
return h("span", t != null && t !== "" ? String(t) : "-");
},
},
{
title: "面值",
key: "faceValue",
width: 150,
align: "left",
render: (h, p) => {
const v = p.row.faceValue;
if (v === null || v === undefined || v === "") {
return h("span", "-");
}
return h("priceColorScheme", {
props: { value: v, color: this.$mainColor },
});
},
},
{
title: "礼品卡名称",
key: "giftCardName",
width: 150,
tooltip: true,
align: "left",
render: (h, p) => {
const t = p.row.giftCardName ?? this.giftCardName;
return h("span", t != null && t !== "" ? String(t) : "-");
},
},
{ title: "制卡人", key: "createUserName", width: 150, tooltip: true ,align: "left"},
{ title: "制卡时间", key: "createTime", width: 200,align: "left" },
{
title: "制卡数量",
key: "quantity",
width: 200,
align: "left",
render: (h, p) => {
const v = p.row.quantity;
if (v === null || v === undefined || v === "") {
return h("span", "-");
}
return h("span", String(v));
},
},
{
title: "过期时间",
key: "expireTime",
width: 200,
align: "left",
render: (h, p) => {
const t = p.row.expireTime;
return h("span", t != null && t !== "" ? String(t) : "长期有效");
},
},
{
title: "操作",
key: "action",
width: 150,
align: "center",
fixed: "right",
render: (h, params) => {
return h(
"Button",
{
props: { type: "primary", size: "small" },
on: { click: () => this.goBatchCredentials(params.row) },
},
"查看"
);
},
},
];
},
issueColumns() {
return [
{
title: "发卡批次ID",
key: "issueBatchId",
minWidth: 160,
tooltip: true,
render: (h, p) => {
const id = p.row.issueBatchId ?? p.row.id;
return h("span", id != null && id !== "" ? String(id) : "-");
},
},
{
title: "卡号范围",
key: "cardNoRange",
minWidth: 160,
tooltip: true,
render: (h, p) => {
const t = p.row.cardNoRange;
return h("span", t != null && t !== "" ? String(t) : "-");
},
},
{
title: "面值",
key: "faceValue",
width: 120,
align: "right",
render: (h, p) => {
const v = p.row.faceValue;
if (v === null || v === undefined || v === "") {
return h("span", "-");
}
return h("priceColorScheme", {
props: { value: v, color: this.$mainColor },
});
},
},
{
title: "卡名称",
key: "giftCardName",
minWidth: 120,
tooltip: true,
render: (h, p) => {
const t = p.row.giftCardName ?? this.giftCardName;
return h("span", t != null && t !== "" ? String(t) : "-");
},
},
{
title: "发卡人",
key: "issueUserName",
minWidth: 100,
tooltip: true,
render: (h, p) => {
const t = p.row.issueUserName;
return h("span", t != null && t !== "" ? String(t) : "-");
},
},
{ title: "发卡时间", key: "createTime", width: 170 },
{
title: "发卡数量",
key: "totalCards",
width: 100,
align: "center",
render: (h, p) => {
const v = p.row.totalCards;
if (v === null || v === undefined || v === "") {
return h("span", "-");
}
return h("span", String(v));
},
},
{
title: "过期时间",
key: "expireTime",
width: 170,
render: (h, p) => {
const t = p.row.expireTime;
return h("span", t != null && t !== "" ? String(t) : "长期有效");
},
},
{
title: "操作",
key: "action",
width: 150,
align: "center",
fixed: "right",
render: (h, params) => {
return h(
"Button",
{
props: { type: "primary", size: "small" },
on: { click: () => this.goIssueBatchCredentials(params.row) },
},
"查看"
);
},
},
];
},
usageColumns() {
return [
{ title: "订单号", key: "orderSn", minWidth: 160, tooltip: true },
{
title: "交易类型",
key: "transactionType",
minWidth: 120,
render: (h, p) => h("span", this.formatUsageBizType(p.row.transactionType || p.row.bizType)),
},
{ title: "卡号", key: "cardNo", minWidth: 150, tooltip: true },
{
title: "现金卡信息",
key: "giftCardName",
minWidth: 180,
render: (h, p) => {
const name = p.row.giftCardName || this.giftCardName || "-";
const faceValue = p.row.faceValue;
return h("div", [
h("div", String(name)),
h(
"div",
{ style: { color: "#808695", marginTop: "4px" } },
`面额:${faceValue != null && faceValue !== "" ? faceValue : "-"}`
),
]);
},
},
{
title: "金额",
key: "changeAmount",
width: 130,
align: "right",
render: (h, p) => {
const display = this.getUsageAmountDisplay(p.row);
if (!display) {
return h("span", "-");
}
return h("priceColorScheme", {
props: { value: display.amount, color: display.color },
});
},
},
{
title: "余额",
key: "balanceAfter",
width: 130,
align: "right",
render: (h, p) => {
const v = p.row.balanceAfter;
if (v === null || v === undefined || v === "") {
return h("span", "-");
}
return h("priceColorScheme", {
props: { value: v, color: this.$mainColor },
});
},
},
{
title: "交易时间",
key: "transactionTime",
width: 170,
render: (h, p) => {
const t = p.row.transactionTime || p.row.createTime;
return h("span", t != null && t !== "" ? String(t) : "-");
},
},
{
title: "客户信息",
key: "memberName",
minWidth: 150,
render: (h, p) => {
const name = p.row.memberName || "-";
const mobile = p.row.memberMobile || "-";
return h("div", [
h("div", String(name)),
h("div", { style: { color: "#808695", marginTop: "4px" } }, String(mobile)),
]);
},
},
{
title: "操作",
key: "action",
width: 100,
align: "center",
fixed: "right",
render: (h, p) => {
const orderSn = p.row.orderSn;
if (!orderSn) {
return h("span", { style: { color: "#c5c8ce" } }, "详情");
}
return h(
"Button",
{
props: { type: "primary", size: "small" },
on: { click: () => this.goOrderDetail(orderSn) },
},
"详情"
);
},
},
];
},
},
mounted() {
this.initFromRoute();
if (this.activityId) {
this.loadCreateBatchList();
}
},
watch: {
"$route.query.activityId"(id) {
this.initFromRoute();
if (id && this.activeTab === "createBatch") {
this.loadCreateBatchList();
}
if (id && this.activeTab === "issue") {
this.issueSearchForm.pageNumber = 1;
this.loadIssueBatchList();
}
if (id && this.activeTab === "usage") {
this.usageSearchForm.pageNumber = 1;
this.loadUsageRecordList();
}
},
},
methods: {
initFromRoute() {
this.activityId = (this.$route.query.activityId && String(this.$route.query.activityId)) || "";
this.giftCardName = (this.$route.query.giftCardName && String(this.$route.query.giftCardName)) || "";
},
closePage() {
this.$store.commit("removeTag", "gift-card-cash-records");
localStorage.pageOpenedList = JSON.stringify(this.$store.state.app.pageOpenedList);
this.$router.go(-1);
},
goBatchCredentials(row) {
const batchId = row.createBatchId != null && row.createBatchId !== "" ? row.createBatchId : row.id;
this.$router.push({
name: "gift-card-cash-batch-credentials",
query: {
activityId: this.activityId,
createBatchId: batchId,
giftCardName: row.giftCardName || this.giftCardName || "",
batchRemark: row.batchRemark || "",
},
});
},
goIssueBatchCredentials(row) {
const batchId = row.issueBatchId != null && row.issueBatchId !== "" ? row.issueBatchId : row.id;
this.$router.push({
name: "gift-card-cash-batch-credentials",
query: {
activityId: this.activityId,
issueBatchId: batchId,
giftCardName: row.giftCardName || this.giftCardName || "",
},
});
},
goOrderDetail(orderSn) {
this.$router.push({
name: "order-detail",
query: { sn: orderSn },
});
},
onTabClick(name) {
if (name === "createBatch" && this.activityId) {
this.loadCreateBatchList();
}
if (name === "issue" && this.activityId) {
this.loadIssueBatchList();
}
if (name === "usage" && this.activityId) {
this.loadUsageRecordList();
}
},
handleCreateSearch() {
this.createSearchForm.pageNumber = 1;
this.loadCreateBatchList();
},
/** 日期区间 → yyyy-MM-dd HH:mm:ss供 Spring 绑定 Date */
toApiDateTimeBoundary(val, endOfDay) {
const dt = val instanceof Date ? val : new Date(val);
if (Number.isNaN(dt.getTime())) {
return null;
}
const y = dt.getFullYear();
const m = String(dt.getMonth() + 1).padStart(2, "0");
const d = String(dt.getDate()).padStart(2, "0");
return endOfDay ? `${y}-${m}-${d} 23:59:59` : `${y}-${m}-${d} 00:00:00`;
},
appendDateRangeToParams(params, range, startKey, endKey) {
if (!Array.isArray(range) || range.length < 2 || !range[0] || !range[1]) {
return;
}
const start = this.toApiDateTimeBoundary(range[0], false);
const end = this.toApiDateTimeBoundary(range[1], true);
if (start) {
params[startKey] = start;
}
if (end) {
params[endKey] = end;
}
},
appendTrimmedParam(params, key, value) {
const text = (value || "").trim();
if (text) {
params[key] = text;
}
},
createChangePage(v) {
this.createSearchForm.pageNumber = v;
this.loadCreateBatchList();
},
createChangePageSize(v) {
this.createSearchForm.pageNumber = 1;
this.createSearchForm.pageSize = v;
this.loadCreateBatchList();
},
loadCreateBatchList() {
if (!this.activityId) {
return;
}
this.createLoading = true;
const params = {
activityId: this.activityId,
pageNumber: this.createSearchForm.pageNumber,
pageSize: this.createSearchForm.pageSize,
sort: this.createSearchForm.sort,
order: this.createSearchForm.order,
};
const cardNo = (this.createSearchForm.cardNo || "").trim();
if (cardNo) {
params.cardNo = cardNo;
}
const createBatchId = (this.createSearchForm.createBatchId || "").trim();
if (createBatchId) {
params.createBatchId = createBatchId;
}
const giftCardName = (this.createSearchForm.giftCardName || "").trim();
if (giftCardName) {
params.giftCardName = giftCardName;
}
const createUserName = (this.createSearchForm.createUserName || "").trim();
if (createUserName) {
params.createUserName = createUserName;
}
this.appendDateRangeToParams(
params,
this.createSearchForm.createTimeRange,
"createTimeStart",
"createTimeEnd"
);
this.appendDateRangeToParams(
params,
this.createSearchForm.expireTimeRange,
"expireTimeStart",
"expireTimeEnd"
);
getGiftCardCashCreateBatchPage(params)
.then((res) => {
this.createLoading = false;
if (res.success && res.result) {
this.createData = res.result.records || [];
this.createTotal = res.result.total || 0;
}
})
.catch(() => {
this.createLoading = false;
});
},
issueChangePage(v) {
this.issueSearchForm.pageNumber = v;
this.loadIssueBatchList();
},
issueChangePageSize(v) {
this.issueSearchForm.pageNumber = 1;
this.issueSearchForm.pageSize = v;
this.loadIssueBatchList();
},
handleIssueSearch() {
this.issueSearchForm.pageNumber = 1;
this.loadIssueBatchList();
},
loadIssueBatchList() {
if (!this.activityId) {
return;
}
this.issueLoading = true;
const params = {
activityId: this.activityId,
pageNumber: this.issueSearchForm.pageNumber,
pageSize: this.issueSearchForm.pageSize,
sort: this.issueSearchForm.sort,
order: this.issueSearchForm.order,
};
[
"cardNo",
"issueBatchId",
"giftCardName",
"issueUserName",
].forEach((key) => {
this.appendTrimmedParam(params, key, this.issueSearchForm[key]);
});
this.appendDateRangeToParams(
params,
this.issueSearchForm.createTimeRange,
"createTimeStart",
"createTimeEnd"
);
this.appendDateRangeToParams(
params,
this.issueSearchForm.expireTimeRange,
"expireTimeStart",
"expireTimeEnd"
);
getGiftCardCashIssueBatchPage(params)
.then((res) => {
this.issueLoading = false;
if (res.success && res.result) {
const r = res.result;
this.issueData = r.records || r.list || r.recordsList || [];
this.issueTotal = r.total != null ? r.total : r.totalCount || 0;
}
})
.catch(() => {
this.issueLoading = false;
});
},
handleUsageSearch() {
this.usageSearchForm.pageNumber = 1;
this.loadUsageRecordList();
},
usageChangePage(v) {
this.usageSearchForm.pageNumber = v;
this.loadUsageRecordList();
},
usageChangePageSize(v) {
this.usageSearchForm.pageNumber = 1;
this.usageSearchForm.pageSize = v;
this.loadUsageRecordList();
},
formatUsageFlowType(type) {
const map = {
INCREASE: "增加",
DECREASE: "减少",
};
return map[type] || type || "-";
},
formatUsageBizType(type) {
const map = {
ORDER_DEDUCT: "订单抵扣",
ORDER_REFUND: "订单退款",
ORDER_CANCEL: "订单取消",
CARD_ACTIVATE: "卡激活",
};
return map[type] || type || "-";
},
getUsageAmountDisplay(row) {
const raw =
row.changeAmount != null && row.changeAmount !== "" ? row.changeAmount : row.deductAmount;
if (raw === null || raw === undefined || raw === "") {
return null;
}
const num = Number(raw);
if (Number.isNaN(num)) {
return null;
}
const txType = row.transactionType || row.bizType;
let color = this.$mainColor;
if (txType === "ORDER_DEDUCT") {
color = "red";
} else if (txType === "ORDER_REFUND") {
color = "green";
}
return { amount: Math.abs(num), color };
},
loadUsageRecordList() {
if (!this.activityId) {
return;
}
this.usageLoading = true;
const params = {
pageNumber: this.usageSearchForm.pageNumber,
pageSize: this.usageSearchForm.pageSize,
sort: this.usageSearchForm.sort,
order: this.usageSearchForm.order,
};
[
"orderSn",
"memberName",
"cardNo",
"transactionType",
].forEach((key) => {
this.appendTrimmedParam(params, key, this.usageSearchForm[key]);
});
this.appendDateRangeToParams(
params,
this.usageSearchForm.transactionTimeRange,
"transactionTimeStart",
"transactionTimeEnd"
);
getGiftCardCashUsageRecordPage(params)
.then((res) => {
this.usageLoading = false;
if (res.success && res.result) {
const r = res.result;
this.usageData = r.records || r.list || [];
this.usageTotal = r.total != null ? r.total : r.totalCount || 0;
}
})
.catch(() => {
this.usageLoading = false;
});
},
},
};
</script>
<style scoped lang="scss">
.gcc-records-toolbar {
margin-bottom: 22px;
padding-bottom: 16px;
border-bottom: 1px solid #e8eaec;
}
.gcc-records-back {
font-weight: 500;
}
.gcc-records-meta {
line-height: 1.6;
color: #515a6e;
}
.gcc-create-batch-search.search-form {
justify-content: flex-start;
align-items: flex-end;
flex-wrap: wrap;
text-align: left;
}
/* 与全局 .search-form > .ivu-form-item 的 margin-left:10px 对齐到表格左缘 */
.gcc-create-batch-search.search-form > .ivu-form-item:first-of-type {
margin-left: 0 !important;
}
.gcc-create-batch-search.search-form ::v-deep .ivu-form-item-label {
text-align: left;
}
</style>

View File

@@ -123,6 +123,17 @@ export default {
this.$options.filters.unitPrice(params.row.kanjiaSettlementPrice, "¥")
);
},
}, {
title: '礼品卡补贴',
key: 'giftCardSubsidy',
align: 'center',
width: 200,
render: (h, params) => {
return h(
"div",
this.$options.filters.unitPrice(params.row.giftCardSubsidy, "¥")
);
},
}, {
title: '分销佣金',
key: 'distributionCommission',
@@ -204,6 +215,19 @@ export default {
}
});
},
}, {
title: '礼品卡返还',
key: 'giftCardRefundSubsidy',
align: 'center',
width: 200,
render: (h, params) => {
return h("priceColorScheme", {
props: {
value: (0 - params.row.giftCardRefundSubsidy),
color: this.$mainColor
}
});
},
}, {
title: '退单返还分销佣金',
key: 'distributionRefundCommission',
@@ -237,12 +261,14 @@ export default {
siteCouponCommission: 0,
pointSettlementPrice: 0,
kanjiaSettlementPrice: 0,
giftCardSubsidy: 0,
distributionCommission: 0,
commissionPrice: 0,
refundPrice: 0,
siteCouponRefundCommission: 0,
pointRefundSettlementPrice: 0,
kanjiaRefundSettlementPrice: 0,
giftCardRefundSubsidy: 0,
distributionRefundCommission: 0,
refundCommissionPrice: 0
},
@@ -568,6 +594,8 @@ export default {
// 账单详细
initTable() {
let bill = this.bill;
const money = (val) =>
val === null || val === undefined || val === "" ? 0 : val;
this.data[0].name = "结算单状态";
this.data[0].value = filters.unixSellerBillStatus(bill.billStatus);
@@ -596,19 +624,21 @@ export default {
this.data[8].name = "支付时间";
this.data[8].value = bill.payTime === null ? "未付款" : bill.payTime;
this.billData[0].billPrice = this.bill.billPrice;
this.billData[0].orderPrice = this.bill.orderPrice;
this.billData[0].siteCouponCommission = this.bill.siteCouponCommission;
this.billData[0].pointSettlementPrice = this.bill.pointSettlementPrice;
this.billData[0].kanjiaSettlementPrice = this.bill.kanjiaSettlementPrice;
this.billData[0].distributionCommission = this.bill.distributionCommission;
this.billData[0].commissionPrice = this.bill.commissionPrice;
this.billData[0].refundPrice = this.bill.refundPrice;
this.billData[0].siteCouponRefundCommission = this.bill.siteCouponRefundCommission;
this.billData[0].pointRefundSettlementPrice = this.bill.pointRefundSettlementPrice;
this.billData[0].kanjiaRefundSettlementPrice = this.bill.kanjiaRefundSettlementPrice;
this.billData[0].distributionRefundCommission = this.bill.distributionRefundCommission;
this.billData[0].refundCommissionPrice = this.bill.refundCommissionPrice;
this.billData[0].billPrice = money(this.bill.billPrice);
this.billData[0].orderPrice = money(this.bill.orderPrice);
this.billData[0].siteCouponCommission = money(this.bill.siteCouponCommission);
this.billData[0].pointSettlementPrice = money(this.bill.pointSettlementPrice);
this.billData[0].kanjiaSettlementPrice = money(this.bill.kanjiaSettlementPrice);
this.billData[0].giftCardSubsidy = money(this.bill.giftCardSubsidy);
this.billData[0].distributionCommission = money(this.bill.distributionCommission);
this.billData[0].commissionPrice = money(this.bill.commissionPrice);
this.billData[0].refundPrice = money(this.bill.refundPrice);
this.billData[0].siteCouponRefundCommission = money(this.bill.siteCouponRefundCommission);
this.billData[0].pointRefundSettlementPrice = money(this.bill.pointRefundSettlementPrice);
this.billData[0].kanjiaRefundSettlementPrice = money(this.bill.kanjiaRefundSettlementPrice);
this.billData[0].giftCardRefundSubsidy = money(this.bill.giftCardRefundSubsidy);
this.billData[0].distributionRefundCommission = money(this.bill.distributionRefundCommission);
this.billData[0].refundCommissionPrice = money(this.bill.refundCommissionPrice);
},
getOrder() {
API_Shop.getStoreFlow(this.id, this.orderParam).then((res) => {