index_v1.vue 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555
  1. <template>
  2. <div class="dashboard-editor-container home">
  3. <div
  4. style="width:100%;position:absolute;background:url(public/titleBackground.png) no-repeat center;background-size: 1500px 80px;">
  5. <el-row :gutter="10" justify="center"
  6. style="width: 360px;margin-top: 10px;margin-bottom: 60px; left: 50%;margin-left: -180px; ">
  7. <el-col :span="10">
  8. <img style="height:60px;" :src="logoL" />
  9. </el-col>
  10. <el-col :span="14">
  11. <span style="font-weight: bold; font-size:30px;height: 60px; line-height: 70px;">监控指挥平台</span>
  12. </el-col>
  13. </el-row>
  14. </div>
  15. <!-- 每日作业/统计信息/关键件占比 -->
  16. <el-row :gutter="10" class="row-space" style="margin-top:55px">
  17. <el-col :md="24" :lg="8" :xl="8">
  18. <el-card shadow="hover" class="card">
  19. <template #header>
  20. <span>每日作业</span>
  21. </template>
  22. <bar-chart />
  23. </el-card>
  24. </el-col>
  25. <el-col :md="24" :lg="8" :xl="8">
  26. <el-row style="margin-top:80px;" justify="center">
  27. <el-col :span="22">
  28. <el-row class="row-space row-space-span" justify="center">
  29. <el-col :span=intStatColWidth0>
  30. <span class="statistics-span">{{ strStatQA }}</span>
  31. </el-col>
  32. <el-col :span=intStatColWidth1>
  33. <div class="statistic-card">
  34. <el-statistic :value=chartBar_qa_key>
  35. <template #suffix>
  36. <span class="than-yesterday green">
  37. 24%<el-icon>
  38. <CaretBottom />
  39. </el-icon>
  40. </span>
  41. </template>
  42. </el-statistic>
  43. </div>
  44. </el-col>
  45. </el-row>
  46. <el-row class="row-space row-space-span" justify="center">
  47. <el-col :span=intStatColWidth0>
  48. <span class="statistics-span">{{ strStatInstore }}</span>
  49. </el-col>
  50. <el-col :span=intStatColWidth1>
  51. <div class="statistic-card">
  52. <el-statistic :value=chartBar_in_key>
  53. <template #suffix>
  54. <span class="than-yesterday red">
  55. 24%<el-icon>
  56. <CaretTop />
  57. </el-icon>
  58. </span>
  59. </template>
  60. </el-statistic>
  61. </div>
  62. </el-col>
  63. </el-row>
  64. <el-row class="row-space row-space-span" justify="center">
  65. <el-col :span=intStatColWidth0>
  66. <span class="statistics-span">{{ strStatOutstore }}</span>
  67. </el-col>
  68. <el-col :span=intStatColWidth1>
  69. <div class="statistic-card">
  70. <el-statistic :value=chartBar_out_key>
  71. <template #suffix>
  72. <span class="than-yesterday red">
  73. 24%<el-icon>
  74. <CaretTop />
  75. </el-icon>
  76. </span>
  77. </template>
  78. </el-statistic>
  79. </div>
  80. </el-col>
  81. </el-row>
  82. <el-row class="row-space row-space-span" justify="center">
  83. <el-col :span=intStatColWidth0>
  84. <span class="statistics-span">{{ strStatAssemble }}</span>
  85. </el-col>
  86. <el-col :span=intStatColWidth1>
  87. <div class="statistic-card">
  88. <el-statistic :value=chartBar_ass_key>
  89. <template #suffix>
  90. <span class="than-yesterday red">
  91. 24%<el-icon>
  92. <CaretTop />
  93. </el-icon>
  94. </span>
  95. </template>
  96. </el-statistic>
  97. </div>
  98. </el-col>
  99. </el-row>
  100. <el-row class="row-space row-space-span" justify="center">
  101. <el-col :span=intStatColWidth0>
  102. <span class="statistics-span">{{ strStatWork }}</span>
  103. </el-col>
  104. <el-col :span=intStatColWidth1>
  105. <div class="statistic-card">
  106. <el-statistic :value=totalUnkey>
  107. <template #suffix>
  108. <span class="than-yesterday red">
  109. 24%<el-icon>
  110. <CaretTop />
  111. </el-icon>
  112. </span>
  113. </template>
  114. </el-statistic>
  115. </div>
  116. </el-col>
  117. </el-row>
  118. </el-col>
  119. </el-row>
  120. </el-col>
  121. <el-col :md="24" :lg="8" :xl="8">
  122. <el-card shadow="hover" class="card">
  123. <template #header>
  124. <span>关键件占比</span>
  125. </template>
  126. <Pie-chart-key />
  127. </el-card>
  128. </el-col>
  129. </el-row>
  130. <!-- 物料类别占比/操作日志/时间段作业效率 -->
  131. <el-row :gutter="10" class="row-space">
  132. <el-col :md="24" :lg="8" :xl="8">
  133. <el-card shadow="hover" class="card">
  134. <template #header>
  135. <span>物料类别占比</span>
  136. </template>
  137. <Pie-chart-category />
  138. </el-card>
  139. </el-col>
  140. <el-col :md="24" :lg="8" :xl="8">
  141. <el-card shadow="hover" class="card">
  142. <template #header>
  143. <span>系统操作日志</span>
  144. <el-button text class="card-button">
  145. <router-link to="/system/log/operlog">
  146. <el-icon>
  147. <MoreFilled />
  148. </el-icon>
  149. </router-link>
  150. </el-button>
  151. </template>
  152. <el-table v-loading="loading" border :data="list">
  153. <el-table-column type="index" label="序号" align="center" />
  154. <el-table-column label="用户" align="center" prop="operName" />
  155. <el-table-column label="IP地址" align="center" prop="operIp" :show-overflow-tooltip="true" />
  156. <el-table-column label="系统模块" align="center" prop="title" :show-overflow-tooltip="true" />
  157. <el-table-column label="操作状态" align="center" prop="status">
  158. <template #default="{ row }">
  159. <dict-tag :options="statusOptions" :value="row.status"></dict-tag>
  160. </template>
  161. </el-table-column>
  162. <el-table-column label="操作日期" align="center" prop="operTime">
  163. <template #default="scope">
  164. <span>{{ scope.row.operTime }}</span>
  165. </template>
  166. </el-table-column>
  167. </el-table>
  168. </el-card>
  169. </el-col>
  170. <el-col :md="24" :lg="8" :xl="8">
  171. <el-card shadow="hover" class="card">
  172. <template #header>
  173. <span>时间段作业效率</span>
  174. </template>
  175. <line-chart :chart-data="lineChartData" :key="dataType" />
  176. </el-card>
  177. </el-col>
  178. </el-row>
  179. </div>
  180. </template>
  181. <script setup name="index">
  182. import { provide, computed } from 'vue'
  183. import LineChart from './dashboard/LineChart'
  184. import PieChartKey from './dashboard/PieChart_key'
  185. import PieChartCategory from './dashboard/PieChart_category'
  186. import BarChart from './dashboard/BarChart'
  187. import useUserStore from '@/store/modules/user'
  188. import useSocketStore from '@/store/modules/socket'
  189. import logoL from '@/assets/logo/logo-L.png'
  190. import { list as listOperLog } from '@/api/monitor/operlog'
  191. const strStatQA = '关键件质检数统计:'
  192. const strStatInstore = '关键件入库数统计:'
  193. const strStatOutstore = '关键件出库数统计:'
  194. const strStatAssemble = '关键件装配数统计:'
  195. const strStatWork = '非关键件作业数统计:'
  196. const strStatQATitle = '关键件质检数统计'
  197. const strStatInstoreTitle = '关键件入库数统计'
  198. const strStatOutstoreTitle = '关键件出库数统计'
  199. const strStatAssembleTitle = '关键件装配数统计'
  200. const strStatWorkTitle = '非关键件作业数统计'
  201. const intStatColWidth0 = 10
  202. const intStatColWidth1 = 10
  203. const intStatColWidth2 = 10
  204. const data = {
  205. newVisitis: {
  206. expectedData: [100, 120, 161, 134, 105, 160, 165],
  207. actualData: [120, 82, 91, 154, 162, 140, 145]
  208. },
  209. messages: {
  210. expectedData: [200, 192, 120, 144, 160, 130, 140],
  211. actualData: [180, 160, 151, 106, 145, 150, 130]
  212. },
  213. purchases: {
  214. expectedData: [80, 100, 121, 104, 105, 90, 100],
  215. actualData: [120, 90, 100, 138, 142, 130, 130]
  216. },
  217. shoppings: {
  218. expectedData: [130, 140, 141, 142, 145, 150, 160],
  219. actualData: [120, 82, 91, 154, 162, 140, 130]
  220. },
  221. wordCloud: [
  222. {
  223. name: 'Vue3',
  224. value: 144
  225. },
  226. {
  227. name: '.net6',
  228. value: 928
  229. },
  230. {
  231. name: 'Sqlsugar',
  232. value: 906
  233. },
  234. {
  235. name: 'Redis',
  236. value: 825
  237. },
  238. {
  239. name: '代码生成',
  240. value: 514
  241. },
  242. {
  243. name: '开源免费',
  244. value: 486
  245. },
  246. {
  247. name: '代码简单',
  248. value: 53
  249. },
  250. {
  251. name: '打赏',
  252. value: 163
  253. },
  254. {
  255. name: '国际化',
  256. value: 163
  257. },
  258. {
  259. name: 'Composition api',
  260. value: 1163
  261. },
  262. {
  263. name: 'Quartz.Net',
  264. value: 190
  265. },
  266. {
  267. name: 'Element UI',
  268. value: 190
  269. }
  270. ]
  271. }
  272. const { proxy } = getCurrentInstance()
  273. const chartBar_qa = 99
  274. provide('chartBar_qa', chartBar_qa)
  275. const chartBar_qa_key = 99
  276. provide('chartBar_qa_key', chartBar_qa_key)
  277. const chartBar_in = 199
  278. provide('chartBar_in', chartBar_in)
  279. const chartBar_in_key = 199
  280. provide('chartBar_in_key', chartBar_in_key)
  281. const chartBar_out = 99
  282. provide('chartBar_out', chartBar_out)
  283. const chartBar_out_key = 99
  284. provide('chartBar_out_key', chartBar_out_key)
  285. const chartBar_ass = 299
  286. provide('chartBar_ass', chartBar_ass)
  287. const chartBar_ass_key = 399
  288. provide('chartBar_ass_key', chartBar_ass_key)
  289. const totalUnkey = computed(() => { return chartBar_qa + chartBar_in + chartBar_out + chartBar_ass })
  290. const chartPie_key = 799
  291. provide('chartPie_key', chartPie_key)
  292. const chartPie_key_key = 1299
  293. provide('chartPie_key_key', chartPie_key_key)
  294. const chartPie_category0 = 1599
  295. provide('chartPie_category0', chartPie_category0)
  296. const chartPie_category1 = 1399
  297. provide('chartPie_category1', chartPie_category1)
  298. const chartPie_category2 = 899
  299. provide('chartPie_category2', chartPie_category2)
  300. const chartPie_category3 = 599
  301. provide('chartPie_category3', chartPie_category3)
  302. const chartPie_category4 = 399
  303. provide('chartPie_category4', chartPie_category4)
  304. const queryParams = ref({
  305. pageNum: 1,
  306. pageSize: 8,
  307. title: undefined,
  308. operName: undefined,
  309. businessType: undefined,
  310. status: undefined,
  311. operParam: undefined
  312. })
  313. // 遮罩层
  314. const loading = ref(true)
  315. // 操作日志数据
  316. const list = ref([])
  317. // 日期范围
  318. const dateRange = ref([])
  319. /** 查询操作日志 */
  320. function getList() {
  321. loading.value = true
  322. listOperLog(proxy.addDateRange(queryParams.value, dateRange.value)).then((response) => {
  323. loading.value = false
  324. if (response.code == 200) {
  325. list.value = response.data.result
  326. } else {
  327. list.value = []
  328. }
  329. })
  330. }
  331. let lineChartData = reactive([])
  332. const dataType = ref(null)
  333. function handleSetLineChartData(type) {
  334. dataType.value = type
  335. lineChartData = data[type]
  336. }
  337. handleSetLineChartData('newVisitis')
  338. // 系统状态字典
  339. const statusOptions = ref([])
  340. proxy.getDicts('sys_common_status').then((response) => {
  341. statusOptions.value = response.data
  342. })
  343. // 操作类型字典
  344. const businessTypeOptions = ref([])
  345. proxy.getDicts('sys_oper_type').then((response) => {
  346. businessTypeOptions.value = response.data
  347. })
  348. getList()
  349. </script>
  350. <style lang="scss" scoped>
  351. .home {
  352. overflow: hidden;
  353. .home-card-more {
  354. float: right;
  355. padding: 3px 0;
  356. font-size: 13px;
  357. }
  358. .statistics-span {
  359. display: flex;
  360. align-items: center;
  361. justify-content: center;
  362. font-size: 16px;
  363. margin: 5px 0px;
  364. }
  365. .row-space {
  366. margin-bottom: 10px;
  367. }
  368. .row-space-span {
  369. line-height: 35px;
  370. }
  371. // .card{
  372. // height: 390px;
  373. // }
  374. .user-item {
  375. height: 198px;
  376. display: flex;
  377. align-items: center;
  378. .user-item-left {
  379. width: 60px;
  380. height: 60px;
  381. border-radius: 50%;
  382. overflow: hidden;
  383. img {
  384. width: 100%;
  385. height: 100%;
  386. }
  387. }
  388. .user-item-right {
  389. flex: 1;
  390. padding: 15px;
  391. .right-title {
  392. font-size: 20px;
  393. }
  394. .right-l-v {
  395. font-size: 13px;
  396. display: flex;
  397. .right-label {
  398. color: gray;
  399. width: 75px;
  400. }
  401. .right-value {
  402. flex: 1;
  403. }
  404. }
  405. }
  406. }
  407. .info {
  408. height: 189px;
  409. // overflow-y: scroll;
  410. .info-scroll {
  411. height: 100%;
  412. overflow: auto;
  413. .info-ul {
  414. list-style: none;
  415. padding: 0;
  416. .info-item {
  417. display: flex;
  418. font-size: 13px;
  419. color: gray;
  420. height: 28px;
  421. line-height: 28px;
  422. &:hover {
  423. color: var(--color-primary);
  424. cursor: pointer;
  425. }
  426. .info-item-left {
  427. flex: 1;
  428. flex-shrink: 0;
  429. text-overflow: ellipsis;
  430. white-space: nowrap;
  431. overflow: hidden;
  432. }
  433. .info-item-right {
  434. width: 140px;
  435. text-align: right;
  436. padding-right: 10px;
  437. }
  438. }
  439. }
  440. }
  441. }
  442. }
  443. .dashboard-editor-container {
  444. background-color: var(--base-bg-main);
  445. position: relative;
  446. .chart-wrapper {
  447. background: var(--base-bg-main);
  448. padding: 16px 16px 0;
  449. margin-bottom: 32px;
  450. }
  451. }
  452. @media (max-width: 1024px) {
  453. .chart-wrapper {
  454. padding: 8px;
  455. }
  456. }
  457. .el-statistic {
  458. --el-statistic-content-font-size: 32px;
  459. }
  460. .statistic-card {
  461. height: 100%;
  462. padding: 5px 10px;
  463. border-radius: 4px;
  464. background-color: var(--el-bg-color-overlay);
  465. }
  466. .statistic-card-templete {
  467. display: inline-flex;
  468. align-items: center;
  469. font-size: 15px;
  470. }
  471. .statistic-footer {
  472. display: flex;
  473. justify-content: space-between;
  474. align-items: center;
  475. flex-wrap: wrap;
  476. font-size: 15px;
  477. color: var(--el-text-color-regular);
  478. margin-top: 16px;
  479. }
  480. .statistic-footer .footer-item {
  481. display: flex;
  482. justify-content: space-between;
  483. align-items: center;
  484. }
  485. .statistic-footer .footer-item span:last-child {
  486. display: inline-flex;
  487. align-items: center;
  488. margin-left: 4px;
  489. }
  490. .than-yesterday {
  491. font-size: 16px;
  492. margin-left: 12px;
  493. }
  494. .green {
  495. color: var(--el-color-success);
  496. }
  497. .red {
  498. color: var(--el-color-error);
  499. }
  500. .card {
  501. height: 400px;
  502. }
  503. .card-button {
  504. float: right;
  505. width: 25px;
  506. height: 25px;
  507. }
  508. </style>