合并代码

This commit is contained in:
szz
2025-08-08 09:43:56 +08:00
parent d57a9dec8f
commit 4b31aad506
4 changed files with 75 additions and 246 deletions

View File

@@ -243,12 +243,6 @@ const router = createRouter({
router.beforeEach(async (to, from, next) => {
NProgress.start()
// 系统维护模式:所有页面都跳转到维护页面
// if (to.name !== 'Loading') {
// next({ name: 'Loading' })
// return
// }
const userStore = useUserStore()
// 设置页面标题

View File

@@ -81,9 +81,11 @@
<!-- 设置选项区域 -->
<div class="settings-section">
<div class="setting-item" v-for="(item, index) in settings" :key="index">
<router-link :to=item.path>
<span class="setting-text">{{ item.text }}</span>
<span class="setting-arrow">></span>
<router-link :to="item.path" class="setting-link"> <!-- 添加 class 便于样式控制 -->
<div class="setting-content"> <!-- 添加 class 便于样式控制 -->
<span class="setting-text">{{ item.text }}</span>
<span class="setting-arrow">></span>
</div>
</router-link>
</div>
</div>
@@ -535,15 +537,31 @@ export default {
}
.setting-item {
display: flex;
display: block;
justify-content: space-between;
align-items: center;
padding: 15px;
padding: 0px;
border-bottom: 1px solid #f0f0f0;
cursor: pointer;
transition: background-color 0.2s ease;
}
.setting-link {
display: block; /* 转为块级元素,占满父容器宽度 */
width: 100%;
height: 100%;
padding: 15px; /* 将原有的 padding 移到这里,确保点击区域完整 */
text-decoration: none; /* 去除链接默认下划线 */
}
.setting-content {
display: flex; /* 使用 flex 布局,方便内容左右对齐 */
justify-content: space-between; /* 文字左对齐,箭头右对齐 */
align-items: center; /* 垂直居中 */
width: 100%; /* 占满父容器宽度 */
height: 100%; /* 占满父容器高度 */
}
.setting-item:last-child {
border-bottom: none;
}

View File

@@ -164,7 +164,7 @@
<div class="transfer-list" v-loading="loading">
<div
v-for="transfer in transferHistory"
v-for="transfer in filteredTransferHistory"
:key="transfer.id"
class="transfer-item"
:class="transfer.status"
@@ -205,7 +205,10 @@
</el-image>
</div>
<!-- 确认收款操作按钮 -->
<div v-if="transfer.status === 'pending' && transfer.to_user_id === userStore.user.id" class="transfer-actions">
<div
v-if="transfer.status === 'pending' && transfer.to_user_id === userStore.user.id"
class="transfer-actions"
>
<el-button
type="success"
size="small"
@@ -227,8 +230,8 @@
</div>
</div>
<div v-if="transferHistory.length === 0" class="empty-state">
<el-empty description="暂无转账记录" />
<div v-if="filteredTransferHistory.length === 0" class="empty-state">
<el-empty :description="statusFilter === 'pending' ? '暂无待确认的转账' : '暂无转账记录'" />
</div>
</div>
@@ -300,9 +303,9 @@ const isMobile = computed(() => {
const paginationLayout = computed(() => {
if (windowWidth.value <= 480) {
return 'prev, pager, next'
} else if (windowWidth.value <= 768) {
return 'total, prev, pager, next'
return 'prev, pager, next'
} else if (windowWidth.value <= 768) {
return 'total, prev, pager, next'
} else {
return 'total, sizes, prev, pager, next, jumper'
}
@@ -324,12 +327,10 @@ onMounted(() => {
loadTransferHistory()
loadUserList()
// 添加窗口大小变化监听
window.addEventListener('resize', handleResize)
})
onUnmounted(() => {
// 移除窗口大小变化监听
window.removeEventListener('resize', handleResize)
})
@@ -339,6 +340,29 @@ watch(statusFilter, () => {
loadTransferHistory()
})
// 计算属性
const filteredTransferHistory = computed(() => {
if (!statusFilter.value) return transferHistory.value
return transferHistory.value.filter(transfer => {
if (statusFilter.value === 'pending') {
return transfer.status === 'pending' && transfer.to_user_id === userStore.user.id
}
return transfer.status === statusFilter.value
})
})
const totalCount = computed(() => pagination.total)
const pendingCount = computed(() => {
return transferHistory.value.filter(t => t.status === 'pending' && t.to_user_id === userStore.user.id).length
})
const confirmedCount = computed(() => {
return transferHistory.value.filter(t => t.status === 'confirmed').length
})
const rejectedCount = computed(() => {
return transferHistory.value.filter(t => t.status === 'rejected').length
})
// 方法
const loadPendingTransfers = async () => {
try {
@@ -348,7 +372,6 @@ const loadPendingTransfers = async () => {
}
})
if (response.data.success) {
// 过滤出需要当前用户确认的转账记录
pendingTransfers.value = response.data.data.filter(
transfer => transfer.to_user_id === userStore.user.id && transfer.status === 'pending'
)
@@ -359,9 +382,6 @@ const loadPendingTransfers = async () => {
}
}
/**
* 加载用户待处理的分配
*/
const loadPendingAllocations = async () => {
try {
const response = await api.get('/matching/pending-allocations')
@@ -379,10 +399,8 @@ const loadTransferHistory = async () => {
loading.value = true
const params = {
page: pagination.page,
limit: pagination.limit
}
if (statusFilter.value) {
params.status = statusFilter.value
limit: pagination.limit,
status: statusFilter.value || undefined
}
const response = await api.get(`/transfers/user/${userStore.user.id}`, { params })
@@ -410,9 +428,6 @@ const loadUserList = async () => {
}
}
/**
* 获取订单状态对应的标签类型
*/
const getOrderStatusType = (status) => {
const statusMap = {
'matching': 'warning',
@@ -423,9 +438,6 @@ const getOrderStatusType = (status) => {
return statusMap[status] || 'info'
}
/**
* 获取订单状态文本
*/
const getOrderStatusText = (status) => {
const statusMap = {
'matching': '进行中',
@@ -436,9 +448,6 @@ const getOrderStatusText = (status) => {
return statusMap[status] || '未知状态'
}
/**
* 获取转账类型文本
*/
const getTransferTypeText = (type) => {
const typeMap = {
'user_to_user': '用户转账',
@@ -450,146 +459,6 @@ const getTransferTypeText = (type) => {
return typeMap[type] || '未知类型'
}
const confirmTransfer = async (transferId, action) => {
try {
const actionText = action === 'confirm' ? '确认' : '拒绝'
await ElMessageBox.confirm(
`确定要${actionText}这笔转账吗?`,
'确认操作',
{
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}
)
confirmLoading.value = true
const response = await api.post(`/transfers/confirm/${transferId}`, { action })
if (response.data.success) {
ElMessage.success(response.data.message)
loadPendingTransfers()
loadTransferHistory()
loadAccountInfo()
}
} catch (error) {
if (error !== 'cancel') {
console.error('确认转账失败:', error)
ElMessage.error(error.response?.data?.message || '操作失败')
}
} finally {
confirmLoading.value = false
}
}
const submitTransfer = async () => {
try {
const valid = await transferFormRef.value.validate()
if (!valid) return
submitLoading.value = true
const formData = new FormData()
formData.append('to_user_id', transferForm.to_user_id)
formData.append('amount', transferForm.amount)
formData.append('transfer_type', transferForm.transfer_type)
formData.append('description', transferForm.description)
if (transferForm.voucher) {
// 如果有上传的凭证,需要处理文件
const fileInput = uploadRef.value?.$el.querySelector('input[type="file"]')
if (fileInput?.files[0]) {
formData.append('voucher', fileInput.files[0])
}
}
const response = await api.post('/transfers/create', formData, {
headers: {
'Content-Type': 'multipart/form-data'
}
})
if (response.data.success) {
ElMessage.success(response.data.message)
showCreateTransfer.value = false
resetTransferForm()
loadTransferHistory()
}
} catch (error) {
console.error('提交转账失败:', error)
ElMessage.error(error.response?.data?.message || '提交失败')
} finally {
submitLoading.value = false
}
}
const resetTransferForm = () => {
Object.assign(transferForm, {
to_user_id: '',
amount: '',
transfer_type: 'user_to_user',
description: '',
voucher: ''
})
transferFormRef.value?.resetFields()
}
// 文件上传处理
const beforeUpload = (file) => {
const isImage = file.type.startsWith('image/')
const isLt5M = file.size / 1024 / 1024 < 5
if (!isImage) {
ElMessage.error('只能上传图片文件!')
return false
}
if (!isLt5M) {
ElMessage.error('图片大小不能超过 5MB!')
return false
}
return true
}
/**
* 处理文件上传成功回调
* @param {Object} response - 上传接口返回的响应数据
*/
const handleUploadSuccess = (response) => {
if (response.success) {
// 使用工具函数将相对路径转换为完整的服务器地址
transferForm.voucher = formatImageUrl(response.url)
ElMessage.success('上传成功')
} else {
ElMessage.error(response.message || '上传失败')
}
}
const handleUploadError = (error) => {
console.error('上传错误:', error)
ElMessage.error('上传失败,请重试')
}
// 工具方法
/**
* 格式化时间显示
* @param {string} time - 时间字符串
* @returns {string} 格式化后的时间
*/
const formatTime = (time) => {
return new Date(time).toLocaleString('zh-CN')
}
/**
* 格式化图片URL
* @param {string} url - 相对路径或完整URL
* @returns {string} 处理后的图片URL
*/
const formatImageUrl = (url) => {
return getImageUrl(url)
}
const getStatusType = (status) => {
const types = {
pending: 'warning',
@@ -612,11 +481,14 @@ const getStatusText = (status) => {
return texts[status] || '未知'
}
/**
* 获取回款时间状态
* @param {Object} allocation - 分配对象
* @returns {string} 时间状态类名
*/
const formatTime = (time) => {
return new Date(time).toLocaleString('zh-CN')
}
const formatImageUrl = (url) => {
return getImageUrl(url)
}
const getReturnTimeStatus = (allocation) => {
if (!allocation.can_return_after) return 'normal'
@@ -630,11 +502,6 @@ const getReturnTimeStatus = (allocation) => {
}
}
/**
* 获取回款时间文本
* @param {Object} allocation - 分配对象
* @returns {string} 时间状态文本
*/
const getReturnTimeText = (allocation) => {
if (!allocation.can_return_after) return ''
@@ -656,11 +523,6 @@ const getReturnTimeText = (allocation) => {
}
}
/**
* 判断是否可以确认回款
* @param {Object} allocation - 分配对象
* @returns {boolean} 是否可以确认回款
*/
const canConfirmReturn = (allocation) => {
if (!allocation.can_return_after) return false
@@ -670,10 +532,6 @@ const canConfirmReturn = (allocation) => {
return now >= canReturnTime
}
/**
* 显示回款确认对话框
* @param {Object} allocation - 分配对象
*/
const showReturnConfirmDialog = (allocation) => {
currentAllocation.value = allocation
returnForm.returnAmount = allocation.amount
@@ -681,9 +539,6 @@ const showReturnConfirmDialog = (allocation) => {
showReturnDialog.value = true
}
/**
* 确认回款
*/
const confirmReturn = async () => {
try {
confirmLoading.value = true
@@ -696,7 +551,6 @@ const confirmReturn = async () => {
ElMessage.success('回款确认成功')
showReturnDialog.value = false
// 重新加载数据
await loadPendingAllocations()
await loadTransferHistory()
@@ -708,59 +562,36 @@ const confirmReturn = async () => {
}
}
/**
* 显示转账凭证并确认收款
*/
const confirmReceived = async (transferId) => {
try {
// 找到对应的转账记录
const transfer = transferHistory.value.find(t => t.id === transferId)
if (!transfer) {
ElMessage.error('转账记录不存在')
return
}
// 设置当前转账信息并显示凭证对话框
currentTransfer.value = transfer
showVoucherDialog.value = true
// 直接调用确认收款方法
await doConfirmReceived()
} catch (error) {
console.error('确认收款失败:', error)
ElMessage.error('操作失败')
}
}
/**
* 执行确认收款操作
*/
const doConfirmReceived = async () => {
try {
await ElMessageBox.confirm(
'确定已收到款项吗?',
'请确认已收到款项并核对凭证,确定要确认收款吗?',
'确认收款',
{
confirmButtonText: '确',
confirmButtonText: '确认收款',
cancelButtonText: '取消',
type: 'warning'
}
)
confirmLoading.value = true
const response = await api.post(`/transfers/confirm-received/${currentTransfer.value.id}`)
const response = await api.post(`/transfers/confirm-received/${transferId}`)
if (response.data.success) {
ElMessage.success(response.data.message)
showVoucherDialog.value = false
loadTransferHistory()
loadPendingTransfers() // 重新加载待确认转账
ElMessage.success('收款确认成功')
await loadTransferHistory()
await loadPendingTransfers()
}
} catch (error) {
if (error !== 'cancel') {
console.error('确认收款失败:', error)
ElMessage.error(error.response?.data?.message || '操作失败')
ElMessage.error(error.response?.data?.message || '确认收款失败')
}
} finally {
confirmLoading.value = false
@@ -785,7 +616,6 @@ const confirmNotReceived = async (transferId) => {
if (response.data.success) {
ElMessage.success(response.data.message)
loadTransferHistory()
loadAccountInfo()
}
} catch (error) {
if (error !== 'cancel') {
@@ -796,19 +626,6 @@ const confirmNotReceived = async (transferId) => {
confirmLoading.value = false
}
}
// 计算各个状态的数量
const totalCount = computed(() => pagination.total)
const pendingCount = computed(() => {
return transferHistory.value.filter(t => t.status === 'pending').length
})
const confirmedCount = computed(() => {
return transferHistory.value.filter(t => t.status === 'confirmed').length
})
const rejectedCount = computed(() => {
return transferHistory.value.filter(t => t.status === 'rejected').length
})
</script>
<style lang="scss" scoped>

View File

@@ -14,11 +14,11 @@ export default defineConfig({
port: 5173,
proxy: {
'/api': {
target: 'http://127.0.0.1:3001',
target: 'http://114.55.111.44:3001',
changeOrigin: true
},
'/uploads': {
target: 'http://127.0.0.1:3001',
target: 'http://114.55.111.44:3001',
changeOrigin: true
}
}