feat: 黄精粉前端功能集成 + 个人中心/资产/公排页面优化 + 去除admin copyright

主要改动:
- 个人中心: 去除HjfMemberBadge徽章, 会员等级改显示vip_name,
  "我的资产"/"公排查询"导航项改为与member-points一致风格
- 我的资产页面: 去除HjfMemberBadge, 美化卡片圆角和阴影
- 公排查询页面: 美化顶部渐变和订单卡片样式
- Admin登录页和后台布局: 彻底删除footer copyright信息
- 新增黄精粉业务页面/组件/API/Mock数据(Phase 1)
- 新增PHP环境配置文档和启动脚本

Made-with: Cursor
This commit is contained in:
apple
2026-03-13 00:49:22 +08:00
parent 21f9cc2c0a
commit f6227c0253
70 changed files with 23359 additions and 1176 deletions

View File

@@ -207,8 +207,45 @@
</view>
</view>
</view>
<view class="cell flex justify-between flex-y-center mt-32" v-if="textareaStatus && send_gift_type != 2">
<text class="text--w111-333 fs-28">留言</text>
<!-- 报单商品公排提示is_queue_goods=1 时显示 -->
<view class="hjf-queue-notice mt-24" v-if="isQueueOrder">
<view class="hjf-queue-notice__header flex-y-center">
<text class="hjf-queue-notice__icon iconfont icon-tishi"></text>
<text class="hjf-queue-notice__title fs-26 fw-500">公排商品提示</text>
</view>
<view class="hjf-queue-notice__body mt-16">
<!-- 拆单提示购买数量 > 1 时显示 -->
<view class="hjf-queue-notice__item flex-y-center" v-if="queueSplitCount > 1">
<text class="hjf-queue-notice__dot"></text>
<text class="fs-24 text--w111-666 lh-34rpx">
本次将拆分为
<text class="hjf-queue-notice__num">{{ queueSplitCount }}</text>
个独立公排订单每单独立排队
</text>
</view>
<!-- 公排规则说明 -->
<view class="hjf-queue-notice__item flex-y-center mt-12">
<text class="hjf-queue-notice__dot"></text>
<text class="fs-24 text--w111-666 lh-34rpx">购买后自动加入公排池进四退一全额返还</text>
</view>
<!-- 预计退款批次 -->
<view class="hjf-queue-notice__item flex-y-center mt-12">
<text class="hjf-queue-notice__dot"></text>
<text class="fs-24 text--w111-666 lh-34rpx">
预计退款时间购买后第
<text class="hjf-queue-notice__num">{{ estimatedRefundBatch }}</text>
个批次仅供参考以实际排队进度为准
</text>
</view>
<!-- 跳转公排状态页 -->
<view class="hjf-queue-notice__link flex-y-center justify-end mt-16" @tap="goPage(1, '/pages/queue/status')">
<text class="fs-24 hjf-queue-notice__link-text">查看公排进度</text>
<text class="iconfont icon-ic_rightarrow fs-20 hjf-queue-notice__link-text pl-4"></text>
</view>
</view>
</view>
<view class="cell flex justify-between flex-y-center mt-32" v-if="textareaStatus && send_gift_type != 2">
<text class="text--w111-333 fs-28">留言</text>
<textarea
class="w-450 fs-28 text-right h-auto"
:auto-height="true"
@@ -613,6 +650,7 @@
const CACHE_CITY = {};
import dayjs from '@/plugin/dayjs/dayjs.min.js';
import { orderConfirm, getCouponsOrderPrice, orderCreate, postOrderComputed, checkShipping, getCartCounts, orderReceiveGift } from '@/api/order.js';
import { getQueueStatus } from '@/api/hjfQueue.js';
import { getAddressDefault, getAddressDetail, invoiceList, invoiceOrder, getAddressList } from '@/api/user.js';
import { openPaySubscribe } from '@/utils/SubscribeMessage.js';
import { storeListApi, postCartAdd, getSendGiftOrderDetail } from '@/api/store.js';
@@ -761,11 +799,49 @@ export default {
giftData: null,
channel: '', // 1 是采购商 "" 正常用户
yue_pay_status: 1,
now_money: ''
now_money: '',
/**
* 公排全局进度快照,由 getQueueStatus() 拉取后写入。
* 结构:{ current_batch: number, trigger_multiple: number, next_refund_queue_no: number }
* Phase 4 集成时此字段由真实 API 填充。
* @type {object|null}
*/
queueStatus: null
};
},
computed: {
...mapGetters(['isLogin']),
/**
* 当前订单是否包含报单商品is_queue_goods=1
* 遍历 cartInfo已过滤赠品只要有一件报单商品即为报单订单。
* @returns {boolean}
*/
isQueueOrder() {
return this.cartInfo.some((item) => item.productInfo && item.productInfo.is_queue_goods == 1);
},
/**
* 报单商品的总购买数量(用于计算公排拆单数)。
* 每件报单商品按购买数量各自独立入队,数量即拆单数。
* @returns {number}
*/
queueSplitCount() {
return this.cartInfo.reduce((sum, item) => {
if (item.productInfo && item.productInfo.is_queue_goods == 1) {
return sum + (parseInt(item.cart_num) || 1);
}
return sum;
}, 0);
},
/**
* 预计退款批次号:基于当前公排全局进度估算。
* 采用保守估算:当前批次余量 + 每批次4单 * 向上取整后的等待批次。
* 实际值由后端 /hjf/queue/status 接口提供,此处仅作展示用途。
* @returns {number}
*/
estimatedRefundBatch() {
const base = this.queueStatus ? this.queueStatus.current_batch : 0;
return base + Math.ceil(this.queueSplitCount / 4) + 1;
},
giftCount() {
let count = 0;
if (this.giveCartInfo.length) {
@@ -838,6 +914,7 @@ export default {
let _this = this;
if (this.isLogin && (this.send_gift_type == 0 || this.send_gift_type == 1)) {
this.getCheckShipping();
this.loadQueueStatus();
} else if (this.send_gift_type == 2 && this.isLogin) {
this.getOrderDetail();
} else {
@@ -1795,6 +1872,24 @@ export default {
tapStoreList() {
this.textareaStatus = false;
this.address.address = true;
},
/**
* 拉取公排全局进度快照,写入 queueStatus 用于计算预计退款批次。
* 仅在订单包含报单商品时展示相关提示,但提前加载可减少感知延迟。
* 失败时静默忽略,不影响正常结算流程。
*/
loadQueueStatus() {
getQueueStatus()
.then((res) => {
if (res && res.data && res.data.progress) {
this.queueStatus = {
current_batch: res.data.progress.current_batch_count || 0,
trigger_multiple: res.data.progress.trigger_multiple || 4,
next_refund_queue_no: res.data.progress.next_refund_queue_no || 0
};
}
})
.catch(() => {});
}
}
};
@@ -1999,6 +2094,53 @@ export default {
.con-border {
border: 1px solid var(--view-theme);
}
/* 报单商品公排提示区块 */
.hjf-queue-notice {
background: #f0f9f0;
border: 1rpx solid #b7e4b7;
border-radius: 12rpx;
padding: 24rpx;
&__header {
gap: 10rpx;
}
&__icon {
color: #3c9c3c;
font-size: 30rpx;
margin-right: 8rpx;
}
&__title {
color: #2d7d2d;
}
&__item {
align-items: flex-start;
}
&__dot {
display: inline-block;
width: 10rpx;
height: 10rpx;
border-radius: 50%;
background: #3c9c3c;
flex-shrink: 0;
margin-top: 12rpx;
margin-right: 12rpx;
}
&__num {
color: #3c9c3c;
font-weight: 600;
padding: 0 4rpx;
}
&__link-text {
color: var(--view-theme);
}
}
.clear-btn {
border-radius: 0 12rpx 0 12rpx;
}

View File

@@ -13,9 +13,27 @@
<text class="fs-40 fw-500 text--w111-fff pl-16" v-if="order_pay_info.pay_type == 'offline' && !order_pay_info.paid">订单创建成功</text>
<text class="fs-40 fw-500 text--w111-fff pl-16" v-else>{{ order_pay_info.paid ? '订单支付成功' : '等待支付...' }}</text>
</view>
<!-- 公排入队成功提示 -->
<view v-if="isQueueOrder && order_pay_info.paid && queueEntries.length > 0" class="queue-success-notice mt-20">
<view class="flex-y-center">
<text class="iconfont icon-chenggong fs-28 queue-icon"></text>
<text class="fs-26 text--w111-fff">已加入公排队列</text>
</view>
<view class="fs-22 text--w111-fff mt-8 opacity-80" v-if="queueEntries.length === 1">
排队序号 #{{ queueEntries[0].queue_no }}{{ queueEntries[0].estimated_wait }}
</view>
<view class="fs-22 text--w111-fff mt-8 opacity-80" v-else>
{{ queueEntries.length }} 个订单已入队
</view>
</view>
<view class="flex-center mt-30">
<view class="w-192 h-64 rd-40rpx flex-center fs-24 text--w111-fff white-border" @tap="goIndex">返回首页</view>
<view v-if="!order_pay_info.is_send_gift || !order_pay_info.paid" class="w-192 h-64 rd-40rpx flex-center fs-24 text--w111-fff white-border ml-48" @tap="goOrderDetails">
<view v-if="isQueueOrder && order_pay_info.paid" class="w-192 h-64 rd-40rpx flex-center fs-24 text--w111-fff white-border ml-48" @tap="goQueueStatus">
查看公排
</view>
<view v-else-if="!order_pay_info.is_send_gift || !order_pay_info.paid" class="w-192 h-64 rd-40rpx flex-center fs-24 text--w111-fff white-border ml-48" @tap="goOrderDetails">
查看订单
</view>
<view v-else-if="order_pay_info.paid" @click="giftModalShow = true" class="w-192 h-64 rd-40rpx flex-center fs-24 text--w111-fff white-border ml-48">送给好友</view>
@@ -108,6 +126,7 @@ import colors from '@/mixins/color';
import { HTTP_REQUEST_URL } from '@/config/app';
import Cache from '@/utils/cache';
import { userShare } from '@/api/user.js';
import { getQueueStatus } from '@/api/hjfQueue.js';
export default {
components: {
gridsLottery,
@@ -168,9 +187,10 @@ export default {
nickname: '',
code: ''
},
userInfo: Cache.get('USER_INFO') || {},
mpGiftImg: HTTP_REQUEST_URL + '/statics/images/gift_share.jpg',
recommendTitle: ""
userInfo: Cache.get('USER_INFO') || {},
mpGiftImg: HTTP_REQUEST_URL + '/statics/images/gift_share.jpg',
recommendTitle: "",
queueEntries: []
};
},
computed: {
@@ -181,6 +201,10 @@ export default {
} else {
return true;
}
},
isQueueOrder() {
if (!this.order_pay_info || !this.order_pay_info.cartInfo) return false;
return this.order_pay_info.cartInfo.some(item => item.productInfo && item.productInfo.is_queue_goods == 1);
}
},
watch: {
@@ -327,6 +351,12 @@ export default {
uni.hideShareMenu()
}
this.loading = true;
// 如果是公排订单且已支付,加载公排入队信息
if (that.isQueueOrder && res.data.paid) {
that.loadQueueEntries();
}
setTimeout(function () {
that.getOrderPrize();
}, 1000);
@@ -473,6 +503,20 @@ export default {
that.recommendTitle = res.data.title ? res.data.title : '猜你喜欢';
});
},
loadQueueEntries() {
getQueueStatus()
.then((res) => {
if (res && res.data && res.data.myOrders && res.data.myOrders.length) {
this.queueEntries = res.data.myOrders.filter(item => item.status === 0);
}
})
.catch(() => {});
},
goQueueStatus() {
uni.navigateTo({
url: '/pages/queue/status'
});
},
goPage(type, url) {
if (type == 1) {
uni.navigateTo({
@@ -502,6 +546,20 @@ export default {
.h-484 {
height: 484rpx;
}
.queue-success-notice {
text-align: center;
padding: 20rpx 40rpx;
background: rgba(255, 255, 255, 0.15);
border-radius: 20rpx;
backdrop-filter: blur(10px);
}
.queue-icon {
color: #52c41a;
margin-right: 8rpx;
}
.opacity-80 {
opacity: 0.8;
}
.content {
background: #f5f5f5;
border-radius: 40rpx 40rpx 0 0;