Files
huangjingfen/pro_v3.5.1_副本/view/uniapp/pages/admin/writeOffCard/index.vue

363 lines
7.8 KiB
Vue
Raw Normal View History

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
<template>
<view class="container">
<view class="goods-box" v-if="list.cart_info">
<view class="header">订单号{{ list.order_id }}</view>
<view class='item acea-row' v-for="(item,index) in list.cart_info" :key="index">
<view class='pictrue'>
<image :src="item.cart_info.productInfo.attrInfo.image" mode=""></image>
</view>
<view class='text acea-row row-column row-between'>
<view class="title line2">{{ item.cart_info.productInfo.store_name }}</view>
<view class='money acea-row row-between row-middle'>
<view class="orangcol">
已核销<text>{{item.write_times - item.surplus_num}}</text>/{{item.write_times}}
</view>
<view v-if="item.is_writeoff == 1" class="txt acea-row row-middle">
核销已完成
</view>
<view v-else class="txt acea-row row-middle">
本次核销
<view class='carnum acea-row row-center-wrapper'>
<view v-if="item.surplus_num_input == 1" class="reduce bggary">
<text class="iconfont icon-ic_Reduce"></text>
</view>
<view v-else class="reduce" @click.stop='subCart(item,index)'>
<text class="iconfont icon-ic_Reduce"></text>
</view>
<!-- <view class='nums'>{{item.surplus_num_input}}</view> -->
<input v-model="item.surplus_num_input" class='nums' type="number" @input="numInput" @blur="numBlur" />
<view v-if="item.surplus_num_input == item.surplus_num" class="plus bggary">
<text class="iconfont icon-ic_increase"></text>
</view>
<view v-else class="plus" @click.stop='addCart(item,index)'>
<text class="iconfont icon-ic_increase"></text>
</view>
</view>
</view>
</view>
</view>
</view>
</view>
<view class="record-box" v-if="recordList.length">
<view class="header">核销记录</view>
<view class="list">
<view class="item acea-row row-middle row-between" v-for="(item, index) in recordList" :key="index">
<view class="left">{{ item.add_time }}</view>
<view class="right">核销{{item.writeoff_num}}</view>
</view>
</view>
</view>
<view class="footer acea-row row-middle row-between">
<navigator class="btn" url="/pages/admin/work/index" hover-class="none">返回工作台</navigator>
<view v-if="list.cart_info && list.cart_info[0].surplus_num" class="btn" @click="verification">确认核销</view>
</view>
</view>
</template>
<script>
import {
orderWriteoffInfo,
orderVerific,
orderCartInfo,
orderWriteoff,
orderWirteOffRecords,
} from '@/api/admin'
export default {
data() {
return {
list: {},
recordList: [],
lists: {},
checkModel: [],
nums: [],
auth: 1,
id: 0,
}
},
watch: {
checkModel() {
if (this.lengt == this.checkModel.length) {
this.checked = true;
} else {
this.checked = false;
}
}
},
onLoad(option) {
this.auth = option.auth || 1;
this.id = option.id;
this.getCartList()
this.orderWirteOffRecords()
},
methods: {
numInput(event) {
let value = event.detail.value;
if (value) {
value = Number(value);
this.$nextTick(() => {
if (value > this.list.cart_info[0].surplus_num) {
this.list.cart_info[0].surplus_num_input = this.list.cart_info[0].surplus_num;
} else if (value < 1) {
this.list.cart_info[0].surplus_num_input = 1;
}
});
}
},
numBlur(event) {
let value = event.detail.value;
if (!value) {
this.$nextTick(() => {
this.list.cart_info[0].surplus_num_input = 1;
});
}
},
orderWirteOffRecords() {
orderWirteOffRecords(this.id, {
product_type: 4
}).then(res => {
this.recordList = res.data.list;
});
},
num() {
for (let index = 0; index < this.lists.cart_info.length; index++) {
this.nums.push({
num: 0
});
}
},
getCartList: function() {
orderCartInfo({
oid: this.id,
auth: this.auth,
}).then(res => {
let list = res.data;
for (let i = 0; i < list.cart_info.length; i++) {
list.cart_info[i].surplus_num_input = 1
}
this.list = res.data
this.lists = JSON.parse(JSON.stringify(res.data))
this.listlet = res.data.cart_info.length
this.$set(this.attr, 'id', this.list.id);
this.num()
}).catch(res => {
this.$util.Tips({
title: res
});
});
},
subCart(item, index) {
this.list.cart_info[index].surplus_num_input--;
},
addCart(item, index) {
this.list.cart_info[index].surplus_num_input++;
},
verification() {
let that = this;
let cart_ids = [];
for (let i = 0; i < this.list.cart_info.length; i++) {
cart_ids.push({
cart_id: this.list.cart_info[i].cart_id,
cart_num: this.list.cart_info[i].surplus_num_input,
});
}
orderWriteoff({
auth: this.auth,
oid: this.id,
cart_ids: cart_ids
}).then(res => {
// uni.hideLoading();
this.$util.Tips({
title: res.msg
}, () => {
this.orderWirteOffRecords();
});
this.list.cart_info[0].surplus_num = this.list.cart_info[0].surplus_num - this.list.cart_info[0].surplus_num_input;
// that.getCartList();
}).catch(err => {
this.$util.Tips({
title: err
});
// uni.hideLoading();
});
}
},
}
</script>
<style lang="scss" scoped>
.container {
padding: 22rpx 20rpx;
}
.goods-box {
padding: 32rpx 24rpx;
border-radius: 24rpx;
background: #FFFFFF;
.header {
margin-bottom: 26rpx;
font-size: 28rpx;
line-height: 40rpx;
color: #333333;
}
.pictrue {
width: 136rpx;
height: 136rpx;
border-radius: 16rpx;
}
image {
width: 100%;
height: 100%;
border-radius: 16rpx;
}
.text {
flex: 1;
padding-left: 20rpx;
}
.title {
font-size: 28rpx;
line-height: 40rpx;
color: #333333;
}
.orangcol {
font-size: 24rpx;
line-height: 34rpx;
color: #666666;
text {
color: #2A7EFB;
}
}
.txt {
font-size: 24rpx;
line-height: 34rpx;
color: #666666;
}
.reduce {
width: 32rpx;
height: 36rpx;
text-align: left;
line-height: 36rpx;
.iconfont {
font-size: 24rpx;
color: #333333;
}
&.bggary {
.iconfont {
color: #CCCCCC;
}
}
}
.plus {
width: 32rpx;
height: 36rpx;
text-align: right;
line-height: 36rpx;
.iconfont {
font-size: 24rpx;
color: #333333;
}
&.bggary {
.iconfont {
color: #CCCCCC;
}
}
}
.nums {
width: 72rpx;
height: 36rpx;
border-radius: 4rpx;
background: #F5F5F5;
text-align: center;
font-family: SemiBold;
font-weight: 600;
font-size: 24rpx;
line-height: 36rpx;
color: #333333;
}
.iconfont {
font-size: 24rpx;
}
}
.record-box {
padding-bottom: 30rpx;
border-radius: 24rpx;
margin-top: 20rpx;
background: #FFFFFF;
.header {
padding: 32rpx 0 16rpx 24rpx;
font-weight: 500;
font-size: 30rpx;
line-height: 42rpx;
color: #333333;
}
.list {
padding: 0 40rpx;
}
.item {
height: 88rpx;
border-bottom: 1rpx solid #F1F1F1;
font-size: 28rpx;
color: #333333;
.right {
color: #666666;
}
}
}
.footer {
position: fixed;
bottom: 0;
left: 0;
width: 100%;
height: 112rpx;
height: calc(112rpx + constant(safe-area-inset-bottom));
height: calc(112rpx + env(safe-area-inset-bottom));
padding: 0 20rpx;
padding-bottom: constant(safe-area-inset-bottom);
padding-bottom: env(safe-area-inset-bottom);
background: #FFFFFF;
.btn {
flex: 1;
height: 72rpx;
border: 2rpx solid #2A7EFB;
border-radius: 36rpx;
margin-right: 16rpx;
text-align: center;
font-weight: 500;
font-size: 26rpx;
line-height: 68rpx;
color: #2A7EFB;
&:last-child {
margin-right: 0;
background: #2A7EFB;
color: #FFFFFF;
}
}
}
.item ~ .item{
margin-top: 40rpx;
}
</style>