Browse Source

完善合同管理功能

master
panxinyu-YUYwp 3 days ago
parent
commit
37ac6bb143
  1. 2
      src/api/contract/contract.js
  2. 294
      src/views/modules/contract/info.vue

2
src/api/contract/contract.js

@ -14,3 +14,5 @@ export const getCustomerList = () => createAPI(`/projectInfo/getCustomerList`, '
// 根据客户ID获取项目下拉列表(仅未结案项目)
export const getProjectListByCustomer = customerId => createAPI(`/contract/getProjectListByCustomer/${customerId}`, 'get')
export const contractArchive = data => createAPI(`/contract/contractArchive`, 'post', data)

294
src/views/modules/contract/info.vue

@ -7,13 +7,13 @@
style="width: 140px;margin-top: 2px" clearable></el-input>
</el-form-item>
<el-form-item label="客户名称">
<el-select filterable v-model="searchData.customerId" clearable size="small" style="width: 200px;">
<el-select filterable v-model="searchData.customerId" clearable size="small" style="width: 200px;margin-top: 2px">
<el-option :label="item.customerName" :value="item.id"
v-for="(item,index) in customerListOptions" :key="index"></el-option>
</el-select>
</el-form-item>
<el-form-item label="往来单位类型">
<el-select v-model="searchData.partnerType" clearable size="small" placeholder="请选择" style="width: 100px;">
<el-select v-model="searchData.partnerType" clearable size="small" placeholder="请选择" style="width: 100px;margin-top: 2px">
<el-option label="供应商" value="供应商"></el-option>
<el-option label="客户" value="客户"></el-option>
<el-option label="其他" value="其他"></el-option>
@ -22,19 +22,32 @@
<el-form-item label="合同日期">
<el-date-picker v-model="searchData.startDate" type="date" format="yyyy-MM-dd"
value-format="yyyy-MM-dd" placeholder="开始日期" size="small"
style="width: 100px;"></el-date-picker>
style="width: 100px;margin-top: 2px"></el-date-picker>
<span style="margin: 0 4px;">~</span>
<el-date-picker v-model="searchData.endDate" type="date" format="yyyy-MM-dd"
value-format="yyyy-MM-dd" placeholder="结束日期" size="small"
style="width: 100px;"></el-date-picker>
style="width: 100px;margin-top: 2px"></el-date-picker>
</el-form-item>
<el-form-item label="有效期至">
<el-date-picker v-model="searchData.validEndDate" type="date" format="yyyy-MM-dd"
value-format="yyyy-MM-dd" placeholder="请选择" size="small"
style="width: 100px;"></el-date-picker>
<el-date-picker v-model="searchData.validEndDateStart" type="date" format="yyyy-MM-dd"
value-format="yyyy-MM-dd" placeholder="开始日期" size="small"
style="width: 100px;margin-top: 2px"></el-date-picker>
<span style="margin: 0 4px;">~</span>
<el-date-picker v-model="searchData.validEndDateEnd" type="date" format="yyyy-MM-dd"
value-format="yyyy-MM-dd" placeholder="结束日期" size="small"
style="width: 100px;margin-top: 2px"></el-date-picker>
</el-form-item>
<el-form-item label="存档日期">
<el-date-picker v-model="searchData.archiveDateStart" type="date" format="yyyy-MM-dd"
value-format="yyyy-MM-dd" placeholder="开始日期" size="small"
style="width: 100px;margin-top: 2px"></el-date-picker>
<span style="margin: 0 4px;">~</span>
<el-date-picker v-model="searchData.archiveDateEnd" type="date" format="yyyy-MM-dd"
value-format="yyyy-MM-dd" placeholder="结束日期" size="small"
style="width: 100px;margin-top: 2px"></el-date-picker>
</el-form-item>
<el-form-item>
<el-button @click="searchContract">查询</el-button>
<el-button @click="searchContract" style="margin-top: 2px">查询</el-button>
<el-button @click="resetSearch" style="margin-left: 10px;">重置</el-button>
<el-button type="primary" @click="openAddContractModal" style="margin-left: 10px;">新增</el-button>
<el-button @click="exportContract" style="margin-left: 10px;">导出</el-button>
@ -54,6 +67,25 @@
<el-table-column prop="validStartDate" header-align="center" align="center" min-width="100" label="有效期起始"></el-table-column>
<el-table-column prop="validEndDate" header-align="center" align="center" min-width="100" label="有效期终止"></el-table-column>
<el-table-column prop="remark" header-align="center" align="left" min-width="120" label="备注" show-overflow-tooltip></el-table-column>
<el-table-column header-align="center" align="center" width="70" label="附件">
<template slot-scope="scope">
<a v-if="scope.row.attachmentCount > 0" type="text" size="small"
style="cursor:pointer; color:#409EFF;"
@click="openAttachmentDetail(scope.row)">详情</a>
<span v-else style="color:#909399;">无</span>
</template>
</el-table-column>
<el-table-column fixed="right" header-align="center" align="center" width="100" label="是否存档">
<template slot-scope="scope">
<el-checkbox
:value="scope.row.whetherArchive === 'Y'"
@change="val => handleArchiveChange(val, scope.row)">
</el-checkbox>
<a v-if="scope.row.whetherArchive === 'Y'"
style="margin-left: 6px; cursor: pointer; color: #409EFF;"
@click="viewArchiveDetail(scope.row)">详情</a>
</template>
</el-table-column>
<el-table-column fixed="right" header-align="center" align="center" width="100" label="操作">
<template slot-scope="scope">
<a type="text" size="small" @click="editContract(scope.row)">编辑</a>
@ -88,6 +120,7 @@
:title="contractModalTitle"
:visible.sync="showContractModal"
width="760px"
top="1vh"
:before-close="beforeCloseContractModal"
:close-on-click-modal="false">
@ -97,7 +130,8 @@
<el-select filterable v-model="contractForm.customerId" placeholder="请选择" size="small"
style="font-size:12px; height:30px;width: 200px"
:disabled="isEditContract"
@change="customerChange">
@change="customerChange"
@visible-change="customerDropdownVisible">
<el-option :label="item.customerName" :value="item.id"
v-for="(item,index) in customerListOptions" :key="index"></el-option>
</el-select>
@ -105,7 +139,8 @@
<el-form-item label="项目名称" required class="wide-item">
<el-select filterable v-model="contractForm.projectId" :placeholder="contractForm.customerId ? '请选择项目' : '请先选择客户'" size="small"
style="font-size:12px; height:30px;width: 200px"
:disabled="!contractForm.customerId || isEditContract">
:disabled="!contractForm.customerId || isEditContract"
@visible-change="projectDropdownVisible">
<el-option :label="item.projectName" :value="item.id"
v-for="(item,index) in projectListOptions" :key="index"></el-option>
</el-select>
@ -181,7 +216,7 @@
<!-- 主要内容 / 付款条款 / 备注:用普通div布局,避免主题把label吃掉 -->
<div style="width: 708px; margin-bottom: 10px;">
<div style="font-size: 12px; color: #606266; margin-bottom: 4px;">主要内容</div>
<el-input v-model="contractForm.mainContent" type="textarea" :rows="3"
<el-input v-model="contractForm.mainContent" type="textarea" :rows="2"
style="width: 100%;"></el-input>
</div>
@ -193,7 +228,7 @@
<div style="width: 708px; margin-bottom: 10px;">
<div style="font-size: 12px; color: #606266; margin-bottom: 4px;">备注</div>
<el-input v-model="contractForm.remark" type="textarea" :rows="3"
<el-input v-model="contractForm.remark" type="textarea" :rows="2"
style="width: 100%;"></el-input>
</div>
@ -228,23 +263,23 @@
style="font-size: 12px; color: #E6A23C; margin-left: 10px;">附件将随合同保存时一并上传</span>
</div>
<!-- 待上传文件预览弹窗 -->
<el-dialog :visible.sync="previewVisible" append-to-body width="70%"
:title="previewName" style="margin-top: -8vh;">
<img v-if="previewType === 'image'" :src="previewUrl" style="width: 100%;"/>
<iframe v-else-if="previewType === 'pdf'" :src="previewUrl" frameborder="0"
width="100%" height="600"></iframe>
<div v-else style="text-align: center; padding: 30px; color: #909399;">
该文件类型不支持预览,请下载后查看
</div>
</el-dialog>
<!-- &lt;!&ndash; 待上传文件预览弹窗 &ndash;&gt;-->
<!-- <el-dialog :visible.sync="previewVisible" append-to-body width="70%"-->
<!-- :title="previewName" style="margin-top: -8vh;">-->
<!-- <img v-if="previewType === 'image'" :src="previewUrl" style="width: 100%;"/>-->
<!-- <iframe v-else-if="previewType === 'pdf'" :src="previewUrl" frameborder="0"-->
<!-- width="100%" height="600"></iframe>-->
<!-- <div v-else style="text-align: center; padding: 30px; color: #909399;">-->
<!-- 该文件类型不支持预览,请下载后查看-->
<!-- </div>-->
<!-- </el-dialog>-->
<!-- 上传信息:仅编辑时显示(新增合同还没有历史附件) -->
<div v-if="isEditContract" style="font-size: 12px; color: #606266; margin-bottom: 4px;">上传信息</div>
<el-table v-if="isEditContract" :data="attachmentList" border size="mini" style="width: 708px;"
:header-cell-style="{background:'#d4e8e8', color:'#333'}">
<el-table-column prop="fileName" header-align="center" align="left" label="文件名称" show-overflow-tooltip></el-table-column>
<el-table-column prop="fileSuffix" header-align="center" align="center" width="90" label="文件类型"></el-table-column>
<!-- <el-table-column prop="fileSuffix" header-align="center" align="center" width="90" label="文件类型"></el-table-column>-->
<el-table-column prop="createdBy" header-align="center" align="center" width="100" label="上传人"></el-table-column>
<el-table-column header-align="center" align="center" width="140" label="操作">
<template slot-scope="scope">
@ -265,11 +300,72 @@
<el-button type="primary" @click="saveContract">保存</el-button>
</div>
</el-dialog>
<el-dialog :visible.sync="previewVisible" append-to-body width="70%"
:title="previewName" style="margin-top: -8vh;">
<img v-if="previewType === 'image'" :src="previewUrl" style="width: 100%;"/>
<iframe v-else-if="previewType === 'pdf'" :src="previewUrl" frameborder="0"
width="100%" height="600"></iframe>
<div v-else style="text-align: center; padding: 30px; color: #909399;">
该文件类型不支持预览,请下载后查看
</div>
</el-dialog>
<!-- 附件详情弹窗(列表"详情"入口) -->
<el-dialog title="附件详情" :visible.sync="showAttachmentModal" width="620px"
top="5vh" :close-on-click-modal="false">
<el-table :data="attachmentDetailList" border size="mini"
:header-cell-style="{background:'#d4e8e8', color:'#333'}">
<el-table-column prop="fileName" header-align="center" align="left" label="文件名称" show-overflow-tooltip></el-table-column>
<el-table-column header-align="center" align="center" width="110" label="操作">
<template slot-scope="scope">
<a type="text" size="small" @click="previewAttachment(scope.row)">预览</a>
<a type="text" size="small" style="margin-left: 8px;" @click="downloadAttachment(scope.row)">下载</a>
</template>
</el-table-column>
<template slot="empty">
<span style="color:#909399; font-size:12px;">暂无附件</span>
</template>
</el-table>
</el-dialog>
<!-- 存档弹窗 -->
<el-dialog title="存档" :visible.sync="showArchiveModal" width="400px" top="15vh">
<el-form :model="archiveForm" label-width="80px">
<el-form-item label="存档人" required>
<el-input v-model="archiveForm.archivePerson" size="small"></el-input>
</el-form-item>
<el-form-item label="存档日期" required>
<el-date-picker v-model="archiveForm.archiveDate" type="date"
format="yyyy-MM-dd" value-format="yyyy-MM-dd"
size="small" style="width: 100%;"></el-date-picker>
</el-form-item>
</el-form>
<span slot="footer">
<el-button size="small" @click="showArchiveModal = false">取消</el-button>
<el-button size="small" type="primary" @click="confirmArchive">确定</el-button>
</span>
</el-dialog>
<!-- 存档详情弹窗 -->
<el-dialog title="存档详情" :visible.sync="showArchiveDetail" width="400px" top="15vh">
<div style="padding: 0 20px;">
<div style="display: flex; line-height: 40px; border-bottom: 1px solid #eee;">
<span style="width: 80px; color: #606266; text-align: right; padding-right: 12px;">存档人</span>
<span style="flex: 1; color: #303133;">{{ archiveForm.archivePerson || '-' }}</span>
</div>
<div style="display: flex; line-height: 40px;">
<span style="width: 80px; color: #606266; text-align: right; padding-right: 12px;">存档日期</span>
<span style="flex: 1; color: #303133;">{{ (archiveForm.archiveDate || '').substring(0, 10) || '-' }}</span>
</div>
</div>
<span slot="footer">
<el-button size="small" @click="showArchiveDetail = false">关闭</el-button>
</span>
</el-dialog>
</div>
</template>
<script>
import { contractData, contractSave, contractDelete, getCustomerList, getProjectListByCustomer } from '@/api/contract/contract.js'
import { contractData, contractSave, contractDelete, getCustomerList, getProjectListByCustomer, contractArchive } from '@/api/contract/contract.js'
import { updateOssRef } from '@/api/oss/oss.js'
import axios from "axios";
import Vue from "vue";
@ -285,7 +381,10 @@ export default {
partnerType: '',
startDate: '',
endDate: '',
validEndDate: '',
validEndDateStart: '',
validEndDateEnd: '',
archiveDateStart: '',
archiveDateEnd: '',
page: 1,
limit: 20
},
@ -313,6 +412,8 @@ export default {
customerListOptions: [],
projectListOptions: [],
attachmentList: [],
showAttachmentModal: false,
attachmentDetailList: [],
uploadUrl: '',
pendingFiles: [],
selectedFileNames: '',
@ -324,6 +425,13 @@ export default {
previewUrl: '',
previewType: '',
previewName: '',
showArchiveModal: false,
showArchiveDetail: false,
currentArchiveRow: null,
archiveForm: {
archivePerson: '',
archiveDate: ''
},
contractForm: {
id: null,
customerId: null,
@ -334,10 +442,10 @@ export default {
currency: 'CNY',
versionNo: '',
contactVersionOverview: '',
partnerType: '',
partnerType: '客户',
validStartDate: '',
validEndDate: '',
contractPerson: '',
contractPerson: this.$store.state.user.userDisplay,
partnerPerson: '',
mainContent: '',
paymentTerms: '',
@ -354,6 +462,24 @@ export default {
this.initData()
},
methods: {
// 客户下拉展开时:实时拉取最新客户列表
customerDropdownVisible(visible) {
if (visible && !this.isEditContract) {
this.fetchCustomerOptions()
}
},
// 项目下拉展开时:按当前客户实时拉取最新项目列表
projectDropdownVisible(visible) {
if (visible && this.contractForm.customerId && !this.isEditContract) {
getProjectListByCustomer(this.contractForm.customerId).then(({data}) => {
if (data && data.code === 0) {
this.projectListOptions = data.rows
}
}).catch(err => {
console.error(err)
})
}
},
resetSearch() {
this.searchData = {
contractNo: '',
@ -361,7 +487,10 @@ export default {
partnerType: '',
startDate: '',
endDate: '',
validEndDate: '',
validEndDateStart: '',
validEndDateEnd: '',
archiveDateStart: '',
archiveDateEnd: '',
page: 1,
limit: this.pageSize
}
@ -440,9 +569,7 @@ export default {
},
// 合同日期变化:有效期起始默认等于合同日期(需求:默认一样,但可修改)
contractDateChange(val) {
if (!this.contractForm.validStartDate) {
this.contractForm.validStartDate = val
}
this.contractForm.validStartDate = val
},
// 每页数
sizeChangeHandle(val) {
@ -465,6 +592,7 @@ export default {
this.selectedFileNames = ''
this.uploading = false
this.closeModalAfterUpload = false
this.fetchCustomerOptions()
this.contractForm = {
id: null,
customerId: null,
@ -479,10 +607,14 @@ export default {
currency: 'CNY',
versionNo: '',
contactVersionOverview: '',
partnerType: '',
validStartDate: '',
partnerType: '客户',
validStartDate: (() => {
let d = new Date()
let pad = n => n < 10 ? '0' + n : n
return d.getFullYear() + '-' + pad(d.getMonth() + 1) + '-' + pad(d.getDate())
})(),
validEndDate: '',
contractPerson: '',
contractPerson: this.$store.state.user.userDisplay,
partnerPerson: '',
mainContent: '',
paymentTerms: '',
@ -641,10 +773,10 @@ export default {
currency: 'CNY',
versionNo: '',
contactVersionOverview: '',
partnerType: '',
partnerType: '客户',
validStartDate: '',
validEndDate: '',
contractPerson: '',
contractPerson: this.$store.state.user.userDisplay,
partnerPerson: '',
mainContent: '',
paymentTerms: '',
@ -700,6 +832,25 @@ export default {
}
}
},
// 列表"详情":打开附件详情弹窗并加载该合同附件
openAttachmentDetail(row) {
this.attachmentDetailList = []
this.showAttachmentModal = true
this.$http({
url: this.$http.adornUrl('/sys/oss/list'),
method: 'get',
params: this.$http.adornParams({
page: 1,
limit: 999,
orderRef1: row.id,
fileType: 'contract'
})
}).then(({data}) => {
if (data && data.code === 0) {
this.attachmentDetailList = data.page.list
}
})
},
// 查询该合同的附件列表(每次重新拼 URL,确保带最新的合同ID)
fetchAttachments(contractId) {
if (!contractId) {
@ -958,6 +1109,72 @@ export default {
return d.getFullYear() + '-' + pad(d.getMonth() + 1) + '-' + pad(d.getDate()) +
' ' + pad(d.getHours()) + ':' + pad(d.getMinutes())
},
// 勾选/取消 存档
handleArchiveChange(checked, row) {
if (checked) {
this.currentArchiveRow = row
let d = new Date()
let pad = n => n < 10 ? '0' + n : n
this.archiveForm = {
archivePerson: this.$store.state.user.userDisplay,
archiveDate: d.getFullYear() + '-' + pad(d.getMonth() + 1) + '-' + pad(d.getDate())
}
this.showArchiveModal = true
} else {
this.$confirm('确定取消存档吗?', '提示', { type: 'warning' }).then(() => {
contractArchive({
id: row.id,
whetherArchive: 'N',
archivePerson: '',
archiveDate: ''
}).then(({data}) => {
if (data && data.code === 0) {
this.$message.success('取消存档成功')
this.fetchContracts()
} else {
this.$message.error((data && data.msg) || '操作失败')
}
}).catch(err => {
console.error(err)
this.$message.error('操作失败')
})
}).catch(() => {})
}
},
// 确定存档
confirmArchive() {
if (!this.archiveForm.archivePerson || !this.archiveForm.archiveDate) {
this.$message.error('请填写存档人和存档日期')
return
}
contractArchive({
id: this.currentArchiveRow.id,
whetherArchive: 'Y',
archivePerson: this.archiveForm.archivePerson,
archiveDate: this.archiveForm.archiveDate + ' 00:00:00'
}).then(({data}) => {
if (data && data.code === 0) {
this.$message.success('存档成功')
this.showArchiveModal = false
this.fetchContracts()
} else {
this.$message.error((data && data.msg) || '存档失败')
}
}).catch(err => {
console.error(err)
this.$message.error('存档失败')
})
},
// 查看存档详情
viewArchiveDetail(row) {
this.archiveForm = {
archivePerson: row.archivePerson || '',
archiveDate: row.archiveDate || ''
}
this.showArchiveDetail = true
}
}
}
</script>
@ -998,4 +1215,9 @@ export default {
.contract-maintenance .el-dialog .el-form-item.wide-item .el-input {
width: 351px !important;
}
/* 查询区:换行时的行间距 + 垂直居中对齐 */
.contract-maintenance > .el-form--inline .el-form-item {
margin-bottom: 10px;
vertical-align: middle;
}
</style>
Loading…
Cancel
Save