index.vue 34 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058
  1. <template>
  2. <div class="list">
  3. <div class="list-head">
  4. <div class="list-head-search">
  5. <div class="left-select __hover" @click.stop="ref_area.togglePopperVisible(true)">
  6. 搜索范围<SvgIcon name="arrow_1" rotate="90" size="14" color="var(--cus-text-color-3)"/>
  7. <el-cascader ref="ref_area" class="area-cascader" v-model="state.cascaderParams.value" :props="state.cascaderParams.props" :options="state.cascaderParams.options"/>
  8. </div>
  9. <el-input v-model="state.searchText" placeholder="请输入关键字进行查询" @keyup.enter="onSearch"/>
  10. <div class="right-icon __hover" @click="onSearch">
  11. <SvgIcon name="search_1" color="var(--cus-main-color)" size="40"/>
  12. </div>
  13. </div>
  14. <div class="list-head-user">
  15. <div class="avatar">
  16. <img src="@/assets/images/web/web-list_avatar.png"/>
  17. </div>
  18. 用户名
  19. </div>
  20. </div>
  21. <div class="count-percent" v-if="state.ws.countPercent < 100">
  22. <div class="bar-bg"><div class="bar-block" :style="{width: state.ws.countPercent + '%'}"/></div>
  23. 已加载{{state.ws.countPercent}}%
  24. </div>
  25. <div class="list-content" :style="{
  26. paddingTop: state.ws.countPercent == 100 ? '24px' : 0
  27. }">
  28. <div class="list-filter">
  29. <div class="label">检索条件:</div>
  30. <div class="value">
  31. <template v-if="isSelectAllCpt || !state.cascaderParams.value.length">
  32. <div class="filter-item">全部</div>
  33. </template>
  34. <template v-else>
  35. <template v-for="(item, index) in state.cascaderParams.value">
  36. <div class="filter-item">
  37. {{ WebStore.searchAreaTypeMap.get(item) }}
  38. <SvgIcon class="__hover" name="close_1" size="10" color="var(--cus-text-color-3)" @click="onDelFilter(index)"/>
  39. </div>
  40. </template>
  41. </template>
  42. </div>
  43. </div>
  44. <div class="list-tab">
  45. <template v-for="item in state.resultParams.tree">
  46. <div class="list-tab-item __hover" :class="{active: item.treeId === state.resultParams.activeTab}" @click="state.resultParams.activeTab = item.treeId" v-if="item.__count > 0">
  47. {{item.treeName}}<span class="total">({{ item.__count }})</span>
  48. </div>
  49. </template>
  50. </div>
  51. <div class="list-result" v-if="state.resultParams.activeTab">
  52. <div class="list-result-tree">
  53. <template v-for="item in state.resultParams.tree.filter(v => v.treeId === state.resultParams.activeTab)[0].children">
  54. <div class="list-result-tree-item" v-if="item.__count > 0">
  55. <div class="item-parent __hover" @click="item.__expend = !item.__expend">
  56. <SvgIcon class="flag" name="flag_1" color="var(--cus-main-color)"/>
  57. {{item.treeName}}
  58. <span class="total">({{item.__count}})</span>
  59. <SvgIcon class="expend" name="arrow_1" :rotate="item.__expend ? -90 : 90" color="var(--cus-text-color-4)"/>
  60. </div>
  61. <template v-if="item.__expend">
  62. <template v-for="son in item.children">
  63. <div class="item-son __hover" :class="{active: son.treeId === state.resultParams.activeIndex}" @click="state.resultParams.activeIndex = son.treeId" v-if="son.__count > 0">
  64. {{son.treeName}}<span class="total">({{son.__count}})</span>
  65. </div>
  66. </template>
  67. </template>
  68. </div>
  69. </template>
  70. </div>
  71. <div class="list-result-table">
  72. <div class="table-head">
  73. <div class="table-head-index">
  74. <SvgIcon class="flag" name="flag_1" color="var(--cus-main-color)"/>
  75. {{currentIndexCpt.treeName}}
  76. <span class="total">({{currentIndexCpt.__count}})</span>
  77. </div>
  78. <div class="table-head-infos">
  79. <div class="main">
  80. <img src="@/assets/images/web/wen-list_table-head-icon-1.png"/>
  81. <div class="one">
  82. <div>更新时间:</div>
  83. <div>{{ state.resultParams.indexConfig?.updateTime }}</div>
  84. <div>接入时间:</div>
  85. <div>{{ state.resultParams.indexConfig?.createTime }}</div>
  86. </div>
  87. <div>
  88. <div>共享方式:</div>
  89. <div>{{ state.resultParams.indexConfig?.shareMethod }}</div>
  90. <div>更新周期:</div>
  91. <div>{{ state.resultParams.indexConfig?.updateCycle }}</div>
  92. </div>
  93. </div>
  94. <div class="info">
  95. <img src="@/assets/images/web/wen-list_table-head-icon-2.png"/>
  96. <div>
  97. <div>数据共享来源</div>
  98. <div>{{ state.resultParams.indexConfig?.dataShareSource }}</div>
  99. </div>
  100. </div>
  101. <div class="info">
  102. <img src="@/assets/images/web/wen-list_table-head-icon-3.png"/>
  103. <div>
  104. <div>数据提供来源</div>
  105. <div>{{ state.resultParams.indexConfig?.dataProvideSource }}</div>
  106. </div>
  107. </div>
  108. <div class="info">
  109. <img src="@/assets/images/web/wen-list_table-head-icon-4.png"/>
  110. <div>
  111. <div>数据量</div>
  112. <div>{{ state.resultParams.indexConfig?.dataTotal }}<span>条</span></div>
  113. </div>
  114. </div>
  115. </div>
  116. </div>
  117. <div class="table-switch" v-if="tableConfigCpt.hasCard">
  118. <div class="__hover" :class="{active: state.tableParams.model === 'list'}" @click="state.tableParams.model = 'list'">
  119. <SvgIcon name="list_1" size="16" :color="state.tableParams.model === 'list' ? '#ffffff' : 'var(--cus-text-color-3)'"/>
  120. </div>
  121. <div class="__hover" :class="{active: state.tableParams.model === 'card'}" @click="state.tableParams.model = 'card'">
  122. <SvgIcon name="card_1" size="16" :color="state.tableParams.model === 'card' ? '#ffffff' : 'var(--cus-text-color-3)'"/>
  123. </div>
  124. </div>
  125. <div class="table-content" v-loading="state.tableParams.loading">
  126. <div class="table-content-result">
  127. <div class="table-list" v-if="state.tableParams.model === 'list'">
  128. <template v-for="(item, index) in state.tableParams.data">
  129. <div class="list-item __hover">
  130. <div class="index">{{index + 1 + (state.tableParams.pageNum - 1) * state.tableParams.pageSize }}</div>
  131. <div class="cols" :style="{
  132. gridTemplateColumns: `repeat(${tableConfigCpt.listCol}, 1fr)`
  133. }">
  134. <template v-for="c in tableConfigCpt.listConfig">
  135. <div class="cols-item" :style="{
  136. gridColumn: `span ${c.col}`
  137. }">
  138. <div class="cols-item-label">{{c.key}}:</div>
  139. <div class="cols-item-value" v-html="item[c.value]"/>
  140. </div>
  141. </template>
  142. </div>
  143. <div class="operation">
  144. <div class="__hover">
  145. <SvgIcon name="detail_1" color="var(--cus-main-color)"/>详情
  146. </div>
  147. <div class="__hover">
  148. <SvgIcon name="archives_1" color="var(--cus-main-color)"/>档案
  149. </div>
  150. </div>
  151. </div>
  152. </template>
  153. </div>
  154. <div class="table-card" v-if="state.tableParams.model === 'card'" :style="{
  155. gridTemplateColumns: `repeat(${tableConfigCpt.cardLayout}, 1fr)`
  156. }">
  157. <template v-for="(item, index) in state.tableParams.data">
  158. <div class="card-item __hover">
  159. <div class="main-row">
  160. <template v-if="tableConfigCpt?.cardImg.value">
  161. <div class="main-row-img">
  162. <el-image
  163. :src="item[tableConfigCpt?.cardImg.value]"
  164. :zoom-rate="1.2"
  165. :max-scale="7"
  166. :min-scale="0.2"
  167. :preview-src-list="[item[tableConfigCpt?.cardImg.value]]"
  168. :preview-teleported="true"
  169. />
  170. </div>
  171. </template>
  172. <div class="main-row-param" v-html="item[tableConfigCpt.cardMain.value]"/>
  173. <div class="main-row-operation">
  174. <div class="__hover">
  175. <SvgIcon name="detail_1" color="var(--cus-main-color)"/>详情
  176. </div>
  177. <div class="__hover">
  178. <SvgIcon name="archives_1" color="var(--cus-main-color)"/>档案
  179. </div>
  180. </div>
  181. </div>
  182. <div class="cols" :style="{
  183. gridTemplateColumns: `repeat(${tableConfigCpt.cardCol}, 1fr)`
  184. }">
  185. <template v-for="c in tableConfigCpt.cardConfig">
  186. <div class="cols-item" :style="{
  187. gridColumn: `span ${c.col}`
  188. }">
  189. <div class="cols-item-label">{{c.key}}:</div>
  190. <div class="cols-item-value" v-html="item[c.value]"/>
  191. </div>
  192. </template>
  193. </div>
  194. </div>
  195. </template>
  196. </div>
  197. </div>
  198. <div class="table-content-page">
  199. <CusPage
  200. :page-num="state.tableParams.pageNum"
  201. :page-size="state.tableParams.pageSize"
  202. :total="state.tableParams.total"
  203. @page="onPage"
  204. />
  205. </div>
  206. </div>
  207. </div>
  208. </div>
  209. </div>
  210. </div>
  211. </template>
  212. <script setup lang="ts">
  213. import {computed, getCurrentInstance, onBeforeMount, onMounted, reactive, ref, watch} from "vue";
  214. import {useRoute, useRouter} from "vue-router";
  215. import {useWebStore} from "@/stores";
  216. import {ElLoading} from "element-plus";
  217. const {proxy} = getCurrentInstance()
  218. const WebStore = useWebStore()
  219. const route = useRoute()
  220. const router = useRouter()
  221. const state: any = reactive({
  222. searchText: '',
  223. cascaderParams: {
  224. value: [],
  225. props: {
  226. label: 'treeName',
  227. value: 'treeId',
  228. multiple: true,
  229. emitPath: false
  230. },
  231. show: false,
  232. options: []
  233. },
  234. searchParams: {
  235. text: '',
  236. indexKey: []
  237. },
  238. resultParams: {
  239. tree: [],
  240. activeTab: '',
  241. activeIndex: '',
  242. indexConfig: {}
  243. },
  244. ws: {
  245. count: () => {},
  246. list: () => {},
  247. countPercent: 100
  248. },
  249. tableParams: {
  250. model: 'list',
  251. pageNum: 1,
  252. pageSize: 10,
  253. total: 0,
  254. data: [],
  255. loading: false
  256. }
  257. })
  258. const ref_area = ref()
  259. const isSelectAllCpt = computed(() => {
  260. return WebStore.searchAreaIndexTotal === state.cascaderParams.value.length
  261. })
  262. const currentIndexCpt = computed(() => {
  263. let obj = {}
  264. state.resultParams.tree.forEach(v => {
  265. v.children.forEach(c => {
  266. c.children.forEach(s => {
  267. if (s.treeId === state.resultParams.activeIndex) {
  268. obj = s
  269. }
  270. })
  271. })
  272. })
  273. return JSON.parse(JSON.stringify(obj))
  274. })
  275. const tableConfigCpt = computed(() => {
  276. return {
  277. listCol: 5,
  278. listConfig: [
  279. {key: '姓名', value: 'name', col: 3},
  280. {key: '性别', value: 'sex', col: 1},
  281. {key: '出生日期', value: 'a', col: 1},
  282. {key: '出生日期1', value: 'a', col: 1},
  283. {key: '出生日期2', value: 'a', col: 3},
  284. {key: '出生日期3', value: 'a', col: 1},
  285. {key: '出生日期4', value: 'a', col: 1},
  286. {key: '出生日期5', value: 'a', col: 1},
  287. {key: '出生日期6', value: 'a', col: 1},
  288. {key: '出生日期7', value: 'a', col: 1},
  289. {key: '出生日期8', value: 'a', col: 1},
  290. {key: '出生日期9', value: 'a', col: 1},
  291. ],
  292. hasCard: true,
  293. cardLayout: 3,
  294. cardCol: 2,
  295. cardMain: {key: '姓名', value: 'name', col: 1},
  296. cardImg: {key: '头像', value: 'avatar', isImg: true},
  297. cardConfig: [
  298. {key: '性别', value: 'sex', col: 1},
  299. {key: '出生日期', value: 'a', col: 2},
  300. {key: '出生日期1', value: 'a', col: 1},
  301. {key: '出生日期2', value: 'a', col: 1},
  302. {key: '出生日期3', value: 'a', col: 1},
  303. {key: '出生日期4', value: 'a', col: 1},
  304. {key: '出生日期5', value: 'a', col: 1},
  305. {key: '出生日期6', value: 'a', col: 1},
  306. ]
  307. }
  308. })
  309. const initArea = () => {
  310. WebStore.getSearchAreaTree().then(res => {
  311. const arr = []
  312. JSON.parse(JSON.stringify(res)).forEach(v => {
  313. v.children.forEach(c => {
  314. c.__children = JSON.parse(JSON.stringify(c.children))
  315. c.children = []
  316. })
  317. arr.push(v)
  318. })
  319. state.cascaderParams.options = arr
  320. onSearch()
  321. })
  322. }
  323. const onDelFilter = (index) => {
  324. const temp = JSON.parse(JSON.stringify(state.cascaderParams.value))
  325. temp.splice(index, 1)
  326. state.cascaderParams.value = temp
  327. }
  328. const onSearch = () => {
  329. state.searchParams = JSON.parse(JSON.stringify({
  330. text: state.searchText,
  331. indexKey: state.cascaderParams.value
  332. }))
  333. initResultTree()
  334. }
  335. const initResultTree = () => {
  336. state.resultParams.activeTab = ''
  337. state.resultParams.activeIndex = ''
  338. const arr = []
  339. WebStore.searchAreaTree.forEach(v => {
  340. const t = {
  341. ...v,
  342. children: []
  343. }
  344. v.children?.forEach(c => {
  345. if (state.searchParams.indexKey.includes(c.treeId)) {
  346. t.children.push(c)
  347. }
  348. })
  349. if (t.children.length > 0) {
  350. arr.push(t)
  351. }
  352. })
  353. if (arr.length > 0) {
  354. state.resultParams.tree = JSON.parse(JSON.stringify(arr))
  355. } else {
  356. state.resultParams.tree = JSON.parse(JSON.stringify(WebStore.searchAreaTree))
  357. }
  358. state.ws.count()
  359. }
  360. const getIndexConfig = () => {
  361. state.resultParams.indexConfig = {}
  362. setTimeout(() => {
  363. state.resultParams.indexConfig = {
  364. updateTime: '2024-09-09 14:20:20',
  365. createTime: '2024-09-09 14:20:20',
  366. shareMethod: '数据库表',
  367. updateCycle: 'T+1',
  368. dataShareSource: '海南省大数据管理局',
  369. dataProvideSource: '海南省大数据管理局',
  370. dataTotal: '9125815819',
  371. }
  372. state.ws.list()
  373. },500)
  374. }
  375. const onPage = (pageNum, pageSize) => {
  376. state.tableParams.pageNum = pageNum
  377. state.tableParams.pageSize = pageSize
  378. state.ws.list(false)
  379. }
  380. watch(() => state.resultParams.activeIndex, (n) => {
  381. if (n) {
  382. getIndexConfig()
  383. }
  384. })
  385. onMounted(() => {
  386. const {text, index} = route.query
  387. if (!text) {
  388. router.replace({
  389. name: '71305311-abcc-4d13-8531-f966b49839c5'
  390. })
  391. } else {
  392. state.searchText = text
  393. if (index) {
  394. state.cascaderParams.value = index.split(',')
  395. }
  396. const ws: any = new WebSocket('ws://localhost:18375')
  397. let sessionId = ''
  398. let timestamp = new Date().getTime()
  399. let lastCountParams = ''
  400. let lastCountStep = 0
  401. let lastCountStep_ = 0
  402. let lastListParams = ''
  403. ws.onopen = (e) => {
  404. state.ws.count = () => {
  405. state.ws.countPercent = 0
  406. // 如果有的话,终止上一次请求
  407. if (lastCountParams) {
  408. const p = JSON.parse(lastCountParams)
  409. p.flag = 'stop'
  410. ws.send(JSON.stringify(p))
  411. }
  412. // 如果有的话,终止上一次请求
  413. if (lastListParams) {
  414. const p = JSON.parse(lastListParams)
  415. p.flag = 'stop'
  416. ws.send(JSON.stringify(p))
  417. lastListParams = ''
  418. }
  419. // 执行新的请求
  420. let step = 0
  421. const builder = state.resultParams.tree.map(tag => ({
  422. tagCode: tag.treeId,
  423. datas: tag.children.map(type => {
  424. step++
  425. return {
  426. typeCode: type.treeId,
  427. datas: type.children.map(index => ({
  428. indexCode: index.treeId,
  429. datas: []
  430. }))
  431. }
  432. })
  433. }))
  434. lastCountStep = step
  435. lastCountStep_ = step
  436. timestamp = new Date().getTime()
  437. const params = {
  438. builder: builder,
  439. keyData: state.searchParams.text,
  440. type: 'count',
  441. sessionId: sessionId,
  442. timestamp: timestamp,
  443. flag: 'run',
  444. orderBy: {}
  445. }
  446. lastCountParams = JSON.stringify(params)
  447. ws.send(lastCountParams)
  448. }
  449. state.ws.list = (init = true) => {
  450. // 如果有的话,终止上一次请求
  451. if (lastListParams) {
  452. const p = JSON.parse(lastListParams)
  453. p.flag = 'stop'
  454. ws.send(JSON.stringify(p))
  455. lastListParams = ''
  456. }
  457. if (init) {
  458. state.tableParams = {
  459. model: 'list',
  460. pageNum: 1,
  461. pageSize: 10,
  462. total: 0,
  463. data: [],
  464. loading: true
  465. }
  466. }
  467. const params = {
  468. keyData: state.searchParams.text,
  469. pageNumber: state.tableParams.pageNum,
  470. pageSize: state.tableParams.pageSize,
  471. indexCode: state.resultParams.activeIndex,
  472. type: 'list',
  473. sessionId: sessionId,
  474. timestamp: timestamp,
  475. flag: 'run',
  476. orderBy: {}
  477. }
  478. lastCountParams = JSON.stringify(params)
  479. ws.send(lastCountParams)
  480. }
  481. }
  482. ws.onmessage = (e) => {
  483. try {
  484. const json = JSON.parse(e.data)
  485. if (typeof json === 'string') {
  486. sessionId = json
  487. initArea()
  488. } else {
  489. switch (json.type) {
  490. case 'count': {
  491. const p = JSON.parse(lastCountParams)
  492. // 返回为最新批次的
  493. if (json.timestamp == p.timestamp) {
  494. const resTag = json.datas[0]
  495. const resType = resTag.datas[0]
  496. state.resultParams.tree.forEach(tag => {
  497. if (tag.treeId == resTag.tagCode) {
  498. tag.children.forEach(type => {
  499. if (type.treeId == resType.typeCode) {
  500. resType.datas.forEach((index, indexI) => {
  501. type.children[indexI].__count = index.data
  502. type.__count = type.__count ? (type.__count + index.data) : index.data
  503. tag.__count = tag.__count ? (tag.__count + index.data) : index.data
  504. })
  505. }
  506. })
  507. }
  508. })
  509. for (let tagI = 0; tagI < state.resultParams.tree.length; tagI++) {
  510. const tag = state.resultParams.tree[tagI]
  511. if (tag.__count > 0 && !state.resultParams.activeTab) {
  512. state.resultParams.activeTab = tag.treeId
  513. for (let typeI = 0; typeI < tag.children.length; typeI++) {
  514. const type = tag.children[typeI]
  515. if (type.__count > 0) {
  516. type.__expend = true
  517. for (let indexI = 0; indexI < type.children.length; indexI++) {
  518. const index = type.children[indexI]
  519. if (index.__count > 0 && !state.resultParams.activeIndex) {
  520. state.resultParams.activeIndex = index.treeId
  521. break
  522. }
  523. }
  524. break
  525. }
  526. }
  527. break
  528. }
  529. }
  530. lastCountStep--
  531. state.ws.countPercent = ((lastCountStep_ - lastCountStep) / lastCountStep_ * 100).toFixed(0)
  532. if (lastCountStep === 0) {
  533. lastCountParams = ''
  534. }
  535. }
  536. } break
  537. case 'list': {
  538. const p = JSON.parse(lastCountParams)
  539. // 返回为最新批次的
  540. if (json.timestamp == p.timestamp) {
  541. state.tableParams.total = json.records
  542. state.tableParams.data = json.datas
  543. state.tableParams.loading = false
  544. }
  545. } break
  546. }
  547. }
  548. } catch (e) {
  549. }
  550. }
  551. state.ws = ws
  552. }
  553. })
  554. </script>
  555. <style lang="scss" scoped>
  556. .list {
  557. width: 100%;
  558. height: 100%;
  559. background-color: #F6F7FB;
  560. display: flex;
  561. flex-direction: column;
  562. .list-head {
  563. display: flex;
  564. align-items: center;
  565. width: 100%;
  566. height: 72px;
  567. background-color: #FFFFFF;
  568. .list-head-search {
  569. margin-left: auto;
  570. width: 800px;
  571. display: flex;
  572. align-items: center;
  573. height: 48px;
  574. background: rgba(255,255,255,0.9);
  575. box-shadow: 0px 0px 2px 0px rgba(167,220,255,0.5);
  576. border-radius: 60px;
  577. border: 1px solid var(--cus-text-color-4);
  578. .left-select {
  579. display: flex;
  580. align-items: center;
  581. justify-content: center;
  582. width: 184px;
  583. gap: 17px;
  584. color: var(--cus-text-color-4);
  585. font-size: 18px;
  586. position: relative;
  587. &:after {
  588. content: '';
  589. position: absolute;
  590. right: 0;
  591. height: 40px;
  592. width: 1px;
  593. background-color: var(--cus-text-color-4);
  594. }
  595. :deep(.area-cascader) {
  596. position: absolute;
  597. z-index: -1;
  598. opacity: 0;
  599. height: 50px;
  600. }
  601. }
  602. :deep(.el-input) {
  603. font-size: 18px;
  604. color: var(--cus-text-color-2);
  605. .el-input__wrapper {
  606. box-shadow: none;
  607. background-color: transparent;
  608. .el-input__inner {
  609. &::placeholder {
  610. color: var(--cus-text-color-4);
  611. }
  612. }
  613. }
  614. }
  615. .right-icon {
  616. margin-right: 20px;
  617. }
  618. }
  619. .list-head-user {
  620. display: flex;
  621. align-items: center;
  622. color: var(--cus-main-color);
  623. margin: 0 24px;
  624. .avatar {
  625. margin-right: 8px;
  626. }
  627. }
  628. }
  629. .count-percent {
  630. display: flex;
  631. align-items: center;
  632. font-weight: 400;
  633. font-size: 10px;
  634. color: var(---cus-text-color-2);
  635. padding: 10px 24px;
  636. line-height: 1;
  637. .bar-bg {
  638. flex: 1;
  639. margin-right: 10px;
  640. background-color: rgba(var(--cus-main-color-rgb), 0.1);
  641. height: 8px;
  642. border-radius: 8px;
  643. position: relative;
  644. .bar-block {
  645. transition: 1s;
  646. border-radius: 8px;
  647. position: absolute;
  648. height: 100%;
  649. background-color: rgba(var(--cus-main-color-rgb), 1);
  650. }
  651. }
  652. }
  653. .list-content {
  654. overflow: hidden;
  655. flex: 1;
  656. padding: 0 24px 24px 24px;
  657. display: flex;
  658. flex-direction: column;
  659. $filterLineHeight: 26px;
  660. .list-filter {
  661. font-weight: 500;
  662. font-size: 14px;
  663. color: var(--cus-text-color-2);
  664. display: flex;
  665. .label {
  666. margin-right: 20px;
  667. line-height: $filterLineHeight;
  668. }
  669. .value {
  670. flex: 1;
  671. display: flex;
  672. flex-wrap: wrap;
  673. gap: 10px 10px;
  674. .filter-item {
  675. height: $filterLineHeight;
  676. padding: 0 16px;
  677. background: #FFFFFF;
  678. border-radius: 45px;
  679. font-size: 12px;
  680. display: flex;
  681. align-items: center;
  682. .svg-icon {
  683. margin-left: 10px;
  684. }
  685. }
  686. }
  687. }
  688. .list-tab {
  689. height: 45px;
  690. margin-top: 19px;
  691. display: flex;
  692. .list-tab-item {
  693. height: 100%;
  694. padding: 0 16px;
  695. display: flex;
  696. align-items: center;
  697. justify-content: center;
  698. color: var(--cus-text-color-2);
  699. border-radius: 8px 8px 0 0;
  700. .total {
  701. font-size: 12px;
  702. margin-left: 4px;
  703. color: var(--cus-text-color-2);
  704. font-weight: 400;
  705. }
  706. &.active {
  707. background-color: #ffffff;
  708. box-shadow: 0px -4px 10px 0px rgba(62,123,250,0.1);
  709. color: var(--cus-main-color);
  710. font-weight: 500;
  711. position: relative;
  712. &:after {
  713. content: '';
  714. position: absolute;
  715. bottom: 0;
  716. width: calc(100% - 16px * 2);
  717. height: 3px;
  718. background-color: var(--cus-main-color);
  719. }
  720. }
  721. }
  722. }
  723. .list-result {
  724. flex: 1;
  725. background-color: #ffffff;
  726. padding: 16px;
  727. display: flex;
  728. gap: 16px;
  729. overflow: hidden;
  730. .list-result-tree {
  731. height: 100%;
  732. width: 300px;
  733. padding-right: 10px;
  734. overflow-y: auto;
  735. .list-result-tree-item {
  736. .item-parent {
  737. min-height: 38px;
  738. display: flex;
  739. align-items: center;
  740. padding-right: 16px;
  741. line-height: 1;
  742. color: var(--cus-text-color-1);
  743. .flag {
  744. margin-right: 10px;
  745. }
  746. .total {
  747. font-size: 14px;
  748. }
  749. .expend {
  750. margin-left: auto;
  751. }
  752. }
  753. .item-son {
  754. padding: 10px 34px;
  755. font-weight: 400;
  756. font-size: 14px;
  757. color: var(--cus-text-color-2);
  758. border-radius: 4px;
  759. .total {
  760. font-size: 12px;
  761. }
  762. &.active {
  763. background-color: rgba(var(--cus-main-color-rgb), 0.1);
  764. color: var(--cus-main-color);
  765. }
  766. }
  767. }
  768. }
  769. .list-result-table {
  770. display: flex;
  771. flex-direction: column;
  772. flex: 1;
  773. .table-head {
  774. width: 100%;
  775. height: 162px;
  776. padding: 16px;
  777. background: linear-gradient( 90deg, rgba(var(--cus-main-color-rgb),0.1) 0%, rgba(var(--cus-main-color-rgb),0.05) 100%), #FFFFFF;
  778. box-shadow: 0px 2px 4px 0px rgba(var(--cus-main-color-rgb),0.3);
  779. border-radius: 4px;
  780. display: flex;
  781. flex-direction: column;
  782. .table-head-index {
  783. display: flex;
  784. align-items: center;
  785. padding-right: 16px;
  786. line-height: 1;
  787. color: var(--cus-text-color-1);
  788. .flag {
  789. margin-right: 10px;
  790. }
  791. .total {
  792. font-size: 14px;
  793. }
  794. }
  795. .table-head-infos {
  796. flex: 1;
  797. display: flex;
  798. align-items: flex-end;
  799. overflow: hidden;
  800. gap: 10px;
  801. .main {
  802. height: 92px;
  803. width: 455px;
  804. display: flex;
  805. align-items: center;
  806. background: linear-gradient( 90deg, rgba(var(--cus-main-color-rgb),0.3) 0%, rgba(var(--cus-main-color-rgb),0.2) 100%);
  807. font-weight: 400;
  808. font-size: 12px;
  809. position: relative;
  810. &:before {
  811. content: '';
  812. background-image: url("@/assets/images/web/wen-list_table-head-bg-2.png");
  813. background-repeat: no-repeat;
  814. background-size: 100% 100%;
  815. position: absolute;
  816. width: 100%;
  817. height: 100%;
  818. z-index: 1;
  819. }
  820. >* {
  821. z-index: 2;
  822. }
  823. >img {
  824. margin-left: 24px;
  825. height: 100%;
  826. }
  827. >div {
  828. >div {
  829. &:nth-child(odd) {
  830. color: var(--cus-text-color-3);
  831. }
  832. &:nth-child(even) {
  833. color: var(--cus-text-color-2);
  834. }
  835. &:nth-child(2) {
  836. margin-bottom: 6px;
  837. }
  838. }
  839. }
  840. .one {
  841. margin: 0 32px;
  842. }
  843. }
  844. .info {
  845. flex: 1;
  846. height: 70px;
  847. background: linear-gradient( 90deg, rgba(var(--cus-main-color-rgb),0.3) 0%, rgba(var(--cus-main-color-rgb),0.2) 100%);
  848. position: relative;
  849. &:before {
  850. content: '';
  851. background-image: url("@/assets/images/web/wen-list_table-head-bg-1.png");
  852. background-repeat: no-repeat;
  853. background-size: 100% 100%;
  854. position: absolute;
  855. width: 100%;
  856. height: 100%;
  857. z-index: 1;
  858. }
  859. >* {
  860. z-index: 2;
  861. }
  862. >img {
  863. position: absolute;
  864. bottom: 0;
  865. left: 20px;
  866. }
  867. >div {
  868. margin-left: 144px;
  869. margin-top: 14px;
  870. position: inherit;
  871. >div:nth-child(1) {
  872. font-weight: 400;
  873. font-size: 14px;
  874. color: var(--cus-text-color-2);
  875. }
  876. >div:nth-child(2) {
  877. margin-top: 4px;
  878. font-weight: 500;
  879. font-size: 16px;
  880. color: var(--cus-main-color);
  881. >span {
  882. font-size: 12px;
  883. }
  884. }
  885. }
  886. }
  887. }
  888. }
  889. .table-switch {
  890. margin: 10px 0 10px auto;
  891. display: flex;
  892. >div {
  893. width: 34px;
  894. height: 34px;
  895. display: flex;
  896. align-items: center;
  897. justify-content: center;
  898. background-color: #F5F7FA;
  899. border: 1px solid #DCDFE5;
  900. &:nth-child(1) {
  901. border-radius: 4px 0 0 4px;
  902. }
  903. &:nth-child(2) {
  904. border-radius: 0 4px 4px 0;
  905. }
  906. &.active {
  907. background-color: var(--cus-main-color);
  908. border-color: var(--cus-main-color);
  909. }
  910. }
  911. }
  912. .table-content {
  913. flex: 1;
  914. display: flex;
  915. flex-direction: column;
  916. overflow: hidden;
  917. .table-content-result {
  918. flex: 1;
  919. overflow: hidden;
  920. .table-list {
  921. width: 100%;
  922. height: 100%;
  923. display: flex;
  924. flex-direction: column;
  925. overflow-y: auto;
  926. border: 1px solid #EAEBEF;
  927. border-radius: 4px;
  928. .list-item {
  929. display: flex;
  930. align-items: center;
  931. font-weight: 400;
  932. font-size: 14px;
  933. color: var(--cus-text-color-2);
  934. padding: 12px 16px;
  935. &:hover {
  936. background-color: rgba(46,129,255,0.05);
  937. }
  938. &:not(:last-child) {
  939. border-bottom: 1px solid #EAEBEF;
  940. }
  941. .index {
  942. margin-right: 16px;
  943. }
  944. .cols {
  945. flex: 1;
  946. display: grid;
  947. row-gap: 4px;
  948. .cols-item {
  949. display: flex;
  950. .cols-item-label {
  951. color: var(--cus-text-color-1);
  952. font-weight: bold;
  953. }
  954. .cols-item-value {
  955. color: var(--cus-text-color-2);
  956. }
  957. }
  958. }
  959. .operation {
  960. display: flex;
  961. align-items: center;
  962. gap: 10px;
  963. font-size: 14px;
  964. color: var(--cus-text-color-2);
  965. >div {
  966. display: flex;
  967. align-items: center;
  968. .svg-icon {
  969. margin-right: 2px;
  970. }
  971. }
  972. }
  973. }
  974. }
  975. .table-card {
  976. width: 100%;
  977. height: 100%;
  978. display: grid;
  979. overflow-y: auto;
  980. gap: 16px;
  981. .card-item {
  982. padding: 16px;
  983. background: linear-gradient( 180deg, rgba(var(--cus-main-color-rgb), 0.1) 0%, rgba(var(--cus-main-color-rgb),0) 100%), #FFFFFF;
  984. box-shadow: 0px 2px 4px 0px rgba(var(--cus-main-color-rgb),0.2);
  985. border-radius: 4px;
  986. .main-row {
  987. display: flex;
  988. align-items: center;
  989. .main-row-img {
  990. width: 40px;
  991. height: 40px;
  992. border-radius: 4px;
  993. margin-right: 10px;
  994. .el-image {
  995. width: 100%;
  996. height: 100%;
  997. >img {
  998. width: 100%;
  999. height: 100%;
  1000. }
  1001. }
  1002. }
  1003. .main-row-param {
  1004. font-size: 20px;
  1005. color: var(--cus-text-color-1);
  1006. font-weight: bold;
  1007. }
  1008. .main-row-operation {
  1009. display: flex;
  1010. align-items: center;
  1011. gap: 10px;
  1012. font-size: 14px;
  1013. color: var(--cus-text-color-2);
  1014. margin-left: auto;
  1015. >div {
  1016. display: flex;
  1017. align-items: center;
  1018. .svg-icon {
  1019. margin-right: 2px;
  1020. }
  1021. }
  1022. }
  1023. }
  1024. .cols {
  1025. flex: 1;
  1026. display: grid;
  1027. row-gap: 4px;
  1028. font-size: 14px;
  1029. .cols-item {
  1030. display: flex;
  1031. .cols-item-label {
  1032. color: var(--cus-text-color-1);
  1033. font-weight: bold;
  1034. }
  1035. .cols-item-value {
  1036. color: var(--cus-text-color-2);
  1037. }
  1038. }
  1039. }
  1040. }
  1041. }
  1042. }
  1043. .table-content-page {
  1044. margin-top: 10px;
  1045. margin-left: auto;
  1046. }
  1047. }
  1048. }
  1049. }
  1050. }
  1051. }
  1052. </style>