添加银行端后端接口
This commit is contained in:
@@ -795,6 +795,345 @@ export const api = {
|
||||
async batchDelete(data) {
|
||||
return api.delete('/supervision-tasks/batch', { data })
|
||||
}
|
||||
},
|
||||
|
||||
// 待安装任务API
|
||||
installationTasks: {
|
||||
/**
|
||||
* 获取待安装任务列表
|
||||
* @param {Object} params - 查询参数
|
||||
* @returns {Promise} 待安装任务列表
|
||||
*/
|
||||
async getList(params = {}) {
|
||||
return api.get('/installation-tasks', { params })
|
||||
},
|
||||
|
||||
/**
|
||||
* 获取待安装任务详情
|
||||
* @param {number} id - 待安装任务ID
|
||||
* @returns {Promise} 待安装任务详情
|
||||
*/
|
||||
async getById(id) {
|
||||
return api.get(`/installation-tasks/${id}`)
|
||||
},
|
||||
|
||||
/**
|
||||
* 创建待安装任务
|
||||
* @param {Object} data - 待安装任务数据
|
||||
* @returns {Promise} 创建结果
|
||||
*/
|
||||
async create(data) {
|
||||
return api.post('/installation-tasks', data)
|
||||
},
|
||||
|
||||
/**
|
||||
* 更新待安装任务
|
||||
* @param {number} id - 待安装任务ID
|
||||
* @param {Object} data - 待安装任务数据
|
||||
* @returns {Promise} 更新结果
|
||||
*/
|
||||
async update(id, data) {
|
||||
return api.put(`/installation-tasks/${id}`, data)
|
||||
},
|
||||
|
||||
/**
|
||||
* 删除待安装任务
|
||||
* @param {number} id - 待安装任务ID
|
||||
* @returns {Promise} 删除结果
|
||||
*/
|
||||
async delete(id) {
|
||||
return api.delete(`/installation-tasks/${id}`)
|
||||
},
|
||||
|
||||
/**
|
||||
* 获取待安装任务统计
|
||||
* @returns {Promise} 统计数据
|
||||
*/
|
||||
async getStats() {
|
||||
return api.get('/installation-tasks/stats')
|
||||
},
|
||||
|
||||
/**
|
||||
* 批量更新待安装任务状态
|
||||
* @param {Object} data - 批量更新数据
|
||||
* @returns {Promise} 更新结果
|
||||
*/
|
||||
async batchUpdateStatus(data) {
|
||||
return api.put('/installation-tasks/batch/status', data)
|
||||
},
|
||||
|
||||
/**
|
||||
* 批量删除待安装任务
|
||||
* @param {Object} data - 批量删除数据
|
||||
* @returns {Promise} 删除结果
|
||||
*/
|
||||
async batchDelete(data) {
|
||||
return api.delete('/installation-tasks/batch/delete', { data })
|
||||
}
|
||||
},
|
||||
|
||||
// 监管任务已结项API
|
||||
completedSupervisions: {
|
||||
/**
|
||||
* 获取监管任务已结项列表
|
||||
* @param {Object} params - 查询参数
|
||||
* @returns {Promise} 监管任务已结项列表
|
||||
*/
|
||||
async getList(params = {}) {
|
||||
return api.get('/completed-supervisions', { params })
|
||||
},
|
||||
|
||||
/**
|
||||
* 获取监管任务已结项详情
|
||||
* @param {number} id - 监管任务已结项ID
|
||||
* @returns {Promise} 监管任务已结项详情
|
||||
*/
|
||||
async getById(id) {
|
||||
return api.get(`/completed-supervisions/${id}`)
|
||||
},
|
||||
|
||||
/**
|
||||
* 创建监管任务已结项
|
||||
* @param {Object} data - 监管任务已结项数据
|
||||
* @returns {Promise} 创建结果
|
||||
*/
|
||||
async create(data) {
|
||||
return api.post('/completed-supervisions', data)
|
||||
},
|
||||
|
||||
/**
|
||||
* 更新监管任务已结项
|
||||
* @param {number} id - 监管任务已结项ID
|
||||
* @param {Object} data - 监管任务已结项数据
|
||||
* @returns {Promise} 更新结果
|
||||
*/
|
||||
async update(id, data) {
|
||||
return api.put(`/completed-supervisions/${id}`, data)
|
||||
},
|
||||
|
||||
/**
|
||||
* 删除监管任务已结项
|
||||
* @param {number} id - 监管任务已结项ID
|
||||
* @returns {Promise} 删除结果
|
||||
*/
|
||||
async delete(id) {
|
||||
return api.delete(`/completed-supervisions/${id}`)
|
||||
},
|
||||
|
||||
/**
|
||||
* 获取监管任务已结项统计
|
||||
* @returns {Promise} 统计数据
|
||||
*/
|
||||
async getStats() {
|
||||
return api.get('/completed-supervisions/stats')
|
||||
},
|
||||
|
||||
/**
|
||||
* 批量更新结清状态
|
||||
* @param {Object} data - 批量更新数据
|
||||
* @returns {Promise} 更新结果
|
||||
*/
|
||||
async batchUpdateStatus(data) {
|
||||
return api.put('/completed-supervisions/batch/status', data)
|
||||
},
|
||||
|
||||
/**
|
||||
* 批量删除监管任务已结项
|
||||
* @param {Object} data - 批量删除数据
|
||||
* @returns {Promise} 删除结果
|
||||
*/
|
||||
async batchDelete(data) {
|
||||
return api.delete('/completed-supervisions/batch/delete', { data })
|
||||
}
|
||||
},
|
||||
|
||||
// 贷款商品API
|
||||
loanProducts: {
|
||||
/**
|
||||
* 获取贷款商品列表
|
||||
* @param {Object} params - 查询参数
|
||||
* @returns {Promise} 贷款商品列表
|
||||
*/
|
||||
async getList(params = {}) {
|
||||
return api.get('/loan-products', { params })
|
||||
},
|
||||
|
||||
/**
|
||||
* 获取贷款商品详情
|
||||
* @param {number} id - 贷款商品ID
|
||||
* @returns {Promise} 贷款商品详情
|
||||
*/
|
||||
async getById(id) {
|
||||
return api.get(`/loan-products/${id}`)
|
||||
},
|
||||
|
||||
/**
|
||||
* 创建贷款商品
|
||||
* @param {Object} data - 贷款商品数据
|
||||
* @returns {Promise} 创建结果
|
||||
*/
|
||||
async create(data) {
|
||||
return api.post('/loan-products', data)
|
||||
},
|
||||
|
||||
/**
|
||||
* 更新贷款商品
|
||||
* @param {number} id - 贷款商品ID
|
||||
* @param {Object} data - 贷款商品数据
|
||||
* @returns {Promise} 更新结果
|
||||
*/
|
||||
async update(id, data) {
|
||||
return api.put(`/loan-products/${id}`, data)
|
||||
},
|
||||
|
||||
/**
|
||||
* 删除贷款商品
|
||||
* @param {number} id - 贷款商品ID
|
||||
* @returns {Promise} 删除结果
|
||||
*/
|
||||
async delete(id) {
|
||||
return api.delete(`/loan-products/${id}`)
|
||||
},
|
||||
|
||||
/**
|
||||
* 获取贷款商品统计
|
||||
* @returns {Promise} 统计数据
|
||||
*/
|
||||
async getStats() {
|
||||
return api.get('/loan-products/stats')
|
||||
},
|
||||
|
||||
/**
|
||||
* 批量更新在售状态
|
||||
* @param {Object} data - 批量更新数据
|
||||
* @returns {Promise} 更新结果
|
||||
*/
|
||||
async batchUpdateStatus(data) {
|
||||
return api.put('/loan-products/batch/status', data)
|
||||
},
|
||||
|
||||
/**
|
||||
* 批量删除贷款商品
|
||||
* @param {Object} data - 批量删除数据
|
||||
* @returns {Promise} 删除结果
|
||||
*/
|
||||
async batchDelete(data) {
|
||||
return api.delete('/loan-products/batch/delete', { data })
|
||||
}
|
||||
},
|
||||
|
||||
// 贷款申请API
|
||||
loanApplications: {
|
||||
/**
|
||||
* 获取贷款申请列表
|
||||
* @param {Object} params - 查询参数
|
||||
* @returns {Promise} 申请列表
|
||||
*/
|
||||
async getList(params = {}) {
|
||||
return api.get('/loan-applications', { params })
|
||||
},
|
||||
|
||||
/**
|
||||
* 获取贷款申请详情
|
||||
* @param {number} id - 申请ID
|
||||
* @returns {Promise} 申请详情
|
||||
*/
|
||||
async getById(id) {
|
||||
return api.get(`/loan-applications/${id}`)
|
||||
},
|
||||
|
||||
/**
|
||||
* 审核贷款申请
|
||||
* @param {number} id - 申请ID
|
||||
* @param {Object} data - 审核数据
|
||||
* @returns {Promise} 审核结果
|
||||
*/
|
||||
async audit(id, data) {
|
||||
return api.post(`/loan-applications/${id}/audit`, data)
|
||||
},
|
||||
|
||||
/**
|
||||
* 获取申请统计信息
|
||||
* @returns {Promise} 统计信息
|
||||
*/
|
||||
async getStats() {
|
||||
return api.get('/loan-applications/stats')
|
||||
},
|
||||
|
||||
/**
|
||||
* 批量更新申请状态
|
||||
* @param {Object} data - 批量操作数据
|
||||
* @returns {Promise} 更新结果
|
||||
*/
|
||||
async batchUpdateStatus(data) {
|
||||
return api.put('/loan-applications/batch/status', data)
|
||||
}
|
||||
},
|
||||
|
||||
// 贷款合同API
|
||||
loanContracts: {
|
||||
/**
|
||||
* 获取贷款合同列表
|
||||
* @param {Object} params - 查询参数
|
||||
* @returns {Promise} 合同列表
|
||||
*/
|
||||
async getList(params = {}) {
|
||||
return api.get('/loan-contracts', { params })
|
||||
},
|
||||
|
||||
/**
|
||||
* 获取贷款合同详情
|
||||
* @param {number} id - 合同ID
|
||||
* @returns {Promise} 合同详情
|
||||
*/
|
||||
async getById(id) {
|
||||
return api.get(`/loan-contracts/${id}`)
|
||||
},
|
||||
|
||||
/**
|
||||
* 创建贷款合同
|
||||
* @param {Object} data - 合同数据
|
||||
* @returns {Promise} 创建结果
|
||||
*/
|
||||
async create(data) {
|
||||
return api.post('/loan-contracts', data)
|
||||
},
|
||||
|
||||
/**
|
||||
* 更新贷款合同
|
||||
* @param {number} id - 合同ID
|
||||
* @param {Object} data - 合同数据
|
||||
* @returns {Promise} 更新结果
|
||||
*/
|
||||
async update(id, data) {
|
||||
return api.put(`/loan-contracts/${id}`, data)
|
||||
},
|
||||
|
||||
/**
|
||||
* 删除贷款合同
|
||||
* @param {number} id - 合同ID
|
||||
* @returns {Promise} 删除结果
|
||||
*/
|
||||
async delete(id) {
|
||||
return api.delete(`/loan-contracts/${id}`)
|
||||
},
|
||||
|
||||
/**
|
||||
* 获取合同统计信息
|
||||
* @returns {Promise} 统计信息
|
||||
*/
|
||||
async getStats() {
|
||||
return api.get('/loan-contracts/stats')
|
||||
},
|
||||
|
||||
/**
|
||||
* 批量更新合同状态
|
||||
* @param {Object} data - 批量操作数据
|
||||
* @returns {Promise} 更新结果
|
||||
*/
|
||||
async batchUpdateStatus(data) {
|
||||
return api.put('/loan-contracts/batch/status', data)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -72,6 +72,164 @@
|
||||
</template>
|
||||
</a-table>
|
||||
</div>
|
||||
|
||||
<!-- 编辑监管任务已结项对话框 -->
|
||||
<a-modal
|
||||
v-model:open="editModalVisible"
|
||||
title="编辑监管任务已结项"
|
||||
width="800px"
|
||||
@ok="handleEditTask"
|
||||
@cancel="handleCancelEdit"
|
||||
:confirmLoading="editLoading"
|
||||
>
|
||||
<a-form
|
||||
ref="editTaskFormRef"
|
||||
:model="editTaskForm"
|
||||
layout="vertical"
|
||||
>
|
||||
<a-row :gutter="16">
|
||||
<a-col :span="12">
|
||||
<a-form-item label="申请单号" name="applicationNumber">
|
||||
<a-input v-model:value="editTaskForm.applicationNumber" placeholder="请输入申请单号" />
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="12">
|
||||
<a-form-item label="放款合同编号" name="contractNumber">
|
||||
<a-input v-model:value="editTaskForm.contractNumber" placeholder="请输入放款合同编号" />
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
</a-row>
|
||||
|
||||
<a-row :gutter="16">
|
||||
<a-col :span="12">
|
||||
<a-form-item label="产品名称" name="productName">
|
||||
<a-input v-model:value="editTaskForm.productName" placeholder="请输入产品名称" />
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="12">
|
||||
<a-form-item label="客户姓名" name="customerName">
|
||||
<a-input v-model:value="editTaskForm.customerName" placeholder="请输入客户姓名" />
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
</a-row>
|
||||
|
||||
<a-row :gutter="16">
|
||||
<a-col :span="12">
|
||||
<a-form-item label="证件类型" name="idType">
|
||||
<a-select v-model:value="editTaskForm.idType" placeholder="请选择证件类型">
|
||||
<a-select-option value="ID_CARD">身份证</a-select-option>
|
||||
<a-select-option value="PASSPORT">护照</a-select-option>
|
||||
<a-select-option value="OTHER">其他</a-select-option>
|
||||
</a-select>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="12">
|
||||
<a-form-item label="证件号码" name="idNumber">
|
||||
<a-input v-model:value="editTaskForm.idNumber" placeholder="请输入证件号码" />
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
</a-row>
|
||||
|
||||
<a-row :gutter="16">
|
||||
<a-col :span="12">
|
||||
<a-form-item label="养殖生资种类" name="assetType">
|
||||
<a-input v-model:value="editTaskForm.assetType" placeholder="请输入养殖生资种类" />
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="12">
|
||||
<a-form-item label="监管生资数量" name="assetQuantity">
|
||||
<a-input-number
|
||||
v-model:value="editTaskForm.assetQuantity"
|
||||
:min="0"
|
||||
placeholder="请输入监管生资数量"
|
||||
style="width: 100%"
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
</a-row>
|
||||
|
||||
<a-row :gutter="16">
|
||||
<a-col :span="12">
|
||||
<a-form-item label="总还款期数" name="totalRepaymentPeriods">
|
||||
<a-input-number
|
||||
v-model:value="editTaskForm.totalRepaymentPeriods"
|
||||
:min="0"
|
||||
placeholder="请输入总还款期数"
|
||||
style="width: 100%"
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="12">
|
||||
<a-form-item label="结清状态" name="settlementStatus">
|
||||
<a-select v-model:value="editTaskForm.settlementStatus" placeholder="请选择结清状态">
|
||||
<a-select-option value="settled">已结清</a-select-option>
|
||||
<a-select-option value="unsettled">未结清</a-select-option>
|
||||
<a-select-option value="partial">部分结清</a-select-option>
|
||||
</a-select>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
</a-row>
|
||||
|
||||
<a-row :gutter="16">
|
||||
<a-col :span="12">
|
||||
<a-form-item label="结清日期" name="settlementDate">
|
||||
<a-date-picker
|
||||
v-model:value="editTaskForm.settlementDate"
|
||||
placeholder="请选择结清日期"
|
||||
style="width: 100%"
|
||||
format="YYYY-MM-DD"
|
||||
value-format="YYYY-MM-DD"
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="12">
|
||||
<a-form-item label="结清任务导入时间" name="importTime">
|
||||
<a-date-picker
|
||||
v-model:value="editTaskForm.importTime"
|
||||
placeholder="请选择导入时间"
|
||||
style="width: 100%"
|
||||
format="YYYY-MM-DD HH:mm:ss"
|
||||
value-format="YYYY-MM-DD HH:mm:ss"
|
||||
show-time
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
</a-row>
|
||||
|
||||
<a-row :gutter="16">
|
||||
<a-col :span="12">
|
||||
<a-form-item label="结清金额" name="settlementAmount">
|
||||
<a-input-number
|
||||
v-model:value="editTaskForm.settlementAmount"
|
||||
:min="0"
|
||||
:precision="2"
|
||||
placeholder="请输入结清金额"
|
||||
style="width: 100%"
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="12">
|
||||
<a-form-item label="剩余金额" name="remainingAmount">
|
||||
<a-input-number
|
||||
v-model:value="editTaskForm.remainingAmount"
|
||||
:min="0"
|
||||
:precision="2"
|
||||
placeholder="请输入剩余金额"
|
||||
style="width: 100%"
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
</a-row>
|
||||
|
||||
<a-form-item label="结清备注" name="settlementNotes">
|
||||
<a-textarea
|
||||
v-model:value="editTaskForm.settlementNotes"
|
||||
placeholder="请输入结清备注"
|
||||
:rows="3"
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
</a-modal>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -79,11 +237,19 @@
|
||||
import { ref, reactive, computed, onMounted } from 'vue'
|
||||
import { message } from 'ant-design-vue'
|
||||
import { UploadOutlined, SearchOutlined } from '@ant-design/icons-vue'
|
||||
import { api } from '@/utils/api'
|
||||
import dayjs from 'dayjs'
|
||||
|
||||
const loading = ref(false)
|
||||
const tasks = ref([])
|
||||
|
||||
// 编辑相关
|
||||
const editModalVisible = ref(false)
|
||||
const editTaskFormRef = ref()
|
||||
const editTaskForm = ref({})
|
||||
const editLoading = ref(false)
|
||||
const currentEditTask = ref(null)
|
||||
|
||||
const searchForm = reactive({
|
||||
contractNumber: undefined,
|
||||
keyword: '',
|
||||
@@ -170,44 +336,39 @@ const mockTasks = [
|
||||
const fetchTasks = async () => {
|
||||
loading.value = true
|
||||
try {
|
||||
// 实际项目中这里会调用API获取数据
|
||||
// const response = await api.completedSupervision.getList({
|
||||
// page: pagination.current,
|
||||
// pageSize: pagination.pageSize,
|
||||
// ...searchForm,
|
||||
// })
|
||||
console.log('开始获取监管任务已结项列表...', {
|
||||
page: pagination.current,
|
||||
pageSize: pagination.pageSize,
|
||||
search: searchForm.keyword,
|
||||
contractNumber: searchForm.contractNumber
|
||||
})
|
||||
|
||||
// 使用模拟数据
|
||||
tasks.value = mockTasks.map(task => ({
|
||||
...task,
|
||||
settlementDate: task.settlementDate ? dayjs(task.settlementDate) : null,
|
||||
importTime: dayjs(task.importTime),
|
||||
}))
|
||||
pagination.total = mockTasks.length
|
||||
const response = await api.completedSupervisions.getList({
|
||||
page: pagination.current,
|
||||
limit: pagination.pageSize,
|
||||
search: searchForm.keyword,
|
||||
contractNumber: searchForm.contractNumber
|
||||
})
|
||||
|
||||
console.log('监管任务已结项列表响应:', response)
|
||||
|
||||
if (response.success) {
|
||||
tasks.value = response.data.tasks || []
|
||||
pagination.total = response.data.pagination.total
|
||||
} else {
|
||||
message.error(response.message || '获取监管任务已结项列表失败')
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('获取结项任务失败:', error)
|
||||
message.error('获取结项任务失败')
|
||||
console.error('获取监管任务已结项失败:', error)
|
||||
message.error('获取监管任务已结项失败')
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
const filteredTasks = computed(() => {
|
||||
let result = tasks.value
|
||||
|
||||
if (searchForm.contractNumber) {
|
||||
result = result.filter(task => task.contractNumber === searchForm.contractNumber)
|
||||
}
|
||||
|
||||
if (searchForm.keyword) {
|
||||
result = result.filter(task =>
|
||||
task.applicationNumber.toLowerCase().includes(searchForm.keyword.toLowerCase()) ||
|
||||
task.customerName.toLowerCase().includes(searchForm.keyword.toLowerCase()) ||
|
||||
task.productName.toLowerCase().includes(searchForm.keyword.toLowerCase())
|
||||
)
|
||||
}
|
||||
|
||||
return result
|
||||
// 后端已经处理了过滤,直接返回任务列表
|
||||
return tasks.value
|
||||
})
|
||||
|
||||
const handleSearch = () => {
|
||||
@@ -250,16 +411,92 @@ const getSettlementStatusName = (status) => {
|
||||
return names[status] || status
|
||||
}
|
||||
|
||||
const viewTask = (record) => {
|
||||
message.info(`查看任务: ${record.applicationNumber}`)
|
||||
const viewTask = async (record) => {
|
||||
try {
|
||||
const response = await api.completedSupervisions.getById(record.id)
|
||||
if (response.success) {
|
||||
message.info(`查看任务: ${record.applicationNumber}`)
|
||||
// 这里可以打开详情对话框显示任务信息
|
||||
console.log('任务详情:', response.data)
|
||||
} else {
|
||||
message.error('获取任务详情失败')
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('获取任务详情失败:', error)
|
||||
message.error('获取任务详情失败')
|
||||
}
|
||||
}
|
||||
|
||||
const editTask = (record) => {
|
||||
message.info(`编辑任务: ${record.applicationNumber}`)
|
||||
const editTask = async (record) => {
|
||||
try {
|
||||
// 保存当前编辑的任务
|
||||
currentEditTask.value = record
|
||||
|
||||
// 填充编辑表单数据
|
||||
editTaskForm.value = {
|
||||
applicationNumber: record.applicationNumber || '',
|
||||
contractNumber: record.contractNumber || '',
|
||||
productName: record.productName || '',
|
||||
customerName: record.customerName || '',
|
||||
idType: record.idType || 'ID_CARD',
|
||||
idNumber: record.idNumber || '',
|
||||
assetType: record.assetType || '',
|
||||
assetQuantity: record.assetQuantity || 0,
|
||||
totalRepaymentPeriods: record.totalRepaymentPeriods || 0,
|
||||
settlementStatus: record.settlementStatus || 'unsettled',
|
||||
settlementDate: record.settlementDate ? dayjs(record.settlementDate) : null,
|
||||
importTime: record.importTime ? dayjs(record.importTime) : null,
|
||||
settlementAmount: record.settlementAmount || null,
|
||||
remainingAmount: record.remainingAmount || null,
|
||||
settlementNotes: record.settlementNotes || ''
|
||||
}
|
||||
|
||||
// 打开编辑对话框
|
||||
editModalVisible.value = true
|
||||
} catch (error) {
|
||||
console.error('打开编辑对话框失败:', error)
|
||||
message.error('打开编辑对话框失败')
|
||||
}
|
||||
}
|
||||
|
||||
const exportTask = (record) => {
|
||||
message.success(`导出任务: ${record.applicationNumber}`)
|
||||
const exportTask = async (record) => {
|
||||
try {
|
||||
message.success(`导出任务: ${record.applicationNumber}`)
|
||||
// 这里可以实现导出功能
|
||||
} catch (error) {
|
||||
console.error('导出任务失败:', error)
|
||||
message.error('导出任务失败')
|
||||
}
|
||||
}
|
||||
|
||||
// 编辑任务处理函数
|
||||
const handleEditTask = async () => {
|
||||
try {
|
||||
editLoading.value = true
|
||||
|
||||
const response = await api.completedSupervisions.update(currentEditTask.value.id, editTaskForm.value)
|
||||
|
||||
if (response.success) {
|
||||
message.success('编辑监管任务已结项成功')
|
||||
editModalVisible.value = false
|
||||
editTaskFormRef.value.resetFields()
|
||||
currentEditTask.value = null
|
||||
fetchTasks() // 刷新列表
|
||||
} else {
|
||||
message.error(response.message || '编辑监管任务已结项失败')
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('编辑监管任务已结项失败:', error)
|
||||
message.error('编辑监管任务已结项失败')
|
||||
} finally {
|
||||
editLoading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
const handleCancelEdit = () => {
|
||||
editModalVisible.value = false
|
||||
editTaskFormRef.value.resetFields()
|
||||
currentEditTask.value = null
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
|
||||
@@ -80,6 +80,143 @@
|
||||
</template>
|
||||
</a-table>
|
||||
</div>
|
||||
|
||||
<!-- 编辑待安装任务对话框 -->
|
||||
<a-modal
|
||||
v-model:open="editModalVisible"
|
||||
title="编辑待安装任务"
|
||||
width="800px"
|
||||
@ok="handleEditTask"
|
||||
@cancel="handleCancelEdit"
|
||||
:confirmLoading="editLoading"
|
||||
>
|
||||
<a-form
|
||||
ref="editTaskFormRef"
|
||||
:model="editTaskForm"
|
||||
layout="vertical"
|
||||
>
|
||||
<a-row :gutter="16">
|
||||
<a-col :span="12">
|
||||
<a-form-item label="申请单号" name="applicationNumber">
|
||||
<a-input v-model:value="editTaskForm.applicationNumber" placeholder="请输入申请单号" />
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="12">
|
||||
<a-form-item label="放款合同编号" name="contractNumber">
|
||||
<a-input v-model:value="editTaskForm.contractNumber" placeholder="请输入放款合同编号" />
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
</a-row>
|
||||
|
||||
<a-row :gutter="16">
|
||||
<a-col :span="12">
|
||||
<a-form-item label="产品名称" name="productName">
|
||||
<a-input v-model:value="editTaskForm.productName" placeholder="请输入产品名称" />
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="12">
|
||||
<a-form-item label="客户姓名" name="customerName">
|
||||
<a-input v-model:value="editTaskForm.customerName" placeholder="请输入客户姓名" />
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
</a-row>
|
||||
|
||||
<a-row :gutter="16">
|
||||
<a-col :span="12">
|
||||
<a-form-item label="证件类型" name="idType">
|
||||
<a-select v-model:value="editTaskForm.idType" placeholder="请选择证件类型">
|
||||
<a-select-option value="ID_CARD">身份证</a-select-option>
|
||||
<a-select-option value="PASSPORT">护照</a-select-option>
|
||||
<a-select-option value="OTHER">其他</a-select-option>
|
||||
</a-select>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="12">
|
||||
<a-form-item label="证件号码" name="idNumber">
|
||||
<a-input v-model:value="editTaskForm.idNumber" placeholder="请输入证件号码" />
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
</a-row>
|
||||
|
||||
<a-row :gutter="16">
|
||||
<a-col :span="12">
|
||||
<a-form-item label="养殖生资种类" name="assetType">
|
||||
<a-input v-model:value="editTaskForm.assetType" placeholder="请输入养殖生资种类" />
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="12">
|
||||
<a-form-item label="待安装设备" name="equipmentToInstall">
|
||||
<a-input v-model:value="editTaskForm.equipmentToInstall" placeholder="请输入待安装设备" />
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
</a-row>
|
||||
|
||||
<a-row :gutter="16">
|
||||
<a-col :span="12">
|
||||
<a-form-item label="安装状态" name="installationStatus">
|
||||
<a-select v-model:value="editTaskForm.installationStatus" placeholder="请选择安装状态">
|
||||
<a-select-option value="pending">待安装</a-select-option>
|
||||
<a-select-option value="in-progress">安装中</a-select-option>
|
||||
<a-select-option value="completed">已完成</a-select-option>
|
||||
<a-select-option value="failed">安装失败</a-select-option>
|
||||
</a-select>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
</a-row>
|
||||
|
||||
<a-row :gutter="16">
|
||||
<a-col :span="12">
|
||||
<a-form-item label="生成安装任务时间" name="taskGenerationTime">
|
||||
<a-date-picker
|
||||
v-model:value="editTaskForm.taskGenerationTime"
|
||||
placeholder="请选择生成时间"
|
||||
style="width: 100%"
|
||||
format="YYYY-MM-DD HH:mm:ss"
|
||||
value-format="YYYY-MM-DD HH:mm:ss"
|
||||
show-time
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="12">
|
||||
<a-form-item label="安装完成生效时间" name="completionTime">
|
||||
<a-date-picker
|
||||
v-model:value="editTaskForm.completionTime"
|
||||
placeholder="请选择完成时间"
|
||||
style="width: 100%"
|
||||
format="YYYY-MM-DD HH:mm:ss"
|
||||
value-format="YYYY-MM-DD HH:mm:ss"
|
||||
show-time
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
</a-row>
|
||||
|
||||
<a-row :gutter="16">
|
||||
<a-col :span="12">
|
||||
<a-form-item label="安装员姓名" name="installerName">
|
||||
<a-input v-model:value="editTaskForm.installerName" placeholder="请输入安装员姓名" />
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="12">
|
||||
<a-form-item label="安装员电话" name="installerPhone">
|
||||
<a-input v-model:value="editTaskForm.installerPhone" placeholder="请输入安装员电话" />
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
</a-row>
|
||||
|
||||
<a-form-item label="安装地址" name="installationAddress">
|
||||
<a-input v-model:value="editTaskForm.installationAddress" placeholder="请输入安装地址" />
|
||||
</a-form-item>
|
||||
|
||||
<a-form-item label="安装备注" name="installationNotes">
|
||||
<a-textarea
|
||||
v-model:value="editTaskForm.installationNotes"
|
||||
placeholder="请输入安装备注"
|
||||
:rows="3"
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
</a-modal>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -87,11 +224,19 @@
|
||||
import { ref, reactive, computed, onMounted } from 'vue'
|
||||
import { message } from 'ant-design-vue'
|
||||
import { DownloadOutlined, SearchOutlined } from '@ant-design/icons-vue'
|
||||
import { api } from '@/utils/api'
|
||||
import dayjs from 'dayjs'
|
||||
|
||||
const loading = ref(false)
|
||||
const tasks = ref([])
|
||||
|
||||
// 编辑相关
|
||||
const editModalVisible = ref(false)
|
||||
const editTaskFormRef = ref()
|
||||
const editTaskForm = ref({})
|
||||
const editLoading = ref(false)
|
||||
const currentEditTask = ref(null)
|
||||
|
||||
const searchForm = reactive({
|
||||
contractNumber: '',
|
||||
dateRange: [],
|
||||
@@ -176,50 +321,47 @@ const mockTasks = [
|
||||
const fetchTasks = async () => {
|
||||
loading.value = true
|
||||
try {
|
||||
// 实际项目中这里会调用API获取数据
|
||||
// const response = await api.installationTasks.getList({
|
||||
// page: pagination.current,
|
||||
// pageSize: pagination.pageSize,
|
||||
// ...searchForm,
|
||||
// })
|
||||
// 构建日期范围参数
|
||||
let dateRangeParam = ''
|
||||
if (searchForm.dateRange && Array.isArray(searchForm.dateRange) && searchForm.dateRange.length === 2) {
|
||||
dateRangeParam = `${searchForm.dateRange[0].format('YYYY-MM-DD')},${searchForm.dateRange[1].format('YYYY-MM-DD')}`
|
||||
}
|
||||
|
||||
// 使用模拟数据
|
||||
tasks.value = mockTasks.map(task => ({
|
||||
...task,
|
||||
taskGenerationTime: dayjs(task.taskGenerationTime),
|
||||
completionTime: task.completionTime ? dayjs(task.completionTime) : null,
|
||||
}))
|
||||
pagination.total = mockTasks.length
|
||||
console.log('开始获取待安装任务列表...', {
|
||||
page: pagination.current,
|
||||
pageSize: pagination.pageSize,
|
||||
search: searchForm.contractNumber,
|
||||
installationStatus: searchForm.installationStatus,
|
||||
dateRange: dateRangeParam
|
||||
})
|
||||
|
||||
const response = await api.installationTasks.getList({
|
||||
page: pagination.current,
|
||||
limit: pagination.pageSize,
|
||||
search: searchForm.contractNumber,
|
||||
installationStatus: searchForm.installationStatus,
|
||||
dateRange: dateRangeParam
|
||||
})
|
||||
|
||||
console.log('待安装任务列表响应:', response)
|
||||
|
||||
if (response.success) {
|
||||
tasks.value = response.data.tasks || []
|
||||
pagination.total = response.data.pagination.total
|
||||
} else {
|
||||
message.error(response.message || '获取待安装任务列表失败')
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('获取安装任务失败:', error)
|
||||
message.error('获取安装任务失败')
|
||||
console.error('获取待安装任务失败:', error)
|
||||
message.error('获取待安装任务失败')
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
const filteredTasks = computed(() => {
|
||||
let result = tasks.value
|
||||
|
||||
if (searchForm.contractNumber) {
|
||||
result = result.filter(task =>
|
||||
task.contractNumber.toLowerCase().includes(searchForm.contractNumber.toLowerCase())
|
||||
)
|
||||
}
|
||||
|
||||
if (searchForm.installationStatus) {
|
||||
result = result.filter(task => task.installationStatus === searchForm.installationStatus)
|
||||
}
|
||||
|
||||
if (searchForm.dateRange && searchForm.dateRange.length === 2) {
|
||||
const [startDate, endDate] = searchForm.dateRange
|
||||
result = result.filter(task => {
|
||||
const taskTime = dayjs(task.taskGenerationTime)
|
||||
return taskTime.isAfter(startDate.startOf('day')) && taskTime.isBefore(endDate.endOf('day'))
|
||||
})
|
||||
}
|
||||
|
||||
return result
|
||||
// 后端已经处理了过滤,直接返回任务列表
|
||||
return tasks.value
|
||||
})
|
||||
|
||||
const handleSearch = () => {
|
||||
@@ -265,16 +407,100 @@ const getStatusName = (status) => {
|
||||
return names[status] || status
|
||||
}
|
||||
|
||||
const viewTask = (record) => {
|
||||
message.info(`查看任务: ${record.applicationNumber}`)
|
||||
const viewTask = async (record) => {
|
||||
try {
|
||||
const response = await api.installationTasks.getById(record.id)
|
||||
if (response.success) {
|
||||
message.info(`查看任务: ${record.applicationNumber}`)
|
||||
// 这里可以打开详情对话框显示任务信息
|
||||
console.log('任务详情:', response.data)
|
||||
} else {
|
||||
message.error('获取任务详情失败')
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('获取任务详情失败:', error)
|
||||
message.error('获取任务详情失败')
|
||||
}
|
||||
}
|
||||
|
||||
const editTask = (record) => {
|
||||
message.info(`编辑任务: ${record.applicationNumber}`)
|
||||
const editTask = async (record) => {
|
||||
try {
|
||||
// 保存当前编辑的任务
|
||||
currentEditTask.value = record
|
||||
|
||||
// 填充编辑表单数据
|
||||
editTaskForm.value = {
|
||||
applicationNumber: record.applicationNumber || '',
|
||||
contractNumber: record.contractNumber || '',
|
||||
productName: record.productName || '',
|
||||
customerName: record.customerName || '',
|
||||
idType: record.idType || 'ID_CARD',
|
||||
idNumber: record.idNumber || '',
|
||||
assetType: record.assetType || '',
|
||||
equipmentToInstall: record.equipmentToInstall || '',
|
||||
installationStatus: record.installationStatus || 'pending',
|
||||
taskGenerationTime: record.taskGenerationTime ? dayjs(record.taskGenerationTime) : null,
|
||||
completionTime: record.completionTime ? dayjs(record.completionTime) : null,
|
||||
installerName: record.installerName || '',
|
||||
installerPhone: record.installerPhone || '',
|
||||
installationAddress: record.installationAddress || '',
|
||||
installationNotes: record.installationNotes || ''
|
||||
}
|
||||
|
||||
// 打开编辑对话框
|
||||
editModalVisible.value = true
|
||||
} catch (error) {
|
||||
console.error('打开编辑对话框失败:', error)
|
||||
message.error('打开编辑对话框失败')
|
||||
}
|
||||
}
|
||||
|
||||
const startInstallation = (record) => {
|
||||
message.success(`开始安装任务: ${record.applicationNumber}`)
|
||||
const startInstallation = async (record) => {
|
||||
try {
|
||||
const response = await api.installationTasks.update(record.id, {
|
||||
installationStatus: 'in-progress'
|
||||
})
|
||||
|
||||
if (response.success) {
|
||||
message.success(`开始安装任务: ${record.applicationNumber}`)
|
||||
fetchTasks() // 刷新列表
|
||||
} else {
|
||||
message.error('开始安装任务失败')
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('开始安装任务失败:', error)
|
||||
message.error('开始安装任务失败')
|
||||
}
|
||||
}
|
||||
|
||||
// 编辑任务处理函数
|
||||
const handleEditTask = async () => {
|
||||
try {
|
||||
editLoading.value = true
|
||||
|
||||
const response = await api.installationTasks.update(currentEditTask.value.id, editTaskForm.value)
|
||||
|
||||
if (response.success) {
|
||||
message.success('编辑待安装任务成功')
|
||||
editModalVisible.value = false
|
||||
editTaskFormRef.value.resetFields()
|
||||
currentEditTask.value = null
|
||||
fetchTasks() // 刷新列表
|
||||
} else {
|
||||
message.error(response.message || '编辑待安装任务失败')
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('编辑待安装任务失败:', error)
|
||||
message.error('编辑待安装任务失败')
|
||||
} finally {
|
||||
editLoading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
const handleCancelEdit = () => {
|
||||
editModalVisible.value = false
|
||||
editTaskFormRef.value.resetFields()
|
||||
currentEditTask.value = null
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
|
||||
@@ -7,9 +7,9 @@
|
||||
<a-button type="primary" @click="showAddTaskModal">
|
||||
<plus-outlined /> 新增监管任务
|
||||
</a-button>
|
||||
<a-button type="primary" @click="showBatchAddModal">
|
||||
<!-- <a-button type="primary" @click="showBatchAddModal">
|
||||
<plus-outlined /> 批量新增
|
||||
</a-button>
|
||||
</a-button> -->
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -221,6 +221,190 @@
|
||||
</a-descriptions>
|
||||
</div>
|
||||
</a-modal>
|
||||
|
||||
<!-- 编辑监管任务对话框 -->
|
||||
<a-modal
|
||||
v-model:open="editModalVisible"
|
||||
title="编辑监管任务"
|
||||
width="800px"
|
||||
@ok="handleEditTask"
|
||||
@cancel="handleCancelEdit"
|
||||
:confirmLoading="editLoading"
|
||||
>
|
||||
<a-form
|
||||
ref="editTaskFormRef"
|
||||
:model="editTaskForm"
|
||||
:rules="addTaskRules"
|
||||
layout="vertical"
|
||||
>
|
||||
<a-row :gutter="16">
|
||||
<a-col :span="12">
|
||||
<a-form-item label="申请单号" name="applicationNumber">
|
||||
<a-input v-model:value="editTaskForm.applicationNumber" placeholder="请输入申请单号" />
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="12">
|
||||
<a-form-item label="放款合同编号" name="contractNumber">
|
||||
<a-input v-model:value="editTaskForm.contractNumber" placeholder="请输入放款合同编号" />
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
</a-row>
|
||||
|
||||
<a-row :gutter="16">
|
||||
<a-col :span="12">
|
||||
<a-form-item label="产品名称" name="productName">
|
||||
<a-input v-model:value="editTaskForm.productName" placeholder="请输入产品名称" />
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="12">
|
||||
<a-form-item label="客户姓名" name="customerName">
|
||||
<a-input v-model:value="editTaskForm.customerName" placeholder="请输入客户姓名" />
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
</a-row>
|
||||
|
||||
<a-row :gutter="16">
|
||||
<a-col :span="12">
|
||||
<a-form-item label="证件类型" name="idType">
|
||||
<a-select v-model:value="editTaskForm.idType" placeholder="请选择证件类型">
|
||||
<a-select-option value="id_card">身份证</a-select-option>
|
||||
<a-select-option value="passport">护照</a-select-option>
|
||||
<a-select-option value="other">其他</a-select-option>
|
||||
</a-select>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="12">
|
||||
<a-form-item label="证件号码" name="idNumber">
|
||||
<a-input v-model:value="editTaskForm.idNumber" placeholder="请输入证件号码" />
|
||||
</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="editTaskForm.assetType" placeholder="请选择养殖生资种类">
|
||||
<a-select-option value="cattle">牛</a-select-option>
|
||||
<a-select-option value="sheep">羊</a-select-option>
|
||||
<a-select-option value="pig">猪</a-select-option>
|
||||
<a-select-option value="poultry">家禽</a-select-option>
|
||||
<a-select-option value="other">其他</a-select-option>
|
||||
</a-select>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="12">
|
||||
<a-form-item label="监管生资数量" name="assetQuantity">
|
||||
<a-input-number
|
||||
v-model:value="editTaskForm.assetQuantity"
|
||||
:min="0"
|
||||
placeholder="请输入监管生资数量"
|
||||
style="width: 100%"
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
</a-row>
|
||||
|
||||
<a-row :gutter="16">
|
||||
<a-col :span="12">
|
||||
<a-form-item label="监管状态" name="supervisionStatus">
|
||||
<a-select v-model:value="editTaskForm.supervisionStatus" placeholder="请选择监管状态">
|
||||
<a-select-option value="pending">待监管</a-select-option>
|
||||
<a-select-option value="supervising">监管中</a-select-option>
|
||||
<a-select-option value="completed">已完成</a-select-option>
|
||||
<a-select-option value="suspended">已暂停</a-select-option>
|
||||
</a-select>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
</a-row>
|
||||
|
||||
<a-row :gutter="16">
|
||||
<a-col :span="12">
|
||||
<a-form-item label="监管起始时间" name="startTime">
|
||||
<a-date-picker
|
||||
v-model:value="editTaskForm.startTime"
|
||||
placeholder="请选择监管起始时间"
|
||||
style="width: 100%"
|
||||
format="YYYY-MM-DD"
|
||||
value-format="YYYY-MM-DD"
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="12">
|
||||
<a-form-item label="监管结束时间" name="endTime">
|
||||
<a-date-picker
|
||||
v-model:value="editTaskForm.endTime"
|
||||
placeholder="请选择监管结束时间"
|
||||
style="width: 100%"
|
||||
format="YYYY-MM-DD"
|
||||
value-format="YYYY-MM-DD"
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
</a-row>
|
||||
|
||||
<a-row :gutter="16">
|
||||
<a-col :span="8">
|
||||
<a-form-item label="贷款金额" name="loanAmount">
|
||||
<a-input-number
|
||||
v-model:value="editTaskForm.loanAmount"
|
||||
:min="0"
|
||||
:precision="2"
|
||||
placeholder="请输入贷款金额"
|
||||
style="width: 100%"
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="8">
|
||||
<a-form-item label="利率" name="interestRate">
|
||||
<a-input-number
|
||||
v-model:value="editTaskForm.interestRate"
|
||||
:min="0"
|
||||
:max="1"
|
||||
:step="0.0001"
|
||||
:precision="4"
|
||||
placeholder="请输入利率"
|
||||
style="width: 100%"
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="8">
|
||||
<a-form-item label="贷款期限(月)" name="loanTerm">
|
||||
<a-input-number
|
||||
v-model:value="editTaskForm.loanTerm"
|
||||
:min="0"
|
||||
placeholder="请输入贷款期限"
|
||||
style="width: 100%"
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
</a-row>
|
||||
|
||||
<a-row :gutter="16">
|
||||
<a-col :span="12">
|
||||
<a-form-item label="监管员姓名" name="supervisorName">
|
||||
<a-input v-model:value="editTaskForm.supervisorName" placeholder="请输入监管员姓名" />
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="12">
|
||||
<a-form-item label="监管员电话" name="supervisorPhone">
|
||||
<a-input v-model:value="editTaskForm.supervisorPhone" placeholder="请输入监管员电话" />
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
</a-row>
|
||||
|
||||
<a-form-item label="养殖场地址" name="farmAddress">
|
||||
<a-input v-model:value="editTaskForm.farmAddress" placeholder="请输入养殖场地址" />
|
||||
</a-form-item>
|
||||
|
||||
<a-form-item label="备注" name="remarks">
|
||||
<a-textarea
|
||||
v-model:value="editTaskForm.remarks"
|
||||
placeholder="请输入备注"
|
||||
:rows="3"
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
</a-modal>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -241,6 +425,13 @@ const detailModalVisible = ref(false)
|
||||
const selectedTask = ref(null)
|
||||
const addTaskFormRef = ref()
|
||||
|
||||
// 编辑相关
|
||||
const editModalVisible = ref(false)
|
||||
const editTaskFormRef = ref()
|
||||
const editTaskForm = ref({})
|
||||
const editLoading = ref(false)
|
||||
const currentEditTask = ref(null)
|
||||
|
||||
// 搜索表单
|
||||
const searchForm = ref({
|
||||
contractNumber: '',
|
||||
@@ -463,13 +654,18 @@ const viewTask = (task) => {
|
||||
const fetchTasks = async (params = {}) => {
|
||||
try {
|
||||
loading.value = true
|
||||
// 构建日期范围参数
|
||||
let dateRangeParam = ''
|
||||
if (searchForm.value.dateRange && Array.isArray(searchForm.value.dateRange) && searchForm.value.dateRange.length === 2) {
|
||||
dateRangeParam = `${searchForm.value.dateRange[0].format('YYYY-MM-DD')},${searchForm.value.dateRange[1].format('YYYY-MM-DD')}`
|
||||
}
|
||||
|
||||
console.log('开始获取监管任务列表...', {
|
||||
page: pagination.value.current,
|
||||
limit: pagination.value.pageSize,
|
||||
search: searchForm.value.contractNumber,
|
||||
supervisionStatus: searchForm.value.supervisionStatus,
|
||||
dateRange: searchForm.value.dateRange ?
|
||||
`${searchForm.value.dateRange[0].format('YYYY-MM-DD')},${searchForm.value.dateRange[1].format('YYYY-MM-DD')}` : ''
|
||||
dateRange: dateRangeParam
|
||||
})
|
||||
|
||||
const response = await api.supervisionTasks.getList({
|
||||
@@ -477,8 +673,7 @@ const fetchTasks = async (params = {}) => {
|
||||
limit: pagination.value.pageSize,
|
||||
search: searchForm.value.contractNumber,
|
||||
supervisionStatus: searchForm.value.supervisionStatus,
|
||||
dateRange: searchForm.value.dateRange ?
|
||||
`${searchForm.value.dateRange[0].format('YYYY-MM-DD')},${searchForm.value.dateRange[1].format('YYYY-MM-DD')}` : '',
|
||||
dateRange: dateRangeParam,
|
||||
...params
|
||||
})
|
||||
|
||||
@@ -522,11 +717,36 @@ const handleReset = () => {
|
||||
|
||||
const editTask = async (task) => {
|
||||
try {
|
||||
// 这里可以实现编辑功能
|
||||
message.info(`编辑任务: ${task.applicationNumber}`)
|
||||
// 保存当前编辑的任务
|
||||
currentEditTask.value = task
|
||||
|
||||
// 填充编辑表单数据
|
||||
editTaskForm.value = {
|
||||
applicationNumber: task.applicationNumber || '',
|
||||
contractNumber: task.contractNumber || '',
|
||||
productName: task.productName || '',
|
||||
customerName: task.customerName || '',
|
||||
idType: task.idType || '',
|
||||
idNumber: task.idNumber || '',
|
||||
assetType: task.assetType || '',
|
||||
assetQuantity: task.assetQuantity || 0,
|
||||
supervisionStatus: task.supervisionStatus || '',
|
||||
startTime: task.startTime || null,
|
||||
endTime: task.endTime || null,
|
||||
loanAmount: task.loanAmount || 0,
|
||||
interestRate: task.interestRate || 0,
|
||||
loanTerm: task.loanTerm || 0,
|
||||
supervisorName: task.supervisorName || '',
|
||||
supervisorPhone: task.supervisorPhone || '',
|
||||
farmAddress: task.farmAddress || '',
|
||||
remarks: task.remarks || ''
|
||||
}
|
||||
|
||||
// 打开编辑对话框
|
||||
editModalVisible.value = true
|
||||
} catch (error) {
|
||||
console.error('编辑任务失败:', error)
|
||||
message.error('编辑任务失败')
|
||||
console.error('打开编辑对话框失败:', error)
|
||||
message.error('打开编辑对话框失败')
|
||||
}
|
||||
}
|
||||
|
||||
@@ -570,6 +790,36 @@ const handleCancelAdd = () => {
|
||||
addTaskFormRef.value.resetFields()
|
||||
}
|
||||
|
||||
// 编辑任务处理函数
|
||||
const handleEditTask = async () => {
|
||||
try {
|
||||
await editTaskFormRef.value.validate()
|
||||
editLoading.value = true
|
||||
|
||||
const response = await api.supervisionTasks.update(currentEditTask.value.id, editTaskForm.value)
|
||||
|
||||
if (response.success) {
|
||||
message.success('编辑监管任务成功')
|
||||
editModalVisible.value = false
|
||||
editTaskFormRef.value.resetFields()
|
||||
currentEditTask.value = null
|
||||
fetchTasks() // 刷新列表
|
||||
} else {
|
||||
message.error(response.message || '编辑监管任务失败')
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('编辑监管任务失败:', error)
|
||||
message.error('编辑监管任务失败')
|
||||
} finally {
|
||||
editLoading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
const handleCancelEdit = () => {
|
||||
editModalVisible.value = false
|
||||
editTaskFormRef.value.resetFields()
|
||||
}
|
||||
|
||||
const handleExport = () => {
|
||||
message.info('任务导出功能开发中...')
|
||||
}
|
||||
|
||||
@@ -183,6 +183,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)
|
||||
@@ -293,94 +294,8 @@ const columns = [
|
||||
}
|
||||
]
|
||||
|
||||
// 模拟申请数据
|
||||
const applications = ref([
|
||||
{
|
||||
id: 1,
|
||||
applicationNumber: '20240325123703784',
|
||||
productName: '惠农贷',
|
||||
farmerName: '刘超',
|
||||
borrowerName: '11',
|
||||
borrowerIdNumber: '511***********3017',
|
||||
assetType: '牛',
|
||||
applicationQuantity: '10头',
|
||||
policyInfo: '查看保单',
|
||||
amount: 100000.00,
|
||||
status: 'pending_review',
|
||||
applicationTime: '2024-03-25 12:37:03',
|
||||
phone: '13800138000',
|
||||
purpose: '养殖贷款',
|
||||
remark: '',
|
||||
auditRecords: [
|
||||
{
|
||||
id: 1,
|
||||
action: 'submit',
|
||||
auditor: '刘超',
|
||||
time: '2024-03-25 12:37:03',
|
||||
comment: '提交申请'
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
applicationNumber: '20240229110801968',
|
||||
productName: '中国工商银行扎旗支行"畜禽活体抵押"',
|
||||
farmerName: '刘超',
|
||||
borrowerName: '1',
|
||||
borrowerIdNumber: '511***********3017',
|
||||
assetType: '牛',
|
||||
applicationQuantity: '10头',
|
||||
policyInfo: '查看保单',
|
||||
amount: 100000.00,
|
||||
status: 'verification_pending',
|
||||
applicationTime: '2024-02-29 11:08:01',
|
||||
phone: '13900139000',
|
||||
purpose: '养殖贷款',
|
||||
remark: '',
|
||||
auditRecords: [
|
||||
{
|
||||
id: 1,
|
||||
action: 'submit',
|
||||
auditor: '刘超',
|
||||
time: '2024-02-29 11:08:01',
|
||||
comment: '提交申请'
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
action: 'approve',
|
||||
auditor: '王经理',
|
||||
time: '2024-03-01 10:15:00',
|
||||
comment: '资料齐全,符合条件,同意放款'
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
applicationNumber: '20240229105806431',
|
||||
productName: '惠农贷',
|
||||
farmerName: '刘超',
|
||||
borrowerName: '1',
|
||||
borrowerIdNumber: '511***********3017',
|
||||
assetType: '牛',
|
||||
applicationQuantity: '10头',
|
||||
policyInfo: '查看保单',
|
||||
amount: 100000.00,
|
||||
status: 'pending_binding',
|
||||
applicationTime: '2024-02-29 10:58:06',
|
||||
phone: '13700137000',
|
||||
purpose: '养殖贷款',
|
||||
remark: '',
|
||||
auditRecords: [
|
||||
{
|
||||
id: 1,
|
||||
action: 'submit',
|
||||
auditor: '刘超',
|
||||
time: '2024-02-29 10:58:06',
|
||||
comment: '提交申请'
|
||||
}
|
||||
]
|
||||
}
|
||||
])
|
||||
// 申请数据
|
||||
const applications = ref([])
|
||||
|
||||
// 计算属性
|
||||
const filteredApplications = computed(() => {
|
||||
@@ -406,9 +321,35 @@ const filteredApplications = computed(() => {
|
||||
return result
|
||||
})
|
||||
|
||||
// 获取申请列表
|
||||
const fetchApplications = async () => {
|
||||
try {
|
||||
loading.value = true
|
||||
const response = await api.loanApplications.getList({
|
||||
page: pagination.value.current,
|
||||
pageSize: pagination.value.pageSize,
|
||||
searchField: searchQuery.value.field,
|
||||
searchValue: searchQuery.value.value
|
||||
})
|
||||
|
||||
if (response.success) {
|
||||
applications.value = response.data.applications
|
||||
pagination.value.total = response.data.pagination.total
|
||||
} else {
|
||||
message.error(response.message || '获取申请列表失败')
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('获取申请列表失败:', error)
|
||||
message.error('获取申请列表失败')
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
// 方法
|
||||
const handleSearch = () => {
|
||||
// 搜索逻辑已在计算属性中处理
|
||||
pagination.value.current = 1
|
||||
fetchApplications()
|
||||
}
|
||||
|
||||
const handleReset = () => {
|
||||
@@ -421,6 +362,7 @@ const handleReset = () => {
|
||||
const handleTableChange = (pag) => {
|
||||
pagination.value.current = pag.current
|
||||
pagination.value.pageSize = pag.pageSize
|
||||
fetchApplications()
|
||||
}
|
||||
|
||||
const handleView = (record) => {
|
||||
@@ -447,26 +389,29 @@ const viewPolicy = (record) => {
|
||||
// 实际项目中这里会打开保单详情页面
|
||||
}
|
||||
|
||||
const handleAuditSubmit = () => {
|
||||
const handleAuditSubmit = async () => {
|
||||
if (!auditForm.value.comment) {
|
||||
message.error('请输入审核意见')
|
||||
return
|
||||
}
|
||||
|
||||
// 更新申请状态
|
||||
selectedApplication.value.status = auditForm.value.action === 'approve' ? 'approved' : 'rejected'
|
||||
|
||||
// 添加审核记录
|
||||
selectedApplication.value.auditRecords.push({
|
||||
id: Date.now(),
|
||||
action: auditForm.value.action,
|
||||
auditor: '当前用户',
|
||||
time: new Date().toLocaleString(),
|
||||
comment: auditForm.value.comment
|
||||
})
|
||||
try {
|
||||
const response = await api.loanApplications.audit(selectedApplication.value.id, {
|
||||
action: auditForm.value.action,
|
||||
comment: auditForm.value.comment
|
||||
})
|
||||
|
||||
auditModalVisible.value = false
|
||||
message.success('审核完成')
|
||||
if (response.success) {
|
||||
message.success('审核完成')
|
||||
auditModalVisible.value = false
|
||||
fetchApplications() // 刷新列表
|
||||
} else {
|
||||
message.error(response.message || '审核失败')
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('审核失败:', error)
|
||||
message.error('审核失败')
|
||||
}
|
||||
}
|
||||
|
||||
const handleAuditCancel = () => {
|
||||
@@ -554,7 +499,7 @@ const formatAmount = (amount) => {
|
||||
|
||||
// 生命周期
|
||||
onMounted(() => {
|
||||
pagination.value.total = applications.value.length
|
||||
fetchApplications()
|
||||
})
|
||||
</script>
|
||||
|
||||
|
||||
@@ -12,8 +12,10 @@
|
||||
placeholder="申请单号"
|
||||
style="width: 100%"
|
||||
>
|
||||
<a-select-option value="contractNumber">合同编号</a-select-option>
|
||||
<a-select-option value="applicationNumber">申请单号</a-select-option>
|
||||
<a-select-option value="customerName">客户姓名</a-select-option>
|
||||
<a-select-option value="borrowerName">贷款人姓名</a-select-option>
|
||||
<a-select-option value="farmerName">申请养殖户</a-select-option>
|
||||
<a-select-option value="productName">贷款产品</a-select-option>
|
||||
</a-select>
|
||||
</a-col>
|
||||
@@ -38,12 +40,13 @@
|
||||
<div class="contracts-table-section">
|
||||
<a-table
|
||||
:columns="columns"
|
||||
:data-source="filteredContracts"
|
||||
:data-source="contracts"
|
||||
:pagination="pagination"
|
||||
:loading="loading"
|
||||
row-key="id"
|
||||
@change="handleTableChange"
|
||||
:locale="{ emptyText: '暂无数据' }"
|
||||
:expand-row-by-click="false"
|
||||
:expand-icon-column-index="0"
|
||||
>
|
||||
<template #bodyCell="{ column, record }">
|
||||
<template v-if="column.key === 'status'">
|
||||
@@ -54,16 +57,16 @@
|
||||
<template v-else-if="column.key === 'amount'">
|
||||
{{ formatAmount(record.amount) }}
|
||||
</template>
|
||||
<template v-else-if="column.key === 'paidAmount'">
|
||||
{{ formatAmount(record.paidAmount) }}
|
||||
</template>
|
||||
<template v-else-if="column.key === 'action'">
|
||||
<a-space>
|
||||
<a-button type="link" size="small" @click="handleView(record)">
|
||||
查看
|
||||
</a-button>
|
||||
<a-button type="link" size="small" @click="handleEdit(record)">
|
||||
编辑
|
||||
</a-button>
|
||||
<a-button type="link" size="small" @click="handleDownload(record)">
|
||||
下载
|
||||
<a-button type="link" size="small" @click="handleView(record)">
|
||||
详情
|
||||
</a-button>
|
||||
</a-space>
|
||||
</template>
|
||||
@@ -75,7 +78,7 @@
|
||||
<a-modal
|
||||
v-model:open="detailModalVisible"
|
||||
title="合同详情"
|
||||
width="900px"
|
||||
width="800px"
|
||||
:footer="null"
|
||||
>
|
||||
<div v-if="selectedContract" class="contract-detail">
|
||||
@@ -83,110 +86,229 @@
|
||||
<a-descriptions-item label="合同编号">
|
||||
{{ selectedContract.contractNumber }}
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item label="客户姓名">
|
||||
{{ selectedContract.customerName }}
|
||||
<a-descriptions-item label="申请单号">
|
||||
{{ selectedContract.applicationNumber }}
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item label="合同类型">
|
||||
<a-tag :color="getTypeColor(selectedContract.type)">
|
||||
{{ getTypeText(selectedContract.type) }}
|
||||
</a-tag>
|
||||
<a-descriptions-item label="贷款产品">
|
||||
{{ selectedContract.productName }}
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item label="申请养殖户">
|
||||
{{ selectedContract.farmerName }}
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item label="贷款人姓名">
|
||||
{{ selectedContract.borrowerName }}
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item label="贷款人身份证号">
|
||||
{{ selectedContract.borrowerIdNumber }}
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item label="生资种类">
|
||||
{{ selectedContract.assetType }}
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item label="申请数量">
|
||||
{{ selectedContract.applicationQuantity }}
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item label="合同金额">
|
||||
{{ formatAmount(selectedContract.amount) }}
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item label="已还款金额">
|
||||
{{ formatAmount(selectedContract.paidAmount) }}
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item label="剩余金额">
|
||||
{{ formatAmount(selectedContract.remainingAmount) }}
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item label="合同状态">
|
||||
<a-tag :color="getStatusColor(selectedContract.status)">
|
||||
{{ getStatusText(selectedContract.status) }}
|
||||
</a-tag>
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item label="贷款金额">
|
||||
{{ formatAmount(selectedContract.amount) }}
|
||||
<a-descriptions-item label="合同类型">
|
||||
{{ getTypeText(selectedContract.type) }}
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item label="贷款期限">
|
||||
<a-descriptions-item label="合同期限">
|
||||
{{ selectedContract.term }} 个月
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item label="年利率">
|
||||
<a-descriptions-item label="利率">
|
||||
{{ selectedContract.interestRate }}%
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item label="还款方式">
|
||||
{{ getRepaymentMethodText(selectedContract.repaymentMethod) }}
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item label="合同签署日期">
|
||||
{{ selectedContract.signDate || '未签署' }}
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item label="合同生效日期">
|
||||
{{ selectedContract.effectiveDate || '未生效' }}
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item label="到期日期">
|
||||
{{ selectedContract.maturityDate }}
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item label="联系电话">
|
||||
{{ selectedContract.phone }}
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item label="身份证号">
|
||||
{{ selectedContract.idCard }}
|
||||
<a-descriptions-item label="贷款用途">
|
||||
{{ selectedContract.purpose }}
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item label="合同条款" :span="2">
|
||||
<div class="contract-terms">
|
||||
<p v-for="(term, index) in selectedContract.terms" :key="index">
|
||||
{{ index + 1 }}. {{ term }}
|
||||
</p>
|
||||
</div>
|
||||
<a-descriptions-item label="合同签订时间">
|
||||
{{ selectedContract.contractTime }}
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item label="放款时间">
|
||||
{{ selectedContract.disbursementTime || '未放款' }}
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item label="到期时间">
|
||||
{{ selectedContract.maturityTime || '未设置' }}
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item label="完成时间">
|
||||
{{ selectedContract.completedTime || '未完成' }}
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item label="备注" :span="2">
|
||||
{{ selectedContract.remark || '无' }}
|
||||
</a-descriptions-item>
|
||||
</a-descriptions>
|
||||
|
||||
<!-- 合同历史 -->
|
||||
<div class="contract-history" v-if="selectedContract.history">
|
||||
<h4>合同历史</h4>
|
||||
<a-timeline>
|
||||
<a-timeline-item
|
||||
v-for="record in selectedContract.history"
|
||||
:key="record.id"
|
||||
:color="getHistoryColor(record.action)"
|
||||
>
|
||||
<div class="history-item">
|
||||
<div class="history-header">
|
||||
<span class="history-action">{{ getHistoryActionText(record.action) }}</span>
|
||||
<span class="history-time">{{ record.time }}</span>
|
||||
</div>
|
||||
<div class="history-user">操作人:{{ record.operator }}</div>
|
||||
<div class="history-comment" v-if="record.comment">
|
||||
备注:{{ record.comment }}
|
||||
</div>
|
||||
</div>
|
||||
</a-timeline-item>
|
||||
</a-timeline>
|
||||
</div>
|
||||
</div>
|
||||
</a-modal>
|
||||
|
||||
<!-- 合同签署模态框 -->
|
||||
<!-- 编辑合同模态框 -->
|
||||
<a-modal
|
||||
v-model:open="signModalVisible"
|
||||
title="合同签署"
|
||||
@ok="handleSignSubmit"
|
||||
@cancel="handleSignCancel"
|
||||
v-model:open="editModalVisible"
|
||||
title="编辑合同"
|
||||
width="800px"
|
||||
:confirm-loading="editLoading"
|
||||
@ok="handleEditSubmit"
|
||||
@cancel="handleEditCancel"
|
||||
>
|
||||
<div class="sign-content">
|
||||
<a-alert
|
||||
message="请确认合同信息无误后签署"
|
||||
type="info"
|
||||
show-icon
|
||||
style="margin-bottom: 16px"
|
||||
/>
|
||||
<a-form :model="signForm" layout="vertical">
|
||||
<a-form-item label="签署密码" required>
|
||||
<a-input-password
|
||||
v-model:value="signForm.password"
|
||||
placeholder="请输入签署密码"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="签署备注">
|
||||
<a-textarea
|
||||
v-model:value="signForm.comment"
|
||||
placeholder="请输入签署备注(可选)"
|
||||
:rows="3"
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
</div>
|
||||
<a-form
|
||||
ref="editFormRef"
|
||||
:model="editForm"
|
||||
:rules="editFormRules"
|
||||
layout="vertical"
|
||||
v-if="editModalVisible"
|
||||
>
|
||||
<a-row :gutter="16">
|
||||
<a-col :span="12">
|
||||
<a-form-item label="贷款产品" name="productName">
|
||||
<a-input v-model:value="editForm.productName" placeholder="请输入贷款产品名称" />
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="12">
|
||||
<a-form-item label="申请养殖户" name="farmerName">
|
||||
<a-input v-model:value="editForm.farmerName" placeholder="请输入申请养殖户姓名" />
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
</a-row>
|
||||
|
||||
<a-row :gutter="16">
|
||||
<a-col :span="12">
|
||||
<a-form-item label="贷款人姓名" name="borrowerName">
|
||||
<a-input v-model:value="editForm.borrowerName" placeholder="请输入贷款人姓名" />
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="12">
|
||||
<a-form-item label="贷款人身份证号" name="borrowerIdNumber">
|
||||
<a-input v-model:value="editForm.borrowerIdNumber" placeholder="请输入身份证号" />
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
</a-row>
|
||||
|
||||
<a-row :gutter="16">
|
||||
<a-col :span="12">
|
||||
<a-form-item label="生资种类" name="assetType">
|
||||
<a-input v-model:value="editForm.assetType" placeholder="请输入生资种类" />
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="12">
|
||||
<a-form-item label="申请数量" name="applicationQuantity">
|
||||
<a-input v-model:value="editForm.applicationQuantity" placeholder="请输入申请数量" />
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
</a-row>
|
||||
|
||||
<a-row :gutter="16">
|
||||
<a-col :span="12">
|
||||
<a-form-item label="合同金额" name="amount">
|
||||
<a-input-number
|
||||
v-model:value="editForm.amount"
|
||||
placeholder="请输入合同金额"
|
||||
:min="0"
|
||||
:precision="2"
|
||||
style="width: 100%"
|
||||
addon-after="元"
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="12">
|
||||
<a-form-item label="已还款金额" name="paidAmount">
|
||||
<a-input-number
|
||||
v-model:value="editForm.paidAmount"
|
||||
placeholder="请输入已还款金额"
|
||||
:min="0"
|
||||
:precision="2"
|
||||
style="width: 100%"
|
||||
addon-after="元"
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
</a-row>
|
||||
|
||||
<a-row :gutter="16">
|
||||
<a-col :span="12">
|
||||
<a-form-item label="合同状态" name="status">
|
||||
<a-select v-model:value="editForm.status" placeholder="请选择合同状态">
|
||||
<a-select-option value="pending">待放款</a-select-option>
|
||||
<a-select-option value="active">已放款</a-select-option>
|
||||
<a-select-option value="completed">已完成</a-select-option>
|
||||
<a-select-option value="defaulted">违约</a-select-option>
|
||||
<a-select-option value="cancelled">已取消</a-select-option>
|
||||
</a-select>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="12">
|
||||
<a-form-item label="合同类型" name="type">
|
||||
<a-select v-model:value="editForm.type" placeholder="请选择合同类型">
|
||||
<a-select-option value="livestock_collateral">畜禽活体抵押</a-select-option>
|
||||
<a-select-option value="farmer_loan">惠农贷</a-select-option>
|
||||
<a-select-option value="business_loan">商业贷款</a-select-option>
|
||||
<a-select-option value="personal_loan">个人贷款</a-select-option>
|
||||
</a-select>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
</a-row>
|
||||
|
||||
<a-row :gutter="16">
|
||||
<a-col :span="12">
|
||||
<a-form-item label="合同期限" name="term">
|
||||
<a-input-number
|
||||
v-model:value="editForm.term"
|
||||
placeholder="请输入合同期限"
|
||||
:min="1"
|
||||
style="width: 100%"
|
||||
addon-after="个月"
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="12">
|
||||
<a-form-item label="利率" name="interestRate">
|
||||
<a-input-number
|
||||
v-model:value="editForm.interestRate"
|
||||
placeholder="请输入利率"
|
||||
:min="0"
|
||||
:max="100"
|
||||
:precision="2"
|
||||
style="width: 100%"
|
||||
addon-after="%"
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
</a-row>
|
||||
|
||||
<a-row :gutter="16">
|
||||
<a-col :span="12">
|
||||
<a-form-item label="联系电话" name="phone">
|
||||
<a-input v-model:value="editForm.phone" placeholder="请输入联系电话" />
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="12">
|
||||
<a-form-item label="贷款用途" name="purpose">
|
||||
<a-input v-model:value="editForm.purpose" placeholder="请输入贷款用途" />
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
</a-row>
|
||||
|
||||
<a-form-item label="备注" name="remark">
|
||||
<a-textarea
|
||||
v-model:value="editForm.remark"
|
||||
placeholder="请输入备注"
|
||||
:rows="3"
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
</a-modal>
|
||||
</div>
|
||||
</template>
|
||||
@@ -195,21 +317,85 @@
|
||||
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)
|
||||
const searchQuery = ref({
|
||||
field: 'applicationNumber',
|
||||
field: 'contractNumber',
|
||||
value: ''
|
||||
})
|
||||
const detailModalVisible = ref(false)
|
||||
const signModalVisible = ref(false)
|
||||
const editModalVisible = ref(false)
|
||||
const editLoading = ref(false)
|
||||
const selectedContract = ref(null)
|
||||
const signForm = ref({
|
||||
password: '',
|
||||
comment: ''
|
||||
const contracts = ref([])
|
||||
|
||||
// 编辑表单
|
||||
const editForm = ref({
|
||||
id: null,
|
||||
productName: '',
|
||||
farmerName: '',
|
||||
borrowerName: '',
|
||||
borrowerIdNumber: '',
|
||||
assetType: '',
|
||||
applicationQuantity: '',
|
||||
amount: null,
|
||||
paidAmount: null,
|
||||
status: 'pending',
|
||||
type: 'livestock_collateral',
|
||||
term: null,
|
||||
interestRate: null,
|
||||
phone: '',
|
||||
purpose: '',
|
||||
remark: ''
|
||||
})
|
||||
|
||||
const editFormRef = ref()
|
||||
|
||||
// 表单验证规则
|
||||
const editFormRules = {
|
||||
productName: [
|
||||
{ required: true, message: '请输入贷款产品名称', trigger: 'blur' }
|
||||
],
|
||||
farmerName: [
|
||||
{ required: true, message: '请输入申请养殖户姓名', trigger: 'blur' }
|
||||
],
|
||||
borrowerName: [
|
||||
{ required: true, message: '请输入贷款人姓名', trigger: 'blur' }
|
||||
],
|
||||
borrowerIdNumber: [
|
||||
{ required: true, message: '请输入贷款人身份证号', trigger: 'blur' }
|
||||
],
|
||||
assetType: [
|
||||
{ required: true, message: '请输入生资种类', trigger: 'blur' }
|
||||
],
|
||||
applicationQuantity: [
|
||||
{ required: true, message: '请输入申请数量', trigger: 'blur' }
|
||||
],
|
||||
amount: [
|
||||
{ required: true, message: '请输入合同金额', trigger: 'blur' },
|
||||
{ type: 'number', min: 0.01, message: '合同金额必须大于0', trigger: 'blur' }
|
||||
],
|
||||
status: [
|
||||
{ required: true, message: '请选择合同状态', trigger: 'change' }
|
||||
],
|
||||
type: [
|
||||
{ required: true, message: '请选择合同类型', trigger: 'change' }
|
||||
],
|
||||
term: [
|
||||
{ required: true, message: '请输入合同期限', trigger: 'blur' },
|
||||
{ type: 'number', min: 1, message: '合同期限必须大于0', trigger: 'blur' }
|
||||
],
|
||||
interestRate: [
|
||||
{ required: true, message: '请输入利率', trigger: 'blur' },
|
||||
{ type: 'number', min: 0, max: 100, message: '利率必须在0-100之间', trigger: 'blur' }
|
||||
],
|
||||
phone: [
|
||||
{ required: true, message: '请输入联系电话', trigger: 'blur' }
|
||||
]
|
||||
}
|
||||
|
||||
// 分页配置
|
||||
const pagination = ref({
|
||||
current: 1,
|
||||
@@ -222,6 +408,12 @@ const pagination = ref({
|
||||
|
||||
// 表格列配置
|
||||
const columns = [
|
||||
{
|
||||
title: '',
|
||||
key: 'expand',
|
||||
width: 50,
|
||||
customRender: () => '>'
|
||||
},
|
||||
{
|
||||
title: '申请单号',
|
||||
dataIndex: 'applicationNumber',
|
||||
@@ -276,51 +468,57 @@ const columns = [
|
||||
title: '当前状态',
|
||||
dataIndex: 'status',
|
||||
key: 'status',
|
||||
width: 120
|
||||
width: 120,
|
||||
filters: [
|
||||
{ text: '待放款', value: 'pending' },
|
||||
{ text: '已放款', value: 'active' },
|
||||
{ text: '已完成', value: 'completed' },
|
||||
{ text: '违约', value: 'defaulted' },
|
||||
{ text: '已取消', value: 'cancelled' }
|
||||
]
|
||||
},
|
||||
{
|
||||
title: '操作',
|
||||
key: 'action',
|
||||
width: 200,
|
||||
width: 150,
|
||||
fixed: 'right'
|
||||
}
|
||||
]
|
||||
|
||||
// 模拟合同数据 - 设置为空数据以匹配图片
|
||||
const contracts = ref([])
|
||||
|
||||
// 计算属性
|
||||
const filteredContracts = computed(() => {
|
||||
let result = contracts.value
|
||||
|
||||
if (searchQuery.value.value) {
|
||||
const searchValue = searchQuery.value.value.toLowerCase()
|
||||
const field = searchQuery.value.field
|
||||
|
||||
result = result.filter(contract => {
|
||||
if (field === 'applicationNumber') {
|
||||
return contract.applicationNumber.toLowerCase().includes(searchValue)
|
||||
} else if (field === 'customerName') {
|
||||
return contract.borrowerName.toLowerCase().includes(searchValue) ||
|
||||
contract.farmerName.toLowerCase().includes(searchValue)
|
||||
} else if (field === 'productName') {
|
||||
return contract.productName.toLowerCase().includes(searchValue)
|
||||
}
|
||||
return true
|
||||
// 获取合同列表
|
||||
const fetchContracts = async () => {
|
||||
try {
|
||||
loading.value = true
|
||||
const response = await api.loanContracts.getList({
|
||||
page: pagination.value.current,
|
||||
pageSize: pagination.value.pageSize,
|
||||
searchField: searchQuery.value.field,
|
||||
searchValue: searchQuery.value.value
|
||||
})
|
||||
|
||||
if (response.success) {
|
||||
contracts.value = response.data.contracts
|
||||
pagination.value.total = response.data.pagination.total
|
||||
} else {
|
||||
message.error(response.message || '获取合同列表失败')
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('获取合同列表失败:', error)
|
||||
message.error('获取合同列表失败')
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
|
||||
return result
|
||||
})
|
||||
}
|
||||
|
||||
// 方法
|
||||
const handleSearch = () => {
|
||||
// 搜索逻辑已在计算属性中处理
|
||||
pagination.value.current = 1
|
||||
fetchContracts()
|
||||
}
|
||||
|
||||
const handleReset = () => {
|
||||
searchQuery.value = {
|
||||
field: 'applicationNumber',
|
||||
field: 'contractNumber',
|
||||
value: ''
|
||||
}
|
||||
}
|
||||
@@ -328,6 +526,7 @@ const handleReset = () => {
|
||||
const handleTableChange = (pag) => {
|
||||
pagination.value.current = pag.current
|
||||
pagination.value.pageSize = pag.pageSize
|
||||
fetchContracts()
|
||||
}
|
||||
|
||||
const handleView = (record) => {
|
||||
@@ -336,127 +535,109 @@ const handleView = (record) => {
|
||||
}
|
||||
|
||||
const handleEdit = (record) => {
|
||||
message.info(`编辑合同: ${record.applicationNumber}`)
|
||||
}
|
||||
|
||||
const handleDownload = (record) => {
|
||||
message.info(`下载合同: ${record.applicationNumber}`)
|
||||
}
|
||||
|
||||
const handleSignSubmit = () => {
|
||||
if (!signForm.value.password) {
|
||||
message.error('请输入签署密码')
|
||||
return
|
||||
}
|
||||
|
||||
// 更新合同状态
|
||||
selectedContract.value.status = 'signed'
|
||||
selectedContract.value.signDate = new Date().toISOString().split('T')[0]
|
||||
selectedContract.value.effectiveDate = new Date().toISOString().split('T')[0]
|
||||
|
||||
// 添加历史记录
|
||||
selectedContract.value.history.push({
|
||||
id: Date.now(),
|
||||
action: 'sign',
|
||||
operator: '当前用户',
|
||||
time: new Date().toLocaleString(),
|
||||
comment: signForm.value.comment || '合同签署'
|
||||
Object.assign(editForm.value, {
|
||||
id: record.id,
|
||||
productName: record.productName,
|
||||
farmerName: record.farmerName,
|
||||
borrowerName: record.borrowerName,
|
||||
borrowerIdNumber: record.borrowerIdNumber,
|
||||
assetType: record.assetType,
|
||||
applicationQuantity: record.applicationQuantity,
|
||||
amount: record.amount,
|
||||
paidAmount: record.paidAmount,
|
||||
status: record.status,
|
||||
type: record.type,
|
||||
term: record.term,
|
||||
interestRate: record.interestRate,
|
||||
phone: record.phone,
|
||||
purpose: record.purpose,
|
||||
remark: record.remark
|
||||
})
|
||||
|
||||
signModalVisible.value = false
|
||||
message.success('合同签署成功')
|
||||
editModalVisible.value = true
|
||||
}
|
||||
|
||||
const handleSignCancel = () => {
|
||||
signModalVisible.value = false
|
||||
selectedContract.value = null
|
||||
const handleEditSubmit = async () => {
|
||||
try {
|
||||
await editFormRef.value.validate()
|
||||
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,
|
||||
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
|
||||
})
|
||||
|
||||
if (response.success) {
|
||||
message.success('合同更新成功')
|
||||
editModalVisible.value = false
|
||||
fetchContracts() // 刷新列表
|
||||
} else {
|
||||
message.error(response.message || '更新失败')
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('更新失败:', error)
|
||||
message.error('更新失败')
|
||||
} finally {
|
||||
editLoading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
const handleEditCancel = () => {
|
||||
editModalVisible.value = false
|
||||
editFormRef.value?.resetFields()
|
||||
}
|
||||
|
||||
const getStatusColor = (status) => {
|
||||
const colors = {
|
||||
pending_review: 'blue',
|
||||
verification_pending: 'blue',
|
||||
pending_binding: 'blue',
|
||||
approved: 'green',
|
||||
rejected: 'red',
|
||||
signed: 'green',
|
||||
pending: 'blue',
|
||||
active: 'green',
|
||||
completed: 'success',
|
||||
terminated: 'red'
|
||||
completed: 'cyan',
|
||||
defaulted: 'red',
|
||||
cancelled: 'gray'
|
||||
}
|
||||
return colors[status] || 'default'
|
||||
}
|
||||
|
||||
const getStatusText = (status) => {
|
||||
const texts = {
|
||||
pending_review: '待初审',
|
||||
verification_pending: '核验待放款',
|
||||
pending_binding: '待绑定',
|
||||
approved: '已通过',
|
||||
rejected: '已拒绝',
|
||||
signed: '已签署',
|
||||
active: '生效中',
|
||||
pending: '待放款',
|
||||
active: '已放款',
|
||||
completed: '已完成',
|
||||
terminated: '已终止'
|
||||
defaulted: '违约',
|
||||
cancelled: '已取消'
|
||||
}
|
||||
return texts[status] || status
|
||||
}
|
||||
|
||||
const getTypeColor = (type) => {
|
||||
const colors = {
|
||||
personal: 'blue',
|
||||
business: 'green',
|
||||
mortgage: 'purple'
|
||||
}
|
||||
return colors[type] || 'default'
|
||||
}
|
||||
|
||||
const getTypeText = (type) => {
|
||||
const texts = {
|
||||
personal: '个人贷款',
|
||||
business: '企业贷款',
|
||||
mortgage: '抵押贷款'
|
||||
livestock_collateral: '畜禽活体抵押',
|
||||
farmer_loan: '惠农贷',
|
||||
business_loan: '商业贷款',
|
||||
personal_loan: '个人贷款'
|
||||
}
|
||||
return texts[type] || type
|
||||
}
|
||||
|
||||
const getRepaymentMethodText = (method) => {
|
||||
const texts = {
|
||||
equal_installment: '等额本息',
|
||||
equal_principal: '等额本金',
|
||||
balloon: '气球贷',
|
||||
interest_only: '先息后本'
|
||||
}
|
||||
return texts[method] || method
|
||||
}
|
||||
|
||||
const getHistoryColor = (action) => {
|
||||
const colors = {
|
||||
create: 'blue',
|
||||
sign: 'green',
|
||||
activate: 'green',
|
||||
terminate: 'red'
|
||||
}
|
||||
return colors[action] || 'default'
|
||||
}
|
||||
|
||||
const getHistoryActionText = (action) => {
|
||||
const texts = {
|
||||
create: '合同创建',
|
||||
sign: '合同签署',
|
||||
activate: '合同生效',
|
||||
terminate: '合同终止'
|
||||
}
|
||||
return texts[action] || action
|
||||
}
|
||||
|
||||
const formatAmount = (amount) => {
|
||||
return `${amount.toFixed(2)}元`
|
||||
}
|
||||
|
||||
// 生命周期
|
||||
onMounted(() => {
|
||||
pagination.value.total = contracts.value.length
|
||||
fetchContracts()
|
||||
})
|
||||
</script>
|
||||
|
||||
@@ -504,71 +685,6 @@ onMounted(() => {
|
||||
padding: 16px 0;
|
||||
}
|
||||
|
||||
.contract-terms {
|
||||
background: #f5f5f5;
|
||||
padding: 12px;
|
||||
border-radius: 4px;
|
||||
max-height: 200px;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.contract-terms p {
|
||||
margin: 0 0 8px 0;
|
||||
font-size: 14px;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
.contract-terms p:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.contract-history {
|
||||
margin-top: 24px;
|
||||
}
|
||||
|
||||
.contract-history h4 {
|
||||
margin-bottom: 16px;
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.history-item {
|
||||
padding: 8px 0;
|
||||
}
|
||||
|
||||
.history-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
|
||||
.history-action {
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.history-time {
|
||||
color: #999;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.history-user {
|
||||
color: #666;
|
||||
font-size: 12px;
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
|
||||
.history-comment {
|
||||
color: #333;
|
||||
font-size: 12px;
|
||||
background: #f5f5f5;
|
||||
padding: 8px;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.sign-content {
|
||||
padding: 16px 0;
|
||||
}
|
||||
|
||||
/* 表格样式优化 */
|
||||
:deep(.ant-table-thead > tr > th) {
|
||||
background-color: #fafafa;
|
||||
@@ -604,16 +720,6 @@ onMounted(() => {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
/* 空数据样式 */
|
||||
:deep(.ant-empty) {
|
||||
padding: 40px 0;
|
||||
}
|
||||
|
||||
:deep(.ant-empty-description) {
|
||||
color: #999;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
/* 响应式调整 */
|
||||
@media (max-width: 768px) {
|
||||
.page-header {
|
||||
@@ -630,4 +736,4 @@ onMounted(() => {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
</style>
|
||||
@@ -31,6 +31,17 @@
|
||||
</a-row>
|
||||
</div>
|
||||
|
||||
<!-- 批量操作工具栏 -->
|
||||
<div class="batch-toolbar" v-if="selectedRowKeys.length > 0">
|
||||
<a-space>
|
||||
<span>已选择 {{ selectedRowKeys.length }} 项</span>
|
||||
<a-button @click="handleBatchDelete" danger>批量删除</a-button>
|
||||
<a-button @click="handleBatchEnable">批量启用</a-button>
|
||||
<a-button @click="handleBatchDisable">批量停用</a-button>
|
||||
<a-button @click="clearSelection">取消选择</a-button>
|
||||
</a-space>
|
||||
</div>
|
||||
|
||||
<!-- 数据表格 -->
|
||||
<div class="table-section">
|
||||
<a-table
|
||||
@@ -41,23 +52,170 @@
|
||||
@change="handleTableChange"
|
||||
row-key="id"
|
||||
:locale="{ emptyText: '暂无数据' }"
|
||||
:row-selection="rowSelection"
|
||||
>
|
||||
<template #bodyCell="{ column, record }">
|
||||
<template v-if="column.key === 'onSaleStatus'">
|
||||
<a-switch
|
||||
v-model:checked="record.onSaleStatus"
|
||||
@change="handleToggleStatus(record)"
|
||||
/>
|
||||
</template>
|
||||
<template v-if="column.key === 'action'">
|
||||
<a-space>
|
||||
<a-button type="link" size="small" @click="handleEdit(record)">编辑</a-button>
|
||||
<a-button type="link" size="small" @click="handleView(record)">详情</a-button>
|
||||
</a-space>
|
||||
</template>
|
||||
</template>
|
||||
<template #bodyCell="{ column, record }">
|
||||
<template v-if="column.key === 'onSaleStatus'">
|
||||
<a-switch
|
||||
v-model:checked="record.onSaleStatus"
|
||||
@change="handleToggleStatus(record)"
|
||||
/>
|
||||
</template>
|
||||
<template v-if="column.key === 'action'">
|
||||
<a-space>
|
||||
<a-button type="link" size="small" @click="handleEdit(record)">编辑</a-button>
|
||||
<a-button type="link" size="small" @click="handleView(record)">详情</a-button>
|
||||
<a-popconfirm
|
||||
title="确定要删除这个贷款商品吗?"
|
||||
ok-text="确定"
|
||||
cancel-text="取消"
|
||||
@confirm="handleDelete(record)"
|
||||
>
|
||||
<a-button type="link" size="small" danger>删除</a-button>
|
||||
</a-popconfirm>
|
||||
</a-space>
|
||||
</template>
|
||||
</template>
|
||||
</a-table>
|
||||
</div>
|
||||
|
||||
<!-- 编辑对话框 -->
|
||||
<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"
|
||||
v-if="editModalVisible"
|
||||
>
|
||||
<a-row :gutter="16">
|
||||
<a-col :span="12">
|
||||
<a-form-item label="贷款产品名称" name="productName">
|
||||
<a-input v-model:value="editForm.productName" placeholder="请输入贷款产品名称" />
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="12">
|
||||
<a-form-item label="贷款额度" name="loanAmount">
|
||||
<a-input
|
||||
v-model:value="editForm.loanAmount"
|
||||
placeholder="请输入贷款额度,如:50000~5000000"
|
||||
style="width: 100%"
|
||||
addon-after="元"
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
</a-row>
|
||||
|
||||
<a-row :gutter="16">
|
||||
<a-col :span="12">
|
||||
<a-form-item label="贷款周期" name="loanTerm">
|
||||
<a-input-number
|
||||
v-model:value="editForm.loanTerm"
|
||||
placeholder="请输入贷款周期"
|
||||
:min="1"
|
||||
style="width: 100%"
|
||||
addon-after="个月"
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="12">
|
||||
<a-form-item label="贷款利率" name="interestRate">
|
||||
<a-input
|
||||
v-model:value="editForm.interestRate"
|
||||
placeholder="请输入贷款利率,如:3.90"
|
||||
style="width: 100%"
|
||||
addon-after="%"
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
</a-row>
|
||||
|
||||
<a-row :gutter="16">
|
||||
<a-col :span="12">
|
||||
<a-form-item label="服务区域" name="serviceArea">
|
||||
<a-input v-model:value="editForm.serviceArea" placeholder="请输入服务区域" />
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="12">
|
||||
<a-form-item label="服务电话" name="servicePhone">
|
||||
<a-input v-model:value="editForm.servicePhone" placeholder="请输入服务电话" />
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
</a-row>
|
||||
|
||||
<a-form-item label="产品描述" name="description">
|
||||
<a-textarea
|
||||
v-model:value="editForm.description"
|
||||
placeholder="请输入产品描述"
|
||||
:rows="3"
|
||||
/>
|
||||
</a-form-item>
|
||||
|
||||
<a-form-item label="在售状态" name="onSaleStatus">
|
||||
<a-switch
|
||||
v-model:checked="editForm.onSaleStatus"
|
||||
checked-children="在售"
|
||||
un-checked-children="停售"
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
</a-modal>
|
||||
|
||||
<!-- 详情对话框 -->
|
||||
<a-modal
|
||||
v-model:open="detailModalVisible"
|
||||
title="贷款商品详情"
|
||||
width="800px"
|
||||
:footer="null"
|
||||
>
|
||||
<a-descriptions :column="2" bordered v-if="currentProduct">
|
||||
<a-descriptions-item label="产品名称" :span="2">
|
||||
{{ currentProduct.productName }}
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item label="贷款额度">
|
||||
{{ currentProduct.loanAmount }} 万元
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item label="贷款周期">
|
||||
{{ currentProduct.loanTerm }} 个月
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item label="贷款利率">
|
||||
{{ currentProduct.interestRate }}%
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item label="服务区域">
|
||||
{{ currentProduct.serviceArea }}
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item label="服务电话">
|
||||
{{ currentProduct.servicePhone }}
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item label="服务客户总数">
|
||||
{{ currentProduct.totalCustomers }}
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item label="监管中客户">
|
||||
{{ currentProduct.supervisionCustomers }}
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item label="已结项客户">
|
||||
{{ currentProduct.completedCustomers }}
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item label="在售状态">
|
||||
<a-tag :color="currentProduct.onSaleStatus ? 'green' : 'red'">
|
||||
{{ currentProduct.onSaleStatus ? '在售' : '停售' }}
|
||||
</a-tag>
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item label="添加时间" :span="2">
|
||||
{{ currentProduct.createdAt }}
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item label="产品描述" :span="2" v-if="currentProduct.description">
|
||||
{{ currentProduct.description }}
|
||||
</a-descriptions-item>
|
||||
</a-descriptions>
|
||||
</a-modal>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -65,9 +223,111 @@
|
||||
import { ref, reactive, computed, onMounted } from 'vue'
|
||||
import { message } from 'ant-design-vue'
|
||||
import { PlusOutlined, SearchOutlined } from '@ant-design/icons-vue'
|
||||
import { api } from '@/utils/api'
|
||||
|
||||
const loading = ref(false)
|
||||
const searchText = ref('')
|
||||
const products = ref([])
|
||||
|
||||
// 编辑相关
|
||||
const editModalVisible = ref(false)
|
||||
const editLoading = ref(false)
|
||||
const editFormRef = ref(null)
|
||||
const editForm = reactive({
|
||||
id: null,
|
||||
productName: '',
|
||||
loanAmount: null,
|
||||
loanTerm: null,
|
||||
interestRate: null,
|
||||
serviceArea: '',
|
||||
servicePhone: '',
|
||||
description: '',
|
||||
onSaleStatus: true
|
||||
})
|
||||
|
||||
// 详情相关
|
||||
const detailModalVisible = ref(false)
|
||||
const currentProduct = ref(null)
|
||||
|
||||
// 批量操作相关
|
||||
const selectedRowKeys = ref([])
|
||||
const selectedRows = ref([])
|
||||
|
||||
// 表单验证规则
|
||||
const editFormRules = {
|
||||
productName: [
|
||||
{ required: true, message: '请输入贷款产品名称', trigger: 'blur' },
|
||||
{ min: 2, max: 50, message: '产品名称长度在2-50个字符', trigger: 'blur' }
|
||||
],
|
||||
loanAmount: [
|
||||
{ required: true, message: '请输入贷款额度', trigger: 'blur' },
|
||||
{
|
||||
validator: (rule, value) => {
|
||||
if (!value) return Promise.reject('请输入贷款额度')
|
||||
// 支持数字或范围字符串(如:50000~5000000)
|
||||
if (typeof value === 'number') {
|
||||
if (value <= 0) return Promise.reject('贷款额度必须大于0')
|
||||
} else if (typeof value === 'string') {
|
||||
// 处理范围字符串
|
||||
if (value.includes('~')) {
|
||||
const [min, max] = value.split('~').map(v => parseFloat(v.trim()))
|
||||
if (isNaN(min) || isNaN(max) || min <= 0 || max <= 0) {
|
||||
return Promise.reject('贷款额度范围格式不正确')
|
||||
}
|
||||
} else {
|
||||
const numValue = parseFloat(value)
|
||||
if (isNaN(numValue) || numValue <= 0) {
|
||||
return Promise.reject('贷款额度必须大于0')
|
||||
}
|
||||
}
|
||||
}
|
||||
return Promise.resolve()
|
||||
},
|
||||
trigger: 'blur'
|
||||
}
|
||||
],
|
||||
loanTerm: [
|
||||
{ required: true, message: '请输入贷款周期', trigger: 'blur' },
|
||||
{ type: 'number', min: 1, message: '贷款周期必须大于0', trigger: 'blur' }
|
||||
],
|
||||
interestRate: [
|
||||
{ required: true, message: '请输入贷款利率', trigger: 'blur' },
|
||||
{
|
||||
validator: (rule, value) => {
|
||||
if (!value) return Promise.reject('请输入贷款利率')
|
||||
const numValue = parseFloat(value)
|
||||
if (isNaN(numValue)) return Promise.reject('请输入有效的数字')
|
||||
if (numValue < 0 || numValue > 100) {
|
||||
return Promise.reject('贷款利率必须在0-100之间')
|
||||
}
|
||||
return Promise.resolve()
|
||||
},
|
||||
trigger: 'blur'
|
||||
}
|
||||
],
|
||||
serviceArea: [
|
||||
{ required: true, message: '请输入服务区域', trigger: 'blur' }
|
||||
],
|
||||
servicePhone: [
|
||||
{ required: true, message: '请输入服务电话', trigger: 'blur' },
|
||||
{ pattern: /^1[3-9]\d{9}$/, message: '请输入正确的手机号码', trigger: 'blur' }
|
||||
]
|
||||
}
|
||||
|
||||
// 行选择配置
|
||||
const rowSelection = {
|
||||
selectedRowKeys: selectedRowKeys,
|
||||
onChange: (keys, rows) => {
|
||||
selectedRowKeys.value = keys
|
||||
selectedRows.value = rows
|
||||
},
|
||||
onSelect: (record, selected, selectedRows) => {
|
||||
console.log('选择行:', record, selected, selectedRows)
|
||||
},
|
||||
onSelectAll: (selected, selectedRows, changeRows) => {
|
||||
console.log('全选:', selected, selectedRows, changeRows)
|
||||
}
|
||||
}
|
||||
|
||||
const pagination = reactive({
|
||||
current: 1,
|
||||
@@ -142,8 +402,8 @@ const columns = [
|
||||
},
|
||||
{
|
||||
title: '添加时间',
|
||||
dataIndex: 'createTime',
|
||||
key: 'createTime',
|
||||
dataIndex: 'createdAt',
|
||||
key: 'createdAt',
|
||||
sorter: true,
|
||||
width: 150
|
||||
},
|
||||
@@ -161,78 +421,31 @@ const columns = [
|
||||
},
|
||||
]
|
||||
|
||||
// 模拟数据
|
||||
const products = ref([
|
||||
{
|
||||
id: 1,
|
||||
productName: '惠农贷',
|
||||
loanAmount: '50000~5000000元',
|
||||
loanTerm: '24',
|
||||
interestRate: '3.90%',
|
||||
serviceArea: '内蒙古自治区:通辽市',
|
||||
servicePhone: '15004901368',
|
||||
totalCustomers: 16,
|
||||
supervisionCustomers: 11,
|
||||
completedCustomers: 5,
|
||||
createTime: '2023-12-18 16:23:03',
|
||||
onSaleStatus: true,
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
productName: '中国工商银行扎旗支行"畜禽活体抵押"',
|
||||
loanAmount: '200000~1000000元',
|
||||
loanTerm: '12',
|
||||
interestRate: '4.70%',
|
||||
serviceArea: '内蒙古自治区:通辽市',
|
||||
servicePhone: '15004901368',
|
||||
totalCustomers: 10,
|
||||
supervisionCustomers: 5,
|
||||
completedCustomers: 5,
|
||||
createTime: '2023-06-20 17:36:17',
|
||||
onSaleStatus: true,
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
productName: '中国银行扎旗支行"畜禽活体抵押"',
|
||||
loanAmount: '200000~1000000元',
|
||||
loanTerm: '12',
|
||||
interestRate: '4.60%',
|
||||
serviceArea: '内蒙古自治区:通辽市',
|
||||
servicePhone: '15004901368',
|
||||
totalCustomers: 2,
|
||||
supervisionCustomers: 2,
|
||||
completedCustomers: 0,
|
||||
createTime: '2023-06-20 17:34:33',
|
||||
onSaleStatus: true,
|
||||
},
|
||||
{
|
||||
id: 4,
|
||||
productName: '中国农业银行扎旗支行"畜禽活体抵押"',
|
||||
loanAmount: '200000~1000000元',
|
||||
loanTerm: '12',
|
||||
interestRate: '4.80%',
|
||||
serviceArea: '内蒙古自治区:通辽市',
|
||||
servicePhone: '15004901368',
|
||||
totalCustomers: 26,
|
||||
supervisionCustomers: 24,
|
||||
completedCustomers: 2,
|
||||
createTime: '2023-06-20 17:09:39',
|
||||
onSaleStatus: true,
|
||||
},
|
||||
])
|
||||
|
||||
// 获取贷款商品列表
|
||||
const fetchProducts = async () => {
|
||||
loading.value = true
|
||||
try {
|
||||
// 实际项目中这里会调用API获取数据
|
||||
// const response = await api.loanProducts.getList({
|
||||
// page: pagination.current,
|
||||
// pageSize: pagination.pageSize,
|
||||
// search: searchText.value,
|
||||
// })
|
||||
const response = await api.loanProducts.getList({
|
||||
page: pagination.current,
|
||||
pageSize: pagination.pageSize,
|
||||
search: searchText.value,
|
||||
})
|
||||
|
||||
// 使用模拟数据
|
||||
pagination.total = products.value.length
|
||||
console.log('API响应数据:', response)
|
||||
|
||||
if (response.success) {
|
||||
console.log('产品数据:', response.data.products)
|
||||
console.log('分页数据:', response.data.pagination)
|
||||
|
||||
products.value = response.data.products || []
|
||||
pagination.total = response.data.pagination?.total || 0
|
||||
pagination.current = response.data.pagination?.current || 1
|
||||
pagination.pageSize = response.data.pagination?.pageSize || 10
|
||||
|
||||
console.log('设置后的products.value:', products.value)
|
||||
} else {
|
||||
message.error(response.message || '获取贷款商品失败')
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('获取贷款商品失败:', error)
|
||||
message.error('获取贷款商品失败')
|
||||
@@ -242,15 +455,9 @@ const fetchProducts = async () => {
|
||||
}
|
||||
|
||||
const filteredProducts = computed(() => {
|
||||
let result = products.value
|
||||
|
||||
if (searchText.value) {
|
||||
result = result.filter(product =>
|
||||
product.productName.toLowerCase().includes(searchText.value.toLowerCase())
|
||||
)
|
||||
}
|
||||
|
||||
return result
|
||||
// 后端已经处理了搜索,直接返回数据
|
||||
console.log('filteredProducts computed:', products.value)
|
||||
return products.value
|
||||
})
|
||||
|
||||
const handleSearch = () => {
|
||||
@@ -268,17 +475,204 @@ const handleAddProduct = () => {
|
||||
message.info('新增贷款功能开发中...')
|
||||
}
|
||||
|
||||
const handleEdit = (record) => {
|
||||
message.info(`编辑产品: ${record.productName}`)
|
||||
const handleEdit = async (record) => {
|
||||
try {
|
||||
const response = await api.loanProducts.getById(record.id)
|
||||
if (response.success) {
|
||||
// 填充编辑表单
|
||||
Object.assign(editForm, {
|
||||
id: record.id,
|
||||
productName: record.productName,
|
||||
loanAmount: record.loanAmount,
|
||||
loanTerm: record.loanTerm,
|
||||
interestRate: record.interestRate,
|
||||
serviceArea: record.serviceArea,
|
||||
servicePhone: record.servicePhone,
|
||||
description: record.description || '',
|
||||
onSaleStatus: record.onSaleStatus
|
||||
})
|
||||
editModalVisible.value = true
|
||||
} else {
|
||||
message.error(response.message || '获取产品详情失败')
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('获取产品详情失败:', error)
|
||||
message.error('获取产品详情失败')
|
||||
}
|
||||
}
|
||||
|
||||
const handleView = (record) => {
|
||||
message.info(`查看详情: ${record.productName}`)
|
||||
const handleView = async (record) => {
|
||||
try {
|
||||
const response = await api.loanProducts.getById(record.id)
|
||||
if (response.success) {
|
||||
currentProduct.value = response.data
|
||||
detailModalVisible.value = true
|
||||
} else {
|
||||
message.error(response.message || '获取产品详情失败')
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('获取产品详情失败:', error)
|
||||
message.error('获取产品详情失败')
|
||||
}
|
||||
}
|
||||
|
||||
const handleToggleStatus = (record) => {
|
||||
const status = record.onSaleStatus ? '启用' : '停用'
|
||||
message.success(`${record.productName} 已${status}`)
|
||||
// 编辑提交
|
||||
const handleEditSubmit = async () => {
|
||||
try {
|
||||
await editFormRef.value.validate()
|
||||
editLoading.value = true
|
||||
|
||||
const response = await api.loanProducts.update(editForm.id, {
|
||||
productName: editForm.productName,
|
||||
loanAmount: editForm.loanAmount,
|
||||
loanTerm: editForm.loanTerm,
|
||||
interestRate: editForm.interestRate,
|
||||
serviceArea: editForm.serviceArea,
|
||||
servicePhone: editForm.servicePhone,
|
||||
description: editForm.description,
|
||||
onSaleStatus: editForm.onSaleStatus
|
||||
})
|
||||
|
||||
if (response.success) {
|
||||
message.success('贷款商品更新成功')
|
||||
editModalVisible.value = false
|
||||
fetchProducts() // 刷新列表
|
||||
} else {
|
||||
message.error(response.message || '更新失败')
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('更新失败:', error)
|
||||
message.error('更新失败')
|
||||
} finally {
|
||||
editLoading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
// 编辑取消
|
||||
const handleEditCancel = () => {
|
||||
editModalVisible.value = false
|
||||
editFormRef.value?.resetFields()
|
||||
}
|
||||
|
||||
// 删除产品
|
||||
const handleDelete = async (record) => {
|
||||
try {
|
||||
const response = await api.loanProducts.delete(record.id)
|
||||
if (response.success) {
|
||||
message.success(`${record.productName} 删除成功`)
|
||||
fetchProducts() // 刷新列表
|
||||
} else {
|
||||
message.error(response.message || '删除失败')
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('删除失败:', error)
|
||||
message.error('删除失败')
|
||||
}
|
||||
}
|
||||
|
||||
// 批量删除
|
||||
const handleBatchDelete = async () => {
|
||||
if (selectedRowKeys.value.length === 0) {
|
||||
message.warning('请先选择要删除的项目')
|
||||
return
|
||||
}
|
||||
|
||||
try {
|
||||
const response = await api.loanProducts.batchDelete({
|
||||
ids: selectedRowKeys.value
|
||||
})
|
||||
|
||||
if (response.success) {
|
||||
message.success(`成功删除 ${selectedRowKeys.value.length} 个贷款商品`)
|
||||
clearSelection()
|
||||
fetchProducts() // 刷新列表
|
||||
} else {
|
||||
message.error(response.message || '批量删除失败')
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('批量删除失败:', error)
|
||||
message.error('批量删除失败')
|
||||
}
|
||||
}
|
||||
|
||||
// 批量启用
|
||||
const handleBatchEnable = async () => {
|
||||
if (selectedRowKeys.value.length === 0) {
|
||||
message.warning('请先选择要启用的项目')
|
||||
return
|
||||
}
|
||||
|
||||
try {
|
||||
const response = await api.loanProducts.batchUpdateStatus({
|
||||
ids: selectedRowKeys.value,
|
||||
onSaleStatus: true
|
||||
})
|
||||
|
||||
if (response.success) {
|
||||
message.success(`成功启用 ${selectedRowKeys.value.length} 个贷款商品`)
|
||||
clearSelection()
|
||||
fetchProducts() // 刷新列表
|
||||
} else {
|
||||
message.error(response.message || '批量启用失败')
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('批量启用失败:', error)
|
||||
message.error('批量启用失败')
|
||||
}
|
||||
}
|
||||
|
||||
// 批量停用
|
||||
const handleBatchDisable = async () => {
|
||||
if (selectedRowKeys.value.length === 0) {
|
||||
message.warning('请先选择要停用的项目')
|
||||
return
|
||||
}
|
||||
|
||||
try {
|
||||
const response = await api.loanProducts.batchUpdateStatus({
|
||||
ids: selectedRowKeys.value,
|
||||
onSaleStatus: false
|
||||
})
|
||||
|
||||
if (response.success) {
|
||||
message.success(`成功停用 ${selectedRowKeys.value.length} 个贷款商品`)
|
||||
clearSelection()
|
||||
fetchProducts() // 刷新列表
|
||||
} else {
|
||||
message.error(response.message || '批量停用失败')
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('批量停用失败:', error)
|
||||
message.error('批量停用失败')
|
||||
}
|
||||
}
|
||||
|
||||
// 清除选择
|
||||
const clearSelection = () => {
|
||||
selectedRowKeys.value = []
|
||||
selectedRows.value = []
|
||||
}
|
||||
|
||||
const handleToggleStatus = async (record) => {
|
||||
try {
|
||||
const response = await api.loanProducts.update(record.id, {
|
||||
onSaleStatus: record.onSaleStatus
|
||||
})
|
||||
|
||||
if (response.success) {
|
||||
const status = record.onSaleStatus ? '启用' : '停用'
|
||||
message.success(`${record.productName} 已${status}`)
|
||||
} else {
|
||||
message.error(response.message || '更新状态失败')
|
||||
// 恢复原状态
|
||||
record.onSaleStatus = !record.onSaleStatus
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('更新状态失败:', error)
|
||||
message.error('更新状态失败')
|
||||
// 恢复原状态
|
||||
record.onSaleStatus = !record.onSaleStatus
|
||||
}
|
||||
}
|
||||
|
||||
const handleTableChange = (pag, filters, sorter) => {
|
||||
@@ -368,6 +762,27 @@ onMounted(() => {
|
||||
color: #40a9ff;
|
||||
}
|
||||
|
||||
/* 批量操作工具栏样式 */
|
||||
.batch-toolbar {
|
||||
background: #e6f7ff;
|
||||
border: 1px solid #91d5ff;
|
||||
border-radius: 6px;
|
||||
padding: 12px 16px;
|
||||
margin-bottom: 16px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.batch-toolbar .ant-space {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.batch-toolbar span {
|
||||
color: #1890ff;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
/* 响应式设计 */
|
||||
@media (max-width: 768px) {
|
||||
.page-header {
|
||||
@@ -383,5 +798,15 @@ onMounted(() => {
|
||||
.search-section .ant-col:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.batch-toolbar {
|
||||
flex-direction: column;
|
||||
gap: 12px;
|
||||
align-items: stretch;
|
||||
}
|
||||
|
||||
.batch-toolbar .ant-space {
|
||||
justify-content: center;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user