diff --git a/buyer/src/api/login.js b/buyer/src/api/login.js index 5ad6d9a5..e9746924 100644 --- a/buyer/src/api/login.js +++ b/buyer/src/api/login.js @@ -69,6 +69,32 @@ export function loginCallback (uuid) { }); } +export function getThirdAccountBindList () { + return request({ + url: '/buyer/passport/connect/bind/list', + method: Method.GET, + needToken: true + }); +} + +export function bindThirdAccount (data) { + return request({ + url: '/buyer/passport/connect/bind', + method: Method.POST, + needToken: true, + data + }); +} + +export function unbindThirdAccount (data) { + return request({ + url: '/buyer/passport/connect/bind/unbind', + method: Method.POST, + needToken: true, + data + }); +} + /** * 忘记密码 验证手机验证码 */ @@ -109,3 +135,12 @@ export function sCLogin(token,params) { params }); } + +export function getWechatH5QrCode (params) { + return request({ + url: '/buyer/other/wechat/h5/qrcode', + method: Method.GET, + needToken: true, + params + }) +} diff --git a/buyer/src/api/member.js b/buyer/src/api/member.js index 28a6880f..2f1eb240 100644 --- a/buyer/src/api/member.js +++ b/buyer/src/api/member.js @@ -489,6 +489,31 @@ export function memberPointHistory (params) { params }); } + +export function memberGradeCurrent (params) { + return request({ + url: `/buyer/member/memberGrade/current`, + method: Method.GET, + needToken: true, + params + }) +} + +export function memberGradeRules () { + return request({ + url: `/buyer/member/memberGrade/rules`, + method: Method.GET, + needToken: true + }) +} + +export function memberGradeList () { + return request({ + url: `/buyer/member/memberGrade/list`, + method: Method.GET, + needToken: true + }) +} /** * 分页获取会员站内信 * @param {Object} params 请求参数,包括pageNumber、pageSize、status diff --git a/buyer/src/pages/home/memberCenter/AccountSafe.vue b/buyer/src/pages/home/memberCenter/AccountSafe.vue index c7028eb0..c2d23a26 100644 --- a/buyer/src/pages/home/memberCenter/AccountSafe.vue +++ b/buyer/src/pages/home/memberCenter/AccountSafe.vue @@ -15,21 +15,112 @@ + + + + + + +
第三方账户绑定
+
绑定后可使用第三方账号快捷登录。
+
+
+
+ {{ wechatConnect.label }} + 已绑定 + 未绑定 +
+
+ +
+ + + + + +
+ + +
+ + + + + +
+
+ + 微信公众号二维码 +
二维码获取失败,请刷新重试
+
+
+ + +
+
请使用微信扫码关注/授权,完成后点击“我已完成绑定”检测绑定状态
+
+
+ + + + +
+
@@ -76,4 +286,67 @@ export default { } } + + .connectList { + position: relative; + margin-top: 8px; + } + + .connectRow { + display: flex; + align-items: center; + justify-content: space-between; + padding: 6px 0; + } + + .connectRowLeft { + display: flex; + align-items: center; + gap: 10px; + } + + .connectName { + color: $title_color; + } + + .wechatQrBox { + width: 100%; + } + + .wechatQrImgBox { + position: relative; + width: 180px; + height: 180px; + border: 1px solid $border_color; + display: flex; + align-items: center; + justify-content: center; + background: #fff; + } + + .wechatQrImg { + width: 168px; + height: 168px; + object-fit: contain; + } + + .wechatQrEmpty { + color: $light_sub_color; + font-size: 12px; + text-align: center; + padding: 0 8px; + } + + .wechatQrActions { + margin-top: 10px; + display: flex; + gap: 10px; + } + + .wechatQrTip { + margin-top: 10px; + color: $light_sub_color; + font-size: 12px; + line-height: 1.6; + } diff --git a/buyer/src/pages/home/memberCenter/MemberGrade.vue b/buyer/src/pages/home/memberCenter/MemberGrade.vue new file mode 100644 index 00000000..13c94807 --- /dev/null +++ b/buyer/src/pages/home/memberCenter/MemberGrade.vue @@ -0,0 +1,431 @@ + + + + + diff --git a/buyer/src/pages/home/memberCenter/Profile.vue b/buyer/src/pages/home/memberCenter/Profile.vue index 8c10ec82..0d258ebb 100644 --- a/buyer/src/pages/home/memberCenter/Profile.vue +++ b/buyer/src/pages/home/memberCenter/Profile.vue @@ -54,14 +54,40 @@ export default { }, mounted () { this.formItem = JSON.parse(storage.getItem('userInfo')) + this.formItem.birthday = this.normalizeBirthday(this.formItem.birthday) this.accessToken.accessToken = storage.getItem('accessToken'); }, methods: { + normalizeBirthday (value) { + if (!value) return '' + if (value instanceof Date) return value + if (typeof value === 'number') return new Date(value) + if (typeof value === 'string') { + const m = value.match(/^(\d{4})-(\d{2})-(\d{2})/) + if (m) return new Date(Number(m[1]), Number(m[2]) - 1, Number(m[3])) + const d = new Date(value) + return isNaN(d.getTime()) ? '' : d + } + return '' + }, + formatBirthday (value) { + if (!value) return null + if (typeof value === 'string') { + const m = value.match(/^(\d{4})-(\d{2})-(\d{2})/) + return m ? `${m[1]}-${m[2]}-${m[3]}` : null + } + const d = value instanceof Date ? value : new Date(value) + if (isNaN(d.getTime())) return null + const yyyy = d.getFullYear() + const mm = String(d.getMonth() + 1).padStart(2, '0') + const dd = String(d.getDate()).padStart(2, '0') + return `${yyyy}-${mm}-${dd}` + }, save () { // 保存 this.$refs.form.validate(valid => { if (valid) { let params = { - birthday: this.$options.filters.unixToDate(this.formItem.birthday / 1000, 'yyyy-MM-dd'), + birthday: this.formatBirthday(this.formItem.birthday), face: this.formItem.face, nickName: this.formItem.nickName, sex: this.formItem.sex diff --git a/buyer/src/pages/user/menu.js b/buyer/src/pages/user/menu.js index 7a9cf9ab..87f925f0 100644 --- a/buyer/src/pages/user/menu.js +++ b/buyer/src/pages/user/menu.js @@ -76,6 +76,11 @@ const member = [{ icon: '', title: '我的积分', path: 'Point' + }, + { + icon: '', + title: '我的等级', + path: 'MemberGrade' } ], display: true diff --git a/buyer/src/router/index.js b/buyer/src/router/index.js index d5886003..09c59e9f 100644 --- a/buyer/src/router/index.js +++ b/buyer/src/router/index.js @@ -68,6 +68,8 @@ const ComplainDetail = (resolve) => require(["@/pages/home/memberCenter/ComplainDetail"], resolve); const Point = (resolve) => require(["@/pages/home/memberCenter/Point"], resolve); +const MemberGrade = (resolve) => + require(["@/pages/home/memberCenter/MemberGrade"], resolve); const MsgList = (resolve) => require(["@/pages/home/memberCenter/memberMsg/MsgList"], resolve); const MsgDetail = (resolve) => @@ -326,6 +328,12 @@ export default new Router({ component: Point, meta: { title: "我的积分" }, }, + { + path: "MemberGrade", + name: "MemberGrade", + component: MemberGrade, + meta: { title: "我的等级" }, + }, { path: "Profile", name: "Profile", diff --git a/manager/src/api/member.js b/manager/src/api/member.js index 193b2e9c..8b8e5877 100644 --- a/manager/src/api/member.js +++ b/manager/src/api/member.js @@ -175,3 +175,56 @@ export const addMemberGroupUsers = (groupId, memberIds) => { memberIds: Array.isArray(memberIds) ? memberIds.join(",") : memberIds, }); }; + +// 客户等级 +export const getMemberGradeByPage = (params) => { + return getRequest("/member/memberGrade/getByPage"); +}; +export const getMemberGrade = (id) => { + return getRequest(`/member/memberGrade/get/${id}`); +}; +export const addMemberGrade = (params) => { + return postRequest(`/member/memberGrade`, params); +}; +export const updateMemberGrade = (id, params) => { + return putRequest(`/member/memberGrade/update/${id}`, params); +}; +export const updateMemberGradeState = (id, state) => { + return putRequest(`/member/memberGrade/state/${id}?state=${state}`); +}; +export const deleteMemberGrade = (id) => { + return deleteRequest(`/member/memberGrade/delete/${id}`); +}; +export const getMemberExperienceByPage = (params) => { + return getRequest(`/member/memberGrade/experience/getByPage`, params); +}; + +// 客户权益 +export const getMemberBenefitByPage = (params) => { + return getRequest("/member/benefit/getByPage", params); +}; + +export const getMemberBenefit = (id) => { + return getRequest(`/member/benefit/get/${id}`); +}; + +export const addMemberBenefit = (params) => { + return postRequest("/member/benefit", params); +}; + +export const updateMemberBenefit = (id, params) => { + return putRequest(`/member/benefit/update/${id}`, params); +}; + +export const updateMemberBenefitState = (id, state) => { + return putRequest(`/member/benefit/state/${id}?state=${state}`); +}; + +export const deleteMemberBenefit = (id) => { + return deleteRequest(`/member/benefit/delete/${id}`); +}; + +/** 客户权益类型枚举(管理端) */ +export const getMemberBenefitTypes = () => { + return getRequest("/member/benefit/types"); +}; diff --git a/manager/src/components/lili/upload-pic-input.vue b/manager/src/components/lili/upload-pic-input.vue index bde7e703..bf2ffec7 100644 --- a/manager/src/components/lili/upload-pic-input.vue +++ b/manager/src/components/lili/upload-pic-input.vue @@ -39,14 +39,20 @@ - + 该资源不存在
- + diff --git a/manager/src/router/router.js b/manager/src/router/router.js index 2e2f4d8e..37086aea 100644 --- a/manager/src/router/router.js +++ b/manager/src/router/router.js @@ -39,7 +39,7 @@ export const otherRouter = { }, { path: "category", - title: "类型列表", + title: "分类列表", name: "category", component: () => import("@/views/goods/goods-manage/category.vue") }, @@ -105,16 +105,10 @@ export const otherRouter = { }, { path: "goods-parameter-edit", - title: "商品参数维护", + title: "编辑商品参数", name: "goods-parameter-edit", component: () => import("@/views/goods/goods-manage/parameter-edit.vue") }, - { - path: "goods-spec", - title: "商品参数", - name: "goods-spec", - component: () => import("@/views/goods/goods-manage/spec.vue") - }, { path: "order-complaint-detail", title: "投诉详情", @@ -159,6 +153,30 @@ export const otherRouter = { name: "member-group", component: () => import("@/views/member/group/index.vue") }, + { + path: "member-grade", + title: "客户等级", + name: "member-grade", + component: () => import("@/views/member/grade/index.vue") + }, + { + path: "member-benefit", + title: "客户权益管理", + name: "member-benefit", + component: () => import("@/views/member/benefit/index.vue") + }, + { + path: "member-grade-experience", + title: "等级权益设置", + name: "member-grade-experience", + component: () => import("@/views/member/grade/experience-setting.vue") + }, + { + path: "member-grade-experience-log", + title: "客户经验值记录", + name: "member-grade-experience-log", + component: () => import("@/views/member/grade/experience-log.vue") + }, { diff --git a/manager/src/utils/promotions.js b/manager/src/utils/promotions.js index 43d031e1..11f7de2d 100644 --- a/manager/src/utils/promotions.js +++ b/manager/src/utils/promotions.js @@ -85,3 +85,36 @@ export function memberPromotionsStatusRender(h, status) { ), ]); } + +/** + * 平台优惠券「活动时间 / 有效期」文案(活动获取券:effectiveDays 为领取后有效天数) + */ +export function formatPromotionCouponValidityHtml(row) { + if (!row) return "-"; + if (row.getType === "ACTIVITY") { + const days = row.effectiveDays; + if (days !== undefined && days !== null && days !== "") { + const n = Number(days); + if (!Number.isNaN(n) && n > 0) { + return `领取后${n}天有效`; + } + } + } + if (row.startTime && row.endTime) { + return `${row.startTime}
${row.endTime}`; + } + if (row.getType === "ACTIVITY" && row.rangeDayType === "DYNAMICTIME") { + return "长期有效"; + } + return "-"; +} + +/** Table 列 render:活动时间(与 formatPromotionCouponValidityHtml 一致) */ +export function promotionsCouponActivityTimeRender(h, params) { + const html = formatPromotionCouponValidityHtml(params.row); + if (html === "-") return h("div", "-"); + if (html.indexOf("
") !== -1) { + return h("div", { domProps: { innerHTML: html } }); + } + return h("div", html); +} diff --git a/manager/src/views/goods/goods-manage/category.vue b/manager/src/views/goods/goods-manage/category.vue index 41421ee9..be2c4157 100644 --- a/manager/src/views/goods/goods-manage/category.vue +++ b/manager/src/views/goods/goods-manage/category.vue @@ -15,9 +15,6 @@ >