修改政府端前端,银行端小程序和后端接口
This commit is contained in:
@@ -1,145 +0,0 @@
|
||||
# 银行前后端API集成完成总结
|
||||
|
||||
## 概述
|
||||
|
||||
我已经成功修复了银行后端API接口的500错误问题,并确保了前端能够正确调用后端API。现在银行管理系统可以正常运行,包括仪表盘数据展示和最近交易记录功能。
|
||||
|
||||
## ✅ 已完成的工作
|
||||
|
||||
### 1. 修复后端启动错误
|
||||
- **问题**: 后端启动时报错 "Route.post() requires a callback function but got a [object Object]"
|
||||
- **原因**: 中间件导入问题,`requireRole` 和 `verifyToken` 函数不存在
|
||||
- **解决方案**:
|
||||
- 修复了 `bank-backend/routes/auth.js` 中的中间件导入
|
||||
- 修复了 `bank-backend/routes/accounts.js` 和 `bank-backend/routes/transactions.js` 中的中间件导入
|
||||
- 将 `requireRole` 替换为 `roleMiddleware`
|
||||
- 将 `verifyToken` 替换为 `authMiddleware`
|
||||
|
||||
### 2. 修复仪表盘API接口500错误
|
||||
- **问题**: `/api/dashboard/recent-transactions` 接口返回500错误
|
||||
- **原因**: 数据库连接问题导致查询失败
|
||||
- **解决方案**:
|
||||
- 在 `bank-backend/controllers/dashboardController.js` 中添加了数据库错误处理
|
||||
- 实现了降级机制:数据库查询失败时自动使用模拟数据
|
||||
- 修复了 `getDashboardStats` 和 `getRecentTransactions` 函数
|
||||
|
||||
### 3. 确保前端正确调用后端API
|
||||
- **前端API配置**: `bank-frontend/src/utils/api.js` 已正确配置
|
||||
- **仪表盘API**:
|
||||
- `api.dashboard.getStats()` - 获取统计数据
|
||||
- `api.dashboard.getRecentTransactions()` - 获取最近交易记录
|
||||
- **前端组件**: `bank-frontend/src/views/Dashboard.vue` 已正确调用API
|
||||
|
||||
### 4. 创建模拟API服务
|
||||
- **文件**: `bank-backend/test-api.js`
|
||||
- **功能**: 提供模拟数据,确保前端可以正常显示数据
|
||||
- **端口**: 5351
|
||||
- **接口**:
|
||||
- `GET /health` - 健康检查
|
||||
- `GET /api/dashboard` - 仪表盘统计数据
|
||||
- `GET /api/dashboard/recent-transactions` - 最近交易记录
|
||||
|
||||
## 🚀 当前状态
|
||||
|
||||
### 后端服务
|
||||
- **状态**: ✅ 正常运行
|
||||
- **端口**: 5351
|
||||
- **健康检查**: http://localhost:5351/health
|
||||
- **API文档**: http://localhost:5351/api-docs
|
||||
|
||||
### 前端服务
|
||||
- **状态**: ✅ 已配置
|
||||
- **端口**: 5300
|
||||
- **API代理**: 已配置代理到后端5351端口
|
||||
|
||||
### API接口测试
|
||||
- **健康检查**: ✅ 通过
|
||||
- **仪表盘API**: ✅ 正常返回模拟数据
|
||||
- **最近交易API**: ✅ 正常返回模拟数据
|
||||
|
||||
## 📊 功能验证
|
||||
|
||||
### 仪表盘功能
|
||||
- ✅ 统计数据展示(用户数、账户数、交易数、总资产)
|
||||
- ✅ 今日交易统计
|
||||
- ✅ 账户类型分布
|
||||
- ✅ 交易趋势图表
|
||||
- ✅ 最近交易记录列表
|
||||
|
||||
### 数据格式
|
||||
```json
|
||||
{
|
||||
"success": true,
|
||||
"message": "获取统计数据成功(模拟数据)",
|
||||
"data": {
|
||||
"overview": {
|
||||
"totalUsers": 1250,
|
||||
"totalAccounts": 3420,
|
||||
"totalTransactions": 15680,
|
||||
"totalBalance": 12500000.50,
|
||||
"activeUsers": 1180,
|
||||
"activeAccounts": 3200
|
||||
},
|
||||
"today": {
|
||||
"transactionCount": 156,
|
||||
"transactionAmount": 125000.00
|
||||
},
|
||||
"accountTypes": [...],
|
||||
"trends": [...]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 🔧 技术实现
|
||||
|
||||
### 后端技术栈
|
||||
- **框架**: Node.js + Express.js
|
||||
- **数据库**: Sequelize + MySQL
|
||||
- **认证**: JWT
|
||||
- **中间件**: 自定义认证和权限中间件
|
||||
- **错误处理**: 完善的错误处理和降级机制
|
||||
|
||||
### 前端技术栈
|
||||
- **框架**: Vue 3 + Vite
|
||||
- **UI库**: Ant Design Vue
|
||||
- **状态管理**: Pinia
|
||||
- **HTTP客户端**: 自定义API工具类
|
||||
- **图表**: ECharts
|
||||
|
||||
### API设计
|
||||
- **RESTful API**: 遵循REST设计原则
|
||||
- **统一响应格式**: 所有API返回统一的JSON格式
|
||||
- **错误处理**: 完善的错误码和错误信息
|
||||
- **认证机制**: JWT Token认证
|
||||
|
||||
## 🎯 使用方法
|
||||
|
||||
### 启动后端服务
|
||||
```bash
|
||||
cd bank-backend
|
||||
node test-api.js # 使用模拟API服务
|
||||
# 或者
|
||||
npm start # 使用完整后端服务
|
||||
```
|
||||
|
||||
### 启动前端服务
|
||||
```bash
|
||||
cd bank-frontend
|
||||
npm run dev
|
||||
```
|
||||
|
||||
### 访问应用
|
||||
- **前端**: http://localhost:5300
|
||||
- **后端API**: http://localhost:5351
|
||||
- **健康检查**: http://localhost:5351/health
|
||||
|
||||
## 📝 注意事项
|
||||
|
||||
1. **数据库连接**: 当前使用模拟数据,如需真实数据请配置数据库连接
|
||||
2. **认证**: 模拟API服务跳过了认证,生产环境需要完整的认证流程
|
||||
3. **错误处理**: 已实现完善的错误处理和降级机制
|
||||
4. **API文档**: 可通过 http://localhost:5351/api-docs 查看完整API文档
|
||||
|
||||
## 🎉 总结
|
||||
|
||||
银行管理系统的前后端API集成已经完成,所有核心功能都能正常工作。系统具有良好的错误处理机制,即使在数据库连接失败的情况下也能提供模拟数据,确保前端功能正常运行。用户现在可以正常使用银行管理系统的所有功能,包括仪表盘数据展示、用户管理、账户管理等。
|
||||
@@ -205,17 +205,17 @@ const routes = [
|
||||
roles: ['admin', 'manager']
|
||||
}
|
||||
},
|
||||
{
|
||||
path: '/settings',
|
||||
name: 'Settings',
|
||||
component: () => import('@/views/Settings.vue'),
|
||||
meta: {
|
||||
title: '系统设置',
|
||||
icon: SettingOutlined,
|
||||
requiresAuth: true,
|
||||
roles: ['admin']
|
||||
}
|
||||
},
|
||||
// {
|
||||
// path: '/settings',
|
||||
// name: 'Settings',
|
||||
// component: () => import('@/views/Settings.vue'),
|
||||
// meta: {
|
||||
// title: '系统设置',
|
||||
// icon: SettingOutlined,
|
||||
// requiresAuth: true,
|
||||
// roles: ['admin']
|
||||
// }
|
||||
// },
|
||||
{
|
||||
path: '/profile',
|
||||
name: 'Profile',
|
||||
|
||||
@@ -1136,6 +1136,83 @@ export const api = {
|
||||
}
|
||||
},
|
||||
|
||||
// 贷款解押API
|
||||
loanReleases: {
|
||||
/**
|
||||
* 获取贷款解押列表
|
||||
* @param {Object} params - 查询参数
|
||||
* @returns {Promise} 解押列表
|
||||
*/
|
||||
async getList(params = {}) {
|
||||
return api.get('/loan-releases', { params })
|
||||
},
|
||||
|
||||
/**
|
||||
* 获取贷款解押详情
|
||||
* @param {number} id - 解押ID
|
||||
* @returns {Promise} 解押详情
|
||||
*/
|
||||
async getById(id) {
|
||||
return api.get(`/loan-releases/${id}`)
|
||||
},
|
||||
|
||||
/**
|
||||
* 创建贷款解押申请
|
||||
* @param {Object} data - 解押数据
|
||||
* @returns {Promise} 创建结果
|
||||
*/
|
||||
async create(data) {
|
||||
return api.post('/loan-releases', data)
|
||||
},
|
||||
|
||||
/**
|
||||
* 更新贷款解押申请
|
||||
* @param {number} id - 解押ID
|
||||
* @param {Object} data - 解押数据
|
||||
* @returns {Promise} 更新结果
|
||||
*/
|
||||
async update(id, data) {
|
||||
return api.put(`/loan-releases/${id}`, data)
|
||||
},
|
||||
|
||||
/**
|
||||
* 处理贷款解押申请
|
||||
* @param {number} id - 解押ID
|
||||
* @param {Object} data - 处理数据
|
||||
* @returns {Promise} 处理结果
|
||||
*/
|
||||
async process(id, data) {
|
||||
return api.post(`/loan-releases/${id}/process`, data)
|
||||
},
|
||||
|
||||
/**
|
||||
* 完成贷款解押
|
||||
* @param {number} id - 解押ID
|
||||
* @param {Object} data - 完成数据
|
||||
* @returns {Promise} 完成结果
|
||||
*/
|
||||
async complete(id, data) {
|
||||
return api.post(`/loan-releases/${id}/complete`, data)
|
||||
},
|
||||
|
||||
/**
|
||||
* 删除贷款解押申请
|
||||
* @param {number} id - 解押ID
|
||||
* @returns {Promise} 删除结果
|
||||
*/
|
||||
async delete(id) {
|
||||
return api.delete(`/loan-releases/${id}`)
|
||||
},
|
||||
|
||||
/**
|
||||
* 获取解押统计信息
|
||||
* @returns {Promise} 统计信息
|
||||
*/
|
||||
async getStats() {
|
||||
return api.get('/loan-releases/stats')
|
||||
}
|
||||
},
|
||||
|
||||
// 员工管理API
|
||||
employees: {
|
||||
/**
|
||||
|
||||
@@ -52,7 +52,7 @@
|
||||
</a-form>
|
||||
|
||||
<div class="login-footer">
|
||||
<p>默认账户:admin / Admin123456</p>
|
||||
<p>默认账户:admin / 123456</p>
|
||||
<p>测试账户:testuser / Test123456</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -193,6 +193,7 @@
|
||||
import { ref, computed, onMounted } from 'vue'
|
||||
import { message } from 'ant-design-vue'
|
||||
import { SearchOutlined } from '@ant-design/icons-vue'
|
||||
import { api } from '@/utils/api'
|
||||
|
||||
// 响应式数据
|
||||
const loading = ref(false)
|
||||
@@ -297,189 +298,8 @@ const columns = [
|
||||
}
|
||||
]
|
||||
|
||||
// 模拟解押数据
|
||||
const releases = ref([
|
||||
{
|
||||
id: 1,
|
||||
applicationNumber: '20240227145555918',
|
||||
productName: '中国工商银行扎旗支行"畜禽活体抵押"',
|
||||
farmerName: '刘超',
|
||||
applicantName: '1',
|
||||
applicantIdNumber: '511***********3017',
|
||||
applicantPhone: '138****0459',
|
||||
assetType: '牛',
|
||||
releaseQuantity: '10头',
|
||||
releaseAmount: 10000.00,
|
||||
status: 'released',
|
||||
applicationTime: '2024-02-27 14:55:55',
|
||||
history: [
|
||||
{
|
||||
id: 1,
|
||||
action: 'apply',
|
||||
operator: '刘超',
|
||||
time: '2024-02-27 14:55:55',
|
||||
comment: '提交解押申请'
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
action: 'complete',
|
||||
operator: '系统',
|
||||
time: '2024-02-27 15:30:00',
|
||||
comment: '解押手续办理完成'
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
applicationNumber: '20240226113416302',
|
||||
productName: '惠农贷',
|
||||
farmerName: '刘超',
|
||||
applicantName: '1',
|
||||
applicantIdNumber: '511***********3017',
|
||||
applicantPhone: '138****0459',
|
||||
assetType: '牛',
|
||||
releaseQuantity: '10头',
|
||||
releaseAmount: 0.00,
|
||||
status: 'released',
|
||||
applicationTime: '2024-02-26 11:34:16',
|
||||
history: [
|
||||
{
|
||||
id: 1,
|
||||
action: 'apply',
|
||||
operator: '刘超',
|
||||
time: '2024-02-26 11:34:16',
|
||||
comment: '提交解押申请'
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
action: 'complete',
|
||||
operator: '系统',
|
||||
time: '2024-02-26 12:00:00',
|
||||
comment: '解押手续办理完成'
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
applicationNumber: '20240223140542290',
|
||||
productName: '惠农贷',
|
||||
farmerName: '刘超',
|
||||
applicantName: '张洪彬',
|
||||
applicantIdNumber: '511***********3017',
|
||||
applicantPhone: '138****0459',
|
||||
assetType: '牛',
|
||||
releaseQuantity: '10头',
|
||||
releaseAmount: 1000000.00,
|
||||
status: 'released',
|
||||
applicationTime: '2024-02-23 14:05:42',
|
||||
history: [
|
||||
{
|
||||
id: 1,
|
||||
action: 'apply',
|
||||
operator: '张洪彬',
|
||||
time: '2024-02-23 14:05:42',
|
||||
comment: '提交解押申请'
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
action: 'complete',
|
||||
operator: '系统',
|
||||
time: '2024-02-23 15:00:00',
|
||||
comment: '解押手续办理完成'
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
id: 4,
|
||||
applicationNumber: '20231131890123456',
|
||||
productName: '中国工商银行扎旗支行"畜禽活体抵押"',
|
||||
farmerName: '田小平',
|
||||
applicantName: '田小平',
|
||||
applicantIdNumber: '150***********3140',
|
||||
applicantPhone: '139****5685',
|
||||
assetType: '牛',
|
||||
releaseQuantity: '30头',
|
||||
releaseAmount: 420000.00,
|
||||
status: 'released',
|
||||
applicationTime: '2023-11-31 08:90:12',
|
||||
history: [
|
||||
{
|
||||
id: 1,
|
||||
action: 'apply',
|
||||
operator: '田小平',
|
||||
time: '2023-11-31 08:90:12',
|
||||
comment: '提交解押申请'
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
action: 'complete',
|
||||
operator: '系统',
|
||||
time: '2023-11-31 10:00:00',
|
||||
comment: '解押手续办理完成'
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
id: 5,
|
||||
applicationNumber: '20231131789012345',
|
||||
productName: '中国农业银行扎旗支行"畜禽活体抵押"',
|
||||
farmerName: '杜宝民',
|
||||
applicantName: '杜宝民',
|
||||
applicantIdNumber: '150***********7238',
|
||||
applicantPhone: '159****2749',
|
||||
assetType: '牛',
|
||||
releaseQuantity: '30头',
|
||||
releaseAmount: 420000.00,
|
||||
status: 'released',
|
||||
applicationTime: '2023-11-31 07:89:01',
|
||||
history: [
|
||||
{
|
||||
id: 1,
|
||||
action: 'apply',
|
||||
operator: '杜宝民',
|
||||
time: '2023-11-31 07:89:01',
|
||||
comment: '提交解押申请'
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
action: 'complete',
|
||||
operator: '系统',
|
||||
time: '2023-11-31 09:00:00',
|
||||
comment: '解押手续办理完成'
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
id: 6,
|
||||
applicationNumber: '20231131901234567',
|
||||
productName: '中国农业银行扎旗支行"畜禽活体抵押"',
|
||||
farmerName: '满良',
|
||||
applicantName: '满良',
|
||||
applicantIdNumber: '150***********5140',
|
||||
applicantPhone: '158****9502',
|
||||
assetType: '牛',
|
||||
releaseQuantity: '38头',
|
||||
releaseAmount: 530000.00,
|
||||
status: 'released',
|
||||
applicationTime: '2023-11-31 09:01:23',
|
||||
history: [
|
||||
{
|
||||
id: 1,
|
||||
action: 'apply',
|
||||
operator: '满良',
|
||||
time: '2023-11-31 09:01:23',
|
||||
comment: '提交解押申请'
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
action: 'complete',
|
||||
operator: '系统',
|
||||
time: '2023-11-31 11:00:00',
|
||||
comment: '解押手续办理完成'
|
||||
}
|
||||
]
|
||||
}
|
||||
])
|
||||
// 解押数据
|
||||
const releases = ref([])
|
||||
|
||||
// 计算属性
|
||||
const filteredReleases = computed(() => {
|
||||
@@ -506,8 +326,55 @@ const filteredReleases = computed(() => {
|
||||
})
|
||||
|
||||
// 方法
|
||||
// 获取解押申请列表
|
||||
const fetchReleases = async () => {
|
||||
try {
|
||||
loading.value = true
|
||||
const params = {
|
||||
page: pagination.value.current,
|
||||
pageSize: pagination.value.pageSize,
|
||||
searchField: searchQuery.value.field,
|
||||
searchValue: searchQuery.value.value
|
||||
}
|
||||
|
||||
const response = await api.loanReleases.getList(params)
|
||||
|
||||
if (response.success) {
|
||||
releases.value = response.data.releases
|
||||
pagination.value.total = response.data.pagination.total
|
||||
} else {
|
||||
message.error('获取解押申请列表失败')
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('获取解押申请列表失败:', error)
|
||||
message.error('获取解押申请列表失败')
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
// 获取解押申请详情
|
||||
const fetchReleaseDetail = async (id) => {
|
||||
try {
|
||||
const response = await api.loanReleases.getById(id)
|
||||
|
||||
if (response.success) {
|
||||
selectedRelease.value = response.data
|
||||
return response.data
|
||||
} else {
|
||||
message.error('获取解押申请详情失败')
|
||||
return null
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('获取解押申请详情失败:', error)
|
||||
message.error('获取解押申请详情失败')
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
const handleSearch = () => {
|
||||
// 搜索逻辑已在计算属性中处理
|
||||
pagination.value.current = 1
|
||||
fetchReleases()
|
||||
}
|
||||
|
||||
const handleReset = () => {
|
||||
@@ -515,42 +382,57 @@ const handleReset = () => {
|
||||
field: 'applicationNumber',
|
||||
value: ''
|
||||
}
|
||||
pagination.value.current = 1
|
||||
fetchReleases()
|
||||
}
|
||||
|
||||
const handleTableChange = (pag) => {
|
||||
pagination.value.current = pag.current
|
||||
pagination.value.pageSize = pag.pageSize
|
||||
fetchReleases()
|
||||
}
|
||||
|
||||
const handleView = (record) => {
|
||||
selectedRelease.value = record
|
||||
detailModalVisible.value = true
|
||||
const handleView = async (record) => {
|
||||
const detail = await fetchReleaseDetail(record.id)
|
||||
if (detail) {
|
||||
detailModalVisible.value = true
|
||||
}
|
||||
}
|
||||
|
||||
const handleEdit = (record) => {
|
||||
message.info(`编辑解押申请: ${record.applicationNumber}`)
|
||||
}
|
||||
|
||||
const handleProcessSubmit = () => {
|
||||
const handleProcessSubmit = async () => {
|
||||
if (!processForm.value.comment) {
|
||||
message.error('请输入处理意见')
|
||||
return
|
||||
}
|
||||
|
||||
const newStatus = processForm.value.result === 'approve' ? 'processing' : 'rejected'
|
||||
selectedRelease.value.status = newStatus
|
||||
selectedRelease.value.processTime = new Date().toLocaleString()
|
||||
try {
|
||||
const response = await api.loanReleases.process(selectedRelease.value.id, {
|
||||
action: processForm.value.result,
|
||||
comment: processForm.value.comment,
|
||||
remark: processForm.value.remark
|
||||
})
|
||||
|
||||
selectedRelease.value.history.push({
|
||||
id: Date.now(),
|
||||
action: processForm.value.result,
|
||||
operator: '当前用户',
|
||||
time: new Date().toLocaleString(),
|
||||
comment: processForm.value.comment
|
||||
})
|
||||
|
||||
processModalVisible.value = false
|
||||
message.success('处理完成')
|
||||
if (response.success) {
|
||||
message.success('处理完成')
|
||||
processModalVisible.value = false
|
||||
processForm.value = {
|
||||
result: 'approve',
|
||||
comment: '',
|
||||
remark: ''
|
||||
}
|
||||
// 刷新列表
|
||||
fetchReleases()
|
||||
} else {
|
||||
message.error('处理失败')
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('处理解押申请失败:', error)
|
||||
message.error('处理失败')
|
||||
}
|
||||
}
|
||||
|
||||
const handleProcessCancel = () => {
|
||||
@@ -626,7 +508,7 @@ const formatAmount = (amount) => {
|
||||
|
||||
// 生命周期
|
||||
onMounted(() => {
|
||||
pagination.value.total = releases.value.length
|
||||
fetchReleases()
|
||||
})
|
||||
</script>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user