This commit is contained in:
2026-10-08 18:34:09 +08:00
commit 2933904f4c
905 changed files with 112129 additions and 0 deletions
+680
View File
@@ -0,0 +1,680 @@
<template> <!-- 合同管理 -->
<view class="wrap">
<!-- 吸顶 -->
<u-sticky offset-top="0" customNavHeight="0">
<!-- 顶部 -->
<uititle title="合同管理"></uititle>
<!-- 选项卡 -->
<view class="layout layout-tab flex justify-between align-center">
<view :class="['tab', {active: tabIndex == 0}]" @click="handTab(0)">待创建</view>
<view :class="['tab', {active: tabIndex == 1}]" @click="handTab(1)">待签署</view>
<view :class="['tab', {active: tabIndex == 2}]" @click="handTab(2)">已完成</view>
<!-- <view :class="['tab', {active: tabIndex == 3}]" @click="handTab(3)">已作废</view>-->
</view>
<u-subsection :list="signTypeList" :current="subsection" keyName="label" active-color="#A92924"
@change="changeSubsection"/>
</u-sticky>
<view>
<u-subsection :list="signTypeFilterList" :current="signTypeFilter" keyName="label" active-color="#A92924"
@change="changeSignTypeFilter" v-if="tabIndex == 2"/>
<u-search bg-color="#FFFFFF" v-model="keyword" placeholder="输入签约方关键字搜索" @blur="query(1)" @custom="query(1)"></u-search>
</view>
<view class="layout layout-contract">
<view class="item" v-for="(item, index) in tableData.rows" :key="index">
<view class="title text-single m-right-20">
<text v-if="item.contract.status > 0">{{ item.contract.docTitle }}</text>
<text v-else-if="item.contract.status === 0 && item.sheet">{{ item.sheet.title }}</text>
</view>
<view class="flex justify-start align-center mt-15">
<template v-if="item.sheet">
<view class="mr-10">
<u-tag plain text="自主交易" size="mini" v-if="item.sheet.tradeMethod === 0" type="primary"
>
</u-tag>
<u-tag plain text="金久信公证" size="mini"
v-if="item.sheet.tradeMethod === 1 && item.contract.type !== 'sign'"
type="success">
</u-tag>
</view>
<view class="mr-10">
<u-tag plain text="标准合同" size="mini" effect="plain" v-if="item.sheet.signMethod === 0"
type="success">
</u-tag>
<u-tag plain text="双方协商合同" size="mini" effect="plain"
v-if="item.sheet.signMethod === 2"
type="primary">
</u-tag>
<u-tag plain text="线下合同" size="mini" effect="plain" v-if="item.sheet.signMethod === 1"
type="warning">
</u-tag>
</view>
</template>
<u-tag plain text="金久信公证" size="mini"
v-if="item.contract.tradeMethod === 1 && item.contract.type === 'sign'" class="mr-10"
type="success">
</u-tag>
<u-tag type="primary" v-if="item.contract.type === 'enquiry'" text="询价单" size="mini"
class="mr-10"/>
<u-tag type="success" v-else-if="item.contract.type === 'process'" text="加工单" size="mini"
class="mr-10"/>
<u-tag type="success" v-else-if="item.contract.type === 'sign'" text="金久信签约宝" size="mini"
class="mr-10"/>
<u-tag type="primary" v-else-if="item.contract.type === 'old'" text="旧货交易" size="mini"
class="mr-10"/>
<u-tag type="errpr" v-else-if="item.contract.type === 'self-support'" text="自营询价" size="mini"
class="mr-10"/>
<view v-if="item.contract.status === 1" class="flex justify-start items-center flex-wrap">
<view class="justify-start items-center flex-wrap"
v-for="(party, pIndex) in item.contract.partyList" :key="pIndex">
<u-tag size="mini" class="mr-10 ml-10"
v-if="party.userId !== userInfo._id && !party.sign && party.role !== 'third'" plain
type="error" text="待交易方签署"/>
<u-tag size="mini" class="mr-10 ml-10"
v-if="party.userId !== userInfo._id && !party.sign && party.role === 'third'" plain
type="error" text="待第三方签署"/>
<u-tag size="mini" class="mr-10 ml-10" v-if="party.userId === userInfo._id && !party.sign"
plain
type="primary" text="待我签署"/>
</view>
</view>
<view v-if="item.order" class="text-main text-25">
(订单状态:{{
item.order.orderStatus === 4 ? '已完成' : ([5, 6].includes(item.order.orderStatus) ? '订单终止' : '执行中')
}})
</view>
<!-- <view class="flex-1"></view>-->
<!-- <view class="date">2023-04-27到期,过期将无法签署</view>-->
</view>
<view class="sm m-top-20 flex flex-col justify-start items-start">
<text class="m-right-20">合同编码:{{ item.contract.transactionId }}</text>
<text class="m-right-20" v-if="item.sheet && item.contract.type !== 'old'">交易编码:{{
item.contract.type === 'enquiry' ? item.sheet.enquiryNo : item.sheet.orderNo
}}
</text>
<text class="m-right-20">创建时间:{{ item.contract._add_time_str }}</text>
<template v-if="parseInt(item.contract.status) > 0">
<text v-for="(party, partyIndex) in item.contract.partyList " :key="partyIndex">
<template v-if="party.role !== 'third'">
<template v-if="party.userId === item.contract.userId">
发起方签订完成时间:{{
party.signedAt ? dayjs(party.signedAt).format('YYYY-MM-DD HH:mm:ss') : ''
}}
</template>
<template v-if="party.userId !== item.contract.userId">
接收方签订完成时间:{{
party.signedAt ? dayjs(party.signedAt).format('YYYY-MM-DD HH:mm:ss') : ''
}}
</template>
</template>
<template v-if="party.role === 'third'">
第三方签订完成时间:{{
party.signedAt ? dayjs(party.signedAt).format('YYYY-MM-DD HH:mm:ss') : ''
}}
</template>
</text>
</template>
<view v-if="item.contract.signEndDate">
<text>签订截止时间:{{
dayjs(item.contract.signEndDate).format('YYYY-MM-DD HH:mm:ss')
}}</text>
<text class="text-red ml-20" v-if="item.contract.signCount === 0">{{ dayjs(item.contract.signEndDate).isBefore(dayjs()) ? '已超时限' : '' }}</text>
</view>
<view v-if="item.contract.type === 'sign' && item.contract.payUser && item.contract.payUser.user">
费用承担方:{{
item.contract.payUser.user.accountType === 2 ?
item.contract.payUser.user.company.companyName : item.contract.payUser.user.person.personName
}}
</view>
</view>
<view class="flex justify-start align-center m-top-20">
<view class="op flex justify-start align-center m-right-30" @click="showParty(item)">
<u-icon name="chat" color="#A92924" size="18"></u-icon>
<text class="op-text m-left-10">查看交易方</text>
</view>
</view>
<view class="mt-20 flex justify-start align-center">
<view class="op flex justify-start align-center"
v-if="item.contract.status === 0 && item.contract.userId === userInfo._id"
@click="createContract(item.contract)">
<u-icon name="plus-circle" color="#A92924" size="18"></u-icon>
<text class="op-text m-left-10">创建合同</text>
</view>
<view class="mr-10">
<u-button @click.native="changeContract(item.contract)" custom-style="padding: 0"
v-if="((item.sheet && item.sheet.signMethod === 2) || item.contract.type === 'sign' || item.contract.type === 'self-support')
&& item.contract.status === 1
&& item.contract.userId === userInfo._id && item.contract.signCount === 0"
size="mini" type="primary">修改合同内容
</u-button>
</view>
<view class="ml-10">
<u-button custom-style="padding: 0" v-if="item.contract.userId === userInfo._id"
@click="delContract(item.contract)" size="mini" type="text">
删除合同
</u-button>
</view>
<template v-if="parseInt(item.contract.status) === 1 && dayjs(item.contract.signEndDate).isAfter(dayjs())">
<view class="ml-10">
<u-button @click="extSign(item.sign, item.contract)" size="mini" type="primary"
:disabled="item.sign">
{{ item.sign ? '已签署' : '签署文件' }}
</u-button>
</view>
</template>
<template v-if="parseInt(item.contract.status) === 2">
<view class="ml-10">
<u-button custom-style="padding: 0"
@click="viewContract(item.contract)"
size="mini" plain>
{{ parseInt(item.contract.signType) === 1 ? '查看单据' : '查看合同' }}
</u-button>
</view>
<view class="ml-10">
<u-button custom-style="padding: 0" @click="downloadContract(item.contract.transactionId)" type="success"
size="mini" plain>
{{ parseInt(item.contract.signType) === 1 ? '下载单据' : '下载合同' }}
</u-button>
</view>
<view class="ml-10">
<u-button @click="payDownloadContract(item.contract)" type="primary" custom-style="padding: 0"
size="mini" plain>
{{
parseInt(item.contract.signType) === 1 ? '下载单据(付费司法调证)' : '下载合同(付费司法调证)'
}}
</u-button>
</view>
</template>
<view class="ml-10">
<u-button custom-style="padding: 0"
v-if="item.order && parseInt(item.contract.status) === 2 && ((item.sheet && item.sheet.tradeMethod === 1) || item.contract.tradeMethod === 1)"
@click="$jump(`/pages/shop/order?menuIndex=${item.role === 'buyer' ? 1 : 0}&keyword=${item.order.orderNo}`)"
size="mini"
:type="(item.order && item.order.orderStatus > 4) ? 'info' :'success'">
{{
(item.order && item.order.orderStatus === 4) ? '订单已结束' : ([5, 6].includes(item.order.orderStatus) ? '订单已终止' : (item.role === 'buyer' ? '去付款' : '去请款'))
}}
</u-button>
</view>
<view class="ml-10">
<u-button custom-style="padding: 0"
v-if="item.contract.otherFile && item.contract.otherFile.length > 0"
@click="openDownload(item.contract.otherFile)" plain
size="mini"
type="info">查看附件
</u-button>
</view>
</view>
</view>
</view>
<!-- 没有数据 u-empty是框架组件 cmempty是自己封装组件 -->
<u-empty mode="list" text="暂无更多内容~"></u-empty>
<!-- <cmempty></cmempty> -->
<u-popup :show="show" mode="center" @close="show = false" closeable close-on-click-overlay
:custom-style="{width: '90%'}">
<view class="p-30">
<view class="mb-10">名称:{{ title }}</view>
<view class="mb-10">联系人:{{ name }}</view>
<view class="mb-10">联系方式:{{ companyMobile }}</view>
</view>
</u-popup>
<contact-modal ref="contactModal"/>
<u-modal :show="showPartyModal" title="交易方" @confirm="showPartyModal = false">
<u-parse :content="partyContent"></u-parse>
</u-modal>
</view>
</template>
<script>
import uititle from '@/components/common/title'
import cmsearch from '@/components/common/search'
import cmempty from '@/components/common/empty'
import dayjs from "dayjs";
import ContactModal from "@/components/ContactModal.vue";
import {Loading} from "element-ui";
const SIGN_CONFIRM_CONTENT = `1、您确认,若全体各签约方未完成全部签约流程,本签约文件不发生法律效力,系统无法对该签约文件予以保存及提供司法调证服务;
2、您确认,当前签约的实名主体名称、手机号码与注册认证阶段提交的信息未发生变更;若发生变更,必须及时进行重新认证后方可继续签约,避免产生严重法律风险与经济损失;
3、您确认,本次签约为本系统实名认证主体操作,如若不是实名认证主体操作,授权委托人需本系统进行授权认证后签约;
4、您确认,您与其他签约方均系在平等、自愿的基础上完成本次签约;
5、你确认,此次签约内容符合《中华人民共和国电子签名法》《民法典》生效保护范畴;
6、如因法律法规、监管部门政策更新等原因,系统提示您重新进行实名认证、证书续期等重要提示时,请您必须在签约前完成,否则造成任何损失,平台不承担任何责任;以上签约条件您均已经知悉并确认,否则您有权拒绝本次签约。`
export default {
components: {
ContactModal,
uititle,
cmsearch,
cmempty,
},
data() {
return {
tabIndex: 0,
tableData: {},
userInfo: null,
show: false,
title: '',
name: '',
companyMobile: '',
signTypeList: [
{
tradeMethod: null,
type: null,
label: '全部'
},
{
tradeMethod: 0,
type: null,
label: '自主交易'
},
{
tradeMethod: 1,
type: null,
label: '金久信公正'
},
{
tradeMethod: null,
type: 'sign',
label: '金久信签约宝'
},
],
subsection: 0,
signTypeFilterList: [
{
value: '2',
label: '合同签约'
},
{
value: '1',
label: '单据签约'
},
],
signTypeFilter: 0,
keyword: '',
numToChForThird: ['三', '四', '五', '六', '七', '八', '九', '十'],
showPartyModal: false,
partyContent: ''
}
},
methods: {
dayjs,
handTab(index) {
this.tabIndex = index
this.query(1)
},
detailLink(val) {
vk.navigateTo('/pages/public/create')
},
menuSelect(e) {
this.menuIndex = String(e)
this.formData.status = Number(e)
this.isSign = false
this.query(1)
},
selectSign() {
this.isSign = true
this.menuIndex = ''
},
changeSubsection(index) {
this.subsection = index
this.query(1)
},
changeSignTypeFilter(index) {
this.signTypeFilter = index
this.query(1)
},
async query(pageIndex) {
this.tableData = await vk.callFunction({
url: 'client/contract/kh/getList',
title: '请求中...',
data: {
pageIndex,
pageSize: 500,
status: this.tabIndex,
tradeMethod: this.signTypeList[this.subsection].tradeMethod,
type: this.signTypeList[this.subsection].type,
keyword: this.keyword,
signType: this.signTypeFilter === 1 ? '1' : '2',
},
});
this.$forceUpdate()
},
/**
* 创建合同
* @param contract
*/
createContract(contract) {
// this.form1.contractId = contract._id
this.$jump(`/pages/public/create?contractId=${contract._id}`)
},
async changeContract(contract) {
this.$jump(`/pages/public/create?contractId=${contract._id}`)
},
onFormSuccess() {
this.form1.props.show = false
// this.form1.data.contractId = null
// this.formData.status = 1
// this.menuIndex = '1'
// this.isSign = false
// this.$refs.form2.resetForm()
// this.$refs.form1.resetForm()
// this.query(1)
vk.redirectTo({url: '/pages/contract/index?tab=1'})
},
/**
* 签署合同
* @param sign
* @param contract
*/
extSign(sign, contract) {
if (sign) return
uni.showModal({
title: '提示',
content: SIGN_CONFIRM_CONTENT,
showCancel: false,
confirmText: '知悉同意',
success: (confirmRes) => {
if (confirmRes.confirm) {
vk.callFunction({
url: 'client/contract/kh/extSign',
title: '请求中...',
data: {
contractId: contract._id,
isWap: true
},
success: (res) => {
window.location.href = res.data
// window.open(res.data)
}
});
}
}
});
},
showStopSign(contract) {
vk.callFunction({
url: 'client/contract/kh/extSign',
title: '请求中...',
data: {
contractId: contract._id
},
success: (res) => {
// window.open(res.data)
window.location.href = res.data
}
});
},
viewContract(contract) {
vk.callFunction({
url: 'client/contract/kh/viewContract',
title: '请求中...',
data: {
contractId: contract._id
},
success: (res) => {
window.location.href = res.data
// window.open(res.data)
this.query(1)
}
});
},
navTo(url) {
vk.navigateTo({
url: url
})
},
showParty(userContract) {
// let content = ''
// userContract.contract.partyList.forEach(party => {
// // if (party.userId !== userContract.userId) partyUser = party.user
// const partyUser = party.user
// if (partyUser) {
// const name = partyUser.nickname
// let role = party.role === 'buyer' ? '购买方' : '销售方'
// if (party.role === 'third') role = '第三方'
// content += `<view class="flex flex-col justify-start items-start py-10 border-bottom">
// <view>身份:${role}</view>
// <view>联系人:${name}</view>
// <view>联系方式:${partyUser.mobile}</view></view>`
// }
// })
let content = ''
const buyer = userContract.contract.partyList.find(item => item.role !== 'third' && userContract.contract.userId === item.userId)
const seller = userContract.contract.partyList.find(item => item.role !== 'third' && userContract.contract.userId !== item.userId)
const thirdList = userContract.contract.partyList.filter(item => item.role === 'third')
content += `<div class="flex flex-col justify-start items-start py-10 border-bottom">
<div>身份:发起方</div>
<div>联系人:${buyer.user.nickname}</div>
<div>联系方式:${buyer.user.mobile}</div></div>`
content += `<div class="flex flex-col justify-start items-start py-10 border-bottom">
<div>身份:接收方</div>
<div>联系人:${seller.user.nickname}</div>
<div>联系方式:${seller.user.mobile}</div></div>`
thirdList.forEach((item, index) => {
console.log(item)
content += `<div class="flex flex-col justify-start items-start py-10 border-bottom">
<div>身份:第${this.numToChForThird[index]}方</div>
<div>联系人:${item.user.nickname}</div>
<div>联系方式:${item.user.mobile}</div></div>`
})
// this.$confirm(content, '', {
// cancelButtonText: '关闭',
// showConfirmButton: false,
// dangerouslyUseHTMLString: true
// })
this.partyContent = content
this.showPartyModal = true
},
changeTradeMethod(tradeMethod) {
this.formData.tradeMethod = tradeMethod
this.formData.type = null
this.query(1)
},
changeType(type) {
this.formData.tradeMethod = null
this.formData.type = type
this.query(1)
},
openDownload(otherFile) {
for (let file in otherFile) {
// window.open(otherFile)
window.location.href = otherFile
}
},
async getCommonContractUrl() {
const res = await vk.callFunction({
url: 'client/dict/pub/getDetail',
data: {
id: '657d36befe975f63af1f24e7'
},
})
this.contractTemplate = res.content
},
downloadContractTemplate() {
// window.open(this.contractTemplate)
window.location.href = this.contractTemplate
},
async delContract(contract) {
uni.showModal({
title: '温馨提示',
content: '请您确认文件无用或已经完成履约后再删除文件,删除后平台将无法为您提供相关数据,您将无法查询已经删除文件。请您谨慎操作。',
success: async res => {
if (res.confirm) {
await vk.callFunction({
url: 'client/contract/kh/del',
data: {
id: contract._id
},
success: (res) => {
this.query(1)
}
})
}
}
})
},
async payDownloadContract(contract) {
const amountRes = await vk.callFunction({
url: 'client/dict/pub/getDetail',
data: {
id: 'ded3e568662e5817000026633aad1e69'
},
})
if (!contract.canDownloadUidList || !contract.canDownloadUidList.includes(this.userInfo.uid)) {
if (contract.certificate && !contract.certificate.paidConfirm) {
if (contract.certificate.paymentMethod === 'online') {
return vk.navigateTo({
url: `/pages/shop/pay?id=${contract.certificate.orderId}`
})
}else return vk.toast('请先等待后台确认支付')
}
vk.navigateTo({
url: `/pages/public/certificate?contractId=${contract._id}&transactionId=${contract.transactionId}&amount=${amountRes.content}`
})
} else {
uni.showModal({
title: '温馨提示',
content: '您提交申请后,平台将在两个工作日内向您提供合法生效文件,客服电话:400-686-5559',
success: async res => {
if (res.confirm) {
if (contract.certificate) {
if (contract.certificate.deliveryMethods.paper) {
vk.toast('您的司法调证文件已发货,请注意查收')
} else {
if (contract.certificate.downloadUrl) window.open(contract.certificate.downloadUrl)
else vk.toast('文件生成中,请耐心等待')
}
} else vk.toast('操作失败,请联系客服')
}
}
})
}
},
async downloadContract(contract_id) {
let loadingInstance1 = Loading.service({fullscreen: true, text: '加载中...'});
const res = await vk.callFunction({
url: 'client/contract/pub/getDownload',
data: {
contract_id
}
});
loadingInstance1.close()
if (res) {
// window.open(`https://textapi.fadada.com/api2/downLoadContract.api?app_id=502704&timestamp=${res.data.timestamp}&v=2.0&msg_digest=${res.data.msg_digest}&contract_id=${contract_id}`)
window.location.href = `https://textapi.fadada.com/api2/downLoadContract.api?app_id=502704&timestamp=${res.data.timestamp}&v=2.0&msg_digest=${res.data.msg_digest}&contract_id=${contract_id}`
}
},
},
onLoad(option) {
if (option.tab) this.tabIndex = parseInt(option.tab)
this.userInfo = vk.getStorageSync('uni_id_user_info')
this.query(1)
},
}
</script>
<style lang="scss">
page {
background: #ffffff;
}
/deep/ .u-tag--mini {
padding: 0 1px !important;
}
.layout-tab {
height: 100rpx;
padding: 0 30rpx;
background: #f1f1f1;
.tab {
margin: 0 20rpx;
padding: 10rpx 0rpx;
font-size: 28rpx;
line-height: 40rpx;
color: #666666;
}
.active {
position: relative;
color: #A92924;
&::after {
position: absolute;
left: 0;
bottom: 0;
z-index: 9;
content: '';
width: 100%;
height: 1px;
background: #A92924;
}
}
}
.layout-contract {
padding: 10rpx 30rpx;
.item {
padding: 30rpx 0rpx;
border-bottom: 1px solid #f2f2f2;
&:last-child {
border-bottom: none;
}
.sm {
font-size: 24rpx;
line-height: 40rpx;
color: #999999;
}
.title {
//max-width: 300rpx;
font-size: 28rpx;
line-height: 40rpx;
color: #101010;
}
}
.tag {
display: inline-block;
padding: 0 10rpx;
height: 36rpx;
font-size: 22rpx;
line-height: 36rpx;
color: #A92924;
text-align: center;
background-color: rgba(169, 41, 36, 0.13);
}
.date, .op-text {
font-size: 24rpx;
line-height: 40rpx;
color: #A92924;
}
.xiugai {
width: 130rpx;
height: 44rpx;
font-size: 24rpx;
line-height: 44rpx;
color: #ffffff;
text-align: center;
background: #A92924;
}
}
.trade-method-item {
cursor: pointer;
font-size: 25rpx;
margin-right: 15rpx;
line-height: 40rpx;
}
</style>