index.vue 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619
  1. <template>
  2. <el-scrollbar ref="dashboardRef" class="dashboard-container column-page-wrap">
  3. <el-card class="info-wrap">
  4. <img class="logo" src="@/assets/images/logo.png" />
  5. <div class="desc-wrap">
  6. <div class="header">早安,Admin, 开始您一天的工作吧</div>
  7. <div class="tip">今日阴转大雨,15℃ - 25℃,出门记得带伞哦.</div>
  8. </div>
  9. <div class="extra-items">
  10. <div class="item">
  11. <div class="label">项目数</div>
  12. <div class="value">16</div>
  13. </div>
  14. <div class="item">
  15. <div class="label">代办</div>
  16. <div class="value">3/15</div>
  17. </div>
  18. <div class="item">
  19. <div class="label">消息</div>
  20. <div class="value">36</div>
  21. </div>
  22. </div>
  23. </el-card>
  24. <el-row :gutter="12">
  25. <el-col :span="16">
  26. <el-card class="box-card">
  27. <template #header>
  28. <div class="common_title">
  29. <span>快捷方式</span>
  30. </div>
  31. </template>
  32. <el-row :gutter="10">
  33. <el-col v-for="(v, i) of flowList" :key="i" :span="6">
  34. <div class="link-item">
  35. <svg-icon :icon-class="v.icon" class-name="icon" />
  36. <div class="desc">
  37. <div class="text-overflow_ellipsis">{{ v.label }}</div>
  38. <div class="tip text-overflow_ellipsis">{{ v.label }}快捷入口</div>
  39. </div>
  40. </div>
  41. </el-col>
  42. </el-row>
  43. </el-card>
  44. </el-col>
  45. <el-col :span="8">
  46. <el-carousel style="margin-top: 12px;border-radius: 8px;" height="288px">
  47. <el-carousel-item>
  48. <img class="banner-img" src="@/assets/images/banner_01.webp" alt=""/>
  49. </el-carousel-item>
  50. <el-carousel-item>
  51. <img class="banner-img" src="@/assets/images/banner_02.webp" alt=""/>
  52. </el-carousel-item>
  53. </el-carousel>
  54. </el-col>
  55. </el-row>
  56. <el-row :gutter="12">
  57. <el-col :span="16">
  58. <el-card class="box-card">
  59. <template #header>
  60. <div class="common_title">
  61. <span>代办任务</span>
  62. </div>
  63. </template>
  64. <LeTable class="local_table" v-bind="tableOpts"></LeTable>
  65. </el-card>
  66. </el-col>
  67. <el-col :span="8">
  68. <!-- Echarts 图表 -->
  69. <el-row :gutter="12">
  70. <el-col :span="24" class="card-panel__col">
  71. <el-card class="box-card box-card--type2">
  72. <template #header>
  73. <div class="common_title">
  74. <span>流量概况</span>
  75. </div>
  76. </template>
  77. <LeChart
  78. ref="chartRef"
  79. style="background-color: var(--el-color-primary-light-9)"
  80. class="local_chartWrap"
  81. :loading="chartLoading"
  82. :show-chart="showChart"
  83. :option="chartOption"
  84. :height="height"
  85. />
  86. </el-card>
  87. </el-col>
  88. <!-- <el-col :sm="24" :lg="12" class="card-panel__col">
  89. <el-card class="box-card box-card&#45;&#45;type3">
  90. <template #header>
  91. <div class="common_title">
  92. <span>授权数</span>
  93. </div>
  94. </template>
  95. <LeChart
  96. style="background-color: var(&#45;&#45;el-color-error-light-9)"
  97. :loading="chartLoading2"
  98. is-init-option
  99. :option="chartOption2"
  100. :height="height"
  101. />
  102. </el-card>
  103. </el-col>-->
  104. </el-row>
  105. </el-col>
  106. </el-row>
  107. </el-scrollbar>
  108. </template>
  109. <script setup name="dashboard" lang="tsx">
  110. import { colorBase1 } from '@/components/Chart.vue'
  111. import { reactive, ref, toRefs } from 'vue'
  112. import * as echarts from 'echarts'
  113. const dashboardRef = ref()
  114. // window.dashboardRef = dashboardRef
  115. const getChartData = () => ({
  116. /*title: {
  117. show: true,
  118. text: '业绩总览',
  119. x: 'center',
  120. padding: 15,
  121. textStyle: {
  122. fontSize: 18,
  123. fontStyle: 'normal',
  124. fontWeight: 'bold',
  125. color: '#337ecc'
  126. }
  127. },*/
  128. // backgroundColor: '',
  129. grid: {
  130. top: '5%',
  131. left: '2%',
  132. right: '4%',
  133. bottom: '0%',
  134. containLabel: true
  135. },
  136. tooltip: {
  137. // show: true,
  138. trigger: 'axis',
  139. axisPointer: {
  140. type: 'cross',
  141. crossStyle: {
  142. color: '#999'
  143. }
  144. }
  145. },
  146. legend: {
  147. show: false
  148. /*x: 'center',
  149. y: 'bottom',
  150. data: ['收入', '毛利润', '收入增长率', '利润增长率']*/
  151. },
  152. xAxis: [
  153. {
  154. type: 'category',
  155. data: ['2024/03/09', '2024/03/19', '2024/03/29', '2024/04/09', '2024/04/13'],
  156. axisPointer: {
  157. type: 'shadow'
  158. }
  159. }
  160. ],
  161. yAxis: [
  162. {
  163. type: 'value',
  164. min: 0,
  165. // max: 10000,
  166. // interval: 2000,
  167. axisLabel: {
  168. formatter: '{value} '
  169. }
  170. }
  171. ],
  172. series: [
  173. {
  174. name: '浏览量',
  175. type: 'line',
  176. smooth: true,
  177. yAxisIndex: 0,
  178. data: [250, 660, 1080, 960, 2100, 2530, 3680, 2909, 3071],
  179. itemStyle: {
  180. color: new echarts.graphic.LinearGradient(1, 1, 0, 0, [
  181. {
  182. // offset: 0,
  183. // color: colorBase1[0]
  184. offset: 0,
  185. color: '#5B8FF9'
  186. },
  187. {
  188. // offset: 1,
  189. // color: colorBase1[1]
  190. offset: 1,
  191. color: 'rgba(91,143,249,0.3)'
  192. }
  193. ])
  194. },
  195. //区域填充样式
  196. areaStyle: {
  197. normal: {
  198. //线性渐变,前4个参数分别是x0,y0,x2,y2(范围0~1);相当于图形包围盒中的百分比。如果最后一个参数是‘true’,则该四个值是绝对像素位置。
  199. color: new echarts.graphic.LinearGradient(
  200. 0,
  201. 0,
  202. 0,
  203. 1,
  204. [
  205. {
  206. offset: 0,
  207. color: '#5B8FF9' // colorBase1[0]
  208. },
  209. // {
  210. // offset: 0.5,
  211. // color: colorBase1[2]
  212. // },
  213. {
  214. offset: 1,
  215. color: 'rgba(91,143,249,0.3)'
  216. }
  217. ],
  218. false
  219. )
  220. // shadowColor: 'rgba(53,142,215, 0.9)', //阴影颜色
  221. // shadowBlur: 20 //shadowBlur设图形阴影的模糊大小。配合shadowColor,shadowOffsetX/Y, 设置图形的阴影效果。
  222. }
  223. }
  224. }
  225. ]
  226. })
  227. const getChartData2 = () => {
  228. // const backgroundColor = dashboardRef.value
  229. // const backgroundColor = (dashboardRef.value && window.getComputedStyle(dashboardRef.value, null)?.getPropertyValue('background-color')) || '#409eff'
  230. return {
  231. // backgroundColor: '#f69cd8',
  232. // backgroundColor,
  233. /*title: {
  234. show: true,
  235. text: '产品分类总览',
  236. x: 'center',
  237. padding: 15,
  238. textStyle: {
  239. fontSize: 18,
  240. fontStyle: 'normal',
  241. fontWeight: 'bold',
  242. color: '#337ecc'
  243. }
  244. },*/
  245. grid: {
  246. top: '5%',
  247. left: '2%',
  248. right: '4%',
  249. bottom: '0%',
  250. containLabel: true
  251. },
  252. xAxis: {
  253. type: 'category',
  254. // data: ['0时', '4时', '8时', '12时', '16时', '20时', '24时'],
  255. data: ['2024/03/09', '2024/03/19', '2024/03/29', '2024/04/09', '2024/04/13'],
  256. axisTick: {
  257. alignWithLabel: true
  258. }
  259. },
  260. yAxis: {
  261. type: 'value'
  262. },
  263. legend: {
  264. show: false
  265. // top: 'bottom',
  266. // data: data.map(v => ({ name: v.name }))
  267. },
  268. series: [
  269. {
  270. name: '授权数',
  271. type: 'bar',
  272. data: [370, 480, 430, 523, 450, 420, 490, 580],
  273. barWidth: 20,
  274. itemStyle: {
  275. color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
  276. { offset: 0, color: '#f56c6c' /*colorBase1[2]*/ },
  277. { offset: 1, color: 'rgba(245,108,108,0.5)' /*colorBase1[3]*/ }
  278. ])
  279. }
  280. }
  281. ]
  282. }
  283. }
  284. const chartRef = ref()
  285. // window.chartRef = chartRef
  286. const state = reactive({
  287. chartLoading: false,
  288. chartOption: {},
  289. showChart: true,
  290. width: '100%',
  291. height: '218px',
  292. chartLoading2: false,
  293. chartOption2: getChartData2()
  294. /*chartOption: getChartData()*/
  295. })
  296. const { chartLoading, chartOption, width, height, showChart, chartLoading2, chartOption2 } = toRefs(state)
  297. window.test_showChart = () => (showChart.value = !showChart.value)
  298. window.test_localStyle = (width_ = '100%', height_ = '600px') => {
  299. width.value = width_
  300. height.value = height_
  301. }
  302. // lineChart
  303. new Promise(resolve => {
  304. state.chartLoading = true
  305. setTimeout(() => {
  306. resolve(getChartData())
  307. }, 1000)
  308. }).then((res: any) => {
  309. console.error(res, 'res////////')
  310. state.chartOption = res
  311. state.chartLoading = false
  312. // setTimeout(() => {
  313. // state.chartLoading = false
  314. // }, 50)
  315. })
  316. // pieChart
  317. new Promise(resolve => {
  318. state.chartLoading2 = true
  319. setTimeout(() => {
  320. resolve(getChartData2())
  321. }, 500)
  322. }).then((res: any) => {
  323. console.error(res, 'pieChart res////////')
  324. state.chartOption2 = res
  325. state.chartLoading2 = false
  326. })
  327. const flowList = [
  328. {
  329. icon: 'flow-car',
  330. label: '组织管理'
  331. },
  332. {
  333. icon: 'flow-cart',
  334. label: '用户管理'
  335. },
  336. {
  337. icon: 'flow-checklist',
  338. label: '职位管理'
  339. },
  340. {
  341. icon: 'flow-bank-card',
  342. label: '角色管理'
  343. },
  344. {
  345. icon: 'flow-approval',
  346. label: '模块管理'
  347. },
  348. {
  349. icon: 'flow-bell',
  350. label: '菜单管理'
  351. },
  352. {
  353. icon: 'flow-calendar',
  354. label: '三方管理'
  355. },
  356. {
  357. icon: 'flow-clock',
  358. label: '数据字典'
  359. },
  360. {
  361. icon: 'flow-coin',
  362. label: '系统管理'
  363. },
  364. {
  365. icon: 'flow-contract',
  366. label: '会话管理'
  367. },
  368. {
  369. icon: 'flow-dimission',
  370. label: '访问日志'
  371. },
  372. {
  373. icon: 'flow-exchange',
  374. label: '操作日志'
  375. }
  376. ]
  377. const tableOpts = ref({
  378. list: [
  379. {
  380. title: '支付页面增加分期选择',
  381. module: '支付',
  382. users: ['01', '02', '03'],
  383. tests: ['09', '10', '06'],
  384. status: '1'
  385. },
  386. {
  387. title: '新增banner轮播图广告',
  388. module: '广告',
  389. users: ['02', '03'],
  390. tests: ['09', '10', '06'],
  391. status: '2'
  392. },
  393. {
  394. title: '支付页支持支付宝支付',
  395. module: '支付',
  396. users: ['02'],
  397. tests: ['05'],
  398. status: '2'
  399. },
  400. {
  401. title: '开发微信小程序',
  402. module: '营销',
  403. users: ['01', '02', '03'],
  404. tests: ['09', '10', '06'],
  405. status: '1'
  406. }
  407. ],
  408. columns: [
  409. {
  410. label: '任务说明',
  411. prop: 'title',
  412. minWidth: '220px'
  413. },
  414. {
  415. label: '模块',
  416. prop: 'module'
  417. // minWidth: '220px',
  418. },
  419. {
  420. label: '协作者',
  421. prop: 'users',
  422. showOverflowTooltip: false,
  423. slots: {
  424. default: ({ row }) => {
  425. return <div>
  426. {
  427. row.users.map(id => {
  428. return <SvgIcon class="avatar-icon" icon-class={`avatar-${id}`}></SvgIcon>
  429. })
  430. }
  431. </div>
  432. }
  433. }
  434. // minWidth: '220px',
  435. },
  436. {
  437. label: '测试者',
  438. prop: 'tests',
  439. showOverflowTooltip: false,
  440. slots: {
  441. default: ({ row }) => {
  442. return <div>
  443. {
  444. row.tests.map(id => {
  445. return <SvgIcon class="avatar-icon" icon-class={`avatar-${id}`}></SvgIcon>
  446. })
  447. }
  448. </div>
  449. }
  450. }
  451. // minWidth: '220px',
  452. },
  453. {
  454. label: '完成度',
  455. prop: 'status',
  456. slots: {
  457. default: ({ row }) => {
  458. const config = ({ 1: { type: 'success', text: '完成' }, 2: { type: 'danger', text: '未完成' } })[row.status]
  459. return <el-tag type={config.type}>{config.text}</el-tag>
  460. }
  461. }
  462. // minWidth: '220px',
  463. }
  464. ],
  465. options: {
  466. showPagination: false
  467. }
  468. })
  469. </script>
  470. <style lang="scss" scoped>
  471. .dashboard-container {
  472. overflow-y: auto;
  473. //padding: 12px;
  474. //overflow-x: hidden;
  475. //background-color: rgb(240, 242, 245);
  476. background: var(--el-bg-color);
  477. //background: #f1f1fd;
  478. //background: var(--el-color-primary-light-9);
  479. //background: var(--el-bg-color-page);
  480. position: relative;
  481. :deep(.el-scrollbar__view) {
  482. padding: 12px;
  483. //background: #000;
  484. .el-scrollbar__wrap {
  485. overflow-x: hidden;
  486. }
  487. .el-scrollbar__bar.is-horizontal {
  488. //.el-scrollbar__thumb {
  489. display: none;
  490. //}
  491. }
  492. }
  493. }
  494. :deep(.info-wrap) {
  495. .el-card__body {
  496. display: flex;
  497. align-items: center;
  498. justify-content: center;
  499. }
  500. min-height: 120px;
  501. background: var(--el-color-white) linear-gradient(120deg, var(--el-color-primary-light-9) 10%, var(--el-color-white)) no-repeat;
  502. .header {
  503. //font-size: var(--el-font-size-bigger);
  504. font-size: 18px;
  505. font-weight: 700;
  506. line-height: 30px;
  507. }
  508. .tip {
  509. min-height: 25px;
  510. line-height: 25px;
  511. }
  512. }
  513. .desc-wrap {
  514. flex: auto;
  515. width: calc(100% - 200px);
  516. min-width: 300px;
  517. font-size: 14px;
  518. }
  519. .extra-items {
  520. display: flex;
  521. align-items: center;
  522. .item {
  523. width: 160px;
  524. color: var(--el-text-color-primary);
  525. font-size: 14px;
  526. .value {
  527. margin-top: 6px;
  528. font-size: 20px;
  529. color: var(--el-text-color-regular);
  530. }
  531. & + .item {
  532. margin-left: 12px;
  533. }
  534. }
  535. }
  536. .logo {
  537. width: 80px;
  538. height: 80px;
  539. /*padding: var(--el-padding);
  540. margin-right: var(--el-margin);*/
  541. padding: 16px;
  542. margin-right: 16px;
  543. border-radius: 6px;
  544. background-color: var(--el-color-primary-light-8);
  545. }
  546. .link-item {
  547. display: flex;
  548. align-items: center;
  549. margin-bottom: 16px;
  550. overflow: hidden;
  551. &:hover {
  552. cursor: pointer;
  553. color: var(--el-color-primary);
  554. }
  555. .icon {
  556. color: #fff;
  557. font-size: 50px;
  558. flex-shrink: 0;
  559. }
  560. .desc {
  561. //padding-top: 10px;
  562. margin-left: 10px;
  563. font-size: 14px;
  564. font-weight: 600;
  565. .tip {
  566. margin-top: 5px;
  567. color: var(--el-text-color-regular);
  568. font-size: 12px;
  569. font-weight: normal;
  570. }
  571. }
  572. }
  573. :deep(.box-card) {
  574. margin-top: 12px;
  575. .common_title {
  576. margin: -16px -12px;
  577. }
  578. .el-card__header {
  579. //background: linear-gradient(to left, var(--el-color-warning-light-8), var(--el-color-white)) no-repeat;
  580. }
  581. &.box-card--type2 {
  582. .el-card__header {
  583. background: linear-gradient(to left, var(--el-color-primary-light-8), var(--el-color-white)) no-repeat;
  584. }
  585. }
  586. &.box-card--type3 {
  587. .el-card__header {
  588. background: linear-gradient(to left, var(--el-color-error-light-8), var(--el-color-white)) no-repeat;
  589. }
  590. }
  591. }
  592. :deep(.local_table) {
  593. padding: 0;
  594. .toolBarWrap {
  595. display: none;
  596. }
  597. .el-table__body-wrapper {
  598. .el-scrollbar {
  599. .el-scrollbar__view {
  600. padding: 0;
  601. }
  602. }
  603. }
  604. .avatar-icon {
  605. font-size: 24px;
  606. & + .avatar-icon {
  607. margin-left: 4px;
  608. }
  609. }
  610. }
  611. .banner-img {
  612. height: 100%;
  613. }
  614. </style>