PreviewData.vue 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552
  1. <template>
  2. <div class='previewData'>
  3. <van-tabs v-if="result && result.length > 0" v-model="active" title-active-color='#2cb7ca' color='#2cb7ca'
  4. line-width='150px' line-height='2px' @click='toggle' sticky :offset-top="offsetTop">
  5. <van-tab title='标准字段包' name='1'>
  6. <div class='table-container'>
  7. <table class='table table-bz' cellspacing='0' cellpadding='0'>
  8. <thead class='thead'>
  9. <tr>
  10. <td>序号</td>
  11. <td>匹配关键词</td>
  12. <td>省份</td>
  13. <td>城市</td>
  14. <td>公告标题</td>
  15. <td>公告类别</td>
  16. <td>发布时间</td>
  17. <td>采购单位</td>
  18. <td>中标单位</td>
  19. <td>中标金额<br>(万元)</td>
  20. <td>项目名称</td>
  21. <td>公告内容</td>
  22. <td>剑鱼标讯地址</td>
  23. </tr>
  24. </thead>
  25. <tbody class="tbody decrypt">
  26. <tr v-for="(bz, index) in result" :key="index">
  27. <td>{{ index + 1 }}</td>
  28. <td>{{ bz.keyword }}</td>
  29. <td>{{ bz.area }}</td>
  30. <td>{{ bz.city }}</td>
  31. <td>{{ bz.title }}</td>
  32. <td>{{ bz.subtype }}</td>
  33. <td>{{ bz.publishtime }}</td>
  34. <td>{{ bz.buyer }}</td>
  35. <td>{{ bz.s_winner }}</td>
  36. <td>{{ moneyFormatForCover(bz.bidamount) }}</td>
  37. <td>{{ bz.projectname }}</td>
  38. <td>{{ bz.detail }}</td>
  39. <td>{{ bz.url }}</td>
  40. </tr>
  41. </tbody>
  42. </table>
  43. </div>
  44. </van-tab>
  45. <van-tab title='高级字段包' name='2'>
  46. <div class='table-container'>
  47. <table class='table table-gj' cellspacing='0' cellpadding='0'>
  48. <thead class='thead'>
  49. <tr>
  50. <td rowspan='2'>序号</td>
  51. <td rowspan='2'>匹配关键词</td>
  52. <td rowspan='2'>省份</td>
  53. <td rowspan='2'>城市</td>
  54. <td rowspan='2'>区县</td>
  55. <td rowspan='2'>公告标题</td>
  56. <td rowspan='2'>公告类别</td>
  57. <td rowspan='2'>公告内容</td>
  58. <td rowspan='2'>发布时间</td>
  59. <td rowspan='2'>公告地址</td>
  60. <td rowspan='2'>剑鱼标讯地址</td>
  61. <td rowspan='2'>项目名称</td>
  62. <td rowspan='2'>行业</td>
  63. <td rowspan=2>项目编号</td>
  64. <td rowspan='2'>项目范围</td>
  65. <td rowspan='2'>预算金额<br>(万元)</td>
  66. <td rowspan='2'>中标金额<br>(万元)</td>
  67. <td rowspan='2'>报名截止日期</td>
  68. <td rowspan='2'>开标日期</td>
  69. <td rowspan='2'>投标截止日期</td>
  70. <td rowspan='2'>合同签订时间</td>
  71. <td colspan='5'>采购单位信息</td>
  72. <td rowspan='2'>招标代理机构</td>
  73. <td colspan='3'>中标单位信息(来源:招标公告网站)</td>
  74. <td colspan='3'>中标单位信息(来源:国家企业公示网站)</td>
  75. </tr>
  76. <tr>
  77. <td>单位名称</td>
  78. <td>采购单位类型</td>
  79. <td>联系人</td>
  80. <td>联系电话</td>
  81. <td>单位地址</td>
  82. <td>单位名称</td>
  83. <td>联系人</td>
  84. <td>联系电话</td>
  85. <td>联系人</td>
  86. <td>联系电话</td>
  87. <td>电子邮箱</td>
  88. </tr>
  89. </thead>
  90. <tbody class="tbody decrypt">
  91. <tr v-for="(gj, iindex) in result" :key="iindex">
  92. <td>{{ iindex + 1 }}</td>
  93. <td>{{ gj.keyword }}</td>
  94. <td>{{ gj.area }}</td>
  95. <td>{{ gj.city }}</td>
  96. <td>{{ gj.district }}</td>
  97. <td>{{ gj.title }}</td>
  98. <td>{{ gj.subtype }}</td>
  99. <td>{{ gj.detail }}</td>
  100. <td>{{ gj.publishtime }}</td>
  101. <td>{{ gj.href }}</td>
  102. <td>{{ gj.url }}</td>
  103. <td>{{ gj.projectname }}</td>
  104. <td>{{ gj.s_topscopeclass }}</td>
  105. <td>{{ gj.projectcode }}</td>
  106. <td>{{ gj.projectscope }}</td>
  107. <td>{{ moneyFormatForCover(gj.budget) }}</td>
  108. <td>{{ moneyFormatForCover(gj.bidamount) }}</td>
  109. <td>{{ gj.signendtime }}</td>
  110. <td>{{ gj.bidopentime }}</td>
  111. <td>{{ gj.bidendtime }}</td>
  112. <td>{{ gj.signaturedate }}</td>
  113. <td>{{ gj.buyer }}</td>
  114. <td>{{ gj.buyerclass }}</td>
  115. <td>{{ textFormatForMosaic(gj.buyerperson) }}</td>
  116. <td>{{ textFormatForMosaic(gj.buyertel) }}</td>
  117. <td>{{ gj.buyeraddr }}</td>
  118. <td>{{ gj.agency }}</td>
  119. <td class="havemore"><tr v-for="( item ,indexs) in gj.s_winnerlist" ><td :class="{'b-none': indexs+1 === gj.s_winnerlist.length}">{{ item }}</td></tr></td>
  120. <td>{{ textFormatForMosaic(gj.winnerperson) }}</td>
  121. <td>{{ textFormatForMosaic(gj.winnertel) }}</td>
  122. <td class="havemore"><tr v-for="( item ,indexs) in gj.legal_person_list" ><td :class="{'b-none': indexs+1 === gj.legal_person_list.length}">{{ textFormatForMosaic(item) || '-'}}</td></tr></td>
  123. <td class="havemore"><tr v-for="( item ,indexs) in gj.company_phone_list" ><td :class="{'b-none': indexs+1 === gj.company_phone_list.length}">{{ textFormatForMosaic(item) || '-' }}</td></tr></td>
  124. <td class="havemore"><tr v-for="( item ,indexs) in gj.company_email_list" ><td :class="{'b-none': indexs+1 === gj.company_email_list.length}">{{ item || '-'}}</td></tr></td>
  125. </tr>
  126. </tbody>
  127. </table>
  128. </div>
  129. </van-tab>
  130. </van-tabs>
  131. <AppEmpty v-else>
  132. <div slot="default">{{ emptyText }}</div>
  133. </AppEmpty>
  134. <van-overlay :show="showMask" z-index="100">
  135. <div class="wrapper">
  136. <span class="loading"></span>
  137. </div>
  138. </van-overlay>
  139. </div>
  140. </template>
  141. <script>
  142. import { Tab, Tabs, Overlay } from 'vant'
  143. import { AppEmpty } from '@/ui'
  144. import { getPreview } from '@/api/modules'
  145. export default {
  146. name: 'previewData',
  147. components: {
  148. [Tab.name]: Tab,
  149. [Tabs.name]: Tabs,
  150. [Overlay.name]: Overlay,
  151. [AppEmpty.name]: AppEmpty
  152. },
  153. data: () => ({
  154. offsetTop: 0,
  155. showMask: true,
  156. active: '1',
  157. emptyText: '',
  158. result: []
  159. }),
  160. created() {
  161. if (this.$route.query.type === 'senior') {
  162. this.active = '2'
  163. this.getPreviewData(2)
  164. } else {
  165. this.active = '1'
  166. this.getPreviewData(1)
  167. }
  168. },
  169. mounted() {
  170. this.getStickyOffset()
  171. },
  172. methods: {
  173. getStickyOffset() {
  174. const header = document.querySelector('.common-app-header')
  175. if (header) {
  176. this.offsetTop = header?.clientHeight || 0
  177. }
  178. },
  179. async getPreviewData(type) {
  180. const params = {
  181. dataType: type,
  182. _id: this.$route.params.id
  183. }
  184. const { res } = await getPreview(params)
  185. if (res) {
  186. this.showMask = false
  187. if (res.data) {
  188. let result = res.data
  189. result.forEach(ele =>{
  190. if (ele.s_winner){
  191. ele.s_winnerlist = ele.s_winner.split(',')
  192. }else{
  193. ele.s_winnerlist = []
  194. }
  195. let company_email_list = []
  196. let company_phone_list = []
  197. let legal_person_list = []
  198. if(ele.winnerMaps && ele.winnerMaps.length > 0){
  199. ele.s_winnerlist.forEach(a =>{
  200. company_email_list.push('')
  201. company_phone_list.push('')
  202. legal_person_list.push('')
  203. })
  204. ele.winnerMaps.forEach(e =>{
  205. company_email_list[ele.s_winnerlist.indexOf(e.company_name)] = e.company_email
  206. company_phone_list[ele.s_winnerlist.indexOf(e.company_name)] = e.company_phone
  207. legal_person_list[ele.s_winnerlist.indexOf(e.company_name)] = e.legal_person
  208. })
  209. }else{
  210. ele.s_winnerlist.forEach(a =>{
  211. company_email_list.push('')
  212. company_phone_list.push('')
  213. legal_person_list.push('')
  214. })
  215. }
  216. ele.company_email_list = company_email_list
  217. ele.company_phone_list = company_phone_list
  218. ele.legal_person_list = legal_person_list
  219. })
  220. this.result = result
  221. } else if (res.msg) {
  222. this.emptyText = '今日已超出预览次数'
  223. } else {
  224. this.emptyText = '暂无数据'
  225. }
  226. }
  227. },
  228. toggle(val) {
  229. this.showMask = true
  230. this.getPreviewData(val)
  231. },
  232. textFormatForMosaic(text, phone) {
  233. if (typeof text === 'string' || typeof text === 'number') {
  234. if (phone) {
  235. return String(text).replace(/([\w\W]*)([\w\W]{4})$/, '$1****')
  236. } else {
  237. return String(text).replace(/^(.)(.*)/, '$1**')
  238. }
  239. }
  240. return text
  241. },
  242. moneyFormatForCover(money) {
  243. if (typeof money === 'string' || typeof money === 'number') {
  244. return String(money).replace(/(\d)(\.){0,1}(\d)/, '$1$2*')
  245. }
  246. return money
  247. }
  248. }
  249. }
  250. </script>
  251. <style scoped lang='scss'>
  252. .havemore{
  253. padding: 0!important;
  254. }
  255. .havemore td{
  256. border-right: none !important;
  257. display: flex;
  258. width: 100%!important;
  259. }
  260. .havemore tr{
  261. display: flex;
  262. width: 100%!important;
  263. background-color: rgba(255, 255, 255, 0) !important;
  264. }
  265. .b-none{
  266. border-bottom: none !important;
  267. }
  268. .previewData {
  269. background: #fff;
  270. .table-container {
  271. flex: 1;
  272. width: 100%;
  273. overflow: scroll;
  274. border-top: 1px solid transparent;
  275. background: #fff;
  276. .table {
  277. height: 100%;
  278. overflow-x: scroll;
  279. position: relative;
  280. margin-bottom: 10px;
  281. background: url(@/assets/image/public/sy.png) repeat;
  282. .thead {
  283. td {
  284. padding: 5px;
  285. height: 35px;
  286. font-size: 12px;
  287. border-top: #DCE1E4 1px solid;
  288. border-right: #DCE1E4 1px solid;
  289. border-bottom: #DCE1E4 1px solid;
  290. white-space: nowrap;
  291. text-align: center;
  292. background-color: #e9f6ff;
  293. }
  294. }
  295. .tbody {
  296. td {
  297. font-size: 10px;
  298. text-align: center;
  299. padding: 5px;
  300. border-right: #DCE1E4 1px solid;
  301. border-bottom: #DCE1E4 1px solid;
  302. }
  303. }
  304. }
  305. .table-bz {
  306. min-width: 2000px;
  307. .tbody {
  308. tr:nth-child(odd) {
  309. background-color: rgba(0, 0, 0, .02);
  310. }
  311. td:nth-child(1) {
  312. width: 2%;
  313. }
  314. td:nth-child(2) {
  315. width: 3%;
  316. }
  317. td:nth-child(3) {
  318. width: 3%;
  319. }
  320. td:nth-child(4) {
  321. width: 10%;
  322. }
  323. tr:nth-child(2) td:nth-child(5) {
  324. width: 4%;
  325. white-space: nowrap;
  326. }
  327. td:nth-child(6) {
  328. width: 5%;
  329. white-space: nowrap;
  330. }
  331. td:nth-child(7) {
  332. width: 12%;
  333. }
  334. td:nth-child(8) {
  335. width: 12%;
  336. }
  337. td:nth-child(9) {
  338. width: 5%;
  339. }
  340. td:nth-child(10) {
  341. width: 12%;
  342. }
  343. td:nth-child(11) {
  344. width: 17%;
  345. }
  346. td:nth-child(12) {
  347. width: 15%;
  348. word-break: break-all;
  349. }
  350. }
  351. }
  352. .table-gj {
  353. min-width: 4020px;
  354. tr:nth-child(odd) {
  355. background-color: rgba(0, 0, 0, .02);
  356. }
  357. td:nth-child(1) {
  358. width: 1%;
  359. }
  360. td:nth-child(2) {
  361. width: 1.5%;
  362. }
  363. td:nth-child(3) {
  364. width: 1%;
  365. white-space: nowrap;
  366. }
  367. td:nth-child(4) {
  368. width: 1%;
  369. white-space: nowrap;
  370. }
  371. td:nth-child(5) {
  372. width: 1%;
  373. }
  374. td:nth-child(6) {
  375. width: 3%;
  376. word-break: break-all;
  377. }
  378. td:nth-child(7) {
  379. width: 1%;
  380. word-break: break-all;
  381. }
  382. td:nth-child(8) {
  383. width: 3.5%;
  384. }
  385. td:nth-child(9) {
  386. width: 1%;
  387. word-break: break-all;
  388. }
  389. td:nth-child(10) {
  390. width: 2.5%;
  391. word-break: break-all;
  392. }
  393. td:nth-child(11) {
  394. width: 2.5%;
  395. word-break: break-all;
  396. }
  397. td:nth-child(12) {
  398. width: 2%;
  399. word-break: break-all;
  400. }
  401. td:nth-child(13) {
  402. width: 1%;
  403. }
  404. td:nth-child(14) {
  405. width: 1.5%;
  406. }
  407. td:nth-child(15) {
  408. width: 1%;
  409. }
  410. td:nth-child(16) {
  411. width: 1%;
  412. }
  413. td:nth-child(17) {
  414. width: 1%;
  415. white-space: nowrap;
  416. }
  417. td:nth-child(18) {
  418. width: 1%;
  419. white-space: nowrap;
  420. }
  421. td:nth-child(19) {
  422. width: 1%;
  423. white-space: nowrap;
  424. }
  425. td:nth-child(20) {
  426. width: 1%;
  427. }
  428. td:nth-child(21) {
  429. width: 1%;
  430. }
  431. td:nth-child(22) {
  432. width: 1%;
  433. }
  434. td:nth-child(23) {
  435. width: 1%;
  436. }
  437. td:nth-child(24) {
  438. width: 1%;
  439. word-break: break-all;
  440. }
  441. td:nth-child(25) {
  442. width: 1%;
  443. }
  444. td:nth-child(26) {
  445. width: 1%;
  446. }
  447. td:nth-child(27) {
  448. width: 1%;
  449. }
  450. td:nth-child(28) {
  451. width: 1%;
  452. }
  453. td:nth-child(29) {
  454. width: 1%;
  455. }
  456. td:nth-child(30) {
  457. width: 1%;
  458. }
  459. }
  460. }
  461. .wrapper {
  462. display: flex;
  463. align-items: center;
  464. justify-content: center;
  465. height: 100%;
  466. .loading {
  467. height: 40px;
  468. width: 40px;
  469. margin: 10px;
  470. border-radius: 50%;
  471. box-shadow: 0 2px 3px rgb(44 183 202 / 80%);
  472. animation: loading_ ease 1s infinite;
  473. }
  474. @keyframes loading_ {
  475. 0% {
  476. transform: rotate(0deg);
  477. }
  478. 100% {
  479. transform: rotate(360deg);
  480. }
  481. }
  482. }
  483. ::v-deep {
  484. .van-tabs__wrap {
  485. height: 50px;
  486. }
  487. .van-tab {
  488. font-size: 18px;
  489. color: #1d1d1d;
  490. }
  491. }
  492. }</style>