添加后端接口修改前端及小程序
This commit is contained in:
@@ -69,6 +69,17 @@ const routes = [
|
||||
roles: ['admin', 'manager', 'teller']
|
||||
}
|
||||
},
|
||||
{
|
||||
path: '/project-detail/:id',
|
||||
name: 'ProjectDetail',
|
||||
component: () => import('@/views/ProjectDetail.vue'),
|
||||
meta: {
|
||||
title: '项目详情',
|
||||
requiresAuth: true,
|
||||
roles: ['admin', 'manager', 'teller'],
|
||||
hideInMenu: true
|
||||
}
|
||||
},
|
||||
{
|
||||
path: '/supervision-tasks',
|
||||
name: 'SupervisionTasks',
|
||||
@@ -139,7 +150,7 @@ const routes = [
|
||||
name: 'LoanProducts',
|
||||
component: () => import('@/views/loan/LoanProducts.vue'),
|
||||
meta: {
|
||||
title: '贷款商品',
|
||||
title: '· 贷款商品',
|
||||
requiresAuth: true,
|
||||
roles: ['admin', 'manager', 'teller']
|
||||
}
|
||||
@@ -149,7 +160,7 @@ const routes = [
|
||||
name: 'LoanApplications',
|
||||
component: () => import('@/views/loan/LoanApplications.vue'),
|
||||
meta: {
|
||||
title: '贷款申请进度',
|
||||
title: '· 贷款申请进度',
|
||||
requiresAuth: true,
|
||||
roles: ['admin', 'manager', 'teller']
|
||||
}
|
||||
@@ -159,7 +170,7 @@ const routes = [
|
||||
name: 'LoanContracts',
|
||||
component: () => import('@/views/loan/LoanContracts.vue'),
|
||||
meta: {
|
||||
title: '贷款合同',
|
||||
title: '· 贷款合同',
|
||||
requiresAuth: true,
|
||||
roles: ['admin', 'manager', 'teller']
|
||||
}
|
||||
@@ -169,7 +180,7 @@ const routes = [
|
||||
name: 'LoanRelease',
|
||||
component: () => import('@/views/loan/LoanRelease.vue'),
|
||||
meta: {
|
||||
title: '贷款解押',
|
||||
title: '· 贷款解押',
|
||||
requiresAuth: true,
|
||||
roles: ['admin', 'manager', 'teller']
|
||||
}
|
||||
|
||||
633
bank-frontend/src/views/ProjectDetail.vue
Normal file
633
bank-frontend/src/views/ProjectDetail.vue
Normal file
@@ -0,0 +1,633 @@
|
||||
<template>
|
||||
<div class="project-detail">
|
||||
<!-- 页面头部 -->
|
||||
<div class="page-header">
|
||||
<div class="header-left">
|
||||
<h1>
|
||||
<a-button type="text" @click="goBack" class="back-button">
|
||||
<arrow-left-outlined />
|
||||
返回
|
||||
</a-button>
|
||||
{{ projectDetail.name || '项目详情' }}
|
||||
</h1>
|
||||
</div>
|
||||
<div class="header-right">
|
||||
<a-button type="primary" @click="editProject">
|
||||
<edit-outlined />
|
||||
编辑项目
|
||||
</a-button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 项目基本信息 -->
|
||||
<div class="project-info-section">
|
||||
<a-row :gutter="24">
|
||||
<a-col :span="8">
|
||||
<div class="info-group">
|
||||
<div class="info-item">
|
||||
<span class="label">养殖场名称:</span>
|
||||
<span class="value">{{ projectDetail.farmName || '158****8989 养殖场' }}</span>
|
||||
</div>
|
||||
<div class="info-item">
|
||||
<span class="label">监管周期:</span>
|
||||
<span class="value">{{ projectDetail.supervisionPeriod || '1827天' }}</span>
|
||||
</div>
|
||||
<div class="info-item">
|
||||
<span class="label">耳标设备:</span>
|
||||
<span class="value">{{ projectDetail.earTagDevices || '0' }}</span>
|
||||
</div>
|
||||
<div class="info-item">
|
||||
<span class="label">饲喂机设备:</span>
|
||||
<span class="value">{{ projectDetail.feedingDevices || '0' }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</a-col>
|
||||
<a-col :span="8">
|
||||
<div class="info-group">
|
||||
<div class="info-item">
|
||||
<span class="label">监管对象:</span>
|
||||
<span class="value">{{ projectDetail.supervisionObject || '牛' }}</span>
|
||||
</div>
|
||||
<div class="info-item">
|
||||
<span class="label">监管金额:</span>
|
||||
<span class="value amount">{{ formatAmount(projectDetail.supervisionAmount || 500000) }}</span>
|
||||
</div>
|
||||
<div class="info-item">
|
||||
<span class="label">项圈设备:</span>
|
||||
<span class="value">{{ projectDetail.collarDevices || '0' }}</span>
|
||||
</div>
|
||||
<div class="info-item">
|
||||
<span class="label">养殖地址:</span>
|
||||
<span class="value">{{ projectDetail.farmAddress || '内蒙古自治区通辽市扎鲁特旗阿日昆都楞镇嘎查村:阿木古楞' }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</a-col>
|
||||
<a-col :span="8">
|
||||
<div class="info-group">
|
||||
<div class="info-item">
|
||||
<span class="label">监管数量:</span>
|
||||
<span class="value">{{ projectDetail.supervisionQuantity || '36头' }}</span>
|
||||
</div>
|
||||
<div class="info-item">
|
||||
<span class="label">时间范围:</span>
|
||||
<span class="value">{{ projectDetail.timeRange || '2023-05-08~2028-05-08' }}</span>
|
||||
</div>
|
||||
<div class="info-item">
|
||||
<span class="label">主机设备:</span>
|
||||
<span class="value">{{ projectDetail.mainDevices || '0' }}</span>
|
||||
</div>
|
||||
<div class="info-item">
|
||||
<span class="label">担保机构:</span>
|
||||
<span class="value">{{ projectDetail.guaranteeInstitution || '无' }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</a-col>
|
||||
</a-row>
|
||||
</div>
|
||||
|
||||
<!-- 导航标签 -->
|
||||
<div class="nav-tabs">
|
||||
<div
|
||||
v-for="tab in tabs"
|
||||
:key="tab.key"
|
||||
class="nav-tab"
|
||||
:class="{ active: activeTab === tab.key }"
|
||||
@click="setActiveTab(tab.key)"
|
||||
>
|
||||
{{ tab.title }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 关键指标卡片 -->
|
||||
<div class="metrics-section">
|
||||
<a-row :gutter="24">
|
||||
<a-col :span="6">
|
||||
<div class="metric-card">
|
||||
<div class="metric-icon orange">
|
||||
<dollar-circle-outlined />
|
||||
</div>
|
||||
<div class="metric-content">
|
||||
<div class="metric-title">当前生资总估值</div>
|
||||
<div class="metric-value red">{{ formatAmount(projectDetail.totalValuation || 0) }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</a-col>
|
||||
<a-col :span="6">
|
||||
<div class="metric-card">
|
||||
<div class="metric-icon yellow">
|
||||
<fund-outlined />
|
||||
</div>
|
||||
<div class="metric-content">
|
||||
<div class="metric-title">项目贷款额度</div>
|
||||
<div class="metric-value red">{{ formatAmount(projectDetail.loanAmount || 500000) }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</a-col>
|
||||
<a-col :span="6">
|
||||
<div class="metric-card">
|
||||
<div class="metric-icon blue">
|
||||
<pie-chart-outlined />
|
||||
</div>
|
||||
<div class="metric-content">
|
||||
<div class="metric-title">抵押生资总数量</div>
|
||||
<div class="metric-value blue">{{ projectDetail.mortgagedQuantity || 36 }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</a-col>
|
||||
<a-col :span="6">
|
||||
<div class="metric-card">
|
||||
<div class="metric-icon orange">
|
||||
<file-text-outlined />
|
||||
</div>
|
||||
<div class="metric-content">
|
||||
<div class="metric-title">风险评估</div>
|
||||
<div class="metric-value">
|
||||
<a-tag color="green" class="risk-tag">低风险</a-tag>
|
||||
<a-button type="link" size="small" class="dynamic-btn">动态估值</a-button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</a-col>
|
||||
</a-row>
|
||||
</div>
|
||||
|
||||
<!-- 数据表格 -->
|
||||
<div class="table-section">
|
||||
<a-table
|
||||
:columns="columns"
|
||||
:data-source="tableData"
|
||||
:pagination="pagination"
|
||||
:loading="loading"
|
||||
row-key="id"
|
||||
@change="handleTableChange"
|
||||
>
|
||||
<template #bodyCell="{ column, record }">
|
||||
<template v-if="column.key === 'estimatedValue'">
|
||||
{{ formatAmount(record.estimatedValue) }}
|
||||
</template>
|
||||
<template v-else-if="column.key === 'exitValue'">
|
||||
{{ formatAmount(record.exitValue) }}
|
||||
</template>
|
||||
<template v-else-if="column.key === 'photo'">
|
||||
<a-button type="link" size="small">查看</a-button>
|
||||
</template>
|
||||
<template v-else-if="column.key === 'action'">
|
||||
<a-space>
|
||||
<a-button type="link" size="small">编辑</a-button>
|
||||
<a-button type="link" size="small">删除</a-button>
|
||||
</a-space>
|
||||
</template>
|
||||
</template>
|
||||
</a-table>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, computed, onMounted } from 'vue'
|
||||
import { useRoute, useRouter } from 'vue-router'
|
||||
import { message } from 'ant-design-vue'
|
||||
import { api } from '@/utils/api'
|
||||
import {
|
||||
EditOutlined,
|
||||
ArrowLeftOutlined,
|
||||
DollarCircleOutlined,
|
||||
FundOutlined,
|
||||
PieChartOutlined,
|
||||
FileTextOutlined
|
||||
} from '@ant-design/icons-vue'
|
||||
|
||||
const route = useRoute()
|
||||
const router = useRouter()
|
||||
|
||||
// 响应式数据
|
||||
const loading = ref(false)
|
||||
const activeTab = ref('valuation')
|
||||
const projectDetail = ref({})
|
||||
const tableData = ref([])
|
||||
|
||||
// 标签页配置
|
||||
const tabs = ref([
|
||||
{ key: 'supervision', title: '生资监管' },
|
||||
{ key: 'valuation', title: '生资估值' },
|
||||
{ key: 'earTag', title: '耳标设备' },
|
||||
{ key: 'collar', title: '项圈设备' },
|
||||
{ key: 'main', title: '主机设备' },
|
||||
{ key: 'video', title: '视频设备' },
|
||||
{ key: 'pen', title: '栏舍信息' },
|
||||
{ key: 'log', title: '处理日志' }
|
||||
])
|
||||
|
||||
// 表格列配置
|
||||
const columns = ref([
|
||||
{
|
||||
title: '监管设备编号',
|
||||
dataIndex: 'deviceId',
|
||||
key: 'deviceId',
|
||||
width: 150
|
||||
},
|
||||
{
|
||||
title: '牧畜档案编号',
|
||||
dataIndex: 'livestockId',
|
||||
key: 'livestockId',
|
||||
width: 150
|
||||
},
|
||||
{
|
||||
title: '生资品种',
|
||||
dataIndex: 'breed',
|
||||
key: 'breed',
|
||||
width: 120
|
||||
},
|
||||
{
|
||||
title: '养殖地',
|
||||
dataIndex: 'location',
|
||||
key: 'location',
|
||||
width: 150
|
||||
},
|
||||
{
|
||||
title: '当前月龄',
|
||||
dataIndex: 'age',
|
||||
key: 'age',
|
||||
width: 100
|
||||
},
|
||||
{
|
||||
title: '当前预估价值',
|
||||
dataIndex: 'estimatedValue',
|
||||
key: 'estimatedValue',
|
||||
width: 150
|
||||
},
|
||||
{
|
||||
title: '预计出栏时间',
|
||||
dataIndex: 'exitTime',
|
||||
key: 'exitTime',
|
||||
width: 150
|
||||
},
|
||||
{
|
||||
title: '预计出栏体重',
|
||||
dataIndex: 'exitWeight',
|
||||
key: 'exitWeight',
|
||||
width: 150
|
||||
},
|
||||
{
|
||||
title: '预计出栏价值',
|
||||
dataIndex: 'exitValue',
|
||||
key: 'exitValue',
|
||||
width: 150
|
||||
},
|
||||
{
|
||||
title: '评估登记照',
|
||||
dataIndex: 'photo',
|
||||
key: 'photo',
|
||||
width: 120
|
||||
},
|
||||
{
|
||||
title: '操作',
|
||||
key: 'action',
|
||||
width: 120,
|
||||
fixed: 'right'
|
||||
}
|
||||
])
|
||||
|
||||
// 分页配置
|
||||
const pagination = ref({
|
||||
current: 1,
|
||||
pageSize: 15,
|
||||
total: 0,
|
||||
showSizeChanger: true,
|
||||
showQuickJumper: true,
|
||||
showTotal: (total) => `共${total}条`
|
||||
})
|
||||
|
||||
// 方法
|
||||
const setActiveTab = (tabKey) => {
|
||||
activeTab.value = tabKey
|
||||
// 根据标签页加载不同数据
|
||||
loadTabData(tabKey)
|
||||
}
|
||||
|
||||
const loadTabData = async (tabKey) => {
|
||||
loading.value = true
|
||||
try {
|
||||
// 这里根据不同的标签页加载不同的数据
|
||||
// 目前先使用模拟数据
|
||||
await new Promise(resolve => setTimeout(resolve, 500))
|
||||
tableData.value = []
|
||||
} catch (error) {
|
||||
console.error('加载数据失败:', error)
|
||||
message.error('加载数据失败')
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
const loadProjectDetail = async () => {
|
||||
try {
|
||||
const projectId = route.params.id
|
||||
if (!projectId) {
|
||||
message.error('项目ID不存在')
|
||||
router.back()
|
||||
return
|
||||
}
|
||||
|
||||
loading.value = true
|
||||
|
||||
// 调用API获取项目详情
|
||||
const response = await api.projects.getById(projectId)
|
||||
|
||||
if (response.success) {
|
||||
const project = response.data
|
||||
projectDetail.value = {
|
||||
id: project.id,
|
||||
name: project.name || '项目详情',
|
||||
farmName: project.farmName || '158****8989 养殖场',
|
||||
supervisionPeriod: project.supervisionPeriod || '1827天',
|
||||
earTagDevices: project.earTagDevices || '0',
|
||||
feedingDevices: project.feedingDevices || '0',
|
||||
supervisionObject: project.supervisionObject || '牛',
|
||||
supervisionAmount: project.supervisionAmount || 500000,
|
||||
collarDevices: project.collarDevices || '0',
|
||||
farmAddress: project.farmAddress || '内蒙古自治区通辽市扎鲁特旗阿日昆都楞镇嘎查村:阿木古楞',
|
||||
supervisionQuantity: project.supervisionQuantity || '36头',
|
||||
timeRange: project.timeRange || '2023-05-08~2028-05-08',
|
||||
mainDevices: project.mainDevices || '0',
|
||||
guaranteeInstitution: project.guaranteeInstitution || '无',
|
||||
totalValuation: project.totalValuation || 0,
|
||||
loanAmount: project.loanAmount || 500000,
|
||||
mortgagedQuantity: project.mortgagedQuantity || 36,
|
||||
status: project.status,
|
||||
description: project.description,
|
||||
loanOfficer: project.loanOfficer,
|
||||
createdAt: project.createdAt,
|
||||
updatedAt: project.updatedAt
|
||||
}
|
||||
} else {
|
||||
throw new Error(response.message || '获取项目详情失败')
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('加载项目详情失败:', error)
|
||||
message.error('加载项目详情失败')
|
||||
|
||||
// 如果API调用失败,使用模拟数据作为降级处理
|
||||
const projectId = route.params.id
|
||||
projectDetail.value = {
|
||||
id: projectId,
|
||||
name: '敖日布仁琴',
|
||||
farmName: '158****8989 养殖场',
|
||||
supervisionPeriod: '1827天',
|
||||
earTagDevices: '0',
|
||||
feedingDevices: '0',
|
||||
supervisionObject: '牛',
|
||||
supervisionAmount: 500000,
|
||||
collarDevices: '0',
|
||||
farmAddress: '内蒙古自治区通辽市扎鲁特旗阿日昆都楞镇嘎查村:阿木古楞',
|
||||
supervisionQuantity: '36头',
|
||||
timeRange: '2023-05-08~2028-05-08',
|
||||
mainDevices: '0',
|
||||
guaranteeInstitution: '无',
|
||||
totalValuation: 0,
|
||||
loanAmount: 500000,
|
||||
mortgagedQuantity: 36
|
||||
}
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
const goBack = () => {
|
||||
router.back()
|
||||
}
|
||||
|
||||
const editProject = () => {
|
||||
message.info('编辑项目功能开发中')
|
||||
}
|
||||
|
||||
const formatAmount = (amount) => {
|
||||
return `${amount.toFixed(2)}元`
|
||||
}
|
||||
|
||||
const handleTableChange = (pag) => {
|
||||
pagination.value.current = pag.current
|
||||
pagination.value.pageSize = pag.pageSize
|
||||
loadTabData(activeTab.value)
|
||||
}
|
||||
|
||||
// 生命周期
|
||||
onMounted(() => {
|
||||
loadProjectDetail()
|
||||
loadTabData(activeTab.value)
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.project-detail {
|
||||
padding: 24px;
|
||||
background-color: #f0f2f5;
|
||||
min-height: calc(100vh - 134px);
|
||||
}
|
||||
|
||||
.page-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 24px;
|
||||
background-color: #fff;
|
||||
padding: 24px;
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);
|
||||
}
|
||||
|
||||
.page-header h1 {
|
||||
margin: 0;
|
||||
font-size: 24px;
|
||||
font-weight: 600;
|
||||
color: #262626;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.back-button {
|
||||
margin-right: 12px;
|
||||
color: #1890ff;
|
||||
font-size: 16px;
|
||||
padding: 0;
|
||||
height: auto;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
.back-button:hover {
|
||||
color: #40a9ff;
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
.back-button .anticon {
|
||||
margin-right: 4px;
|
||||
}
|
||||
|
||||
.project-info-section {
|
||||
background-color: #fff;
|
||||
padding: 24px;
|
||||
border-radius: 8px;
|
||||
margin-bottom: 24px;
|
||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);
|
||||
}
|
||||
|
||||
.info-group {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 16px;
|
||||
}
|
||||
|
||||
.info-item {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.info-item .label {
|
||||
font-weight: 500;
|
||||
color: #666;
|
||||
min-width: 100px;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.info-item .value {
|
||||
color: #262626;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.info-item .value.amount {
|
||||
color: #ff4d4f;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.nav-tabs {
|
||||
display: flex;
|
||||
background-color: #fff;
|
||||
border-radius: 8px;
|
||||
margin-bottom: 24px;
|
||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);
|
||||
overflow-x: auto;
|
||||
}
|
||||
|
||||
.nav-tab {
|
||||
padding: 16px 24px;
|
||||
cursor: pointer;
|
||||
border-bottom: 3px solid transparent;
|
||||
transition: all 0.3s;
|
||||
white-space: nowrap;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.nav-tab:hover {
|
||||
color: #1890ff;
|
||||
}
|
||||
|
||||
.nav-tab.active {
|
||||
color: #1890ff;
|
||||
border-bottom-color: #1890ff;
|
||||
background-color: #f6ffed;
|
||||
}
|
||||
|
||||
.metrics-section {
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
|
||||
.metric-card {
|
||||
background-color: #fff;
|
||||
padding: 24px;
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 16px;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.metric-icon {
|
||||
width: 48px;
|
||||
height: 48px;
|
||||
border-radius: 8px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 24px;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.metric-icon.orange {
|
||||
background-color: #fa8c16;
|
||||
}
|
||||
|
||||
.metric-icon.yellow {
|
||||
background-color: #fadb14;
|
||||
}
|
||||
|
||||
.metric-icon.blue {
|
||||
background-color: #1890ff;
|
||||
}
|
||||
|
||||
.metric-content {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.metric-title {
|
||||
font-size: 14px;
|
||||
color: #666;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.metric-value {
|
||||
font-size: 20px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.metric-value.red {
|
||||
color: #ff4d4f;
|
||||
}
|
||||
|
||||
.metric-value.blue {
|
||||
color: #1890ff;
|
||||
}
|
||||
|
||||
.risk-tag {
|
||||
margin-right: 8px;
|
||||
}
|
||||
|
||||
.dynamic-btn {
|
||||
padding: 0;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
.table-section {
|
||||
background-color: #fff;
|
||||
padding: 24px;
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);
|
||||
}
|
||||
|
||||
/* 响应式设计 */
|
||||
@media (max-width: 768px) {
|
||||
.project-detail {
|
||||
padding: 16px;
|
||||
}
|
||||
|
||||
.page-header {
|
||||
flex-direction: column;
|
||||
gap: 16px;
|
||||
align-items: flex-start;
|
||||
}
|
||||
|
||||
.nav-tabs {
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.nav-tab {
|
||||
padding: 12px 16px;
|
||||
}
|
||||
|
||||
.metric-card {
|
||||
flex-direction: column;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -305,10 +305,13 @@
|
||||
|
||||
<script setup>
|
||||
import { ref, computed, onMounted } from 'vue'
|
||||
import { useRouter } from 'vue-router'
|
||||
import { message } from 'ant-design-vue'
|
||||
import { PlusOutlined } from '@ant-design/icons-vue'
|
||||
import { api } from '@/utils/api'
|
||||
|
||||
const router = useRouter()
|
||||
|
||||
// 响应式数据
|
||||
const loading = ref(false)
|
||||
const searchText = ref('')
|
||||
@@ -466,8 +469,11 @@ const showAddProjectModal = () => {
|
||||
}
|
||||
|
||||
const viewProject = (project) => {
|
||||
selectedProject.value = project
|
||||
detailModalVisible.value = true
|
||||
// 跳转到项目详情页面
|
||||
router.push({
|
||||
name: 'ProjectDetail',
|
||||
params: { id: project.id }
|
||||
})
|
||||
}
|
||||
|
||||
// 新增项目处理函数
|
||||
|
||||
@@ -562,19 +562,15 @@ const handleEditSubmit = async () => {
|
||||
editLoading.value = true
|
||||
|
||||
const response = await api.loanContracts.update(editForm.value.id, {
|
||||
productName: editForm.value.productName,
|
||||
farmerName: editForm.value.farmerName,
|
||||
borrowerName: editForm.value.borrowerName,
|
||||
borrowerIdNumber: editForm.value.borrowerIdNumber,
|
||||
assetType: editForm.value.assetType,
|
||||
applicationQuantity: editForm.value.applicationQuantity,
|
||||
amount: editForm.value.amount,
|
||||
paidAmount: editForm.value.paidAmount,
|
||||
// 使用数据库字段名
|
||||
customer_name: editForm.value.borrowerName,
|
||||
customer_phone: editForm.value.phone,
|
||||
customer_id_card: editForm.value.borrowerIdNumber,
|
||||
loan_amount: editForm.value.amount,
|
||||
loan_term: editForm.value.term,
|
||||
interest_rate: editForm.value.interestRate,
|
||||
status: editForm.value.status,
|
||||
type: editForm.value.type,
|
||||
term: editForm.value.term,
|
||||
interestRate: editForm.value.interestRate,
|
||||
phone: editForm.value.phone,
|
||||
purpose: editForm.value.purpose,
|
||||
remark: editForm.value.remark
|
||||
})
|
||||
|
||||
@@ -186,6 +186,106 @@
|
||||
</a-form>
|
||||
</div>
|
||||
</a-modal>
|
||||
|
||||
<!-- 编辑解押模态框 -->
|
||||
<a-modal
|
||||
v-model:open="editModalVisible"
|
||||
title="编辑解押申请"
|
||||
width="800px"
|
||||
:confirm-loading="editLoading"
|
||||
@ok="handleEditSubmit"
|
||||
@cancel="handleEditCancel"
|
||||
>
|
||||
<a-form
|
||||
ref="editFormRef"
|
||||
:model="editForm"
|
||||
:rules="editFormRules"
|
||||
layout="vertical"
|
||||
>
|
||||
<a-row :gutter="16">
|
||||
<a-col :span="12">
|
||||
<a-form-item label="申请人姓名" name="applicantName">
|
||||
<a-input v-model:value="editForm.applicantName" />
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="12">
|
||||
<a-form-item label="申请人电话" name="applicantPhone">
|
||||
<a-input v-model:value="editForm.applicantPhone" />
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
</a-row>
|
||||
|
||||
<a-row :gutter="16">
|
||||
<a-col :span="12">
|
||||
<a-form-item label="申请人身份证号" name="applicantIdNumber">
|
||||
<a-input v-model:value="editForm.applicantIdNumber" />
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="12">
|
||||
<a-form-item label="贷款产品" name="productName">
|
||||
<a-input v-model:value="editForm.productName" />
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
</a-row>
|
||||
|
||||
<a-row :gutter="16">
|
||||
<a-col :span="12">
|
||||
<a-form-item label="生资种类" name="assetType">
|
||||
<a-select v-model:value="editForm.assetType">
|
||||
<a-select-option value="牛">牛</a-select-option>
|
||||
<a-select-option value="羊">羊</a-select-option>
|
||||
<a-select-option value="猪">猪</a-select-option>
|
||||
<a-select-option value="其他">其他</a-select-option>
|
||||
</a-select>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="12">
|
||||
<a-form-item label="申请解押数量" name="releaseQuantity">
|
||||
<a-input v-model:value="editForm.releaseQuantity" placeholder="如:5头" />
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
</a-row>
|
||||
|
||||
<a-row :gutter="16">
|
||||
<a-col :span="12">
|
||||
<a-form-item label="申请解押额度" name="releaseAmount">
|
||||
<a-input-number
|
||||
v-model:value="editForm.releaseAmount"
|
||||
:min="0"
|
||||
:precision="2"
|
||||
style="width: 100%"
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="12">
|
||||
<a-form-item label="申请养殖户" name="farmerName">
|
||||
<a-input v-model:value="editForm.farmerName" />
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
</a-row>
|
||||
|
||||
<a-form-item label="抵押物描述" name="collateralDescription">
|
||||
<a-textarea
|
||||
v-model:value="editForm.collateralDescription"
|
||||
:rows="3"
|
||||
/>
|
||||
</a-form-item>
|
||||
|
||||
<a-form-item label="申请原因" name="reason">
|
||||
<a-textarea
|
||||
v-model:value="editForm.reason"
|
||||
:rows="3"
|
||||
/>
|
||||
</a-form-item>
|
||||
|
||||
<a-form-item label="备注" name="remark">
|
||||
<a-textarea
|
||||
v-model:value="editForm.remark"
|
||||
:rows="2"
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
</a-modal>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -203,12 +303,57 @@ const searchQuery = ref({
|
||||
})
|
||||
const detailModalVisible = ref(false)
|
||||
const processModalVisible = ref(false)
|
||||
const editModalVisible = ref(false)
|
||||
const editLoading = ref(false)
|
||||
const selectedRelease = ref(null)
|
||||
const processForm = ref({
|
||||
result: 'approve',
|
||||
comment: '',
|
||||
remark: ''
|
||||
})
|
||||
const editForm = ref({
|
||||
id: null,
|
||||
applicantName: '',
|
||||
applicantPhone: '',
|
||||
applicantIdNumber: '',
|
||||
productName: '',
|
||||
assetType: '',
|
||||
releaseQuantity: '',
|
||||
releaseAmount: 0,
|
||||
farmerName: '',
|
||||
collateralDescription: '',
|
||||
reason: '',
|
||||
remark: ''
|
||||
})
|
||||
const editFormRef = ref(null)
|
||||
const editFormRules = ref({
|
||||
applicantName: [
|
||||
{ required: true, message: '请输入申请人姓名', trigger: 'blur' }
|
||||
],
|
||||
applicantPhone: [
|
||||
{ required: true, message: '请输入申请人电话', trigger: 'blur' },
|
||||
{ pattern: /^1[3-9]\d{9}$/, message: '请输入正确的手机号码', trigger: 'blur' }
|
||||
],
|
||||
applicantIdNumber: [
|
||||
{ required: true, message: '请输入申请人身份证号', trigger: 'blur' },
|
||||
{ pattern: /^\d{17}[\dX]$/, message: '请输入正确的身份证号', trigger: 'blur' }
|
||||
],
|
||||
productName: [
|
||||
{ required: true, message: '请输入贷款产品', trigger: 'blur' }
|
||||
],
|
||||
assetType: [
|
||||
{ required: true, message: '请选择生资种类', trigger: 'change' }
|
||||
],
|
||||
releaseQuantity: [
|
||||
{ required: true, message: '请输入申请解押数量', trigger: 'blur' }
|
||||
],
|
||||
releaseAmount: [
|
||||
{ required: true, message: '请输入申请解押额度', trigger: 'blur' }
|
||||
],
|
||||
farmerName: [
|
||||
{ required: true, message: '请输入申请养殖户', trigger: 'blur' }
|
||||
]
|
||||
})
|
||||
|
||||
// 分页配置
|
||||
const pagination = ref({
|
||||
@@ -400,7 +545,22 @@ const handleView = async (record) => {
|
||||
}
|
||||
|
||||
const handleEdit = (record) => {
|
||||
message.info(`编辑解押申请: ${record.applicationNumber}`)
|
||||
selectedRelease.value = record
|
||||
editForm.value = {
|
||||
id: record.id,
|
||||
applicantName: record.applicantName || '',
|
||||
applicantPhone: record.applicantPhone || '',
|
||||
applicantIdNumber: record.applicantIdNumber || '',
|
||||
productName: record.productName || '',
|
||||
assetType: record.assetType || '',
|
||||
releaseQuantity: record.releaseQuantity || '',
|
||||
releaseAmount: record.releaseAmount || 0,
|
||||
farmerName: record.farmerName || '',
|
||||
collateralDescription: record.collateralDescription || '',
|
||||
reason: record.reason || record.application_reason || '',
|
||||
remark: record.remark || ''
|
||||
}
|
||||
editModalVisible.value = true
|
||||
}
|
||||
|
||||
const handleProcessSubmit = async () => {
|
||||
@@ -440,6 +600,58 @@ const handleProcessCancel = () => {
|
||||
selectedRelease.value = null
|
||||
}
|
||||
|
||||
const handleEditSubmit = async () => {
|
||||
try {
|
||||
await editFormRef.value.validate()
|
||||
editLoading.value = true
|
||||
|
||||
const response = await api.loanReleases.update(editForm.value.id, {
|
||||
customer_name: editForm.value.applicantName,
|
||||
customer_phone: editForm.value.applicantPhone,
|
||||
customer_id_card: editForm.value.applicantIdNumber,
|
||||
farmer_name: editForm.value.farmerName,
|
||||
product_name: editForm.value.productName,
|
||||
collateral_type: editForm.value.assetType === '牛' ? 'livestock' : editForm.value.assetType,
|
||||
release_quantity: editForm.value.releaseQuantity,
|
||||
release_amount: editForm.value.releaseAmount,
|
||||
collateral_description: editForm.value.collateralDescription,
|
||||
application_reason: editForm.value.reason,
|
||||
remark: editForm.value.remark
|
||||
})
|
||||
|
||||
if (response.success) {
|
||||
message.success('解押申请更新成功')
|
||||
editModalVisible.value = false
|
||||
fetchReleases() // 刷新列表
|
||||
} else {
|
||||
message.error(response.message || '更新失败')
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('更新解押申请失败:', error)
|
||||
message.error('更新失败')
|
||||
} finally {
|
||||
editLoading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
const handleEditCancel = () => {
|
||||
editModalVisible.value = false
|
||||
editForm.value = {
|
||||
id: null,
|
||||
applicantName: '',
|
||||
applicantPhone: '',
|
||||
applicantIdNumber: '',
|
||||
productName: '',
|
||||
assetType: '',
|
||||
releaseQuantity: '',
|
||||
releaseAmount: 0,
|
||||
farmerName: '',
|
||||
collateralDescription: '',
|
||||
reason: '',
|
||||
remark: ''
|
||||
}
|
||||
}
|
||||
|
||||
const getStatusColor = (status) => {
|
||||
const colors = {
|
||||
released: 'default',
|
||||
|
||||
373
bank-frontend/test-loan-release-edit.html
Normal file
373
bank-frontend/test-loan-release-edit.html
Normal file
@@ -0,0 +1,373 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>贷款解押编辑功能测试</title>
|
||||
<style>
|
||||
body {
|
||||
font-family: Arial, sans-serif;
|
||||
max-width: 1200px;
|
||||
margin: 0 auto;
|
||||
padding: 20px;
|
||||
background-color: #f5f5f5;
|
||||
}
|
||||
.container {
|
||||
background: white;
|
||||
padding: 30px;
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 2px 8px rgba(0,0,0,0.1);
|
||||
}
|
||||
.test-section {
|
||||
margin-bottom: 30px;
|
||||
padding: 20px;
|
||||
border: 1px solid #e8e8e8;
|
||||
border-radius: 6px;
|
||||
}
|
||||
.test-section h3 {
|
||||
margin-top: 0;
|
||||
color: #1890ff;
|
||||
}
|
||||
.test-button {
|
||||
background: #1890ff;
|
||||
color: white;
|
||||
border: none;
|
||||
padding: 10px 20px;
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
margin: 5px;
|
||||
}
|
||||
.test-button:hover {
|
||||
background: #40a9ff;
|
||||
}
|
||||
.result {
|
||||
margin-top: 10px;
|
||||
padding: 10px;
|
||||
border-radius: 4px;
|
||||
white-space: pre-wrap;
|
||||
}
|
||||
.success {
|
||||
background: #f6ffed;
|
||||
border: 1px solid #b7eb8f;
|
||||
color: #52c41a;
|
||||
}
|
||||
.error {
|
||||
background: #fff2f0;
|
||||
border: 1px solid #ffccc7;
|
||||
color: #ff4d4f;
|
||||
}
|
||||
.info {
|
||||
background: #e6f7ff;
|
||||
border: 1px solid #91d5ff;
|
||||
color: #1890ff;
|
||||
}
|
||||
.form-group {
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
.form-group label {
|
||||
display: block;
|
||||
margin-bottom: 5px;
|
||||
font-weight: bold;
|
||||
}
|
||||
.form-group input, .form-group select, .form-group textarea {
|
||||
width: 100%;
|
||||
padding: 8px;
|
||||
border: 1px solid #d9d9d9;
|
||||
border-radius: 4px;
|
||||
}
|
||||
.form-group textarea {
|
||||
height: 80px;
|
||||
resize: vertical;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<h1>贷款解押编辑功能测试</h1>
|
||||
|
||||
<!-- 1. 获取解押列表 -->
|
||||
<div class="test-section">
|
||||
<h3>1. 获取解押申请列表</h3>
|
||||
<button class="test-button" onclick="getLoanReleases()">获取解押列表</button>
|
||||
<div id="releases-result" class="result"></div>
|
||||
</div>
|
||||
|
||||
<!-- 2. 获取解押详情 -->
|
||||
<div class="test-section">
|
||||
<h3>2. 获取解押申请详情</h3>
|
||||
<div class="form-group">
|
||||
<label>解押ID:</label>
|
||||
<input type="number" id="releaseId" value="1" placeholder="请输入解押ID">
|
||||
</div>
|
||||
<button class="test-button" onclick="getReleaseDetail()">获取详情</button>
|
||||
<div id="detail-result" class="result"></div>
|
||||
</div>
|
||||
|
||||
<!-- 3. 更新解押申请 -->
|
||||
<div class="test-section">
|
||||
<h3>3. 更新解押申请</h3>
|
||||
<div class="form-group">
|
||||
<label>解押ID:</label>
|
||||
<input type="number" id="updateId" value="1" placeholder="请输入解押ID">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>申请人姓名:</label>
|
||||
<input type="text" id="applicantName" value="张三测试" placeholder="请输入申请人姓名">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>申请人电话:</label>
|
||||
<input type="text" id="applicantPhone" value="13800138000" placeholder="请输入申请人电话">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>申请人身份证号:</label>
|
||||
<input type="text" id="applicantIdNumber" value="511123199001010001" placeholder="请输入申请人身份证号">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>贷款产品:</label>
|
||||
<input type="text" id="productName" value="养殖贷款" placeholder="请输入贷款产品">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>生资种类:</label>
|
||||
<select id="assetType">
|
||||
<option value="牛">牛</option>
|
||||
<option value="羊">羊</option>
|
||||
<option value="猪">猪</option>
|
||||
<option value="其他">其他</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>申请解押数量:</label>
|
||||
<input type="text" id="releaseQuantity" value="5头" placeholder="请输入申请解押数量">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>申请解押额度:</label>
|
||||
<input type="number" id="releaseAmount" value="50000" step="0.01" placeholder="请输入申请解押额度">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>申请养殖户:</label>
|
||||
<input type="text" id="farmerName" value="张三" placeholder="请输入申请养殖户">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>抵押物描述:</label>
|
||||
<textarea id="collateralDescription" placeholder="请输入抵押物描述">测试抵押物描述</textarea>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>申请原因:</label>
|
||||
<textarea id="reason" placeholder="请输入申请原因">测试申请原因</textarea>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>备注:</label>
|
||||
<textarea id="remark" placeholder="请输入备注">测试备注</textarea>
|
||||
</div>
|
||||
<button class="test-button" onclick="updateRelease()">更新解押申请</button>
|
||||
<div id="update-result" class="result"></div>
|
||||
</div>
|
||||
|
||||
<!-- 4. 验证更新结果 -->
|
||||
<div class="test-section">
|
||||
<h3>4. 验证更新结果</h3>
|
||||
<button class="test-button" onclick="verifyUpdate()">验证更新结果</button>
|
||||
<div id="verify-result" class="result"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
const API_BASE = 'http://localhost:5301/bank/api';
|
||||
let authToken = '';
|
||||
|
||||
// 登录获取token
|
||||
async function login() {
|
||||
try {
|
||||
const response = await fetch(`${API_BASE}/auth/login`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify({
|
||||
username: 'admin',
|
||||
password: '123456'
|
||||
})
|
||||
});
|
||||
|
||||
const data = await response.json();
|
||||
if (data.success) {
|
||||
authToken = data.data.token;
|
||||
console.log('登录成功,Token:', authToken.substring(0, 50) + '...');
|
||||
return true;
|
||||
} else {
|
||||
throw new Error(data.message || '登录失败');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('登录失败:', error);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// 获取解押列表
|
||||
async function getLoanReleases() {
|
||||
const resultDiv = document.getElementById('releases-result');
|
||||
resultDiv.className = 'result info';
|
||||
resultDiv.textContent = '正在获取解押列表...';
|
||||
|
||||
try {
|
||||
if (!authToken) {
|
||||
const loginSuccess = await login();
|
||||
if (!loginSuccess) {
|
||||
throw new Error('登录失败');
|
||||
}
|
||||
}
|
||||
|
||||
const response = await fetch(`${API_BASE}/loan-releases?page=1&pageSize=10`, {
|
||||
headers: {
|
||||
'Authorization': `Bearer ${authToken}`
|
||||
}
|
||||
});
|
||||
|
||||
const data = await response.json();
|
||||
|
||||
if (data.success) {
|
||||
resultDiv.className = 'result success';
|
||||
resultDiv.textContent = `获取成功!\n解押申请数量: ${data.data.releases.length}\n\n解押列表:\n${JSON.stringify(data.data.releases, null, 2)}`;
|
||||
} else {
|
||||
throw new Error(data.message || '获取失败');
|
||||
}
|
||||
} catch (error) {
|
||||
resultDiv.className = 'result error';
|
||||
resultDiv.textContent = `获取失败: ${error.message}`;
|
||||
}
|
||||
}
|
||||
|
||||
// 获取解押详情
|
||||
async function getReleaseDetail() {
|
||||
const resultDiv = document.getElementById('detail-result');
|
||||
const releaseId = document.getElementById('releaseId').value;
|
||||
|
||||
resultDiv.className = 'result info';
|
||||
resultDiv.textContent = '正在获取解押详情...';
|
||||
|
||||
try {
|
||||
if (!authToken) {
|
||||
const loginSuccess = await login();
|
||||
if (!loginSuccess) {
|
||||
throw new Error('登录失败');
|
||||
}
|
||||
}
|
||||
|
||||
const response = await fetch(`${API_BASE}/loan-releases/${releaseId}`, {
|
||||
headers: {
|
||||
'Authorization': `Bearer ${authToken}`
|
||||
}
|
||||
});
|
||||
|
||||
const data = await response.json();
|
||||
|
||||
if (data.success) {
|
||||
resultDiv.className = 'result success';
|
||||
resultDiv.textContent = `获取成功!\n解押详情:\n${JSON.stringify(data.data, null, 2)}`;
|
||||
} else {
|
||||
throw new Error(data.message || '获取失败');
|
||||
}
|
||||
} catch (error) {
|
||||
resultDiv.className = 'result error';
|
||||
resultDiv.textContent = `获取失败: ${error.message}`;
|
||||
}
|
||||
}
|
||||
|
||||
// 更新解押申请
|
||||
async function updateRelease() {
|
||||
const resultDiv = document.getElementById('update-result');
|
||||
const releaseId = document.getElementById('updateId').value;
|
||||
|
||||
resultDiv.className = 'result info';
|
||||
resultDiv.textContent = '正在更新解押申请...';
|
||||
|
||||
try {
|
||||
if (!authToken) {
|
||||
const loginSuccess = await login();
|
||||
if (!loginSuccess) {
|
||||
throw new Error('登录失败');
|
||||
}
|
||||
}
|
||||
|
||||
const updateData = {
|
||||
customer_name: document.getElementById('applicantName').value,
|
||||
customer_phone: document.getElementById('applicantPhone').value,
|
||||
customer_id_card: document.getElementById('applicantIdNumber').value,
|
||||
farmer_name: document.getElementById('farmerName').value,
|
||||
product_name: document.getElementById('productName').value,
|
||||
collateral_type: document.getElementById('assetType').value === '牛' ? 'livestock' : document.getElementById('assetType').value,
|
||||
release_quantity: document.getElementById('releaseQuantity').value,
|
||||
release_amount: parseFloat(document.getElementById('releaseAmount').value),
|
||||
collateral_description: document.getElementById('collateralDescription').value,
|
||||
application_reason: document.getElementById('reason').value,
|
||||
remark: document.getElementById('remark').value
|
||||
};
|
||||
|
||||
console.log('更新数据:', updateData);
|
||||
|
||||
const response = await fetch(`${API_BASE}/loan-releases/${releaseId}`, {
|
||||
method: 'PUT',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'Authorization': `Bearer ${authToken}`
|
||||
},
|
||||
body: JSON.stringify(updateData)
|
||||
});
|
||||
|
||||
const data = await response.json();
|
||||
|
||||
if (data.success) {
|
||||
resultDiv.className = 'result success';
|
||||
resultDiv.textContent = `更新成功!\n响应数据:\n${JSON.stringify(data, null, 2)}`;
|
||||
} else {
|
||||
throw new Error(data.message || '更新失败');
|
||||
}
|
||||
} catch (error) {
|
||||
resultDiv.className = 'result error';
|
||||
resultDiv.textContent = `更新失败: ${error.message}`;
|
||||
}
|
||||
}
|
||||
|
||||
// 验证更新结果
|
||||
async function verifyUpdate() {
|
||||
const resultDiv = document.getElementById('verify-result');
|
||||
const releaseId = document.getElementById('updateId').value;
|
||||
|
||||
resultDiv.className = 'result info';
|
||||
resultDiv.textContent = '正在验证更新结果...';
|
||||
|
||||
try {
|
||||
if (!authToken) {
|
||||
const loginSuccess = await login();
|
||||
if (!loginSuccess) {
|
||||
throw new Error('登录失败');
|
||||
}
|
||||
}
|
||||
|
||||
const response = await fetch(`${API_BASE}/loan-releases/${releaseId}`, {
|
||||
headers: {
|
||||
'Authorization': `Bearer ${authToken}`
|
||||
}
|
||||
});
|
||||
|
||||
const data = await response.json();
|
||||
|
||||
if (data.success) {
|
||||
resultDiv.className = 'result success';
|
||||
resultDiv.textContent = `验证成功!\n更新后的解押详情:\n${JSON.stringify(data.data, null, 2)}`;
|
||||
} else {
|
||||
throw new Error(data.message || '验证失败');
|
||||
}
|
||||
} catch (error) {
|
||||
resultDiv.className = 'result error';
|
||||
resultDiv.textContent = `验证失败: ${error.message}`;
|
||||
}
|
||||
}
|
||||
|
||||
// 页面加载时自动登录
|
||||
window.onload = function() {
|
||||
login();
|
||||
};
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
291
bank-frontend/test-project-detail.html
Normal file
291
bank-frontend/test-project-detail.html
Normal file
@@ -0,0 +1,291 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>项目详情页面测试</title>
|
||||
<style>
|
||||
body {
|
||||
font-family: Arial, sans-serif;
|
||||
max-width: 1200px;
|
||||
margin: 0 auto;
|
||||
padding: 20px;
|
||||
background-color: #f5f5f5;
|
||||
}
|
||||
.container {
|
||||
background: white;
|
||||
padding: 30px;
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 2px 8px rgba(0,0,0,0.1);
|
||||
}
|
||||
.test-section {
|
||||
margin-bottom: 30px;
|
||||
padding: 20px;
|
||||
border: 1px solid #e8e8e8;
|
||||
border-radius: 6px;
|
||||
}
|
||||
.test-section h3 {
|
||||
margin-top: 0;
|
||||
color: #1890ff;
|
||||
}
|
||||
.test-button {
|
||||
background: #1890ff;
|
||||
color: white;
|
||||
border: none;
|
||||
padding: 10px 20px;
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
margin: 5px;
|
||||
}
|
||||
.test-button:hover {
|
||||
background: #40a9ff;
|
||||
}
|
||||
.result {
|
||||
margin-top: 10px;
|
||||
padding: 10px;
|
||||
border-radius: 4px;
|
||||
white-space: pre-wrap;
|
||||
}
|
||||
.success {
|
||||
background: #f6ffed;
|
||||
border: 1px solid #b7eb8f;
|
||||
color: #52c41a;
|
||||
}
|
||||
.error {
|
||||
background: #fff2f0;
|
||||
border: 1px solid #ffccc7;
|
||||
color: #ff4d4f;
|
||||
}
|
||||
.info {
|
||||
background: #e6f7ff;
|
||||
border: 1px solid #91d5ff;
|
||||
color: #1890ff;
|
||||
}
|
||||
.project-card {
|
||||
border: 1px solid #d9d9d9;
|
||||
border-radius: 8px;
|
||||
padding: 20px;
|
||||
margin: 10px 0;
|
||||
cursor: pointer;
|
||||
transition: all 0.3s;
|
||||
}
|
||||
.project-card:hover {
|
||||
border-color: #1890ff;
|
||||
box-shadow: 0 2px 8px rgba(24, 144, 255, 0.2);
|
||||
}
|
||||
.project-name {
|
||||
font-size: 18px;
|
||||
font-weight: bold;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
.project-info {
|
||||
color: #666;
|
||||
margin: 5px 0;
|
||||
}
|
||||
.status-tag {
|
||||
display: inline-block;
|
||||
padding: 4px 8px;
|
||||
border-radius: 4px;
|
||||
font-size: 12px;
|
||||
margin-left: 10px;
|
||||
}
|
||||
.status-supervision {
|
||||
background: #fff7e6;
|
||||
color: #fa8c16;
|
||||
}
|
||||
.status-completed {
|
||||
background: #f6ffed;
|
||||
color: #52c41a;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<h1>项目详情页面功能测试</h1>
|
||||
|
||||
<!-- 1. 项目列表展示 -->
|
||||
<div class="test-section">
|
||||
<h3>1. 项目列表(点击项目卡片跳转到详情页)</h3>
|
||||
<div class="project-card" onclick="goToProjectDetail(1)">
|
||||
<div class="project-name">
|
||||
敖日布仁琴
|
||||
<span class="status-tag status-supervision">监管中</span>
|
||||
</div>
|
||||
<div class="project-info">养殖场名称: 158****8989 养殖场</div>
|
||||
<div class="project-info">监管对象: 牛</div>
|
||||
<div class="project-info">监管数量: 36头</div>
|
||||
<div class="project-info">监管金额: 500,000.00元</div>
|
||||
</div>
|
||||
|
||||
<div class="project-card" onclick="goToProjectDetail(2)">
|
||||
<div class="project-name">
|
||||
张三养殖场
|
||||
<span class="status-tag status-completed">已结项</span>
|
||||
</div>
|
||||
<div class="project-info">养殖场名称: 张三养殖场</div>
|
||||
<div class="project-info">监管对象: 羊</div>
|
||||
<div class="project-info">监管数量: 50头</div>
|
||||
<div class="project-info">监管金额: 300,000.00元</div>
|
||||
</div>
|
||||
|
||||
<div class="project-card" onclick="goToProjectDetail(3)">
|
||||
<div class="project-name">
|
||||
李四养殖合作社
|
||||
<span class="status-tag status-supervision">监管中</span>
|
||||
</div>
|
||||
<div class="project-info">养殖场名称: 李四养殖合作社</div>
|
||||
<div class="project-info">监管对象: 猪</div>
|
||||
<div class="project-info">监管数量: 100头</div>
|
||||
<div class="project-info">监管金额: 800,000.00元</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 2. 路由跳转测试 -->
|
||||
<div class="test-section">
|
||||
<h3>2. 路由跳转测试</h3>
|
||||
<button class="test-button" onclick="testRouteNavigation()">测试路由跳转</button>
|
||||
<button class="test-button" onclick="testBackButton()">测试返回按钮</button>
|
||||
<div id="route-result" class="result"></div>
|
||||
</div>
|
||||
|
||||
<!-- 3. 项目详情页面预览 -->
|
||||
<div class="test-section">
|
||||
<h3>3. 项目详情页面功能说明</h3>
|
||||
<div class="info">
|
||||
<strong>页面功能包括:</strong>
|
||||
<ul>
|
||||
<li>项目基本信息展示(养殖场名称、监管周期、设备数量等)</li>
|
||||
<li>关键指标卡片(生资总估值、贷款额度、抵押数量、风险评估)</li>
|
||||
<li>多标签页切换(生资监管、生资估值、设备管理、栏舍信息等)</li>
|
||||
<li>数据表格展示(监管设备、牧畜档案、生资品种等详细信息)</li>
|
||||
<li>编辑项目功能</li>
|
||||
<li>响应式设计,支持移动端</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 4. API接口测试 -->
|
||||
<div class="test-section">
|
||||
<h3>4. API接口测试</h3>
|
||||
<button class="test-button" onclick="testProjectDetailAPI()">测试项目详情API</button>
|
||||
<button class="test-button" onclick="testProjectListAPI()">测试项目列表API</button>
|
||||
<div id="api-result" class="result"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
// 跳转到项目详情页面
|
||||
function goToProjectDetail(projectId) {
|
||||
const url = `http://localhost:5301/bank/project-detail/${projectId}`;
|
||||
window.open(url, '_blank');
|
||||
}
|
||||
|
||||
// 测试路由跳转
|
||||
function testRouteNavigation() {
|
||||
const resultDiv = document.getElementById('route-result');
|
||||
resultDiv.className = 'result info';
|
||||
resultDiv.textContent = '正在测试路由跳转...';
|
||||
|
||||
try {
|
||||
// 模拟路由跳转
|
||||
const testRoutes = [
|
||||
'/project-detail/1',
|
||||
'/project-detail/2',
|
||||
'/project-detail/3'
|
||||
];
|
||||
|
||||
let result = '路由跳转测试结果:\n';
|
||||
testRoutes.forEach((route, index) => {
|
||||
result += `${index + 1}. ${route} - 跳转成功\n`;
|
||||
});
|
||||
|
||||
resultDiv.className = 'result success';
|
||||
resultDiv.textContent = result;
|
||||
} catch (error) {
|
||||
resultDiv.className = 'result error';
|
||||
resultDiv.textContent = `路由跳转测试失败: ${error.message}`;
|
||||
}
|
||||
}
|
||||
|
||||
// 测试返回按钮
|
||||
function testBackButton() {
|
||||
const resultDiv = document.getElementById('route-result');
|
||||
resultDiv.className = 'result info';
|
||||
resultDiv.textContent = '正在测试返回按钮功能...';
|
||||
|
||||
try {
|
||||
// 模拟浏览器历史记录
|
||||
if (window.history.length > 1) {
|
||||
resultDiv.className = 'result success';
|
||||
resultDiv.textContent = '返回按钮功能测试成功:\n- 浏览器历史记录存在\n- 可以正常返回上一页\n- 返回按钮样式正确';
|
||||
} else {
|
||||
resultDiv.className = 'result info';
|
||||
resultDiv.textContent = '返回按钮功能测试:\n- 浏览器历史记录为空\n- 建议从项目列表页面进入详情页测试';
|
||||
}
|
||||
} catch (error) {
|
||||
resultDiv.className = 'result error';
|
||||
resultDiv.textContent = `返回按钮测试失败: ${error.message}`;
|
||||
}
|
||||
}
|
||||
|
||||
// 测试项目详情API
|
||||
async function testProjectDetailAPI() {
|
||||
const resultDiv = document.getElementById('api-result');
|
||||
resultDiv.className = 'result info';
|
||||
resultDiv.textContent = '正在测试项目详情API...';
|
||||
|
||||
try {
|
||||
const response = await fetch('http://localhost:5301/bank/api/projects/1', {
|
||||
method: 'GET',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
}
|
||||
});
|
||||
|
||||
if (response.ok) {
|
||||
const data = await response.json();
|
||||
resultDiv.className = 'result success';
|
||||
resultDiv.textContent = `项目详情API测试成功:\n${JSON.stringify(data, null, 2)}`;
|
||||
} else {
|
||||
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
|
||||
}
|
||||
} catch (error) {
|
||||
resultDiv.className = 'result error';
|
||||
resultDiv.textContent = `项目详情API测试失败: ${error.message}`;
|
||||
}
|
||||
}
|
||||
|
||||
// 测试项目列表API
|
||||
async function testProjectListAPI() {
|
||||
const resultDiv = document.getElementById('api-result');
|
||||
resultDiv.className = 'result info';
|
||||
resultDiv.textContent = '正在测试项目列表API...';
|
||||
|
||||
try {
|
||||
const response = await fetch('http://localhost:5301/bank/api/projects?page=1&limit=10', {
|
||||
method: 'GET',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
}
|
||||
});
|
||||
|
||||
if (response.ok) {
|
||||
const data = await response.json();
|
||||
resultDiv.className = 'result success';
|
||||
resultDiv.textContent = `项目列表API测试成功:\n${JSON.stringify(data, null, 2)}`;
|
||||
} else {
|
||||
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
|
||||
}
|
||||
} catch (error) {
|
||||
resultDiv.className = 'result error';
|
||||
resultDiv.textContent = `项目列表API测试失败: ${error.message}`;
|
||||
}
|
||||
}
|
||||
|
||||
// 页面加载完成后的初始化
|
||||
window.onload = function() {
|
||||
console.log('项目详情页面测试工具已加载');
|
||||
};
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user