123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499 |
- <script lang="ts" setup>
- import { ref, reactive, onMounted, inject } from "vue";
- import { tableShowOverflowTooltip } from '@/utils/globalVariables'
- import { getFromValue, resetFromValue, setTemplateDataDisable, downloadFile, formatDate, confirmAction, getTemplateKey, downloadTemplate } from '@/utils/tools'
- import { GenerateForm } from '@zmjs/form-design';
- import { post, get, uploadFile } from "@/utils/request";
- import { CONTRACT_DELETION, CONTRACT_OPERATION, DELETE_CONTRACT_FILE, EDIT_CONTRACT, EXPORT_CONTRACT, GET_CONTRACT_LIST, GET_PAYMENT_LIST, IMPORITEM, OBTAIN_CONTRACT_TYPE, statusArray, UPLOAD_ATTACHMENTS } from './api'
- import { GET_CONTRACT_TEMPLATE, ADD_CONTRACT } from './api'
- import { UploadRequestOptions } from "element-plus";
- import AddEditor from "./component/addEditor.vue";
- const globalPopup = inject<GlobalPopup>('globalPopup')
- const filterContractForm = reactive({
- name: '',
- number: '',
- typeName: '', // 合同类型
- status: '',
- startDate: '',
- endDate: '',
- paymentStartDate: '',
- paymentEndDate: '',
- })
- const fixedData = reactive({
- typeOfContractList: [] as optionType[],
- stateList: statusArray as optionType[],
- })
- const allLoading = reactive({
- exportLoading: false,
- contractTableLading: false,
- addEditorSaveLoading: false,
- importLoading: false
- })
- const allVisable = reactive({
- addEditorVisable: false,
- rejectDataVisable: false,
- importVisible: false
- })
- const allDynamicText = reactive({
- addEditorText: '新增合同',
- importText: '合同管理导入模板.xlsx'
- })
- const paging = reactive({
- pageIndex: 1,
- pageSize: 20,
- pageTotal: 0
- })
- const contractTableList = ref<any>([]);
- const addEditorVisableForm = reactive({
- paymentPlan: [],
- enclosure: [],
- enclosureDetele: []
- })
- const editForm = ref<any>({})
- const generateForm = ref<any>(null) // 模板
- const addEditorRef = ref<any>(null)
- const generateFormKey = ref<number>(1)
- const contractTemplate = ref<any>({
- list: [] as any[],
- config: {}
- })
- const rejectData = reactive({
- id: '',
- status: 2,
- msg: '',
- })
- onMounted(() => {
- getObtainContractType()
- getTemplateConfig()
- getContractTableList()
- })
- function contractRejection(row: any, status: number) {
- rejectData.id = row.id
- rejectData.status = status
- rejectData.msg = ''
- allVisable.rejectDataVisable = true
- }
- function deleteContract(row: any) {
- confirmAction('确定要删除该合同吗?', '合同删除').then(() => {
- post(CONTRACT_DELETION, { id: row.id }).then(() => {
- globalPopup?.showSuccess('删除成功')
- getContractTableList()
- })
- })
- }
- function contractApproved(row: any, status: number) {
- confirmAction('确认审核通过吗?,通过后合同基本信息无法修改', '合同通过').then(() => {
- contractOperation(row, status)
- })
- }
- function rejectTheContract() {
- confirmAction('确认驳回吗?,驳回后合同基本信息无法修改', '合同驳回').then(() => {
- contractOperation(rejectData, 2)
- })
- }
- async function importBusiness(param: UploadRequestOptions) {
- allLoading.importLoading = true
- const formData = new FormData();
- formData.append('file', param.file)
- formData.append('userId', sessionStorage.getItem('token') || '')
- const res = await uploadFile(IMPORITEM, formData).finally(() => {
- allLoading.importLoading = false
- })
- if (res.code == 'ok') {
- globalPopup?.showSuccess('导入成功' || '')
- getContractTableList()
- return
- }
- globalPopup?.showError(res.msg || '')
- }
- function exportContract() {
- allLoading.exportLoading = true
- post(EXPORT_CONTRACT, {}).then((res) => {
- downloadFile('合同导出.xlsx', res.data)
- }).finally(() => {
- allLoading.exportLoading = false
- })
- }
- async function addEditor(row?: any) {
- allLoading.addEditorSaveLoading = false
- editForm.value = row ? setEditForm(row) : {}
- allDynamicText.addEditorText = row ? '编辑合同' : '新增合同'
- contractTemplate.value.list = setTemplateDataDisable(contractTemplate.value.list, [...getTemplateKey(contractTemplate.value.list)], row?.status == 0)
- generateFormKey.value++
- setAddEditorVisableFormData(row)
- if (row) {
- const { data = [] } = await post(GET_PAYMENT_LIST, { contractId: row.id })
- addEditorVisableForm.paymentPlan = data.map((item: any) => {
- return {
- isPayed: item.isPayed, amount: item.amount, payDate: item.payDate, id: item.id
- }
- })
- }
- allVisable.addEditorVisable = true
- }
- function setEditForm(row: any) {
- const { id } = row
- const filedList = getTemplateKey(contractTemplate.value.list)
- const formFiled: any = {}
- filedList.forEach((item: any) => {
- formFiled[item] = row[item]
- })
- return {
- ...formFiled, id
- }
- }
- function setAddEditorVisableFormData(row: any) {
- addEditorVisableForm.enclosureDetele = []
- if (!row) {
- addEditorVisableForm.paymentPlan = []
- addEditorVisableForm.enclosure = []
- }
- if (row) {
- const { files = [] } = row
- addEditorVisableForm.enclosure = files.map((item: any) => {
- return {
- name: item.documentName,
- id: item.id,
- url: item.url
- }
- })
- }
- }
- function resetFiltering() {
- let newResetForm = resetFromValue(filterContractForm)
- Object.assign(filterContractForm, newResetForm)
- }
- function contractOperation(row: any, status: number) {
- let formVal = { status, id: row.id }
- if (status == 2) {
- formVal = row
- }
- post(CONTRACT_OPERATION, { ...formVal }).then(() => {
- globalPopup?.showSuccess("操作成功")
- if (status == 2) {
- allVisable.rejectDataVisable = false
- }
- getContractTableList()
- })
- }
- function getContractTableList() {
- allLoading.contractTableLading = true
- const formVal = getFromValue({ ...filterContractForm, pageIndex: paging.pageIndex, pageSize: paging.pageSize })
- post(GET_CONTRACT_LIST, { ...formVal }).then((res) => {
- // 赋值列表
- const { total = 0, data = [] } = res.data
- paging.pageTotal = total
- contractTableList.value = data
- }).finally(() => {
- allLoading.contractTableLading = false
- })
- }
- async function addEditorSave() {
- const url = editForm.value.id ? EDIT_CONTRACT : ADD_CONTRACT
- const data = await generateForm.value.getData()
- const { paymentPlan = [], enclosure = [], enclosureDetele = [] } = addEditorRef.value.getAddEditorData()
- let newPaymentPlan = paymentPlan
- if (editForm.value.id) {
- newPaymentPlan = paymentPlan.map((item: any) => { return { ...item, contractId: editForm.value.id } })
- }
- const formVal = getFromValue({
- ...editForm.value,
- ...data,
- startDate: data.startDate ? formatDate(new Date(data.startDate)) : '',
- endDate: data.endDate ? formatDate(new Date(data.endDate)) : '',
- paymentListStr: JSON.stringify(newPaymentPlan)
- })
- let totalAmount = 0
- // 判断
- for(let i in paymentPlan) {
- if(!paymentPlan[i].payDate) {
- globalPopup?.showWarning('回款日期不能为空')
- return
- }
- if(!paymentPlan[i].amount || paymentPlan[i].amount == 0) {
- globalPopup?.showWarning('回款金额不能为空和0')
- return
- }
- totalAmount += +paymentPlan[i].amount || 0
- }
- if(totalAmount > +(formVal.amounts || 0)) {
- globalPopup?.showWarning('总回款金额不得大于合同金额')
- return
- }
- allLoading.addEditorSaveLoading = true
- post(url, { ...formVal }).then((res) => {
- if (enclosure.length > 0) {
- fileUpload(String(res.data || editForm.value.id), enclosure)
- }
- if (enclosureDetele.length > 0) {
- fileUploadDetele(String(res.data || editForm.value.id), enclosureDetele)
- }
- if(enclosure.length == 0) {
- allLoading.addEditorSaveLoading = false
- globalPopup?.showSuccess('添加成功')
- allVisable.addEditorVisable = false
- getContractTableList()
- }
- }).catch(() => {
- allVisable.addEditorVisable = false
- })
- }
- function fileUpload(id: string, enclosure = []) {
- const formData = new FormData()
- formData.append('ContractId', id);
- enclosure.forEach((item: any) => {
- if (item.needUpload) {
- formData.append('file', item.file);
- }
- });
- post(UPLOAD_ATTACHMENTS, formData).then(re => {
- globalPopup?.showSuccess(re.msg)
- getContractTableList()
- }).finally(() => {
- allVisable.addEditorVisable = false
- })
- }
- function fileUploadDetele(id: string, enclosureDetele = []) {
- post(DELETE_CONTRACT_FILE, { contractId: id, fileIds: enclosureDetele.join(',') })
- }
- function handleSizeChange(val: number) {
- paging.pageIndex = 1
- paging.pageSize = val
- getContractTableList()
- }
- function handleCurrentChange(val: number) {
- paging.pageIndex = val
- getContractTableList()
- }
- function getTemplateConfig() {
- get(GET_CONTRACT_TEMPLATE).then(res => {
- const datas = JSON.parse(res.data[0] && res.data[0].config)
- contractTemplate.value = datas
- })
- }
- function getObtainContractType() {
- get(OBTAIN_CONTRACT_TYPE).then(res => {
- const list = res.data || []
- fixedData.typeOfContractList = list.map((item: any) => {
- return {
- label: item.name,
- value: item.id
- }
- })
- })
- }
- </script>
- <template>
- <div class="h-full flex">
- <div class="p-5 w-80 pr-0">
- <div class="bg-white w-full h-full shadow-md rounded-md flex flex-col">
- <div class="flex-1 p-3 overflow-y-auto">
- <el-form :model="filterContractForm" label-width="100px" style="max-width: 600px">
- <el-form-item label="合同编号">
- <el-input v-model="filterContractForm.number" clearable placeholder="请输入"></el-input>
- </el-form-item>
- <el-form-item label="合同类型">
- <el-select v-model="filterContractForm.typeName" placeholder="请选择" clearable filterable>
- <el-option v-for="item in fixedData.typeOfContractList" :key="item.value" :label="item.label"
- :value="item.value" />
- </el-select>
- </el-form-item>
- <el-form-item label="状态">
- <el-select v-model="filterContractForm.status" placeholder="请选择" clearable filterable>
- <el-option v-for="item in fixedData.stateList" :key="item.value" :label="item.label"
- :value="item.value" />
- </el-select>
- </el-form-item>
- <el-form-item label="创建时间">
- <el-date-picker v-model="filterContractForm.startDate" type="date" placeholder="请选择" :clearable="false"
- format="YYYY-MM-DD" value-format="YYYY-MM-DD" />
- </el-form-item>
- <el-form-item label="">
- <el-date-picker v-model="filterContractForm.endDate" type="date" placeholder="请选择" :clearable="false"
- format="YYYY-MM-DD" value-format="YYYY-MM-DD" />
- </el-form-item>
- <el-form-item label="下笔回款日期">
- <el-date-picker v-model="filterContractForm.paymentStartDate" type="date" placeholder="请选择"
- :clearable="false" format="YYYY-MM-DD" value-format="YYYY-MM-DD" />
- </el-form-item>
- <el-form-item label="">
- <el-date-picker v-model="filterContractForm.paymentEndDate" type="date" placeholder="请选择"
- :clearable="false" format="YYYY-MM-DD" value-format="YYYY-MM-DD" />
- </el-form-item>
- </el-form>
- </div>
- <div class="w-full flex p-3 shadow-[0_-3px_5px_0px_rgba(0,0,0,0.2)]">
- <El-button class="w-full" @click="resetFiltering()">重置</El-Button>
- <El-button type="primary" class="w-full" :loading="allLoading.contractTableLading"
- @click="getContractTableList()">搜索</El-Button>
- </div>
- </div>
- </div>
- <div class="flex-1 p-5 overflow-auto">
- <div class="bg-white w-full h-full p-3 shadow-md rounded-md flex flex-col">
- <div class="flex justify-end pb-3">
- <el-button type="primary" v-permission="['contractAdd']" @click="addEditor()">新增合同</el-button>
- <el-button type="primary" v-permission="['contractImport']" @click="allVisable.importVisible = true">导入</el-button>
- <el-button type="primary" v-permission="['contractExport']" :loading="allLoading.exportLoading"
- @click="exportContract()">导出</el-button>
- </div>
- <div class="flex-1 w-full overflow-hidden">
- <el-table ref="contractTableRef" :show-overflow-tooltip="tableShowOverflowTooltip" :data="contractTableList"
- border v-loading="allLoading.contractTableLading" style="width: 100%;height: 100%;">
- <el-table-column prop="number" label="合同编号" width="180"></el-table-column>
- <el-table-column prop="name" label="合同名称" width="180"></el-table-column>
- <el-table-column prop="amounts" label="合同金额" width="180">
- <template #default="scope">
- ¥ {{ scope.row.amounts ? scope.row.amounts.toFixed(2) : '0.00' }}
- </template>
- </el-table-column>
- <el-table-column prop="payment" label="已回款金额" width="180">
- <template #default="scope">
- ¥ {{ scope.row.payment ? scope.row.payment.toFixed(2) : '0.00' }}
- </template>
- </el-table-column>
- <el-table-column prop="payment" label="已回款进度" width="180">
- <template #default="scope">
- {{ scope.row.payment ? (100 * scope.row.payment / scope.row.amounts).toFixed(1) + '%' : '0%' }}
- </template>
- </el-table-column>
- <el-table-column prop="nextPaymentDate" label="下笔回款日期" width="180">
- <template #default="scope">
- {{ scope.row.nextPaymentDate ? scope.row.nextPaymentDate : '-' }}
- </template>
- </el-table-column>
- <el-table-column prop="nextPaymentAmount" label="下笔回款金额" width="180">
- <template #default="scope">
- {{ scope.row.nextPaymentAmount ? '¥' + scope.row.nextPaymentAmount.toFixed(2) : '-' }}
- </template>
- </el-table-column>
- <el-table-column prop="typeName" label="合同类型" width="180"></el-table-column>
- <el-table-column prop="name" label="状态" width="180">
- <template #default="scope">
- <span :style="fixedData.stateList[scope.row.status].color">{{
- fixedData.stateList[scope.row.status].label }}</span>
- </template>
- </el-table-column>
- <el-table-column prop="indate" label="创建时间" width="180"></el-table-column>
- <el-table-column label="操作" fixed="right" width="200" v-permission="['contractAdd', 'auditContractData']">
- <template #default="scope">
- <el-button link type="primary" size="large" v-permission="['contractAdd']"
- @click="addEditor(scope.row)">编辑</el-button>
- <el-button link type="success" size="large" v-permission="['auditContractData']"
- v-if="(scope.row.status == 1 || scope.row.status == 3)"
- @click="contractApproved(scope.row, 0)">通过</el-button>
- <el-button link type="danger" size="large" v-permission="['auditContractData']"
- v-if="(scope.row.status == 1 || scope.row.status == 3)"
- @click="contractRejection(scope.row, 2)">驳回</el-button>
- <el-button link type="danger" size="large" v-permission="['contractAdd']"
- @click="deleteContract(scope.row)">删除</el-button>
- </template>
- </el-table-column>
- </el-table>
- </div>
- <div class="flex justify-end pt-3">
- <el-pagination layout="total, prev, pager, next, sizes" v-model:current-page="paging.pageIndex"
- v-model:page-size="paging.pageSize" :page-sizes="[10, 20, 30, 50, 100]" @size-change="handleSizeChange"
- @current-change="handleCurrentChange" :total="paging.pageTotal" />
- </div>
- </div>
- </div>
- <!-- 弹窗 -->
- <el-dialog v-model="allVisable.addEditorVisable" width="1000" :show-close="false" top="10vh">
- <template #header="{ close, titleId, titleClass }">
- <div class="flex justify-between items-center border-b pb-3 dialog-header">
- <h4 :id="titleId">{{ allDynamicText.addEditorText }}</h4>
- <div>
- <el-button type="primary" :loading="allLoading.addEditorSaveLoading" @click="addEditorSave">保存</el-button>
- <el-button @click="allVisable.addEditorVisable = false">取消</el-button>
- </div>
- </div>
- </template>
- <div class="h-[60vh] overflow-y-auto scroll-bar pt-3">
- <div class="ml-4 mr-4">
- <GenerateForm ref="generateForm" :data="contractTemplate" :value="editForm" :key="generateFormKey" />
- <AddEditor ref="addEditorRef" :payment-plan="addEditorVisableForm.paymentPlan"
- :enclosure="addEditorVisableForm.enclosure" :enclosure-detele="addEditorVisableForm.enclosureDetele">
- </AddEditor>
- </div>
- </div>
- </el-dialog>
- <el-dialog v-model="allVisable.rejectDataVisable" width="1000" :show-close="false" top="10vh">
- <template #header="{ close, titleId, titleClass }">
- <div class="flex justify-between items-center border-b pb-3 dialog-header">
- <h4 :id="titleId">驳回合同</h4>
- <div>
- <el-button type="primary" @click="rejectTheContract">驳回</el-button>
- <el-button @click="allVisable.rejectDataVisable = false">取消</el-button>
- </div>
- </div>
- </template>
- <div class="overflow-y-auto scroll-bar pt-3">
- <div class="ml-4 mr-4">
- <el-input v-model="rejectData.msg" style="width: 100%" :autosize="{ minRows: 6, maxRows: 6 }" type="textarea"
- placeholder="请输入驳回原因" />
- </div>
- </div>
- </el-dialog>
- <!-- 导入 -->
- <el-dialog v-model="allVisable.importVisible" width="680" :show-close="false" top="10vh">
- <template #header="{ close, titleId, titleClass }">
- <div class="flex justify-between items-center border-b pb-3 dialog-header">
- <h4 :id="titleId">导入合同</h4>
- <div class="flex">
- <el-upload class="upload-demo mr-3" :limit="1" :show-file-list="false" accept=".xlsx"
- :http-request="importBusiness">
- <el-button type="primary" :loading="allLoading.importLoading">导入</el-button>
- </el-upload>
- <el-button @click="allVisable.importVisible = false">取消</el-button>
- </div>
- </div>
- </template>
- <div class="p-8">
- <div class="ml-4 mr-4">
- <div class="flex items-center">1、点击下载 <el-link type="primary"
- @click="downloadTemplate('Contract', allDynamicText.importText)">{{ allDynamicText.importText }}</el-link></div>
- <div class="mt-4">2、填写合同名称必填</div>
- </div>
- </div>
- </el-dialog>
- </div>
- </template>
- <style lang="scss" scoped></style>
|