diff --git a/buyer/src/api/cart.js b/buyer/src/api/cart.js index c8d13461..e2ab9f50 100644 --- a/buyer/src/api/cart.js +++ b/buyer/src/api/cart.js @@ -92,6 +92,21 @@ export function selectCoupon (params) { }); } +/** + * 选择礼品卡 + * @param way 购物车购买:CART/立即购买:BUY_NOW/拼团购买:PINTUAN / 积分购买:POINT + * @param credentialId 礼品卡凭证 id;used=false 且不传则清空全部 + * @param used 使用 true / 弃用 false + */ +export function selectGiftCard (params) { + return request({ + url: '/buyer/trade/carts/select/giftCard', + method: Method.GET, + needToken: true, + params + }); +} + /** * 可用优惠券数量 */ diff --git a/buyer/src/api/promotion.js b/buyer/src/api/promotion.js index e0856d52..c917c1fe 100644 --- a/buyer/src/api/promotion.js +++ b/buyer/src/api/promotion.js @@ -57,3 +57,50 @@ export function pointGoodsDetail (id) { id }); } + +/** + * 分页查询当前客户礼品卡 + */ +export function getGiftCardCashMemberCardPage (params) { + return request({ + url: '/buyer/promotion/giftCardCash/memberCard', + method: Method.GET, + needToken: true, + params + }); +} + +/** + * 绑定礼品卡(卡号 + 兑换码/卡密) + */ +export function bindGiftCardCashMemberCard (data) { + return request({ + url: '/buyer/promotion/giftCardCash/memberCard/bind', + method: Method.POST, + needToken: true, + headers: { 'Content-Type': 'application/json' }, + data + }); +} + +/** + * 激活礼品卡 + */ +export function activateGiftCardCashMemberCard (memberCardId) { + return request({ + url: `/buyer/promotion/giftCardCash/memberCard/${memberCardId}/activate`, + method: Method.POST, + needToken: true + }); +} + +/** + * 下单页可用礼品卡列表 + */ +export function getAvailableGiftCardCashMemberCards () { + return request({ + url: '/buyer/promotion/giftCardCash/memberCard/available', + method: Method.GET, + needToken: true + }); +} diff --git a/buyer/src/pages/home/orderCenter/OrderDetail.vue b/buyer/src/pages/home/orderCenter/OrderDetail.vue index cafa529c..65eb36de 100644 --- a/buyer/src/pages/home/orderCenter/OrderDetail.vue +++ b/buyer/src/pages/home/orderCenter/OrderDetail.vue @@ -231,6 +231,14 @@ }} +
+ 礼品卡抵扣:-{{ + order.order.priceDetailDTO.giftCardPrice || 0 | unitPrice("¥") + }} +
活动优惠:-{{ order.order.discountPrice | unitPrice("¥") }} diff --git a/buyer/src/pages/home/userCenter/MyGiftCards.vue b/buyer/src/pages/home/userCenter/MyGiftCards.vue new file mode 100644 index 00000000..ad8d447e --- /dev/null +++ b/buyer/src/pages/home/userCenter/MyGiftCards.vue @@ -0,0 +1,461 @@ + + + + + diff --git a/buyer/src/pages/payment/Pay.vue b/buyer/src/pages/payment/Pay.vue index 019b5e67..0ca28643 100644 --- a/buyer/src/pages/payment/Pay.vue +++ b/buyer/src/pages/payment/Pay.vue @@ -195,6 +195,60 @@
+ +
+
+
+ 使用礼品卡 + + (已抵扣 {{ giftCardDeductAmount | unitPrice("¥") }}) + +
+ + 使用说明 + +
+
+
+
+
暂无可用礼品卡
+
+
+
+ +
+ +
+
+
+
+
+
+
@@ -209,6 +263,9 @@
优惠券金额:-{{ priceDetailDTO.couponPrice | unitPrice("¥") }}
+
+ 礼品卡抵扣:-{{ giftCardDeductAmount | unitPrice("¥") }} +
应付积分:{{ priceDetailDTO.payPoint }} @@ -238,6 +295,14 @@ + +

+ 请在礼品卡有效期内使用;结算时勾选礼品卡即可按规则抵扣订单金额,可与优惠券等活动叠加规则以平台说明为准。放弃勾选或取消抵扣将恢复对应余额。 +

+
+ +
+
@@ -250,6 +315,7 @@ import { createTrade, selectAddr, selectCoupon, + selectGiftCard, setShipMethod, setStoreAddressId, shippingMethodList, @@ -282,6 +348,30 @@ export default { "" ); }, + giftCardDeductAmount() { + if (this.tradeGiftCardDeductTotal != null && Number(this.tradeGiftCardDeductTotal) > 0) { + return Number(this.tradeGiftCardDeductTotal); + } + const items = this.giftCardDeductItems || []; + let sum = 0; + items.forEach((it) => { + sum += Number(it.deductAmount || 0); + }); + if (sum > 0) { + return sum; + } + const p = this.priceDetailDTO || {}; + const n = Number( + p.giftCardPrice != null + ? p.giftCardPrice + : p.giftCardDiscountPrice != null + ? p.giftCardDiscountPrice + : p.memberCardPrice != null + ? p.memberCardPrice + : 0 + ); + return Number.isFinite(n) ? n : 0; + }, }, data() { return { @@ -326,6 +416,11 @@ export default { usedCouponId: [], // 已使用优惠券id selectedCoupon: {}, // 已选优惠券对象 storeId: '', //店铺Id + giftCardList: [], // TradeDTO.canUseGiftCards + giftCardNoticeModal: false, + giftCardDeductItems: [], // 已选礼品卡抵扣明细(TradeDTO.giftCardDeductItems) + tradeGiftCardDeductTotal: null, // TradeDTO.giftCardDeductTotal + selectedGiftCardCredentialIds: [], // 已选凭证 id,与 deductItems 同步 }; }, mounted() { @@ -476,12 +571,110 @@ export default { this.$forceUpdate(); }); } + this.giftCardDeductItems = Array.isArray(res.result.giftCardDeductItems) + ? res.result.giftCardDeductItems + : []; + this.tradeGiftCardDeductTotal = + res.result.giftCardDeductTotal != null && res.result.giftCardDeductTotal !== "" + ? Number(res.result.giftCardDeductTotal) + : null; + this.giftCardList = Array.isArray(res.result.canUseGiftCards) ? res.result.canUseGiftCards : []; + this.syncGiftCardSelectionFromCart(res.result); } }) .catch(() => { this.$Spin.hide(); }); }, + syncGiftCardSelectionFromCart(result) { + if (!result) { + this.selectedGiftCardCredentialIds = []; + return; + } + const selectedIds = result.selectedGiftCardIds; + if (Array.isArray(selectedIds) && selectedIds.length) { + this.selectedGiftCardCredentialIds = selectedIds + .map((id) => (id != null && id !== "" ? String(id) : "")) + .filter(Boolean); + return; + } + const items = Array.isArray(result.giftCardDeductItems) ? result.giftCardDeductItems : []; + if (items.length) { + this.selectedGiftCardCredentialIds = items + .map((it) => (it.credentialId != null && it.credentialId !== "" ? String(it.credentialId) : "")) + .filter(Boolean); + return; + } + const pd = result.priceDetailDTO || {}; + const id = + result.selectedGiftCardCredentialId || + result.usedGiftCardCredentialId || + pd.selectedGiftCardCredentialId || + pd.usedGiftCardCredentialId || + (result.selectedGiftCard && (result.selectedGiftCard.id || result.selectedGiftCard.credentialId)) || + (result.giftCardCashSelected && result.giftCardCashSelected.id) || + null; + this.selectedGiftCardCredentialIds = + id != null && id !== "" ? [String(id)] : []; + }, + formatGiftFaceValue(val) { + if (val == null || val === "") { + return "—"; + } + const n = Number(val); + if (Number.isNaN(n)) { + return String(val); + } + return Number.isInteger(n) ? String(n) : n.toFixed(2).replace(/\.?0+$/, ""); + }, + formatGiftExpire(row) { + const t = row && row.expireTime; + if (!t) { + return "长期有效"; + } + const d = new Date(t); + if (Number.isNaN(d.getTime())) { + return "长期有效"; + } + if (d.getFullYear() >= 2099) { + return "长期有效"; + } + const y = d.getFullYear(); + const m = String(d.getMonth() + 1).padStart(2, "0"); + const day = String(d.getDate()).padStart(2, "0"); + return `${y}-${m}-${day} 到期`; + }, + toggleGiftCard(item) { + if (!item || item.id == null || item.id === "") { + return; + } + if (this.isGiftCardSelected(item)) { + this.useGiftCard(item.id, false); + } else { + this.useGiftCard(item.id, true); + } + }, + isGiftCardSelected(item) { + if (!item || !this.selectedGiftCardCredentialIds.length) { + return false; + } + const id = item.id != null ? String(item.id) : ""; + return id && this.selectedGiftCardCredentialIds.includes(id); + }, + useGiftCard(credentialId, used) { + const params = { + way: this.$route.query.way, + used, + }; + if (credentialId != null && credentialId !== "") { + params.credentialId = String(credentialId); + } + selectGiftCard(params).then((res) => { + if (res.success) { + this.init(); + } + }); + }, getCouponNum() { // 获取可用优惠券数量 couponNum({ way: this.$route.query.way }).then((res) => { @@ -1189,4 +1382,189 @@ export default { max-height: 260px; overflow: scroll; } + +.pay-gcc-module { + margin-top: 10px; +} +.pay-gcc-head { + display: flex; + align-items: center; + justify-content: space-between; + padding-bottom: 10px; + border-bottom: 1px solid #eee; +} +.pay-gcc-title { + font-size: 18px; + font-weight: 500; + color: #333; +} +.pay-gcc-deduct { + margin-left: 8px; + font-size: 14px; + font-weight: normal; + color: #666; +} +.pay-gcc-deduct-num { + color: #e54d42; + font-weight: 600; +} +.pay-gcc-help { + font-size: 13px; + color: #999; + cursor: pointer; + display: inline-flex; + align-items: center; + gap: 2px; +} +.pay-gcc-help:hover { + color: $theme_color; +} +.pay-gcc-body { + min-height: 120px; + margin-top: 16px; +} +.pay-gcc-panel { + position: relative; +} +.pay-gcc-grid-wrap { + position: relative; + min-height: 100px; +} +.pay-gcc-empty { + padding: 24px 0; + text-align: center; + color: #999; + font-size: 14px; +} +.pay-gcc-cards { + display: flex; + flex-wrap: wrap; + gap: 16px 18px; +} +.pay-gcc-item { + position: relative; + width: 280px; + max-width: 100%; + border-radius: 10px; + overflow: hidden; + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1); + cursor: pointer; + transition: transform 0.15s, box-shadow 0.15s; +} +.pay-gcc-item:hover { + transform: translateY(-2px); + box-shadow: 0 6px 16px rgba(0, 0, 0, 0.12); +} +.pay-gcc-item-inner { + position: relative; + min-height: 150px; + background: linear-gradient(135deg, #ff9a4a 0%, #ff7729 48%, #e86a1f 100%); +} +.pay-gcc-pattern { + position: absolute; + inset: 0; + opacity: 0.2; + pointer-events: none; + background-image: repeating-linear-gradient( + -32deg, + transparent, + transparent 5px, + rgba(255, 255, 255, 0.45) 5px, + rgba(255, 255, 255, 0.45) 6px + ); +} +.pay-gcc-item-main { + position: relative; + z-index: 1; + padding: 14px 14px 12px; + color: #fff; +} +.pay-gcc-top-row { + display: flex; + justify-content: space-between; + align-items: flex-start; + gap: 10px; +} +.pay-gcc-name { + font-size: 16px; + font-weight: 700; + line-height: 1.3; +} +.pay-gcc-face { + margin-top: 6px; + font-size: 12px; + opacity: 0.92; +} +.pay-gcc-right-meta { + text-align: right; + flex-shrink: 0; +} +.pay-gcc-type { + font-size: 15px; + font-weight: 700; +} +.pay-gcc-valid { + margin-top: 6px; + font-size: 11px; + opacity: 0.9; + white-space: nowrap; +} +.pay-gcc-balance-row { + margin-top: 14px; + display: flex; + align-items: baseline; + gap: 6px; +} +.pay-gcc-amt { + font-size: 22px; + font-weight: 700; + letter-spacing: 0.02em; +} +.pay-gcc-bal-label { + font-size: 13px; + opacity: 0.9; +} +.pay-gcc-no { + margin-top: 10px; + font-size: 11px; + opacity: 0.75; + word-break: break-all; + line-height: 1.4; +} +.pay-gcc-corner { + position: absolute; + right: 0; + bottom: 0; + z-index: 2; + width: 44px; + height: 44px; + overflow: hidden; + pointer-events: none; +} +.pay-gcc-corner::before { + content: ""; + position: absolute; + right: -22px; + bottom: -22px; + width: 44px; + height: 44px; + background: #e54d42; + transform: rotate(45deg); +} +.pay-gcc-corner .ivu-icon { + position: absolute; + right: 3px; + bottom: 3px; + color: #fff; + font-size: 15px; + z-index: 1; +} +.pay-gcc-notice-p { + line-height: 1.75; + color: #515a6e; + margin-bottom: 16px; +} +.pay-gcc-notice-foot { + text-align: right; +} diff --git a/buyer/src/pages/user/Home.vue b/buyer/src/pages/user/Home.vue index 28d53b3f..4ff905f9 100644 --- a/buyer/src/pages/user/Home.vue +++ b/buyer/src/pages/user/Home.vue @@ -10,7 +10,7 @@ theme="light" width="auto" :active-name="$route.name" - :open-names="['订单中心', '会员中心', '账户中心']" + :open-names="['订单中心', '会员中心']" @on-select="onSelect" >
diff --git a/buyer/src/pages/user/menu.js b/buyer/src/pages/user/menu.js index 87f925f0..846f182f 100644 --- a/buyer/src/pages/user/menu.js +++ b/buyer/src/pages/user/menu.js @@ -81,27 +81,25 @@ const member = [{ icon: '', title: '我的等级', path: 'MemberGrade' - } - ], - display: true -}]; - -// 账户中心 -const user = [{ - icon: '', - title: '账户中心', - menus: [{ + }, + { icon: '', title: '我的优惠券', path: 'Coupons' }, { icon: '', - title: '资金管理', + title: '我的余额', path: 'MoneyManagement' - }], + }, + { + icon: '', + title: '我的礼品卡', + path: 'MyGiftCards' + } + ], display: true -}] +}]; // 活动中心 // const activity = [{ @@ -171,6 +169,6 @@ const user = [{ // ] // wholesale[0], shop[0] let menuList = [] -menuList.push(order[0], member[0], user[0]) +menuList.push(order[0], member[0]) export default menuList diff --git a/buyer/src/router/index.js b/buyer/src/router/index.js index 09c59e9f..0cc27969 100644 --- a/buyer/src/router/index.js +++ b/buyer/src/router/index.js @@ -76,15 +76,16 @@ const MsgDetail = (resolve) => require(["@/pages/home/memberCenter/memberMsg/MsgDetail"], resolve); /* - * 会员中心 - * 账户中心 - * */ + * 会员中心(我的优惠券、我的余额等) + */ const Coupons = (resolve) => require(["@/pages/home/userCenter/Coupons"], resolve); const MyTracks = (resolve) => require(["@/pages/home/userCenter/MyTracks"], resolve); const MoneyManagement = (resolve) => require(["@/pages/home/userCenter/MoneyManagement"], resolve); +const MyGiftCards = (resolve) => + require(["@/pages/home/userCenter/MyGiftCards"], resolve); const Home = (resolve) => require(["@/pages/user/Home"], resolve); @@ -261,6 +262,13 @@ export default new Router({ path: "MoneyManagement", name: "MoneyManagement", component: MoneyManagement, + meta: { title: "我的余额" }, + }, + { + path: "MyGiftCards", + name: "MyGiftCards", + component: MyGiftCards, + meta: { title: "我的礼品卡" }, }, { path: "Complain", @@ -271,6 +279,7 @@ export default new Router({ path: "Coupons", name: "Coupons", component: Coupons, + meta: { title: "我的优惠券" }, }, { path: "CommentList", diff --git a/manager/package.json b/manager/package.json index 0257c919..472bab85 100644 --- a/manager/package.json +++ b/manager/package.json @@ -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", diff --git a/manager/src/api/promotion.js b/manager/src/api/promotion.js index 880ae648..67ae6e13 100644 --- a/manager/src/api/promotion.js +++ b/manager/src/api/promotion.js @@ -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 批量发卡(multipart:file) +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); }; \ No newline at end of file diff --git a/manager/src/router/router.js b/manager/src/router/router.js index 37086aea..5c0e9a89 100644 --- a/manager/src/router/router.js +++ b/manager/src/router/router.js @@ -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: "优惠券领取记录", diff --git a/manager/src/views/member/advance/withdrawApply.vue b/manager/src/views/member/advance/withdrawApply.vue index 1f7b6aba..36bcf667 100644 --- a/manager/src/views/member/advance/withdrawApply.vue +++ b/manager/src/views/member/advance/withdrawApply.vue @@ -6,10 +6,11 @@ - +