Files
huangjingfen/pro_v3.5.1_副本/view/uniapp/components/skeleton/index.vue
apple 434aa8c69d feat(fsgx): 完成全部24项开发任务 Phase1-7
Phase1 后端核心:
- 新增 fsgx_v1.sql 迁移脚本(is_queue_goods/frozen_points/available_points/no_assess)
- SystemConfigServices 返佣设置扩展(周期人数/分档比例/范围/时机)
- StoreOrderCreateServices 周期循环佣金计算
- StoreOrderTakeServices 佣金发放后同步冻结积分
- StoreProductServices/StoreProduct 保存 is_queue_goods

Phase2 后端接口:
- GET /api/hjf/brokerage/progress 佣金周期进度
- GET /api/hjf/assets/overview 资产总览
- HjfPointsServices 每日 frozen_points 0.4‰ 释放定时任务
- PUT /adminapi/hjf/member/{uid}/no_assess 不考核接口
- GET /adminapi/hjf/points/release_log 积分日志接口

Phase3 前端清理:
- hjfCustom.js 路由精简(仅保留 points/log)
- hjfQueue.js/hjfMember.js API 清理/重定向至 CRMEB 原生接口
- pages.json 公排→推荐佣金/佣金记录/佣金规则

Phase4-5 前端改造:
- queue/status.vue 推荐佣金进度页整体重写
- 商品详情/订单确认/支付结果页文案与逻辑改造
- 个人中心/资产页/引导页/规则页文案改造
- HjfQueueProgress/HjfRefundNotice/HjfAssetCard 组件改造
- 推广中心嵌入佣金进度摘要
- hjfMockData.js 全量更新(公排字段→佣金字段)

Phase6 Admin 增强:
- 用户列表新增 frozen_points/available_points 列及不考核操作按钮
- hjfPoints.js USE_MOCK=false 对接真实积分日志接口

Phase7 配置文档:
- docs/fsgx-phase7-config-checklist.md 后台配置与全链路验收清单

Made-with: Cursor
2026-03-23 22:32:19 +08:00

199 lines
4.1 KiB
Vue

<template>
<view v-if="show"
:style="{width: systemInfo.width + 'px', height: systemInfo.height + 'px', backgroundColor: bgcolor, position: 'absolute', left: 0, top: 0, zIndex: 9998}">
<view v-for="(item,rect_idx) in skeletonRectLists" :key="item.rect"
:class="[loading == 'chiaroscuro' ? 'chiaroscuro' : '']"
:style="{width: item.width + 'px', height: item.height + 'px', backgroundColor: 'rgb(194, 207, 214,.3)', position: 'absolute', left: item.left + 'px', top: item.top + 'px'}">
</view>
<view v-for="(item,circle_idx) in skeletonCircleLists" :key="item.circle"
:class="loading == 'chiaroscuro' ? 'chiaroscuro' : ''"
:style="{width: item.width + 'px', height: item.height + 'px', backgroundColor: 'rgb(194, 207, 214,.3)', borderRadius: item.width + 'px', position: 'absolute', left: item.left + 'px', top: item.top + 'px'}">
</view>
<view class="spinbox" v-if="loading == 'spin'">
<view class="spin"></view>
</view>
</view>
</template>
<script>
export default {
name: "skeleton",
props: {
bgcolor: {
type: String,
value: '#FFF'
},
selector: {
type: String,
value: 'skeleton'
},
loading: {
type: String,
value: 'spin'
},
show: {
type: Boolean,
value: false
},
isNodes: {
type: Number,
value: false
} //控制什么时候开始抓取元素节点,只要数值改变就重新抓取
},
data() {
return {
loadingAni: ['spin', 'chiaroscuro'],
systemInfo: {},
skeletonRectLists: [],
skeletonCircleLists: []
}
},
watch: {
isNodes(val) {
this.readyAction();
}
},
mounted() {
this.attachedAction();
},
methods: {
attachedAction: function() {
//默认的首屏宽高,防止内容闪现
const systemInfo = uni.getWindowInfo();
this.systemInfo = {
width: systemInfo.windowWidth,
height: systemInfo.windowHeight
};
this.loading = this.loadingAni.includes(this.loading) ? this.loading : 'spin';
},
readyAction: function() {
const that = this;
//绘制背景
uni.createSelectorQuery().selectAll(`.${this.selector}`).boundingClientRect().exec(function(res) {
if(res[0].length>0)
that.systemInfo.height = res[0][0].height + res[0][0].top;
});
//绘制矩形
this.rectHandle();
//绘制圆形
this.radiusHandle();
},
rectHandle: function() {
const that = this;
//绘制不带样式的节点
uni.createSelectorQuery().selectAll(`.${this.selector}-rect`).boundingClientRect().exec(function(res) {
let obj = res[0];
obj.forEach((item,index)=>{
item.rect = 'rect'+index
})
that.skeletonRectLists = obj;
});
},
radiusHandle() {
const that = this;
uni.createSelectorQuery().selectAll(`.${this.selector}-radius`).boundingClientRect().exec(function(res) {
let obj = res[0];
obj.forEach((item,index)=>{
item.circle = 'circle'+index
})
that.skeletonCircleLists = obj;
});
}
}
}
</script>
<style>
.spinbox {
position: fixed;
display: flex;
justify-content: center;
align-items: center;
height: 100%;
width: 100%;
z-index: 9999
}
.spin {
display: inline-block;
width: 64rpx;
height: 64rpx;
}
.spin:after {
content: " ";
display: block;
width: 46rpx;
height: 46rpx;
margin: 1rpx;
border-radius: 50%;
border: 5rpx solid #409eff;
border-color: #409eff transparent #409eff transparent;
animation: spin 1.2s linear infinite;
}
@keyframes spin {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
.chiaroscuro {
width: 100%;
height: 100%;
background: rgb(194, 207, 214);
animation-duration: 2s;
animation-name: blink;
animation-iteration-count: infinite;
}
@keyframes blink {
0% {
opacity: .4;
}
50% {
opacity: 1;
}
100% {
opacity: .4;
}
}
@keyframes flush {
0% {
left: -100%;
}
50% {
left: 0;
}
100% {
left: 100%;
}
}
.shine {
animation: flush 2s linear infinite;
position: absolute;
top: 0;
bottom: 0;
width: 100%;
background: linear-gradient(to left,
rgba(255, 255, 255, 0) 0%,
rgba(255, 255, 255, .85) 50%,
rgba(255, 255, 255, 0) 100%)
}
</style>