Commit 3e43dae6 by liangjianmin

feat(approve): refactor detail page with modal approval workflow and uView config

- Update uView configuration to use setConfig with unit and component size settings
- Add approval modal component with radio selection and textarea for remarks
- Refactor detail page field bindings to use snake_case API response format
- Simplify order information section and remove agent fee details
- Add bottom action buttons for cancel and review approval
- Implement modal state management for approval workflow
- Add approve-modal styling with proper padding and layout
- Format code with consistent spacing and indentation in main.js
parent 448118af
...@@ -183,4 +183,30 @@ ...@@ -183,4 +183,30 @@
align-items: center; align-items: center;
z-index: 100; z-index: 100;
} }
.approve-modal {
padding: 40rpx 32rpx;
padding-bottom: calc(40rpx + env(safe-area-inset-bottom));
.modal-title {
font-size: 34rpx;
font-weight: 700;
color: #1e293b;
text-align: center;
margin-bottom: 40rpx;
}
.modal-body {
margin-bottom: 40rpx;
.modal-textarea-wrap {
margin-top: 32rpx;
}
}
.modal-footer {
display: flex;
align-items: center;
}
}
} }
import App from './App' import App from './App'
import {request} from './util/util.js' import { request } from './util/util.js'
import uView from '@/uni_modules/uview-ui' import uView from '@/uni_modules/uview-ui'
// #ifndef VUE3 // #ifndef VUE3
import Vue from 'vue' import Vue from 'vue'
Vue.use(uView) Vue.use(uView)
uni.$u.config.unit = 'rpx'
uni.$u.setConfig({
config: {
unit: 'rpx'
},
props: {
radio: {
size: 30,
labelSize: 30
},
checkbox: {
labelSize: 30
},
text: {
size: 30
},
input: {
fontSize: 30
},
textarea: {
fontSize: 30
}
}
})
Vue.config.productionTip = false; Vue.config.productionTip = false;
Vue.prototype.request = request; Vue.prototype.request = request;
App.mpType = 'app' App.mpType = 'app'
const app = new Vue({ const app = new Vue({
...App ...App
}) })
app.$mount() app.$mount()
// #endif // #endif
......
...@@ -3,15 +3,15 @@ ...@@ -3,15 +3,15 @@
<view class="section"> <view class="section">
<view class="section-title">申请信息</view> <view class="section-title">申请信息</view>
<u-cell-group> <u-cell-group>
<u-cell title="申请类型" :value="detail.applyType"></u-cell> <u-cell title="申请类型" :value="detail.apply_type"></u-cell>
<u-cell title="客户名称" :value="detail.customerName"></u-cell> <u-cell title="客户名称" :value="detail.customer_name"></u-cell>
<u-cell title="减免明细" :value="detail.deductionType"></u-cell> <u-cell title="减免明细" :value="detail.relief_detail"></u-cell>
<u-cell title="申请时间" :value="detail.applyTime"></u-cell> <u-cell title="申请时间" :value="detail.create_time_cn"></u-cell>
<u-cell title="订单号" :value="detail.orderNo" :value-style="{ flex: 1 }" :border="false"> <u-cell title="订单号" :value="detail.order_sn" :value-style="{ flex: 1 }" :border="false">
<template #value> <template #value>
<view class="row verCenter bothSide" style="flex: 1;"> <view class="row verCenter bothSide" style="flex: 1;">
<text>{{ detail.orderNo }}</text> <text>{{ detail.order_sn }}</text>
<text class="link-text">申请人:{{ detail.applicant }}</text> <text class="link-text">申请人:{{ detail.applicant_name }}</text>
</view> </view>
</template> </template>
</u-cell> </u-cell>
...@@ -21,16 +21,8 @@ ...@@ -21,16 +21,8 @@
<view class="section"> <view class="section">
<view class="section-title">订单信息</view> <view class="section-title">订单信息</view>
<u-cell-group> <u-cell-group>
<u-cell title="订单金额(商币)" :value="detail.orderAmount"></u-cell> <u-cell title="订单金额(商币)" :value="detail.apply_fee_amount"></u-cell>
<u-cell title="订单币别" :value="detail.currency"></u-cell> <u-cell title="减免明细" :value="detail.relief_detail" :border="false"></u-cell>
<u-cell title="代理费金额" :value="detail.agentFee" :border="false">
<template #value>
<view class="row verCenter">
<text style="margin-right: 40rpx;">{{ detail.agentFee }}</text>
<text>最低代理费:{{ detail.minAgentFee }}</text>
</view>
</template>
</u-cell>
</u-cell-group> </u-cell-group>
</view> </view>
...@@ -39,96 +31,136 @@ ...@@ -39,96 +31,136 @@
<view class="detail-content"> <view class="detail-content">
<view class="amount-box"> <view class="amount-box">
<text class="amount-label">申请免收金额(元)</text> <text class="amount-label">申请免收金额(元)</text>
<text class="amount-value">{{ detail.amount }}</text> <text class="amount-value">{{ detail.apply_fee_amount }}</text>
</view> </view>
<view class="reason-box"> <view class="reason-box">
<text class="reason-label">免收原因</text> <text class="reason-label">免收原因</text>
<text class="reason-text">{{ detail.reason }}</text> <text class="reason-text">{{ detail.relief_reason }}</text>
</view> </view>
</view> </view>
</view> </view>
<view class="section"> <!-- 审批日志 - 暂不渲染,等通知 -->
<view class="section-title">审批日志</view>
<view class="timeline-wrap"> <view class="bottom-actions" v-if="detail.status === 0">
<view class="timeline-item" v-for="(log, index) in detail.logs" :key="index"> <u-button text="取消" shape="circle" :customStyle="{ flex: 1, marginRight: '24rpx', background: '#ffffff', color: '#606266', border: '1rpx solid #dcdfe6' }" @click="goBack"></u-button>
<view class="timeline-dot"></view> <u-button text="审核" type="primary" shape="circle" :customStyle="{ flex: 1, background: '#2979ff' }" @click="openModal"></u-button>
<view class="timeline-content"> </view>
<view class="log-header row verCenter bothSide">
<text class="log-time">{{ log.time }}</text> <!-- 审批弹窗 - 底部弹出 -->
<text class="log-user">审批人:{{ log.approver }}</text> <u-popup :show="showModal" mode="bottom" round="24" @close="closeModal">
</view> <view class="approve-modal">
<view class="log-body"> <view class="modal-title">审核销售订单</view>
<text class="log-label">审批意见:</text> <view class="modal-body">
<text class="log-text">{{ log.comment }}</text> <u-radio-group v-model="modalStatus" placement="row">
</view> <u-radio :name="1" label="同意" :customStyle="{ marginRight: '60rpx' }"></u-radio>
<view class="log-footer"> <u-radio :name="2" label="不同意" activeColor="#2979ff"></u-radio>
<text class="log-label">审批结果:</text> </u-radio-group>
<text :class="['log-status', log.status]">{{ log.statusText }}</text> <view class="modal-textarea-wrap">
</view> <u-textarea v-model="remark" :placeholder="modalStatus === 2 ? '不同意时,必须填写说明...' : '请输入审批意见(选填)'" :maxlength="200" height="200"></u-textarea>
</view> </view>
</view> </view>
<view class="modal-footer">
<u-button text="取消" shape="circle" :customStyle="{ flex: 1, marginRight: '20rpx', background: '#ffffff', color: '#606266', border: '1rpx solid #dcdfe6' }" @click="closeModal"></u-button>
<u-button text="确认" type="primary" shape="circle" :loading="submitting" :customStyle="{ flex: 1, background: '#2979ff' }" @click="submitApprove"></u-button>
</view>
</view> </view>
</view> </u-popup>
<view class="bottom-actions">
<u-button text="拒绝" shape="circle" :customStyle="{ flex: 1, marginRight: '24rpx', background: '#ffffff', color: '#606266', border: '1rpx solid #dcdfe6' }" @click="handleReject"></u-button>
<u-button text="同意" type="primary" shape="circle" :customStyle="{ flex: 1, background: 'linear-gradient(135deg, #3b82f6 0%, #2563eb 100%)' }" @click="handleApprove"></u-button>
</view>
</view> </view>
</template> </template>
<script> <script>
import { API } from '@/util/api';
export default { export default {
data() { data() {
return { return {
detail: { id: '',
applyType: '费用减免申请', detail: {},
customerName: '深圳市海克斯科技有限公司', showModal: false,
deductionType: '代理费减免', modalStatus: 1,
applyTime: '2026-04-10 15:00', remark: '',
orderNo: 'B123456', submitting: false
applicant: '陈小将',
orderAmount: '100000.00',
currency: '美元',
agentFee: '300.00',
minAgentFee: '300.00',
amount: '3,000.00',
reason: '业务员在发起申请的时必须填写,字数长度不限定,宇航长度不限定',
logs: [
{
time: '1.2026-01-20 16:37',
approver: '周家仪',
comment: 'xxxxxxxxxxxx',
status: 'approved',
statusText: '通过'
},
{
time: '2.2026-01-20 16:37',
approver: '周家仪',
comment: 'xxxxxxxxxxxx',
status: 'approved',
statusText: '通过'
}
]
}
}; };
}, },
onLoad(options) {
this.id = options.id || '';
},
onShow() {
if (this.id) {
this.getData();
}
},
methods: { methods: {
/** /**
* 拒绝审批 * 通过列表接口获取当前审批详情
* @return {void} * @return {void}
*/ */
handleReject() { getData() {
// 后续接入接口逻辑 this.request(API.feeApproveList, 'GET', { id: this.id }, true).then(res => {
if (res.code === 0) {
var { list = [] } = res.data || {};
this.detail = list[0] || {};
if (this.detail.order_sn) {
uni.setNavigationBarTitle({
title: `${this.detail.order_sn} - 审核详情`
});
}
}
});
},
/**
* 返回上一页
* @return {void}
*/
goBack() {
uni.navigateBack();
},
/**
* 打开审批弹窗
* @return {void}
*/
openModal() {
this.modalStatus = 1;
this.remark = '';
this.showModal = true;
}, },
/** /**
* 同意审批 * 关闭审批弹窗
* @return {void} * @return {void}
*/ */
handleApprove() { closeModal() {
// 后续接入接口逻辑 this.showModal = false;
},
/**
* 提交审批
* @return {void}
*/
submitApprove() {
if (this.modalStatus === 2 && !this.remark.trim()) {
uni.showToast({ title: '请输入驳回原因', icon: 'none' });
return;
}
this.submitting = true;
var params = {
id: this.id,
status: this.modalStatus
};
if (this.remark.trim()) {
params.remark = this.remark.trim();
}
this.request(API.updateFeeApproveStatus, 'POST', params).then(res => {
this.submitting = false;
if (res.code === 0) {
uni.showToast({ title: '操作成功', icon: 'success' });
this.closeModal();
setTimeout(() => {
uni.navigateBack();
}, 1500);
}
}).catch(() => {
this.submitting = false;
});
} }
} }
}; };
......
...@@ -117,7 +117,7 @@ ...@@ -117,7 +117,7 @@
*/ */
handleApprove(item) { handleApprove(item) {
uni.navigateTo({ uni.navigateTo({
url: '/pages/approve/detail' url: `/pages/approve/detail?id=${item.id}`
}); });
} }
} }
......
...@@ -58,7 +58,11 @@ const API = { ...@@ -58,7 +58,11 @@ const API = {
/** /**
* 获取审批列表 * 获取审批列表
*/ */
feeApproveList: API_BASE + '/api/approve/feeApproveList' feeApproveList: API_BASE + '/api/approve/feeApproveList',
/**
* 费用审批状态修改
*/
updateFeeApproveStatus: API_BASE + '/api/approve/updateFeeApproveStatus'
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment