合并代码
This commit is contained in:
@@ -31,7 +31,7 @@ const routes = [
|
|||||||
{
|
{
|
||||||
path: '/mymatching',
|
path: '/mymatching',
|
||||||
name: 'MyMatching',
|
name: 'MyMatching',
|
||||||
component: () => import('@/views/MyMatching.vue'),
|
component: () => import('@/views/Matching.vue'),
|
||||||
meta: {
|
meta: {
|
||||||
title: '资金匹配',
|
title: '资金匹配',
|
||||||
requiresAuth: true
|
requiresAuth: true
|
||||||
|
|||||||
@@ -100,8 +100,13 @@ api.interceptors.response.use(
|
|||||||
ElMessage.error('服务器内部错误')
|
ElMessage.error('服务器内部错误')
|
||||||
break
|
break
|
||||||
|
|
||||||
|
case 400:
|
||||||
|
// 处理业务逻辑错误(如坏账等)
|
||||||
|
ElMessage.error(data.error?.message || data.message || '请求失败')
|
||||||
|
break
|
||||||
|
|
||||||
default:
|
default:
|
||||||
ElMessage.error(data.message || '请求失败')
|
ElMessage.error(data.error?.message || data.message || '请求失败')
|
||||||
}
|
}
|
||||||
} else if (error.request) {
|
} else if (error.request) {
|
||||||
// 网络错误
|
// 网络错误
|
||||||
|
|||||||
@@ -41,7 +41,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="stat-content">
|
<div class="stat-content">
|
||||||
<div class="stat-number">{{ stats.used_codes || 0 }}</div>
|
<div class="stat-number">{{ stats.used_codes || 0 }}</div>
|
||||||
<div class="stat-label">已使用邀请码</div>
|
<div class="stat-label">已使用二维码</div>
|
||||||
<div class="stat-sub">有效:{{ stats.active_codes || 0 }}</div>
|
<div class="stat-sub">有效:{{ stats.active_codes || 0 }}</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -52,9 +52,9 @@
|
|||||||
<!-- 生成邀请码 -->
|
<!-- 生成邀请码 -->
|
||||||
<div class="function-card">
|
<div class="function-card">
|
||||||
<div class="card-header">
|
<div class="card-header">
|
||||||
<h3>生成邀请二维码</h3>
|
<h3>生成注册二维码</h3>
|
||||||
<el-button type="primary" @click="generateInviteCode" :loading="generating">
|
<el-button type="primary" @click="generateInviteCode" :loading="generating">
|
||||||
生成新的邀请码
|
生成新的邀请二维码
|
||||||
</el-button>
|
</el-button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -68,9 +68,9 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="code-info">
|
<div class="code-info">
|
||||||
<p><strong>邀请码:</strong>{{ currentInviteCode.code }}</p>
|
|
||||||
<p><strong>过期时间:</strong>{{ formatDate(currentInviteCode.expires_at) }}</p>
|
<p><strong>过期时间:</strong>{{ formatDate(currentInviteCode.expires_at) }}</p>
|
||||||
<p class="code-tip">商户扫描此二维码可自动填写激活码进行注册</p>
|
<p class="code-tip">商户扫描此二维码可直接进入注册页面</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -291,7 +291,7 @@ const generateInviteCode = async () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
currentInviteCode.value = data.data
|
currentInviteCode.value = data.data
|
||||||
ElMessage.success('邀请码生成成功')
|
ElMessage.success('二维码生成成功')
|
||||||
|
|
||||||
// 刷新统计信息
|
// 刷新统计信息
|
||||||
loadStats()
|
loadStats()
|
||||||
@@ -299,7 +299,7 @@ const generateInviteCode = async () => {
|
|||||||
if (error.response?.data?.message) {
|
if (error.response?.data?.message) {
|
||||||
ElMessage.error(error.response.data.message)
|
ElMessage.error(error.response.data.message)
|
||||||
} else {
|
} else {
|
||||||
ElMessage.error('生成邀请码失败')
|
ElMessage.error('生成二维码失败')
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
generating.value = false
|
generating.value = false
|
||||||
@@ -319,7 +319,7 @@ const saveQRCode = () => {
|
|||||||
// 创建一个临时的a标签用于下载
|
// 创建一个临时的a标签用于下载
|
||||||
const link = document.createElement('a')
|
const link = document.createElement('a')
|
||||||
link.href = currentInviteCode.value.qr_code
|
link.href = currentInviteCode.value.qr_code
|
||||||
link.download = `邀请码_${currentInviteCode.value.code}_${new Date().toISOString().slice(0, 10)}.png`
|
link.download = `注册二维码_${new Date().toISOString().slice(0, 10)}.png`
|
||||||
|
|
||||||
// 触发下载
|
// 触发下载
|
||||||
document.body.appendChild(link)
|
document.body.appendChild(link)
|
||||||
|
|||||||
@@ -262,7 +262,7 @@
|
|||||||
<!-- 转账信息 -->
|
<!-- 转账信息 -->
|
||||||
<div class="transfer-info">
|
<div class="transfer-info">
|
||||||
<h4>转账信息</h4>
|
<h4>转账信息</h4>
|
||||||
<p><strong>收款人:</strong> {{ transferDialog.toUser.name }}</p>
|
<p><strong>收款人:</strong> {{ transferDialog.toUser.to_user_real_name }}</p>
|
||||||
<p><strong>转账金额:</strong> ¥{{ transferDialog.amount }}</p>
|
<p><strong>转账金额:</strong> ¥{{ transferDialog.amount }}</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -378,7 +378,8 @@ export default {
|
|||||||
wechatQr: '',
|
wechatQr: '',
|
||||||
alipayQr: '',
|
alipayQr: '',
|
||||||
unionpayQr: '',
|
unionpayQr: '',
|
||||||
bankCard: ''
|
bankCard: '',
|
||||||
|
to_user_real_name:'',
|
||||||
},
|
},
|
||||||
amount: 0,
|
amount: 0,
|
||||||
actualAmount: 0,
|
actualAmount: 0,
|
||||||
@@ -534,7 +535,8 @@ export default {
|
|||||||
wechatQr: userPaymentInfo.wechat_qr,
|
wechatQr: userPaymentInfo.wechat_qr,
|
||||||
alipayQr: userPaymentInfo.alipay_qr,
|
alipayQr: userPaymentInfo.alipay_qr,
|
||||||
unionpayQr: userPaymentInfo.unionpay_qr,
|
unionpayQr: userPaymentInfo.unionpay_qr,
|
||||||
bankCard: userPaymentInfo.bank_card
|
bankCard: userPaymentInfo.bank_card,
|
||||||
|
to_user_real_name: allocation.to_user_real_name,
|
||||||
},
|
},
|
||||||
amount: expectedAmount,
|
amount: expectedAmount,
|
||||||
actualAmount: expectedAmount
|
actualAmount: expectedAmount
|
||||||
|
|||||||
@@ -290,6 +290,41 @@ export default {
|
|||||||
window.addEventListener('autoStartMatching', handleAutoStartMatching)
|
window.addEventListener('autoStartMatching', handleAutoStartMatching)
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
/**
|
||||||
|
* 确认分配并创建转账记录
|
||||||
|
* @param {number} allocationId - 分配ID
|
||||||
|
* @param {number} expectedAmount - 预期转账金额
|
||||||
|
*/
|
||||||
|
async confirmAllocation(allocationId, expectedAmount) {
|
||||||
|
try {
|
||||||
|
// 获取分配详情和收款用户信息
|
||||||
|
const allocationResponse = await api.get(`/matching/allocation/${allocationId}`)
|
||||||
|
const allocation = allocationResponse.data.data
|
||||||
|
|
||||||
|
// 获取收款用户的收款码信息
|
||||||
|
const userResponse = await api.get(`/users/payment-info/${allocation.to_user_id}`)
|
||||||
|
const userPaymentInfo = userResponse.data.data
|
||||||
|
|
||||||
|
// 设置转账弹窗数据
|
||||||
|
this.transferDialog = {
|
||||||
|
visible: true,
|
||||||
|
allocationId: allocationId,
|
||||||
|
toUser: {
|
||||||
|
id: allocation.to_user_id,
|
||||||
|
name: allocation.to_user_name,
|
||||||
|
wechatQr: userPaymentInfo.wechat_qr,
|
||||||
|
alipayQr: userPaymentInfo.alipay_qr,
|
||||||
|
unionpayQr: userPaymentInfo.unionpay_qr,
|
||||||
|
bankCard: userPaymentInfo.bank_card
|
||||||
|
},
|
||||||
|
amount: expectedAmount,
|
||||||
|
actualAmount: expectedAmount
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('获取转账信息失败:', error)
|
||||||
|
this.$message.error('获取转账信息失败')
|
||||||
|
}
|
||||||
|
},
|
||||||
formatDeadline(deadlineString) {
|
formatDeadline(deadlineString) {
|
||||||
// 根据需要的格式进行处理,示例:
|
// 根据需要的格式进行处理,示例:
|
||||||
return new Date(deadlineString).toLocaleString('zh-CN', {
|
return new Date(deadlineString).toLocaleString('zh-CN', {
|
||||||
|
|||||||
@@ -156,12 +156,15 @@ export default {
|
|||||||
// 加载账户信息
|
// 加载账户信息
|
||||||
const loadAccountInfo = async () => {
|
const loadAccountInfo = async () => {
|
||||||
try {
|
try {
|
||||||
|
console.log(userStore.user,'userStore.user');
|
||||||
|
|
||||||
if (userStore.user?.id) {
|
if (userStore.user?.id) {
|
||||||
const response = await api.get(`/user/profile`);
|
const response = await api.get(`/user/profile`);
|
||||||
|
console.log(response.data);
|
||||||
if (response.data.success) {
|
if (response.data.success) {
|
||||||
accountInfo.value = response.data.data || { balance: '0.00' };
|
accountInfo.value = response.data.user || { balance: '0.00' };
|
||||||
// 确保加载头像
|
// 确保加载头像
|
||||||
if (response.data.data?.avatar) {
|
if (response.data.user?.avatar) {
|
||||||
avatarUrl.value = response.data.data.avatar;
|
avatarUrl.value = response.data.data.avatar;
|
||||||
// 更新store中的头像
|
// 更新store中的头像
|
||||||
if(userStore.user) {
|
if(userStore.user) {
|
||||||
|
|||||||
@@ -32,10 +32,15 @@
|
|||||||
<div class="category-header">分类区</div>
|
<div class="category-header">分类区</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="category-items">
|
<div class="category-items">
|
||||||
<div class="category-grid">1</div>
|
<div
|
||||||
<div class="category-grid">2</div>
|
v-for="category in categories"
|
||||||
<div class="category-grid">3</div>
|
:key="category.id"
|
||||||
<div class="category-grid">4</div>
|
class="category-grid"
|
||||||
|
@click="goToCategory(category.id)"
|
||||||
|
>
|
||||||
|
<div class="category-icon">{{ category.icon }}</div>
|
||||||
|
<div class="category-name">{{ category.name }}</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -44,32 +49,54 @@
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { ref } from 'vue'
|
import { ref } from 'vue'
|
||||||
|
import { useRouter } from 'vue-router'
|
||||||
import { transferAPI } from '../utils/api'
|
import { transferAPI } from '../utils/api'
|
||||||
import { ElMessage } from 'element-plus'
|
import { ElMessage } from 'element-plus'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
setup() {
|
setup() {
|
||||||
|
const router = useRouter()
|
||||||
const userPoints = ref(0)
|
const userPoints = ref(0)
|
||||||
|
|
||||||
|
// 分类数据
|
||||||
|
const categories = ref([
|
||||||
|
{ id: '数码产品', name: '数码产品', icon: '📱' },
|
||||||
|
{ id: '图书文具', name: '图书文具', icon: '📚' },
|
||||||
|
{ id: '生活用品', name: '生活用品', icon: '🏠' },
|
||||||
|
{ id: '食品饮料', name: '食品饮料', icon: '🍔' },
|
||||||
|
{ id: '服装配饰', name: '服装配饰', icon: '👕' },
|
||||||
|
{ id: '其他', name: '其他', icon: '📦' }
|
||||||
|
])
|
||||||
|
|
||||||
// 获取用户积分
|
// 获取用户积分
|
||||||
const getUserPoints = async () => {
|
const getUserPoints = async () => {
|
||||||
try {
|
try {
|
||||||
const response = await transferAPI.getUserAccount()
|
const {data} = await transferAPI.getUserAccount();
|
||||||
userPoints.value = response.data.balance ||
|
console.log(data);
|
||||||
response.data.points ||
|
|
||||||
response.data.currentPoints ||
|
// 根据实际API响应结构调整,以下是几种可能的取值方式
|
||||||
0
|
userPoints.value = data.data.points || 0;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('获取积分信息失败', error)
|
console.error('获取积分信息失败', error)
|
||||||
ElMessage.error('获取积分信息失败,请稍后重试')
|
ElMessage.error('获取积分信息失败,请稍后重试')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 跳转到商城对应分类
|
||||||
|
const goToCategory = (categoryId) => {
|
||||||
|
router.push({
|
||||||
|
path: '/shop',
|
||||||
|
query: { category: categoryId }
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
getUserPoints()
|
getUserPoints()
|
||||||
|
|
||||||
return {
|
return {
|
||||||
userPoints,
|
userPoints,
|
||||||
getUserPoints
|
categories,
|
||||||
|
getUserPoints,
|
||||||
|
goToCategory
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -284,7 +311,8 @@ export default {
|
|||||||
.category-items {
|
.category-items {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-rows: repeat(4, 1fr);
|
grid-template-columns: repeat(2, 1fr);
|
||||||
|
grid-template-rows: repeat(2, 1fr);
|
||||||
gap: 16px;
|
gap: 16px;
|
||||||
margin-left: 16px;
|
margin-left: 16px;
|
||||||
}
|
}
|
||||||
@@ -295,8 +323,30 @@ export default {
|
|||||||
background-color: #fff0d0;
|
background-color: #fff0d0;
|
||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
display: flex;
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
padding: 0 16px;
|
justify-content: center;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
padding: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.category-grid:hover {
|
||||||
|
background-color: #ffe4b3;
|
||||||
|
transform: translateY(-2px);
|
||||||
|
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.category-icon {
|
||||||
|
font-size: 24px;
|
||||||
|
margin-bottom: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.category-name {
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: 500;
|
||||||
|
color: var(--dark-color);
|
||||||
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 使用与主页面一致的变量 */
|
/* 使用与主页面一致的变量 */
|
||||||
|
|||||||
@@ -470,20 +470,21 @@ const getOrders = async (isLoadMore = false) => {
|
|||||||
loadingMore.value = true
|
loadingMore.value = true
|
||||||
}
|
}
|
||||||
|
|
||||||
const response = await api.get('/orders', {
|
const {data} = await api.get('/orders', {
|
||||||
params: {
|
params: {
|
||||||
page: page.value,
|
page: page.value,
|
||||||
limit: 10
|
limit: 10
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
console.log(data,'response');
|
||||||
|
|
||||||
if (isLoadMore) {
|
if (isLoadMore) {
|
||||||
orders.value.push(...response.data.orders)
|
orders.value.push(...data.data.orders)
|
||||||
} else {
|
} else {
|
||||||
orders.value = response.data.orders
|
orders.value = data.data.orders
|
||||||
}
|
}
|
||||||
|
|
||||||
hasMore.value = response.data.hasMore
|
hasMore.value = data.data.hasMore
|
||||||
page.value++
|
page.value++
|
||||||
|
|
||||||
updateStatusCounts()
|
updateStatusCounts()
|
||||||
|
|||||||
@@ -106,9 +106,8 @@
|
|||||||
<!-- 商品详情 -->
|
<!-- 商品详情 -->
|
||||||
<div class="product-details">
|
<div class="product-details">
|
||||||
<h3>商品详情</h3>
|
<h3>商品详情</h3>
|
||||||
<div class="detail-item" v-for="(value, key) in product.details" :key="key">
|
<div class="detail-content">
|
||||||
<span class="detail-label">{{ key }}:</span>
|
<p>{{ product.description || '暂无详细描述' }}</p>
|
||||||
<span class="detail-value">{{ value }}</span>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -267,10 +266,13 @@ const getProductDetail = async () => {
|
|||||||
api.get(`/products/${productId}/reviews`),
|
api.get(`/products/${productId}/reviews`),
|
||||||
api.get(`/products/${productId}/recommended`)
|
api.get(`/products/${productId}/recommended`)
|
||||||
])
|
])
|
||||||
|
console.log(productRes,'productRes');
|
||||||
|
console.log(reviewsRes,'reviewsRes');
|
||||||
|
console.log(recommendedRes,'recommendedRes');
|
||||||
|
|
||||||
product.value = productRes.data
|
product.value = productRes.data.data.product
|
||||||
reviews.value = reviewsRes.data
|
reviews.value = reviewsRes.data.data.reviews || []
|
||||||
recommendedProducts.value = recommendedRes.data
|
recommendedProducts.value = recommendedRes.data.data.products || []
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
ElMessage.error('获取商品详情失败')
|
ElMessage.error('获取商品详情失败')
|
||||||
router.go(-1)
|
router.go(-1)
|
||||||
|
|||||||
@@ -192,7 +192,7 @@
|
|||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { ref, reactive, computed, onMounted } from 'vue'
|
import { ref, reactive, computed, onMounted } from 'vue'
|
||||||
import { useRouter } from 'vue-router'
|
import { useRouter, useRoute } from 'vue-router'
|
||||||
import { useUserStore } from '@/stores/user'
|
import { useUserStore } from '@/stores/user'
|
||||||
import { ElMessage, ElMessageBox } from 'element-plus'
|
import { ElMessage, ElMessageBox } from 'element-plus'
|
||||||
import {
|
import {
|
||||||
@@ -207,6 +207,7 @@ import api from '@/utils/api'
|
|||||||
import { debounce } from 'lodash-es'
|
import { debounce } from 'lodash-es'
|
||||||
|
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
|
const route = useRoute()
|
||||||
const userStore = useUserStore()
|
const userStore = useUserStore()
|
||||||
|
|
||||||
// 响应式数据
|
// 响应式数据
|
||||||
@@ -227,12 +228,12 @@ const userPoints = ref(0)
|
|||||||
// 分类数据
|
// 分类数据
|
||||||
const categories = ref([
|
const categories = ref([
|
||||||
{ id: 'all', name: '全部', icon: '🛍️' },
|
{ id: 'all', name: '全部', icon: '🛍️' },
|
||||||
{ id: 'electronics', name: '数码', icon: '📱' },
|
{ id: '数码产品', name: '数码产品', icon: '📱' },
|
||||||
{ id: 'books', name: '图书', icon: '📚' },
|
{ id: '图书文具', name: '图书文具', icon: '📚' },
|
||||||
{ id: 'lifestyle', name: '生活', icon: '🏠' },
|
{ id: '生活用品', name: '生活用品', icon: '🏠' },
|
||||||
{ id: 'food', name: '美食', icon: '🍔' },
|
{ id: '食品饮料', name: '食品饮料', icon: '🍔' },
|
||||||
{ id: 'sports', name: '运动', icon: '⚽' },
|
{ id: '服装配饰', name: '服装配饰', icon: '👕' },
|
||||||
{ id: 'beauty', name: '美妆', icon: '💄' }
|
{ id: '其他', name: '其他', icon: '📦' }
|
||||||
])
|
])
|
||||||
|
|
||||||
// 计算属性
|
// 计算属性
|
||||||
@@ -382,7 +383,7 @@ const getProducts = async (isLoadMore = false) => {
|
|||||||
loadingMore.value = true
|
loadingMore.value = true
|
||||||
}
|
}
|
||||||
|
|
||||||
const response = await api.get('/products', {
|
const {data} = await api.get('/products', {
|
||||||
params: {
|
params: {
|
||||||
page: page.value,
|
page: page.value,
|
||||||
limit: 20,
|
limit: 20,
|
||||||
@@ -391,14 +392,15 @@ const getProducts = async (isLoadMore = false) => {
|
|||||||
sort: sortBy.value
|
sort: sortBy.value
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
console.log(data,'response');
|
||||||
|
|
||||||
if (isLoadMore) {
|
if (isLoadMore) {
|
||||||
products.value.push(...response.data.products)
|
products.value.push(...data.data.products)
|
||||||
} else {
|
} else {
|
||||||
products.value = response.data.products
|
products.value = data.data.products
|
||||||
}
|
}
|
||||||
|
|
||||||
hasMore.value = response.data.hasMore
|
hasMore.value = data.data.hasMore
|
||||||
page.value++
|
page.value++
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
ElMessage.error('获取商品列表失败')
|
ElMessage.error('获取商品列表失败')
|
||||||
@@ -414,8 +416,8 @@ const loadMore = () => {
|
|||||||
|
|
||||||
const getUserPoints = async () => {
|
const getUserPoints = async () => {
|
||||||
try {
|
try {
|
||||||
const response = await api.get('/user/points')
|
const {data} = await api.get('/user/points')
|
||||||
userPoints.value = response.data.points
|
userPoints.value = data.data.points
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('获取用户积分失败:', error)
|
console.error('获取用户积分失败:', error)
|
||||||
}
|
}
|
||||||
@@ -428,6 +430,12 @@ const truncateText = (text, maxLength) => {
|
|||||||
|
|
||||||
// 生命周期
|
// 生命周期
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
|
// 检查URL参数中是否有分类
|
||||||
|
const categoryFromQuery = route.query.category
|
||||||
|
if (categoryFromQuery && categories.value.some(cat => cat.id === categoryFromQuery)) {
|
||||||
|
selectedCategory.value = categoryFromQuery
|
||||||
|
}
|
||||||
|
|
||||||
getProducts()
|
getProducts()
|
||||||
getUserPoints()
|
getUserPoints()
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -59,7 +59,9 @@
|
|||||||
<div class="transfer-details">
|
<div class="transfer-details">
|
||||||
<p class="description">匹配订单 {{ allocation.matching_order_id }} - 第{{ allocation.cycle_number }}轮</p>
|
<p class="description">匹配订单 {{ allocation.matching_order_id }} - 第{{ allocation.cycle_number }}轮</p>
|
||||||
<p class="time">创建时间:{{ formatTime(allocation.created_at) }}</p>
|
<p class="time">创建时间:{{ formatTime(allocation.created_at) }}</p>
|
||||||
<div class="deadline-info">
|
|
||||||
|
<!-- 待出款状态 -->
|
||||||
|
<div v-if="allocation.status === 'pending'" class="deadline-info">
|
||||||
<span class="deadline-label">转账截止:</span>
|
<span class="deadline-label">转账截止:</span>
|
||||||
<span class="deadline-time" :class="allocation.time_status">
|
<span class="deadline-time" :class="allocation.time_status">
|
||||||
{{ formatTime(allocation.deadline) }}
|
{{ formatTime(allocation.deadline) }}
|
||||||
@@ -68,6 +70,34 @@
|
|||||||
({{ allocation.time_left }})
|
({{ allocation.time_left }})
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<!-- 已出款状态 -->
|
||||||
|
<div v-if="allocation.status === 'confirmed'" class="return-info">
|
||||||
|
<p class="confirmed-time">出款时间:{{ formatTime(allocation.confirmed_at) }}</p>
|
||||||
|
<div class="return-deadline-info">
|
||||||
|
<span class="return-time" :class="getReturnTimeStatus(allocation)">
|
||||||
|
{{ formatTime(allocation.can_return_after) }}
|
||||||
|
</span>
|
||||||
|
<span v-if="!allocation.return_date" class="return-status" :class="getReturnTimeStatus(allocation)">
|
||||||
|
({{ getReturnTimeText(allocation) }})
|
||||||
|
</span>
|
||||||
|
<el-tag v-if="allocation.return_date" type="success" size="small">
|
||||||
|
已回款
|
||||||
|
</el-tag>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 回款确认按钮 -->
|
||||||
|
<div v-if="!allocation.return_date && canConfirmReturn(allocation)" class="return-action">
|
||||||
|
<el-button
|
||||||
|
type="success"
|
||||||
|
size="small"
|
||||||
|
@click="showReturnConfirmDialog(allocation)"
|
||||||
|
>
|
||||||
|
确认收到回款
|
||||||
|
</el-button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<!-- 超时警告 -->
|
<!-- 超时警告 -->
|
||||||
<div v-if="!allocation.can_transfer" class="timeout-warning">
|
<div v-if="!allocation.can_transfer" class="timeout-warning">
|
||||||
<el-icon><Warning /></el-icon>
|
<el-icon><Warning /></el-icon>
|
||||||
@@ -362,6 +392,49 @@
|
|||||||
</span>
|
</span>
|
||||||
</template>
|
</template>
|
||||||
</el-dialog>
|
</el-dialog>
|
||||||
|
|
||||||
|
<!-- 回款确认对话框 -->
|
||||||
|
<el-dialog
|
||||||
|
v-model="showReturnDialog"
|
||||||
|
title="确认回款"
|
||||||
|
width="500px"
|
||||||
|
:close-on-click-modal="false"
|
||||||
|
>
|
||||||
|
<el-form :model="returnForm" label-width="100px">
|
||||||
|
<el-form-item label="回款金额">
|
||||||
|
<el-input
|
||||||
|
v-model="returnForm.returnAmount"
|
||||||
|
type="number"
|
||||||
|
placeholder="请输入回款金额"
|
||||||
|
:disabled="true"
|
||||||
|
>
|
||||||
|
<template #append>元</template>
|
||||||
|
</el-input>
|
||||||
|
</el-form-item>
|
||||||
|
|
||||||
|
<el-form-item label="备注说明">
|
||||||
|
<el-input
|
||||||
|
v-model="returnForm.description"
|
||||||
|
type="textarea"
|
||||||
|
:rows="3"
|
||||||
|
placeholder="请输入备注说明"
|
||||||
|
/>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
|
||||||
|
<template #footer>
|
||||||
|
<span class="dialog-footer">
|
||||||
|
<el-button @click="showReturnDialog = false">取消</el-button>
|
||||||
|
<el-button
|
||||||
|
type="success"
|
||||||
|
@click="confirmReturn"
|
||||||
|
:loading="confirmLoading"
|
||||||
|
>
|
||||||
|
确认回款
|
||||||
|
</el-button>
|
||||||
|
</span>
|
||||||
|
</template>
|
||||||
|
</el-dialog>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@@ -383,8 +456,14 @@ const submitLoading = ref(false)
|
|||||||
const confirmLoading = ref(false)
|
const confirmLoading = ref(false)
|
||||||
const showCreateTransfer = ref(false)
|
const showCreateTransfer = ref(false)
|
||||||
const showVoucherDialog = ref(false)
|
const showVoucherDialog = ref(false)
|
||||||
|
const showReturnDialog = ref(false)
|
||||||
const statusFilter = ref('')
|
const statusFilter = ref('')
|
||||||
const currentTransfer = ref({})
|
const currentTransfer = ref({})
|
||||||
|
const currentAllocation = ref({})
|
||||||
|
const returnForm = reactive({
|
||||||
|
returnAmount: '',
|
||||||
|
description: ''
|
||||||
|
})
|
||||||
|
|
||||||
const accountInfo = ref({})
|
const accountInfo = ref({})
|
||||||
const pendingTransfers = ref([])
|
const pendingTransfers = ref([])
|
||||||
@@ -748,6 +827,102 @@ const getStatusText = (status) => {
|
|||||||
return texts[status] || '未知'
|
return texts[status] || '未知'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取回款时间状态
|
||||||
|
* @param {Object} allocation - 分配对象
|
||||||
|
* @returns {string} 时间状态类名
|
||||||
|
*/
|
||||||
|
const getReturnTimeStatus = (allocation) => {
|
||||||
|
if (!allocation.can_return_after) return 'normal'
|
||||||
|
|
||||||
|
const now = new Date()
|
||||||
|
const canReturnTime = new Date(allocation.can_return_after)
|
||||||
|
|
||||||
|
if (now >= canReturnTime) {
|
||||||
|
return 'can-return'
|
||||||
|
} else {
|
||||||
|
return 'waiting'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取回款时间文本
|
||||||
|
* @param {Object} allocation - 分配对象
|
||||||
|
* @returns {string} 时间状态文本
|
||||||
|
*/
|
||||||
|
const getReturnTimeText = (allocation) => {
|
||||||
|
if (!allocation.can_return_after) return ''
|
||||||
|
|
||||||
|
const now = new Date()
|
||||||
|
const canReturnTime = new Date(allocation.can_return_after)
|
||||||
|
|
||||||
|
if (now >= canReturnTime) {
|
||||||
|
return '可以回款'
|
||||||
|
} else {
|
||||||
|
const timeDiff = canReturnTime - now
|
||||||
|
const hours = Math.floor(timeDiff / (60 * 60 * 1000))
|
||||||
|
const minutes = Math.floor((timeDiff % (60 * 60 * 1000)) / (60 * 1000))
|
||||||
|
|
||||||
|
if (hours > 0) {
|
||||||
|
return `${hours}小时${minutes}分钟后可回款`
|
||||||
|
} else {
|
||||||
|
return `${minutes}分钟后可回款`
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 判断是否可以确认回款
|
||||||
|
* @param {Object} allocation - 分配对象
|
||||||
|
* @returns {boolean} 是否可以确认回款
|
||||||
|
*/
|
||||||
|
const canConfirmReturn = (allocation) => {
|
||||||
|
if (!allocation.can_return_after) return false
|
||||||
|
|
||||||
|
const now = new Date()
|
||||||
|
const canReturnTime = new Date(allocation.can_return_after)
|
||||||
|
|
||||||
|
return now >= canReturnTime
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 显示回款确认对话框
|
||||||
|
* @param {Object} allocation - 分配对象
|
||||||
|
*/
|
||||||
|
const showReturnConfirmDialog = (allocation) => {
|
||||||
|
currentAllocation.value = allocation
|
||||||
|
returnForm.returnAmount = allocation.amount
|
||||||
|
returnForm.description = `匹配订单 ${allocation.matching_order_id} 回款确认`
|
||||||
|
showReturnDialog.value = true
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 确认回款
|
||||||
|
*/
|
||||||
|
const confirmReturn = async () => {
|
||||||
|
try {
|
||||||
|
confirmLoading.value = true
|
||||||
|
|
||||||
|
await api.post(`/matching/confirm-return/${currentAllocation.value.id}`, {
|
||||||
|
returnAmount: returnForm.returnAmount,
|
||||||
|
description: returnForm.description
|
||||||
|
})
|
||||||
|
|
||||||
|
ElMessage.success('回款确认成功')
|
||||||
|
showReturnDialog.value = false
|
||||||
|
|
||||||
|
// 重新加载数据
|
||||||
|
await loadPendingAllocations()
|
||||||
|
await loadTransferHistory()
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
console.error('确认回款失败:', error)
|
||||||
|
ElMessage.error(error.response?.data?.message || '确认回款失败')
|
||||||
|
} finally {
|
||||||
|
confirmLoading.value = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 显示转账凭证并确认收款
|
* 显示转账凭证并确认收款
|
||||||
@@ -1075,7 +1250,24 @@ const confirmNotReceived = async (transferId) => {
|
|||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 回款时间状态样式 */
|
||||||
|
.return-time-status {
|
||||||
|
font-size: 13px;
|
||||||
|
font-weight: 500;
|
||||||
|
margin-top: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.return-time-status.can-return {
|
||||||
|
color: #67c23a;
|
||||||
|
}
|
||||||
|
|
||||||
|
.return-time-status.waiting {
|
||||||
|
color: #e6a23c;
|
||||||
|
}
|
||||||
|
|
||||||
|
.return-time-status.normal {
|
||||||
|
color: #909399;
|
||||||
|
}
|
||||||
|
|
||||||
/* 订单状态标签样式优化 */
|
/* 订单状态标签样式优化 */
|
||||||
.transfer-header .el-tag {
|
.transfer-header .el-tag {
|
||||||
@@ -1342,6 +1534,18 @@ const confirmNotReceived = async (transferId) => {
|
|||||||
font-size: 10px;
|
font-size: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.return-time-status {
|
||||||
|
font-size: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.return-time-status.can-return {
|
||||||
|
color: #67c23a;
|
||||||
|
}
|
||||||
|
|
||||||
|
.return-time-status.waiting {
|
||||||
|
color: #e6a23c;
|
||||||
|
}
|
||||||
|
|
||||||
.navbar {
|
.navbar {
|
||||||
padding: 0 10px;
|
padding: 0 10px;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,11 +14,11 @@ export default defineConfig({
|
|||||||
port: 5173,
|
port: 5173,
|
||||||
proxy: {
|
proxy: {
|
||||||
'/api': {
|
'/api': {
|
||||||
target: 'http://114.55.111.44:3001',
|
target: 'http://localhost:3000',
|
||||||
changeOrigin: true
|
changeOrigin: true
|
||||||
},
|
},
|
||||||
'/uploads': {
|
'/uploads': {
|
||||||
target: 'http://114.55.111.44:3001',
|
target: 'http://localhost:3000',
|
||||||
changeOrigin: true
|
changeOrigin: true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user