edit.vue 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628
  1. <template>
  2. <view class="add-page white-wrap">
  3. <view class="section white-wrap">
  4. <view class="section-title require">用印用途</view>
  5. <view class="section-select-box" :style="{color:purpose?'#333':'#999'}" @click="showPurpose=true">{{purpose?purpose:'请选择'}}</view>
  6. </view>
  7. <!-- 系统合同模块 -->
  8. <view v-if="radioVal==='系统合同'">
  9. <view class="section white-wrap">
  10. <view class="section-title require">客户名称(全称)</view>
  11. <view
  12. class="section-select-box"
  13. :style="{color:customeName?'#333':'#999'}"
  14. @click="showCustome=true"
  15. >
  16. {{customeName?customeName:'请输入客户名称'}}
  17. </view>
  18. </view>
  19. <view class="section white-wrap" v-if="CreditCode">
  20. <view class="section-title require">统一社会信用码</view>
  21. <input type="text" v-model="CreditCode" placeholder="请填写统一社会信用码" disabled/>
  22. </view>
  23. <view class="section white-wrap" v-if="UseCompanyName">
  24. <view class="section-title">实际使用方名称</view>
  25. <input type="text" v-model="UseCompanyName" placeholder="请填写实际使用方名称" disabled/>
  26. </view>
  27. <view class="section white-wrap" v-if="ServiceType">
  28. <view class="section-title require">业务类型</view>
  29. <view :style="{color:ServiceType?'#333':'#999'}">{{ServiceType?ServiceType:'请选择业务类型'}}</view>
  30. </view>
  31. </view>
  32. <!-- 上传附件模块 -->
  33. <view v-if="radioVal==='上传附件'">
  34. <view class="section white-wrap">
  35. <view class="section-title require">客户名称(全称)</view>
  36. <input type="text" v-model="customeName" placeholder="请输入客户名称"/>
  37. </view>
  38. <view class="section white-wrap">
  39. <view class="section-title require">统一社会信用码</view>
  40. <input type="text" v-model="CreditCode" placeholder="请填写统一社会信用码"/>
  41. </view>
  42. <view class="section white-wrap">
  43. <view class="section-title">实际使用方名称</view>
  44. <input type="text" v-model="UseCompanyName" placeholder="请填写实际使用方名称"/>
  45. </view>
  46. <view class="section white-wrap">
  47. <view class="section-title require">业务类型</view>
  48. <view class="section-select-box" :style="{color:ServiceType?'#333':'#999'}" @click="showServiceType=true">{{ServiceType?ServiceType:'请选择业务类型'}}</view>
  49. </view>
  50. </view>
  51. <view class="section white-wrap">
  52. <view class="section-title require">文件份数</view>
  53. <input type="number" v-model="fileNum" placeholder="请填写总共盖章文件份数"/>
  54. </view>
  55. <view class="section white-wrap">
  56. <view class="section-title require">加盖何种印章</view>
  57. <view class="section-select-box" :style="{color:type?'#333':'#999'}" @click="showType=true">{{type?type:'请选择'}}</view>
  58. </view>
  59. <view class="section white-wrap">
  60. <view class="section-title">备注</view>
  61. <textarea type="text" v-model="remark" placeholder="请填写备注"></textarea>
  62. </view>
  63. <view class="section white-wrap" v-if="radioVal==='系统合同'&&file">
  64. <view class="section-title require">合同附件</view>
  65. <image src="../static/pdf.png" mode="aspectFill" style="width: 102rpx;height: 120rpx;" @click="handlePreviewFiles(file)"></image>
  66. </view>
  67. <view class="section white-wrap" v-if="radioVal==='上传附件'">
  68. <view class="section-title require">附件上传</view>
  69. <!-- <image :src="img" mode="aspectFill" style="width: 102rpx;height: 120rpx;margin:0 10rpx 10rpx 0" v-for="img in fileUrlArr" :key="img"></image>
  70. <image @click="handleUpload" src="../static/upload-icon.png" mode="aspectFill" style="width: 102rpx;height: 120rpx;margin:0 10rpx 10rpx 0"></image> -->
  71. <div class="check-file-box" :style="'background-image:url('+file.img+')'" v-if="file.url" @click="handlePreviewFiles(file)">
  72. <image class="del-icon" src="../static/del-icon.png" @click.stop="handleDeleteCheckFile"></image>
  73. </div>
  74. <image v-else @click="handleUpload" src="../static/upload-icon.png" mode="aspectFill" style="width: 102rpx;height: 120rpx;"></image>
  75. </view>
  76. <!-- 流程模块 -->
  77. <view class="section white-wrap process-wrap" v-if="processData">
  78. <view class="title" style="font-size: 16px;font-weight: bold;">审批流程</view>
  79. <steps :data="processData"></steps>
  80. </view>
  81. <view class="fix-bottom-wrap" style="text-align: center;">
  82. <van-button type="info" custom-class="btn" round @click="handleSubmit">提交</van-button>
  83. </view>
  84. <!-- 用印用途 -->
  85. <van-popup :show="showPurpose" @close="showPurpose=false" position="bottom">
  86. <van-picker
  87. show-toolbar
  88. title="选择用印用途"
  89. :columns="purposeArr"
  90. @confirm="handlePurposeConfirm"
  91. @cancel="showPurpose=false"
  92. />
  93. </van-popup>
  94. <!-- 何种印章 -->
  95. <van-popup :show="showType" @close="showType=false" position="bottom">
  96. <van-picker
  97. show-toolbar
  98. title="选择何种印章"
  99. :columns="typeArr"
  100. @confirm="handleTypeConfirm"
  101. @cancel="showType=false"
  102. />
  103. </van-popup>
  104. <!-- 业务类型 -->
  105. <van-popup :show="showServiceType" @close="showServiceType=false" position="bottom">
  106. <van-picker
  107. show-toolbar
  108. title="选择业务类型"
  109. :columns="ServiceTypeArr"
  110. @confirm="handleServiceTypeConfirm"
  111. @cancel="showServiceType=false"
  112. />
  113. </van-popup>
  114. <!-- 客户搜索 -->
  115. <van-popup :show="showCustome" @close="showCustome=false" position="bottom" custom-style="height: 100vh">
  116. <view class="custome-search-wrap">
  117. <van-search use-left-icon-slot use-action-slot shape="round" :value="searchCustomeVal" placeholder="请输入客户名称/社会信用码" @change="onSearchValChange" @search="onSearch"
  118. custom-class="search-box" field-class="search-con">
  119. <view slot="left-icon">
  120. <image src="../static/search-icon.png" mode="aspectFill" class="search-icon"></image>
  121. </view>
  122. <view slot="action" @click="showCustome=false" class="search-btn">取消</view>
  123. </van-search>
  124. <view class="search-result">
  125. <view class="result-custome-box" v-if="searchContractList.length===0">
  126. <view class="result-item flex" v-for="item in searchCustomeList" :key="item" @click="getContract(item)">
  127. <image src="../static/search-icon.png" mode="aspectFill" class="search-icon"></image>
  128. <view class="con van-ellipsis">{{item}}</view>
  129. <image src="../static/click-icon.png" mode="aspectFill" class="click-icon"></image>
  130. </view>
  131. </view>
  132. <view class="result-contract-box" v-else>
  133. <view class="result-contract-item" v-for="item in searchContractList" :key="item.ContractId" @click="handleChooseContract(item)">
  134. <view class="name">{{item.CompanyName}}</view>
  135. <view style="margin-top: 20rpx;">合同编号:{{item.ContractCode}}</view>
  136. <view style="margin-top: 20rpx;">合同类型:{{item.ContractType}}</view>
  137. <view style="margin-top: 20rpx;">合同金额:{{item.Price}}</view>
  138. </view>
  139. </view>
  140. </view>
  141. </view>
  142. </van-popup>
  143. </view>
  144. </template>
  145. <script>
  146. import steps from '../components/steps.vue'
  147. import {apiFlowDetail,apiSealEdit,apiSearchCustome,apiSearchContract,apiSealDetail} from '@/api/approve/seal.js'
  148. import {uploadFiles} from '@/utils/uploadFile.js'
  149. import {preViewFile} from '../utils/util.js'
  150. export default{
  151. components:{
  152. steps
  153. },
  154. data() {
  155. return {
  156. SealId:0,
  157. showPurpose:false,//显示用印用途选项
  158. purposeArr:['销售合同','渠道合同','付款通知函','招投标','战略合作协议'],
  159. purpose:"",
  160. showType:false,//显示用印用途选项
  161. typeArr:['公章','合同章','法人章'],
  162. type:"",
  163. showServiceType:false,//显示业务类型选项
  164. ServiceTypeArr:['新签合同','续约合同','补充协议'],
  165. ServiceType:'',//业务类型
  166. showCustome:false,//显示搜索客户名称
  167. customeName: '',//客户名称
  168. fileNum:'',//文件数
  169. remark:'',//备注
  170. CreditCode:'',//社会统一信用代码
  171. UseCompanyName:'',//实际使用方客户名称
  172. ContractId:0,//合同id
  173. // ContractfileUrl:'',//合同文件地址 pdf
  174. // fileUrlArr:[],//上传附件 文件地址
  175. file:{
  176. type:'',
  177. img:'',
  178. url:''
  179. },
  180. processData:null,//流程数据
  181. radioVal:'系统合同',
  182. searchCustomeVal:'',//搜索客户输入数据
  183. searchCustomeList:[],//搜索到的客户名称列表
  184. searchContractList:[],//选择搜索中的客户后合同列表数据
  185. }
  186. },
  187. onLoad(options) {
  188. let ContractApprovalId=options.ContractApprovalId
  189. let ContractApprovalRecordId=options.ContractApprovalRecordId
  190. this.getDetail({ContractApprovalId,ContractApprovalRecordId})
  191. },
  192. methods: {
  193. //删除上传的附件
  194. handleDeleteCheckFile(){
  195. this.file={
  196. type:'',
  197. img:'',
  198. url:''
  199. }
  200. },
  201. //预览文件
  202. handlePreviewFiles(e){
  203. if (e.type === "pdf") {
  204. preViewFile(e.url)
  205. } else {
  206. uni.previewImage({
  207. urls: [e.url]
  208. })
  209. }
  210. },
  211. // 获取详情
  212. async getDetail({ContractApprovalId,ContractApprovalRecordId}){
  213. const res=await apiSealDetail({
  214. ContractApprovalId:Number(ContractApprovalId),
  215. ContractApprovalRecordId:Number(ContractApprovalRecordId)
  216. })
  217. if(res.code===200){
  218. if(res.data.SealDetail.ContractId>0){
  219. this.radioVal='系统合同'
  220. }else{
  221. this.radioVal='上传附件'
  222. }
  223. this.SealId=res.data.SealDetail.SealId
  224. this.purpose=res.data.SealDetail.Use
  225. this.type=res.data.SealDetail.SealType
  226. this.ServiceType=res.data.SealDetail.ServiceType
  227. this.customeName=res.data.SealDetail.CompanyName
  228. this.fileNum=res.data.SealDetail.FileNum
  229. this.remark=res.data.SealDetail.Remark
  230. this.CreditCode=res.data.SealDetail.CreditCode
  231. this.UseCompanyName=res.data.SealDetail.UseCompanyName
  232. // this.ContractfileUrl=res.data.SealDetail.FileUrl
  233. this.handleFile(res.data.SealDetail.FileUrl)
  234. this.ContractId=res.data.SealDetail.ContractId
  235. this.getProcessData()
  236. }
  237. },
  238. //处理文件
  239. handleFile(filesUrl){
  240. const reg = /\.(pdf)$/;
  241. if(reg.test(filesUrl)){
  242. this.file={
  243. type: "pdf",
  244. url: filesUrl,
  245. img: require("../static/pdf.png"),
  246. }
  247. }else{
  248. this.file={
  249. type: "img",
  250. url: filesUrl,
  251. img: filesUrl,
  252. }
  253. }
  254. },
  255. //上传附件
  256. async handleUpload(){
  257. const res=await uploadFiles({type:'all'})
  258. const reg = /\.(pdf)$/;
  259. if(reg.test(res[0])){
  260. this.file={
  261. type:'pdf',
  262. url:res[0],
  263. img:require('../static/pdf.png')
  264. }
  265. }else{
  266. this.file={
  267. type:'img',
  268. url:res[0],
  269. img:res[0]
  270. }
  271. }
  272. },
  273. // 客户搜索
  274. // 先搜索出客户 再通过客户去请求出客户下面存在的合同
  275. onSearchValChange(e){
  276. this.searchCustomeVal=e.detail
  277. },
  278. //搜索客户
  279. async onSearch(){
  280. this.searchContractList=[]
  281. this.searchCustomeList=[]
  282. const res=await apiSearchCustome({Keyword:this.searchCustomeVal})
  283. if(res.code===200){
  284. this.searchCustomeList=res.data
  285. }
  286. },
  287. // 搜索客户对应的合同
  288. async getContract(e){
  289. const res=await apiSearchContract({Keyword:e})
  290. if(res.code===200){
  291. if(res.data.List){
  292. this.searchContractList=res.data.List
  293. }else{
  294. uni.showToast({
  295. title:"此客户无合同,请重新选择",
  296. icon:"none"
  297. })
  298. }
  299. }
  300. },
  301. // 选择合同 更新表单数据
  302. handleChooseContract(e){
  303. this.customeName=e.CompanyName
  304. this.CreditCode=e.CreditCode
  305. this.ServiceType=e.ContractType
  306. this.UseCompanyName=e.CompanyName
  307. this.ContractId=e.ContractId
  308. this.ContractfileUrl=e.FileUrl
  309. // 关闭搜索弹窗
  310. this.showCustome=false
  311. this.searchCustomeVal=''
  312. this.searchContractList=[]
  313. this.searchCustomeList=[]
  314. },
  315. // 选择用印用途
  316. handlePurposeConfirm(e) {
  317. this.purpose=e.detail.value
  318. this.showPurpose=false
  319. },
  320. //选择盖章类型
  321. handleTypeConfirm(e){
  322. this.type=e.detail.value
  323. this.showType=false
  324. this.getProcessData()
  325. },
  326. //选择业务类型
  327. handleServiceTypeConfirm(e){
  328. this.ServiceType=e.detail.value
  329. this.showServiceType=false
  330. },
  331. //合同章5 公章、法人章 6
  332. async getProcessData(){
  333. let id=0
  334. if(this.type==='合同章'){
  335. id=5
  336. }else{
  337. id=6
  338. }
  339. let res=await apiFlowDetail({FlowId:id})
  340. if(res.code===200){
  341. this.processData=res.data||[]
  342. }
  343. },
  344. // 提交申请
  345. async handleSubmit(){
  346. let params={
  347. CompanyName:this.customeName,
  348. ContractId:this.ContractId,
  349. CreditCode:this.CreditCode,
  350. FileUrl:this.file.url,
  351. FileNum:Number(this.fileNum),
  352. Remark:this.remark,
  353. SealType:this.type,
  354. ServiceType:this.ServiceType,
  355. Use:this.purpose,
  356. UseCompanyName:this.UseCompanyName,
  357. SealId:Number(this.SealId)
  358. }
  359. if(!params.Use){
  360. uni.showToast({
  361. title:'请选择用印用途',
  362. icon:"none"
  363. })
  364. return
  365. }
  366. if(!params.CompanyName){
  367. uni.showToast({
  368. title:'客户名称不能为空',
  369. icon:"none"
  370. })
  371. return
  372. }
  373. if(!params.CreditCode){
  374. uni.showToast({
  375. title:'信用代码不能为空',
  376. icon:"none"
  377. })
  378. return
  379. }
  380. if(!params.ServiceType){
  381. uni.showToast({
  382. title:'业务类型不能为空',
  383. icon:"none"
  384. })
  385. return
  386. }
  387. if(!params.FileNum){
  388. uni.showToast({
  389. title:'请填写文件份数',
  390. icon:"none"
  391. })
  392. return
  393. }
  394. if(params.FileNum<1){
  395. uni.showToast({
  396. title:'文件份数不合法',
  397. icon:"none"
  398. })
  399. return
  400. }
  401. if(!params.SealType){
  402. uni.showToast({
  403. title:'印章类型不能为空',
  404. icon:"none"
  405. })
  406. return
  407. }
  408. if(!params.FileUrl){
  409. uni.showToast({
  410. title:'请上传文件',
  411. icon:"none"
  412. })
  413. return
  414. }
  415. const res=await apiSealEdit(params)
  416. if(res.code===200){
  417. uni.showToast({
  418. title:"用印申请单已提交",
  419. icon:"none"
  420. })
  421. setTimeout(()=>{
  422. uni.navigateBack({
  423. delta:2
  424. })
  425. },1000)
  426. }
  427. }
  428. },
  429. }
  430. </script>
  431. <style lang="scss">
  432. .check-file-box{
  433. width: 102rpx;
  434. height: 120rpx;
  435. background-size: cover;
  436. background-position: center;
  437. position: relative;
  438. .del-icon{
  439. position: absolute;
  440. width: 30rpx;
  441. height: 30rpx;
  442. top: -15rpx;
  443. right: -15rpx;
  444. }
  445. }
  446. .add-page{
  447. width: 100%;
  448. min-height: 100vh;
  449. padding-bottom: calc(150rpx + constant(safe-area-inset-bottom));
  450. padding-bottom: calc(150rpx + env(safe-area-inset-bottom));
  451. }
  452. .section{
  453. padding: 30rpx 34rpx;
  454. border-top: 10rpx solid #F5F5F5;
  455. position: relative;
  456. textarea{
  457. width: 100%;
  458. height: 200rpx;
  459. }
  460. .section-title{
  461. font-size: 16px;
  462. margin-bottom: 20rpx;
  463. }
  464. .require::before{
  465. content: '*';
  466. font-size: 16px;
  467. color: #FF0000;
  468. position: absolute;
  469. left: 20rpx;
  470. }
  471. .section-select-box{
  472. color: #999;
  473. position: relative;
  474. &::after{
  475. position: absolute;
  476. right: 0;
  477. top: 50%;
  478. content: '';
  479. display: block;
  480. width: 18rpx;
  481. height: 18rpx;
  482. border-top: 1px solid #999;
  483. border-right: 1px solid #999;
  484. transform: translateY(-50%) rotate(45deg);
  485. }
  486. }
  487. }
  488. .btn{
  489. width: 360rpx;
  490. height: 60rpx;
  491. }
  492. .radio-wrap{
  493. .radio{
  494. font-size: 14px;
  495. &::before{
  496. content: '';
  497. display: inline-block;
  498. }
  499. }
  500. }
  501. .custome-search-wrap{
  502. padding: 34rpx;
  503. height: 100%;
  504. .search-box {
  505. border: 1px solid #3385FF;
  506. padding: 0 !important;
  507. border-radius: 60rpx;
  508. background-color: #fff !important;
  509. }
  510. .search-con {
  511. background-color: #fff !important;
  512. }
  513. .van-search__content {
  514. background-color: #fff !important;
  515. padding-left: 30rpx !important;
  516. }
  517. .search-btn {
  518. position: relative;
  519. color: #3385FF;
  520. &::before {
  521. content: '';
  522. display: block;
  523. width: 1px;
  524. height: 60%;
  525. background-color: #D1D1D1;
  526. position: absolute;
  527. left: -16rpx;
  528. top: 20%;
  529. }
  530. }
  531. .search-icon{
  532. width: 40rpx;
  533. height: 40rpx;
  534. display: block;
  535. position: relative;
  536. top: 4rpx;
  537. margin-right: 20rpx;
  538. }
  539. .click-icon{
  540. width: 24rpx;
  541. height: 24rpx;
  542. }
  543. .result-item{
  544. align-items: center;
  545. padding: 20rpx 0;
  546. border-bottom: 1px solid #EBEBEB;
  547. .con{
  548. flex: 1;
  549. margin-right: 20rpx;
  550. }
  551. }
  552. .search-result{
  553. overflow-y: auto;
  554. height: 100%;
  555. }
  556. .result-contract-box{
  557. padding: 0 10rpx;
  558. .result-contract-item{
  559. margin-top: 30rpx;
  560. box-shadow: 0px 0px 12rpx rgba(175, 175, 175, 0.38);
  561. padding: 30rpx;
  562. border-radius: 8px;
  563. .name{
  564. font-size: 16px;
  565. font-weight: bold;
  566. &::before{
  567. content:'';
  568. display:inline-block;
  569. width: 31rpx;
  570. height: 34rpx;
  571. background-image: url(../../static/man.png);
  572. background-size: cover;
  573. position: relative;
  574. top: 4rpx;
  575. margin-right: 10rpx;
  576. }
  577. }
  578. }
  579. }
  580. }
  581. </style>