feat(hjf): H5路由修复、分销等级显示优化、个人中心等级徽章

H5 部署与路由:
- manifest.json: router.base 改为 "/" 适配 public/ 根目录部署
- nginx-crmeb.conf: 恢复与 feature/fsgx 一致的原始配置
- App.vue: PC端重定向路径改为动态推导,修复死循环加载问题
- static/html/pc.html: 动态推导 H5 根路径,适配本地/云端两种部署

H5登录:
- pages/users/login/index.vue: H5端获取验证码跳过安全验证(条件编译)

分销等级展示修复:
- AgentLevelServices: 新增 loadHjfUserListLevelMaps/pickHjfLevelRowForUserListDisplay
  统一等级名称解析逻辑,优先返回 HJF 官方名称;新增 getUpgradeTasksForLevel 封装
- UserServices/MemberLevelServices: 改用统一解析方法,修复 protected $dao 访问错误
- api/hjf/MemberController: 直接取 eb_agent_level.name,新增 agent_level 原始值返回
- admin/v1/hjf/MemberController: team() 改用封装方法替代直接访问 protected dao

个人中心等级徽章:
- pages/user/index.vue + member/index.vue: memberInfo 沿链路透传
- member/template1.vue: UID右侧显示HjfMemberBadge,直接读 userInfo.agent_level_name
  无需等待异步 memberInfo,agentLevelGrade 计算属性从名称推导颜色等级

商品列表修复:
- BaseController.php/Common.php: 恢复加密版,修复 CRMEB 授权检查失败导致的400错误
- StoreProduct model: 移除冲突的 model maker 回调

数据库:
- hjf_migration.sql: 完善会员等级体系迁移脚本
- eb_agent_level.sql: 新增等级初始数据脚本

Made-with: Cursor
This commit is contained in:
apple
2026-03-22 01:43:36 +08:00
parent 590eca8c22
commit 8592243d36
34 changed files with 1467 additions and 745 deletions

View File

@@ -95,7 +95,11 @@
success(e) {
/* 窗口宽度大于420px且不在PC页面且不在移动设备时跳转至 PC.html 页面 */
if (e.windowWidth > 420 && !window.top.isPC && !/iOS|Android/i.test(e.system)) {
window.location.pathname = '/h5/static/html/pc.html';
const p = (window.location.pathname || '/').replace(/\/$/, '') || '/';
if (p.endsWith('/static/html/pc.html')) return;
/* 与 manifest h5.router.base 一致:根路径为 / 或子路径 /h5/ */
const h5Base = p.startsWith('/h5/') || p === '/h5' ? '/h5' : '';
window.location.pathname = `${h5Base}/static/html/pc.html`;
}
}
});

View File

@@ -1,6 +1,6 @@
{
"name" : "crmeb",
"appid" : "__UNI__70A74E1",
"appid" : "__UNI__6691FE3",
"description" : "crmeb商城",
"versionName" : "3.5.1",
"versionCode" : 351,
@@ -218,7 +218,7 @@
},
"router" : {
"mode" : "history",
"base" : "/h5/"
"base" : "/"
},
"domain" : "",
"sdkConfigs" : {

View File

@@ -39,6 +39,11 @@ export default {
balanceStatus: {
type: Number,
default: 0
},
// HJF 分销等级信息,向下透传给各 template
memberInfo: {
type: Object,
default: () => ({ agent_level: 0, member_level: 0, member_level_name: '' })
}
},
data() {
@@ -97,7 +102,7 @@ export default {
<!-- #ifdef MP || APP-PLUS -->
<topBar v-if="memberData.style != 5" :styleType="memberData.style" :isScrolling="isScrolling"></topBar>
<!-- #endif -->
<template1 v-if="memberData.style == 1" :perShowType="memberData.per_show_type" :userInfo="userInfo" :property="property"></template1>
<template1 v-if="memberData.style == 1" :perShowType="memberData.per_show_type" :userInfo="userInfo" :property="property" :memberInfo="memberInfo"></template1>
<template2 v-if="memberData.style == 2" :perShowType="memberData.per_show_type" :userInfo="userInfo" :property="property"></template2>
<template3 v-if="memberData.style == 3" :perShowType="memberData.per_show_type" :userInfo="userInfo" :property="property"></template3>
<template4 v-if="memberData.style == 4" :perShowType="memberData.per_show_type" :userInfo="userInfo" :commission="orderAdminData.commission"></template4>

View File

@@ -14,12 +14,23 @@ export default {
perShowType: {
type: Number,
default: 0
},
// HJF 分销等级信息(由 member/index.vue 向下传递)
memberInfo: {
type: Object,
default: () => ({ agent_level: 0, member_level: 0, member_level_name: '' })
}
},
inject: ['intoPage', 'tapQrCode', 'goMenuPage', 'goEdit', 'bindPhone', 'checkApp'],
computed:{
showMerBtn(){
return this.$store.state.app.channel_func_status
},
/** 从 userInfo.agent_level_name 推导 grade0-4用于徽章颜色 */
agentLevelGrade() {
const nameGradeMap = { '创客': 1, '云店': 2, '服务商': 3, '分公司': 4 };
const name = (this.userInfo && this.userInfo.agent_level_name) || '';
return nameGradeMap[name] || 0;
}
},
methods: {
@@ -58,10 +69,20 @@ export default {
<view class="bind-phone" v-if="!userInfo.phone && userInfo.uid" @tap="bindPhone">绑定手机号</view>
<view class="acea-row row-middle" v-else>
<view class="phone">{{ perShowType ? 'ID' + userInfo.uid : userInfo.phone }}</view>
<!--
<view class="vip flex-center" v-if="userInfo.level">
<text class="iconfont icon-huiyuandengji"></text>
{{ userInfo.vip_name || ('V' + userInfo.level) }}
</view>
-->
<!-- HJF 分销等级徽章直接用 userInfo.agent_level / agent_level_name无需等待异步 memberInfo -->
<HjfMemberBadge
v-if="userInfo.agent_level > 0"
:level="agentLevelGrade"
:levelName="userInfo.agent_level_name"
size="small"
class="ml-10"
/>
</view>
</template>

View File

@@ -2,12 +2,7 @@
<!-- 个人中心模块 -->
<view class="user-page" :style="colorStyle">
<template v-if="isObjectData(diyData)">
<user-member :userInfo="userInfo" :memberData="diyData.member" :orderAdminData="orderAdminData" :balanceStatus="balanceStatus" :isScrolling="isScrolling"></user-member>
<!-- HJF 会员等级徽章 -->
<view class="flex-y-center px-30 py-20 bg--w111-fff mt-16 mx-20 rd-16rpx">
<text class="fs-26 text--w111-666 mr-16">当前等级</text>
<HjfMemberBadge :level="memberInfo.member_level" :levelName="memberInfo.member_level_name" size="normal" />
</view>
<user-member :userInfo="userInfo" :memberData="diyData.member" :orderAdminData="orderAdminData" :balanceStatus="balanceStatus" :isScrolling="isScrolling" :memberInfo="memberInfo"></user-member>
<user-order :orderMenu="orderMenu" :orderAdminData="orderAdminData" :userInfo="userInfo" :memberData="diyData.member" :orderData="diyData.order"></user-order>
<!-- 黄精粉快捷入口我的资产 & 公排记录 member-points 保持一致风格 -->
<view class="acea-row member-points hjf-nav-row">
@@ -239,6 +234,7 @@ export default {
routineContact: 0,
/** HJF 会员等级信息 */
memberInfo: {
agent_level: 0,
member_level: 0,
member_level_name: '普通',
}
@@ -305,9 +301,10 @@ export default {
loadMemberInfo() {
getMemberInfo().then(res => {
if (res && res.data) {
this.memberInfo = {
member_level: res.data.member_level || 0,
member_level_name: res.data.member_level_name || '普通',
this.memberInfo = {
agent_level: res.data.agent_level || 0,
member_level: res.data.member_level || 0,
member_level_name: res.data.member_level_name || '普通',
};
}
}).catch(() => {});

View File

@@ -79,8 +79,10 @@
<text class="main-color" @click.stop="privacy('privacy')">隐私协议</text>
</checkbox-group>
</view>
<!-- #ifndef H5 -->
<Verify v-if="!disabled" @success="success" :captchaType="captchaType" :imgSize="{ width: '330px', height: '155px' }"
ref="verify"></Verify>
<!-- #endif -->
</view>
</template>
@@ -114,12 +116,16 @@
// #endif
const BACK_URL = "login_back_url";
import colors from '@/mixins/color.js';
// #ifndef H5
import Verify from '../components/verify/verify.vue';
// #endif
import { HTTP_REQUEST_URL, CAPTCHA_TYPE } from '@/config/app';
export default {
name: "Login",
components: {
// #ifndef H5
Verify
// #endif
},
mixins: [sendVerifyCode, colors],
data: function() {
@@ -397,7 +403,11 @@
Date.parse(new Date());
},
success(data) {
this.$refs.verify.hide()
// #ifndef H5
if (this.$refs.verify) {
this.$refs.verify.hide();
}
// #endif
getCodeApi()
.then(res => {
this.keyCode = res.data.key;
@@ -423,17 +433,22 @@
if (!/^1(3|4|5|7|8|9|6)\d{9}$/i.test(that.account)) return that.$util.Tips({
title: '请输入正确的手机号码'
});
// getCodeApi()
// .then(res => {
// that.keyCode = res.data.key;
// that.getCode();
// })
// .catch(res => {
// that.$util.Tips({
// title: res
// });
// });
this.$refs.verify.show()
// #ifdef H5
// H5不弹出滑块/图形安全验证,直接取 key 并发短信(后端 register/verify 已关闭 aj 二次校验)
getCodeApi()
.then(res => {
that.keyCode = res.data.key;
that.getCode({ captchaVerification: '' });
})
.catch(res => {
that.$util.Tips({
title: res
});
});
// #endif
// #ifndef H5
this.$refs.verify.show();
// #endif
},
async getLogoImage() {
let that = this;
@@ -569,7 +584,11 @@
that.sendCode();
})
.catch(res => {
this.$refs.verify.refresh()
// #ifndef H5
if (this.$refs.verify) {
this.$refs.verify.refresh();
}
// #endif
that.$util.Tips({
title: res
});

View File

@@ -35,21 +35,30 @@
}
}
</style>
<script type="text/javascript">
window.isPC = true;
window.onload = function(){
/* 监听电脑浏览器窗口尺寸改变 */
window.onresize = function(){
/* 窗口宽度 小于或等于420px 时跳转回H5页面 */
if(window.innerWidth <= 420){
window.location.pathname = '/h5/';
}
}
}
</script>
</head>
<body>
<iframe src="/h5/?type=1"></iframe>
<iframe id="app-frame"></iframe>
<script type="text/javascript">
window.isPC = true;
/* 根据当前地址推导 H5 根路径:本地 dev 多为 /,线上部署多为 /h5/ */
function h5AppRootPathname() {
var path = (window.location.pathname || '/').replace(/\/$/, '') || '/';
var marker = '/static/html/pc.html';
if (path.endsWith(marker)) {
var root = path.slice(0, -marker.length);
if (!root) root = '/';
return root === '/' ? '/' : (root + '/');
}
return '/';
}
var H5_ROOT = h5AppRootPathname();
document.getElementById('app-frame').src = H5_ROOT + '?type=1';
window.onresize = function(){
if (window.innerWidth <= 420) {
var target = H5_ROOT.replace(/\/$/, '');
window.location.pathname = target || '/';
}
};
</script>
</body>
</html>
</html>