index.vue 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581
  1. <template>
  2. <div class="base">
  3. <div class="content">
  4. <div class="words">
  5. <h1>渐进、交互式文档生成</h1>
  6. <p>
  7. 覆盖房地产、土地和各类资产评估报告自动生成。
  8. <br />支持测算表生成和下载,亦可以应用于文档。
  9. <br />用户仅需提交必要评估物数据和测算数据,由平台自动生成商业级评估报告。
  10. </p>
  11. </div>
  12. <div style="display:flex;">
  13. <div class="option" style="display: inline-block">
  14. <div class="create-btn">
  15. <button class="cssbuttons-io-button" @click="goto('house/parent')">
  16. 房地产
  17. <div class="icon">
  18. <svg height="24" width="24" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
  19. <path d="M0 0h24v24H0z" fill="none" />
  20. <path d="M16.172 11l-5.364-5.364 1.414-1.414L20 12l-7.778 7.778-1.414-1.414L16.172 13H4v-2z" fill="currentColor" />
  21. </svg>
  22. </div>
  23. </button>
  24. <button class="cssbuttons-io-button" @click="goto('assets/parent')">
  25. 资产
  26. <div class="icon">
  27. <svg height="24" width="24" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
  28. <path d="M0 0h24v24H0z" fill="none" />
  29. <path d="M16.172 11l-5.364-5.364 1.414-1.414L20 12l-7.778 7.778-1.414-1.414L16.172 13H4v-2z" fill="currentColor" />
  30. </svg>
  31. </div>
  32. </button>
  33. <button class="cssbuttons-io-button" @click="goto('planning')">
  34. 土地
  35. <div class="icon">
  36. <svg height="24" width="24" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
  37. <path d="M0 0h24v24H0z" fill="none" />
  38. <path d="M16.172 11l-5.364-5.364 1.414-1.414L20 12l-7.778 7.778-1.414-1.414L16.172 13H4v-2z" fill="currentColor" />
  39. </svg>
  40. </div>
  41. </button>
  42. </div>
  43. <div class="example-list" style="min-height:500px;">
  44. <div class="input-container">
  45. <el-input v-model="listQuery.docName" style="max-width: 300px; margin-bottom: 10px;" placeholder="关键字搜索" class="input-with-select">
  46. <template #append>
  47. <el-button type="primary" @click="getDocuments()">
  48. <el-icon color="#ff6154">
  49. <Search />
  50. </el-icon>
  51. </el-button>
  52. </template>
  53. </el-input>
  54. </div>
  55. <div class="dayChoice_div">
  56. <el-button link style="border:0;width:10px;margin-right: 10px;" @click="activeBtn--, choiceDay(activeBtn)" :disabled="activeBtn <= 0">
  57. <el-icon>
  58. <Back />
  59. </el-icon>
  60. </el-button>
  61. <el-button v-for="(item, index) in days" :key="index" text :class="{ show: index === activeBtn }" style="border:0;width:10px;margin:0" @click="choiceDay(index)">{{ item.id }}</el-button>
  62. <el-button link style="border:0;width:10px" @click="activeBtn++, choiceDay(activeBtn)" :disabled="activeBtn >= (days.length - 1)">
  63. <el-icon>
  64. <Right />
  65. </el-icon>
  66. </el-button>
  67. </div>
  68. <el-card class="report-item no-border" shadow="never" v-for="(doc, id) in page" v-if="page !== null && page.length !== 0">
  69. <div class="report-icon">
  70. <img :src="docLog(doc.docType)" style="width: 52px; height: 52px;" />
  71. </div>
  72. <div class="report-text">
  73. <div>
  74. <span class="report-text-type">{{ doc.businessType + doc.businessCate + '【' + doc.docNo + '】' }}</span>
  75. <span>一</span>
  76. <span class="report-text-name">{{ doc.docName }}</span>
  77. </div>
  78. <div style="padding-top: 5px;">
  79. <span>
  80. <el-icon>
  81. <Avatar />
  82. </el-icon>
  83. {{ doc.consignor }}
  84. </span>
  85. <span>
  86. <el-tag style="margin-left: 5px;">{{ doc.businessType }}</el-tag>
  87. <el-tag style="margin-left: 5px;" type="success">{{ doc.businessCate }}</el-tag>
  88. </span>
  89. <span style="float: right; color:darkgrey">{{ doc.updateTime }}</span>
  90. </div>
  91. </div>
  92. <div class="report-button" @click="downloadFile(doc.docUrl, doc.docName)">
  93. <el-icon>
  94. <Download />
  95. </el-icon>
  96. </div>
  97. </el-card>
  98. <div class="null-div" v-if="page === null || page.length == 0">
  99. <img src="../../assets/icons/null.png" style="width: 128px; height: 128px;" />
  100. <div>
  101. <span>还没有项目</span>
  102. </div>
  103. </div>
  104. </div>
  105. </div>
  106. <el-tree
  107. ref="treeDataYear"
  108. style="width: 300px;display: inline-block;margin-top: 10px;margin-left:20px"
  109. :data="treeDataYear"
  110. accordion
  111. node-key="id"
  112. highlight-current
  113. :default-expanded-keys="[1]"
  114. :default-checked-keys="[101]"
  115. icon="none"
  116. :check-on-click-node="true"
  117. @node-click="nodeClick"
  118. />
  119. </div>
  120. <div class="pagination" v-if="page !== null && page.length !== 0">
  121. <el-pagination background layout="prev, pager, next" style="--el-color-primary: #ff6154" :page-count="listQuery.pages" v-model:current-page="listQuery.current" @current-change="getDocuments" />
  122. </div>
  123. </div>
  124. </div>
  125. </template>
  126. <script>
  127. import { loginByOAInfo } from '@/api/user'
  128. import { setToken, getToken } from '@/utils/auth'
  129. import { mapStores } from 'pinia'
  130. import { useUserStore } from '@/stores/useUserStore'
  131. import documentProduction from '@/api/documentProduction'
  132. import wordLog from '../../assets/icons/word.png'
  133. import excelLog from '../../assets/icons/excel.png'
  134. import folderLog from '../../assets/icons/folder.png'
  135. import fileUtil from '@/utils/file'
  136. export default {
  137. data() {
  138. return {
  139. activeBtn: 0,
  140. days: [],
  141. treeDataYear: [],
  142. page: [],
  143. listQuery: {
  144. current: 1,
  145. size: 10,
  146. pages: null,
  147. total: null,
  148. createDate: null,
  149. docName: null,
  150. },
  151. }
  152. },
  153. mounted() {
  154. // 使用$nextTick 等页面加载完毕之后,再选中tree组件默认节点,防止加载顺序问题
  155. this.$nextTick(function () {
  156. // 这行会生效
  157. let childrenIndex = 0
  158. // 默认拿当前月份
  159. switch (new Date().getMonth() + 1) {
  160. case 12:
  161. childrenIndex = 0
  162. break
  163. case 11:
  164. childrenIndex = 1
  165. break
  166. case 10:
  167. childrenIndex = 2
  168. break
  169. case 9:
  170. childrenIndex = 3
  171. break
  172. case 8:
  173. childrenIndex = 4
  174. break
  175. case 7:
  176. childrenIndex = 5
  177. break
  178. case 6:
  179. childrenIndex = 6
  180. break
  181. case 5:
  182. childrenIndex = 7
  183. break
  184. case 4:
  185. childrenIndex = 8
  186. break
  187. case 3:
  188. childrenIndex = 9
  189. break
  190. case 2:
  191. childrenIndex = 10
  192. break
  193. case 1:
  194. childrenIndex = 11
  195. break
  196. }
  197. this.$refs.treeDataYear.setCurrentKey(this.treeDataYear[0].children[childrenIndex].id)
  198. this.setDay(this.$refs.treeDataYear.getCurrentNode())
  199. })
  200. },
  201. computed: {
  202. // 非setup语法,需要使用mapStores()才能访问
  203. // 直接放在生命周期函数也可以访问,但是似乎会导致持久化失效,没找到解决办法,建议还是用mapStores
  204. // 名字会变成id + 'Store' 的形式,比如id本来是user,那么这种方式使用就需要变成this.userStore.xxx
  205. ...mapStores(useUserStore),
  206. },
  207. created() {
  208. this.login()
  209. // this.getDocuments();
  210. this.setYearMonth()
  211. },
  212. methods: {
  213. nodeClick(node) {
  214. this.setDay(node)
  215. },
  216. choiceDay(index) {
  217. this.activeBtn = index
  218. this.listQuery.createDate = this.days[index].date
  219. this.getDocuments()
  220. },
  221. // 设置横向的天数
  222. setDay(node) {
  223. this.days = []
  224. if (node.year) {
  225. // 计算是平年还是闰年
  226. let dayLength = 31
  227. if ((node.year % 4 === 0 && node.year % 100 !== 0) || node.year % 400 === 0) {
  228. // 闰年且二月
  229. if (node.month === 2) {
  230. dayLength = 28
  231. } else if ([1, 3, 5, 7, 8, 10, 12].includes(node.month)) {
  232. dayLength = 31
  233. } else {
  234. dayLength = 30
  235. }
  236. } else {
  237. if (node.month === 2) {
  238. dayLength = 29
  239. } else if ([1, 3, 5, 7, 8, 10, 12].includes(node.month)) {
  240. dayLength = 31
  241. } else {
  242. dayLength = 30
  243. }
  244. }
  245. for (let index = 1; index <= dayLength; index++) {
  246. this.days.push({ id: index, date: node.year + '-' + node.month + '-' + index })
  247. }
  248. }
  249. // 默认选中当前月的第一天
  250. this.choiceDay(0)
  251. },
  252. // 设置tree组件节点
  253. setYearMonth() {
  254. const currentYear = new Date().getFullYear() // 获取当前年份
  255. let idVal = 100
  256. for (let i = 0; i < 10; i++) {
  257. const month = [
  258. {
  259. id: null,
  260. label: '十二月',
  261. year: null,
  262. month: null,
  263. },
  264. {
  265. id: null,
  266. label: '十一月',
  267. year: null,
  268. month: null,
  269. },
  270. {
  271. id: null,
  272. label: '十月',
  273. year: null,
  274. month: null,
  275. },
  276. {
  277. id: null,
  278. label: '九月',
  279. year: null,
  280. month: null,
  281. },
  282. {
  283. id: null,
  284. label: '八月',
  285. year: null,
  286. month: null,
  287. },
  288. {
  289. id: null,
  290. label: '七月',
  291. year: null,
  292. month: null,
  293. },
  294. {
  295. id: null,
  296. label: '六月',
  297. year: null,
  298. month: null,
  299. },
  300. {
  301. id: null,
  302. label: '五月',
  303. year: null,
  304. month: null,
  305. },
  306. {
  307. id: null,
  308. label: '四月',
  309. year: null,
  310. month: null,
  311. },
  312. {
  313. id: null,
  314. label: '三月',
  315. year: null,
  316. month: null,
  317. },
  318. {
  319. id: null,
  320. label: '二月',
  321. year: null,
  322. month: null,
  323. },
  324. {
  325. id: null,
  326. label: '一月',
  327. year: null,
  328. month: null,
  329. },
  330. ]
  331. let m = 12
  332. for (let n = 1; n <= month.length; n++) {
  333. // 设置id
  334. month[n - 1].id = n + idVal
  335. // 设置节点的年月
  336. month[n - 1].year = currentYear - i
  337. month[n - 1].month = m--
  338. }
  339. this.treeDataYear.push({ id: i + 1, label: currentYear - i, children: month })
  340. idVal = idVal + 100
  341. }
  342. },
  343. goto(path) {
  344. this.$router.push(`/home/${path}`)
  345. },
  346. login() {
  347. // 如果路由上带了token,说明是从oa刚跳转过来,需要进行登录
  348. // 解析url获取token
  349. var url = window.location.href //获取当前url
  350. var dz_url = url.split('#')[0] //获取#之前的字符串
  351. var cs = url.split('?')[1] //获取?之后的参数字符串
  352. // 判断参数是否为空
  353. if (cs) {
  354. var cs_arr = cs.split('&') //参数字符串分割为数组
  355. var params = {}
  356. for (var i = 0; i < cs_arr.length; i++) {
  357. //遍历数组,拿到json对象
  358. params[cs_arr[i].split('=')[0]] = cs_arr[i].split('=')[1]
  359. }
  360. let token = params.token
  361. if (token) {
  362. loginByOAInfo(token).then((res) => {
  363. setToken(res.data.tokenValue)
  364. this.userStore.setUserInfo(res.data)
  365. // 登录成功,重新跳转到主页
  366. this.$router.push(`/home/index`)
  367. })
  368. }
  369. }
  370. },
  371. getDocuments() {
  372. documentProduction.page(this.listQuery).then((res) => {
  373. if (res.code === 200) {
  374. this.page = res.data.records
  375. this.listQuery.pages = res.data.pages
  376. }
  377. })
  378. },
  379. docLog(docType) {
  380. switch (docType) {
  381. case 'CALCULATE_TABLE':
  382. return excelLog
  383. case 'FOLDER':
  384. return folderLog
  385. default:
  386. return wordLog
  387. }
  388. },
  389. // 下载文件
  390. downloadFile(docUrl, docName) {
  391. if (docUrl && docName) {
  392. let downloadUrl = '/file/download?fileDiskPath=' + docUrl + '&fileName=' + docName
  393. fileUtil.download(downloadUrl)
  394. } else {
  395. ElMessage({
  396. showClose: true,
  397. message: '文档还未生成,请完成生成步骤!',
  398. type: 'warning',
  399. })
  400. }
  401. },
  402. },
  403. }
  404. </script>
  405. <style scoped>
  406. :deep(.el-input__wrapper.is-focus) {
  407. --el-input-focus-border: #ff6154;
  408. --el-input-focus-border-color: #ff6154;
  409. }
  410. :deep(.el-button--text:hover) {
  411. color: #ff6154;
  412. }
  413. :deep(.el-button--text) {
  414. color: #ff6154;
  415. }
  416. .input-container {
  417. display: flex; /* 使用 Flexbox 布局 */
  418. justify-content: flex-end; /* 右对齐 */
  419. }
  420. .show {
  421. color: #ff6154;
  422. background-color: #fdf0ee;
  423. }
  424. .dayChoice_div {
  425. height: 45px;
  426. /* 灰色边框线 */
  427. border: 1px solid #cccccc;
  428. /* 圆角 */
  429. border-radius: 10px;
  430. line-height: 38px;
  431. text-align: center;
  432. padding-left: 10px;
  433. padding-right: 10px;
  434. margin-bottom: 20px;
  435. }
  436. .base {
  437. min-height: calc(100vh - 80px);
  438. width: 100%;
  439. }
  440. /* .content { */
  441. /* margin-left: 160px; */
  442. /* margin-right: 160px; */
  443. /* padding: 50px 20px 20px 20px; */
  444. /* } */
  445. .words {
  446. padding: 70px 20px 20px 20px;
  447. background: linear-gradient(180deg, transparent, hsla(0, 0%, 95%, 0.29) 47.39%, #fff),
  448. linear-gradient(90deg, #f9ddf1 0.07%, #e5e1ff 16.73%, #daedff 34.48%, #e2f4e3 49.98%, #ebf5d8 66.12%, #faf2da 81.95%, #fbe5d8 99.9%);
  449. }
  450. h1 {
  451. margin-left: 160px;
  452. font-size: 50px;
  453. font-weight: 400;
  454. }
  455. p {
  456. margin-left: 160px;
  457. font-size: 20px;
  458. letter-spacing: 1px;
  459. margin-top: 20px;
  460. }
  461. .option {
  462. width: 58.5%;
  463. margin-top: 10px;
  464. margin-left: 160px;
  465. border-right: 1.5px #dae1eb solid;
  466. padding: 0px 20px 20px 20px;
  467. }
  468. .create-btn {
  469. height: 50px;
  470. }
  471. /* From Uiverse.io by adamgiebl */
  472. .cssbuttons-io-button {
  473. background: #ff6154;
  474. color: white;
  475. padding: 0.35em;
  476. padding-left: 1.2em;
  477. font-size: 20px;
  478. font-weight: 400;
  479. border-radius: 0.3em;
  480. border: none;
  481. letter-spacing: 0.05em;
  482. display: flex;
  483. align-items: center;
  484. box-shadow: inset 0 0 1.6em -0.6em #ff6154;
  485. overflow: hidden;
  486. position: relative;
  487. height: 2.7em;
  488. padding-right: 3.3em;
  489. cursor: pointer;
  490. margin-right: 20px;
  491. float: left;
  492. width: 8em;
  493. }
  494. .cssbuttons-io-button .icon {
  495. background: white;
  496. margin-left: 1em;
  497. position: absolute;
  498. display: flex;
  499. align-items: center;
  500. justify-content: center;
  501. height: 2.2em;
  502. width: 2.2em;
  503. border-radius: 0.3em;
  504. box-shadow: 0.1em 0.1em 0.6em 0.2em #ff6154;
  505. right: 0.3em;
  506. transition: all 0.3s;
  507. }
  508. .cssbuttons-io-button:hover .icon {
  509. width: calc(100% - 0.6em);
  510. }
  511. .cssbuttons-io-button .icon svg {
  512. width: 1.1em;
  513. transition: transform 0.3s;
  514. color: #ff6154;
  515. }
  516. .cssbuttons-io-button:hover .icon svg {
  517. transform: translateX(0.1em);
  518. }
  519. .cssbuttons-io-button:active .icon {
  520. transform: scale(0.95);
  521. }
  522. .no-border {
  523. border: none;
  524. border-radius: 0.6em;
  525. }
  526. .pagination {
  527. margin-top: 10px;
  528. margin-left: 160px;
  529. width: 58.5%;
  530. justify-content: center;
  531. display: flex;
  532. }
  533. :deep(.el-tree-node__content:hover) {
  534. border-radius: 5px;
  535. color: #ff6154;
  536. background-color: #fdf0ee !important;
  537. }
  538. :deep(v-deep .el-tree-node.is-current > .el-tree-node__content) {
  539. margin: 5px;
  540. border-radius: 5px;
  541. color: #ff6154;
  542. background-color: #fdf0ee !important;
  543. }
  544. :deep(.el-tree--highlight-current .el-tree-node.is-current > .el-tree-node__content) {
  545. border-radius: 5px;
  546. color: #ff6154;
  547. background-color: #fdf0ee !important;
  548. }
  549. .null-div {
  550. width: 100%;
  551. height: 100%;
  552. text-align: center;
  553. margin-top: 20%;
  554. color: var(--vt-c-text-light-2);
  555. }
  556. </style>