index.vue 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789
  1. <template>
  2. <div class="home">
  3. <div class="second">
  4. <div class="topPanel">
  5. <!-- 原始数据 -->
  6. <div class="tPanel">
  7. <el-table size="mini" :data="originalList">
  8. <el-table-column prop="dataName" label="数据" align="center">
  9. </el-table-column>
  10. <el-table-column prop="status" label="状态" align="center">
  11. </el-table-column>
  12. </el-table>
  13. </div>
  14. <!-- 补全 -->
  15. <div class="tPanel">
  16. <el-table size="mini" :data="completionList">
  17. <el-table-column prop="dataName" label="数据" align="center">
  18. <template slot-scope="scope">
  19. <span class="file" @click="handleFile(scope.row.dataPath, scope.row.dataType)">{{ scope.row.dataName
  20. }}</span>
  21. </template>
  22. </el-table-column>
  23. <el-table-column prop="status" label="状态" align="center">
  24. </el-table-column>
  25. </el-table>
  26. </div>
  27. <!-- 特征提取 -->
  28. <div class="tPanel">
  29. <el-table size="mini" :data="featureExtractionList">
  30. <el-table-column prop="dataName" label="数据" align="center">
  31. <template slot-scope="scope">
  32. <span class="file" @click="handleFile(scope.row.dataPath, scope.row.dataType)">{{ scope.row.dataName
  33. }}</span>
  34. </template>
  35. </el-table-column>
  36. <el-table-column prop="status" label="状态" align="center">
  37. </el-table-column>
  38. </el-table>
  39. </div>
  40. <!-- 故障预测 -->
  41. <div class="tPanel">
  42. <el-table size="mini" :data="faultPredictionList">
  43. <el-table-column prop="dataName" label="数据" align="center">
  44. <template slot-scope="scope">
  45. <span class="file" @click="imgShow(scope.row.dataPath,scope.row.dataType)">{{ scope.row.dataName
  46. }}</span>
  47. </template>
  48. </el-table-column>
  49. <el-table-column prop="status" label="状态" align="center">
  50. </el-table-column>
  51. </el-table>
  52. </div>
  53. </div>
  54. <div class="step">
  55. <div class="yuan">
  56. <div class="img yuanBg odd">
  57. <div class="tag">原始数据</div>
  58. </div>
  59. </div>
  60. <div class="one">
  61. <div class="img oneBg even" @click="handleProcess(0)">
  62. <div class="tag">去噪</div>
  63. </div>
  64. </div>
  65. <div class="two">
  66. <div class="img twoBg odd" @click="handleProcess(1)">
  67. <div class="tag">补全</div>
  68. </div>
  69. </div>
  70. <div class="three">
  71. <div class="img threeBg even" @click="handleProcess(2)">
  72. <div class="tag">扩充</div>
  73. </div>
  74. </div>
  75. <div class="four">
  76. <div class="img fourBg odd" @click="handleProcess(3)">
  77. <div class="tag">特征提取</div>
  78. </div>
  79. </div>
  80. <div class="five">
  81. <div class="img fiveBg even" @click="handleProcess(4)">
  82. <div class="tag">退化评估</div>
  83. </div>
  84. </div>
  85. <div class="six">
  86. <div class="img sixBg odd noAfter" style="content: none;" @click="handleProcess(5)">
  87. <div class="tag">故障预测</div>
  88. </div>
  89. </div>
  90. </div>
  91. <div class="bottomPanel">
  92. <!-- 去噪 -->
  93. <div class="bPanel">
  94. <el-table size="mini" :data="denoisingList">
  95. <el-table-column prop="dataName" label="数据" align="center">
  96. </el-table-column>
  97. <el-table-column prop="status" label="状态" align="center">
  98. </el-table-column>
  99. </el-table>
  100. </div>
  101. <!-- 扩充 -->
  102. <div class="bPanel">
  103. <el-table size="mini" :data="expansionList">
  104. <el-table-column prop="dataName" label="数据" align="center">
  105. <template slot-scope="scope">
  106. <span class="file" @click="handleFile(scope.row.dataPath, scope.row.dataType)">{{ scope.row.dataName
  107. }}</span>
  108. </template>
  109. </el-table-column>
  110. <el-table-column prop="status" label="状态" align="center">
  111. </el-table-column>
  112. </el-table>
  113. </div>
  114. <!-- 退化评估 -->
  115. <div class="bPanel">
  116. <el-table size="mini" :data="assessmentList">
  117. <el-table-column prop="dataName" label="数据" align="center">
  118. <template slot-scope="scope">
  119. <span class="file" @click="handleFile(scope.row.dataPath, scope.row.dataType)">{{ scope.row.dataName
  120. }}</span>
  121. </template>
  122. </el-table-column>
  123. <el-table-column prop="status" label="状态" align="center">
  124. </el-table-column>
  125. </el-table>
  126. </div>
  127. <div>
  128. </div>
  129. </div>
  130. </div>
  131. <div class="first">
  132. <h4 style="margin:13px 0px 0px 20px;color: #fff;">算法统计</h4>
  133. <div class="chart">
  134. <RingChart />
  135. <BarChart width="700px" />
  136. </div>
  137. </div>
  138. <el-dialog :title="title" :visible.sync="dialogVisible" width="30%" :close-on-click-modal="false">
  139. <el-form ref="formRef" :model="form" :rules="rules" label-width="80px">
  140. <el-form-item label="数据" prop="processType">
  141. <el-select v-model="form.data" placeholder="请选择执行的数据">
  142. <el-option v-for="(item, index) in optionalData" :key="index" :label="item.name"
  143. :value="item.id"></el-option>
  144. </el-select>
  145. </el-form-item>
  146. <el-form-item label="算法" prop="processType">
  147. <el-select v-model="form.aglo" placeholder="请选择执行的算法">
  148. <el-option v-for="(item, index) in optionalAglo" :key="index" :label="item.name"
  149. :value="item.id"></el-option>
  150. </el-select>
  151. </el-form-item>
  152. </el-form>
  153. <span slot="footer" class="dialog-footer">
  154. <el-button @click="dialogVisible = false">取 消</el-button>
  155. <el-button type="primary" @click="submitHandle()">确 定</el-button>
  156. </span>
  157. </el-dialog>
  158. <el-dialog title="数据展示" :visible.sync="fileShowVisible" width="80%" :close-on-click-modal="false">
  159. <el-button v-if="fileType !== '4'&& fileType!=='5'" style="margin-left:50px;" type="text" @click="changeShow">{{ isTableShow ?
  160. '表格展示'
  161. :
  162. '曲线展示'
  163. }}</el-button>
  164. <div v-if="isTableShow && fileType!=='5'">
  165. <el-table :data="completionData" size="mini" style="width: 100%;height: 500px;overflow:scroll;">
  166. <el-table-column v-for="(item, index) in completionHeadData" :key="index" align="center" :prop="'val' + index"
  167. :label="item">
  168. </el-table-column>
  169. </el-table>
  170. </div>
  171. <div v-if="!isTableShow && fileType!=='5'" ref="completionChartRef" style="width: 100%; height: 400px;"></div>
  172. <ImagePreview v-if="fileType==='5'" :src="imgPreviewUrl"></ImagePreview>
  173. </el-dialog>
  174. </div>
  175. </template>
  176. <script>
  177. import CountTo from 'vue-count-to'
  178. import RingChart from '@/views/homePage/ringChart'
  179. import BarChart from '@/views/dashboard/BarChart'
  180. import { getAlgConfigByType } from "@/api/system/algConfig";
  181. import { getDataProcessByType, addProcess } from "@/api/system/process";
  182. import { getDataByType } from "@/api/system/data";
  183. import * as echarts from 'echarts';
  184. export default {
  185. name: 'Index',
  186. components: {
  187. CountTo,
  188. RingChart,
  189. BarChart,
  190. },
  191. data() {
  192. return {
  193. loading: true,
  194. rules: {},
  195. title: '选择数据',
  196. baseUrl: process.env.VUE_APP_BASE_API,
  197. dialogVisible: false,
  198. fileShowVisible: false,
  199. originalList: [],
  200. denoisingList: [],
  201. completionList: [],
  202. expansionList: [],
  203. featureExtractionList: [],
  204. assessmentList: [],
  205. faultPredictionList: [],
  206. optionalData: [],
  207. optionalAglo: [],
  208. form: {
  209. data: null,
  210. aglo: null
  211. },
  212. // 对话框展示数据内容
  213. completionData: [],
  214. completionHeadData: [],
  215. isTableShow: false,
  216. filePath: null,
  217. fileType: null,
  218. chart: null,
  219. imgPreviewUrl:null
  220. }
  221. },
  222. created() {
  223. this.getTableData()
  224. },
  225. methods: {
  226. getTableData() {
  227. getDataByType(1).then(res => {
  228. this.completionList = res.data
  229. })
  230. getDataByType(2).then(res => {
  231. this.expansionList = res.data
  232. })
  233. getDataByType(3).then(res => {
  234. this.featureExtractionList = res.data
  235. })
  236. getDataByType(4).then(res => {
  237. this.assessmentList = res.data
  238. })
  239. getDataByType(5).then(res => {
  240. this.faultPredictionList = res.data
  241. })
  242. },
  243. goTarget(href) {
  244. window.open(href, '_blank')
  245. },
  246. handleSetLineChartData(type) {
  247. this.$emit('handleSetLineChartData', type)
  248. },
  249. handleProcess(type) {
  250. this.dialogVisible = true;
  251. getDataProcessByType(type).then(res => {
  252. this.optionalData = res.data;
  253. });
  254. getAlgConfigByType(type).then(res => {
  255. this.optionalAglo = res.data;
  256. });
  257. },
  258. submitHandle() {
  259. addProcess(this.form).then(response => {
  260. this.$modal.msgSuccess("开始执行");
  261. this.dialogVisible = false;
  262. this.getTableData()
  263. });
  264. },
  265. handleFile(dataPath, dataType) {
  266. if (this.chart) {
  267. this.chart.dispose();
  268. this.chart = null
  269. }
  270. this.filePath = dataPath
  271. this.fileType = dataType
  272. const url = `${process.env.VUE_APP_BASE_API}${dataPath}`;
  273. this.fetchLogFile(url)
  274. .then((text) => {
  275. const color = ['#5470c6', '#91cc75', '#fac858', '#ee6666', '#73c0de', '#3ba272', '#fc8452', '#9a60b4', '#ea7ccc']
  276. switch (dataType) {
  277. case '1':
  278. const returnData = this.handleFileData(text)
  279. const contentData = returnData.contentData
  280. const headData = returnData.headData
  281. this.fileShowVisible = true
  282. this.$nextTick(() => {
  283. this.chart = echarts.init(this.$refs.completionChartRef);
  284. // series数据
  285. const series = contentData.map((lineData, index) => ({
  286. name: `${headData[index]}`,
  287. type: 'line',
  288. data: lineData,
  289. stack: 'Total',
  290. connectNulls: true, // 连接相邻的非空数据点
  291. markPoint: {
  292. data: lineData.map((value, idx) => ({
  293. value: value === 0 ? '缺失' : null,
  294. xAxis: idx,
  295. // yAxis: lineData[idx-1],
  296. yAxis: value,
  297. itemStyle: { color: color[index] } // 高亮显示缺失值
  298. })).filter(point => point.value)
  299. }
  300. }));
  301. const option = {
  302. tooltip: {
  303. trigger: 'axis'
  304. },
  305. legend: {
  306. data: headData,
  307. textStyle: {//图例文字的样式
  308. color: '#fff'
  309. }
  310. },
  311. color: color,
  312. xAxis: {
  313. type: 'category',
  314. data: contentData[0].map((_, index) => index), // 生成x轴下标
  315. name: 'Index'
  316. },
  317. yAxis: {
  318. type: 'value',
  319. name: 'Value'
  320. },
  321. dataZoom: [
  322. {
  323. type: 'slider',
  324. start: 0,
  325. end: 100
  326. },
  327. {
  328. type: 'inside',
  329. start: 0,
  330. end: 100
  331. }
  332. ],
  333. series: series
  334. };
  335. this.chart.setOption(option);
  336. })
  337. break;
  338. case '2':
  339. const data = text.split("\r\n").filter(line => line.trim() !== '').map(row => row.split(','));
  340. data[0].shift();
  341. const completionHead = data[0];
  342. const completionContent = Array.from({ length: completionHead.length }, () => []);
  343. const timeData = []
  344. for (let i = 1; i < data.length; i++) {
  345. data[i].forEach((value, index) => {
  346. if (index === 0) {
  347. timeData.push(value)
  348. } else {
  349. completionContent[index - 1].push(Number(value));
  350. }
  351. });
  352. }
  353. this.fileShowVisible = true
  354. this.$nextTick(() => {
  355. this.chart = echarts.init(this.$refs.completionChartRef);
  356. // series数据
  357. const series = completionContent.map((lineData, index) => ({
  358. name: `${completionHead[index]}`,
  359. type: 'line',
  360. data: lineData,
  361. stack: 'Total',
  362. connectNulls: true, // 连接相邻的非空数据点
  363. }));
  364. const option = {
  365. tooltip: {
  366. trigger: 'axis'
  367. },
  368. legend: {
  369. data: headData,
  370. textStyle: {//图例文字的样式
  371. color: '#fff'
  372. }
  373. },
  374. color: color,
  375. xAxis: {
  376. type: 'category',
  377. data: timeData,
  378. name: 'time'
  379. },
  380. yAxis: {
  381. type: 'value',
  382. name: 'Value'
  383. },
  384. dataZoom: [
  385. {
  386. type: 'slider',
  387. start: 0,
  388. end: 100
  389. },
  390. {
  391. type: 'inside',
  392. start: 0,
  393. end: 100
  394. }
  395. ],
  396. series: series
  397. };
  398. this.chart.setOption(option);
  399. })
  400. break;
  401. case '3':
  402. const ExtractionData = text.split("\r\n").filter(line => line.trim() !== '').map(row => row.split(','));
  403. ExtractionData[0].shift();
  404. const ExtractionHead = ExtractionData[0];
  405. const ExtractionContent = Array.from({ length: ExtractionHead.length }, () => []);
  406. const ExtractionTime = []
  407. for (let i = 1; i < ExtractionData.length; i++) {
  408. ExtractionData[i].forEach((value, index) => {
  409. if (index === 0) {
  410. ExtractionTime.push(value)
  411. } else {
  412. ExtractionContent[index - 1].push(Number(value));
  413. }
  414. });
  415. }
  416. this.fileShowVisible = true
  417. this.$nextTick(() => {
  418. this.chart = echarts.init(this.$refs.completionChartRef);
  419. // series数据
  420. const series = ExtractionContent.map((lineData, index) => ({
  421. name: `${ExtractionHead[index]}`,
  422. type: 'line',
  423. data: lineData,
  424. stack: 'Total',
  425. connectNulls: true, // 连接相邻的非空数据点
  426. }));
  427. const option = {
  428. tooltip: {
  429. trigger: 'axis'
  430. },
  431. legend: {
  432. data: headData,
  433. textStyle: {//图例文字的样式
  434. color: '#fff'
  435. }
  436. },
  437. color: color,
  438. xAxis: {
  439. type: 'category',
  440. data: ExtractionTime,
  441. name: 'time'
  442. },
  443. yAxis: {
  444. type: 'value',
  445. name: 'Value'
  446. },
  447. dataZoom: [
  448. {
  449. type: 'slider',
  450. start: 0,
  451. end: 100
  452. },
  453. {
  454. type: 'inside',
  455. start: 0,
  456. end: 100
  457. }
  458. ],
  459. series: series
  460. };
  461. this.chart.setOption(option);
  462. })
  463. break;
  464. case '4':
  465. const assessmentData = this.handleFileData(text)
  466. const assessmentcontent = assessmentData.contentData
  467. const assessmenthead = assessmentData.headData
  468. this.fileShowVisible = true
  469. this.$nextTick(() => {
  470. this.chart = echarts.init(this.$refs.completionChartRef);
  471. // series数据
  472. const series = assessmentcontent.map((lineData, index) => ({
  473. name: `${assessmenthead[index]}`,
  474. type: 'line',
  475. data: lineData,
  476. stack: 'Total',
  477. connectNulls: true, // 连接相邻的非空数据点
  478. }));
  479. const option = {
  480. tooltip: {
  481. trigger: 'axis'
  482. },
  483. legend: {
  484. data: assessmenthead,
  485. textStyle: {//图例文字的样式
  486. color: '#fff'
  487. }
  488. },
  489. color: color,
  490. xAxis: {
  491. type: 'category',
  492. data: assessmentcontent[0].map((_, index) => index), // 生成x轴下标
  493. name: 'Index'
  494. },
  495. yAxis: {
  496. type: 'value',
  497. name: 'Value'
  498. },
  499. series: series
  500. };
  501. this.chart.setOption(option);
  502. })
  503. break;
  504. default:
  505. break;
  506. }
  507. })
  508. .catch((error) => {
  509. console.error("Failed to fetch the log file:", error);
  510. this.$modal.msgSuccess("文件读取错误");
  511. });
  512. },
  513. // 读取文件内容
  514. async fetchLogFile(url) {
  515. try {
  516. const response = await fetch(url, { method: "GET" });
  517. if (!response.ok) {
  518. throw new Error(`HTTP error! status: ${response.status}`);
  519. }
  520. return await response.text();
  521. } catch (error) {
  522. throw error;
  523. }
  524. },
  525. // 对数据的处理
  526. handleFileData(fileData) {
  527. // 每行数据转换成数组、过滤出存在的空白行、将没行数据按照,号分割
  528. const data = fileData.split("\r\n").filter(line => line.trim() !== '').map(row => row.split(','));
  529. const headData = data[0];
  530. const contentData = Array.from({ length: headData.length }, () => []);
  531. for (let i = 1; i < data.length; i++) { // 从 1 开始,跳过表头
  532. data[i].forEach((value, index) => {
  533. contentData[index].push(Number(value));
  534. });
  535. }
  536. return { contentData, headData }
  537. },
  538. // 切换表格/曲线展示
  539. changeShow() {
  540. this.isTableShow = !this.isTableShow
  541. if (!this.isTableShow) {
  542. this.handleFile(this.filePath, this.fileType)
  543. } else {
  544. this.tableShow(this.filePath, this.fileType)
  545. }
  546. },
  547. tableShow(path, type) {
  548. const url = `${process.env.VUE_APP_BASE_API}${path}`;
  549. this.fetchLogFile(url)
  550. .then((text) => {
  551. const data = text.split("\r\n").filter(line => line.trim() !== '').map(row => row.split(','));
  552. this.completionHeadData = data.shift();
  553. this.completionData = data.map(row => {
  554. const rowData = {};
  555. for (let i = 0; i < this.completionHeadData.length; i++) {
  556. rowData[`val${i}`] = (row[i]) === 0 ? null : (row[i]);
  557. }
  558. return rowData;
  559. })
  560. })
  561. },
  562. imgShow(url,dataType){
  563. this.fileType = dataType
  564. this.imgPreviewUrl = url
  565. this.fileShowVisible = true
  566. }
  567. }
  568. }
  569. </script>
  570. <style scoped lang="scss">
  571. .home {
  572. width: 100%;
  573. /* 设置宽度为100%,以充满父 div 的宽度 */
  574. min-height: calc(100vh - 84px);
  575. /* 设置高度为100%,以充满父 div 的高度 */
  576. // background-color: #f4f4f4;
  577. overflow: hidden;
  578. }
  579. .first {
  580. width: 97%;
  581. height: 210px;
  582. margin: 20px;
  583. // background-color: white;
  584. border-radius: 15px;
  585. overflow: hidden;
  586. // box-shadow: 0 0 10px rgba(63, 155, 255, 0.5);
  587. // background: url("../assets/images/msgBg3.png") no-repeat center / contain;
  588. }
  589. .chart {
  590. display: flex;
  591. justify-content: space-around;
  592. margin-left: 30px;
  593. }
  594. .second {
  595. width: 97%;
  596. height: 440px;
  597. margin: 50px 20px;
  598. // overflow: hidden;
  599. display: flex;
  600. flex-direction: column;
  601. .step {
  602. width: 100%;
  603. height: 120px;
  604. display: flex;
  605. justify-content: space-around;
  606. .yuan,
  607. .one,
  608. .two,
  609. .three,
  610. .four,
  611. .five,
  612. .six,
  613. .final {
  614. width: 12%;
  615. height: 100%;
  616. text-align: center;
  617. }
  618. .item {
  619. margin-top: 10px;
  620. margin-right: 40px;
  621. }
  622. .img {
  623. width: 40%;
  624. height: 95%;
  625. margin: 0 auto;
  626. position: relative;
  627. }
  628. .img::after {
  629. content: "";
  630. position: absolute;
  631. top: 50%;
  632. transform: translateX(26%);
  633. width: 200%;
  634. height: 1px;
  635. // background-color: #546882;
  636. background-color: #00aaff;
  637. box-shadow: 0 5px 15px rgba(0, 170, 255, 0.5);
  638. }
  639. .noAfter::after {
  640. content: none;
  641. }
  642. .odd::before {
  643. content: "";
  644. position: absolute;
  645. transform: translateY(-50%);
  646. width: 1px;
  647. height: 50%;
  648. // background-color: #546882;
  649. background-color: #00aaff;
  650. box-shadow: 0 5px 15px rgba(0, 170, 255, 0.5);
  651. }
  652. .even::before {
  653. content: "";
  654. position: absolute;
  655. bottom: 0;
  656. transform: translateY(50%);
  657. width: 1px;
  658. height: 50%;
  659. // background-color: #546882;00aaff
  660. background-color: #00aaff;
  661. box-shadow: 0 5px 15px rgba(0, 170, 255, 0.5);
  662. }
  663. .yuanBg {
  664. background: url("../assets/images/yuan.png") no-repeat center / contain;
  665. }
  666. .oneBg {
  667. background: url("../assets/images/one.png") no-repeat center / contain;
  668. }
  669. .twoBg {
  670. background: url("../assets/images/two.png") no-repeat center / contain;
  671. }
  672. .threeBg {
  673. background: url("../assets/images/three.png") no-repeat center / contain;
  674. }
  675. .fourBg {
  676. background: url("../assets/images/four.png") no-repeat center / contain;
  677. }
  678. .fiveBg {
  679. background: url("../assets/images/five.png") no-repeat center / contain;
  680. }
  681. .sixBg {
  682. background: url("../assets/images/six.png") no-repeat center / contain;
  683. }
  684. .tag {
  685. color: #fff;
  686. background: linear-gradient(to right, rgba(8, 200, 236, 0), rgba(8, 200, 236, 0.8), rgba(8, 200, 236, 0.8), rgba(8, 200, 236, 0));
  687. position: absolute;
  688. top: -15px;
  689. left: 100%;
  690. }
  691. }
  692. .topPanel {
  693. width: 100%;
  694. height: 37%;
  695. display: flex;
  696. justify-content: space-between;
  697. margin-bottom: 1.5%;
  698. }
  699. .bottomPanel {
  700. width: 100%;
  701. height: 37%;
  702. display: flex;
  703. justify-content: space-around;
  704. margin-left: 6%;
  705. margin-top: 1%;
  706. }
  707. .tPanel,
  708. .bPanel {
  709. // position: relative;
  710. width: 18%;
  711. height: 95%;
  712. overflow: auto;
  713. // background: url("../assets/images/msgBg3.png") no-repeat center / contain;
  714. // background: rgba(0, 0, 0, 0.15);
  715. border: 2px solid transparent;
  716. background-clip: padding-box;
  717. box-shadow: 0 0 10px rgba(63, 155, 255, 0.5);
  718. border-radius: 5%;
  719. }
  720. }
  721. .file {
  722. cursor: pointer;
  723. }
  724. .file:hover {
  725. color: #00aaff;
  726. }
  727. .square {
  728. width: 90px;
  729. height: 50px;
  730. line-height: 50px;
  731. text-align: center;
  732. border-radius: 12px;
  733. font-size: 14px;
  734. border: 2px solid grey;
  735. }
  736. .diamond {
  737. height: 100px;
  738. width: 100px;
  739. transform: rotateZ(45deg) skew(-20deg, -20deg);
  740. position: relative;
  741. border: 2px solid grey;
  742. .diamond-p {
  743. position: absolute;
  744. width: 140px;
  745. top: 14%;
  746. left: -17%;
  747. transform: skew(20deg, 20deg) rotateZ(-45deg);
  748. }
  749. }
  750. ::-webkit-scrollbar {
  751. display: none;
  752. }
  753. ::v-deep .el-table__empty-block {
  754. background-color: #0b333f !important;
  755. border: #0b333f;
  756. }
  757. </style>