index.vue 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655
  1. <template>
  2. <div id="DataLog">
  3. <div class="top">
  4. <!-- <h2>数据同步管理</h2> -->
  5. <!-- <div class="serve-updata">
  6. <span> 中台状态 </span>
  7. <el-popover placement="bottom" width="200" trigger="hover">
  8. <div>
  9. <div><span class="status-1"></span><span>:正常</span></div>
  10. <div><span class="status-2"></span><span>:异常</span></div>
  11. </div>
  12. <i slot="reference" className="infomations el-icon-information"></i> </el-popover
  13. >:
  14. <div ref="status" class="state"></div>
  15. </div> -->
  16. </div>
  17. <div style="margin-top: 8px" class="">
  18. <div class="modify">
  19. <el-button type="primary" icon="el-icon-download" @click="exportSqlHandle" :loading='sqlBtnLoading' :disabled='sqlBtnLoading'>导出SQL文件</el-button>
  20. <div>
  21. <el-input style="width: 220px" placeholder="请输入内容" @input="httpInputChange" @blur="httpInputBlur" :value="httpValue" />
  22. <el-button type="primary" style="margin-left: 8px" :loading='httpBtnLoading' :disabled='!httpValue' @click="httpExportHandle">导出Excel</el-button>
  23. <el-button type="primary" :loading='syncBtnLoading' :disabled='!httpValue || !isExported' @click="syncDataHandle">同步</el-button>
  24. </div>
  25. </div>
  26. <el-divider />
  27. <div v-if="isShowTable" class="screen">
  28. <p>筛选条件</p>
  29. <ul class="screen-list">
  30. <li>
  31. <span>&emsp;操作符:</span>
  32. <el-select v-model="operationValue" :clearable="true" @change="operationChange" placeholder="请选择">
  33. <el-option v-for="item in operation" :key="item.value" :label="item.label" :value="item.value"> </el-option>
  34. </el-select>
  35. </li>
  36. <li>
  37. <span>&emsp;&emsp;状态:</span>
  38. <el-select v-model="sign" @change="signChange">
  39. <el-option label="成功" :value="2"> </el-option>
  40. <el-option label="失败" :value="1"> </el-option>
  41. </el-select>
  42. </li>
  43. <li>
  44. <span>&emsp;目标id:</span>
  45. <el-input v-model="targetId" :clearable="true" placeholder="请输入对象id" style="width: 220px" @change="objIdChange"></el-input>
  46. </li>
  47. <li>
  48. <span>&emsp;对象表:</span>
  49. <el-select v-model="tableName" @change="objTableChange" placeholder="请选择">
  50. <el-option v-for="(item, key) in ENUM_OBJECT_TABLE" :key="key" :label="item" :value="key"></el-option>
  51. </el-select>
  52. </li>
  53. </ul>
  54. <ul class="screen-list">
  55. <li v-if="tableName === 'dt_object'">
  56. <span>对象类型:</span>
  57. <el-select v-model="objTypeValue" :clearable="true" @change="objTypeChange" placeholder="请选择">
  58. <el-option v-for="item in objType" :key="item.value" :label="item.label" :value="item.value"> </el-option>
  59. </el-select>
  60. </li>
  61. <li>
  62. <span>同步时间:</span>
  63. <el-date-picker
  64. v-model="timeParam"
  65. type="datetimerange"
  66. format="yyyy-MM-dd HH:mm"
  67. start-placeholder="开始日期"
  68. end-placeholder="结束日期"
  69. @change="timeChange"
  70. >
  71. </el-date-picker>
  72. </li>
  73. <li></li>
  74. <li></li>
  75. </ul>
  76. <el-table
  77. v-loading="loading"
  78. element-loading-text="拼命加载中"
  79. style="width: 100%; margin-top: 24px"
  80. :data="data"
  81. :stripe="true"
  82. :maxHeight="620"
  83. size='small'
  84. @sort-change="handleSort"
  85. >
  86. <el-table-column label="Id" >
  87. <template slot-scope="scope">
  88. <span style="margin-left: 10px">{{ scope.row.targetId ? scope.row.targetId : "--" }}</span>
  89. </template>
  90. </el-table-column>
  91. <el-table-column :label='TABLE_NAME[tableName]' >
  92. <template slot-scope="scope">
  93. <span style="margin-left: 10px">{{ scope.row.name ? scope.row.name : "--" }}</span>
  94. </template>
  95. </el-table-column>
  96. <el-table-column label="操作类型">
  97. <template slot-scope="scope">
  98. <span style="margin-left: 10px">{{ typeObj[scope.row.type] ? typeObj[scope.row.type] : "--" }}</span>
  99. </template>
  100. </el-table-column>
  101. <!-- 关系实例表 -->
  102. <template v-if="tableName === 'dt_relation'">
  103. <el-table-column label="fromId" >
  104. <template slot-scope="scope">
  105. <span style="margin-left: 10px">{{ scope.row.fromId ? scope.row.fromId : "--" }}</span>
  106. </template>
  107. </el-table-column>
  108. <el-table-column label="toId" >
  109. <template slot-scope="scope">
  110. <span style="margin-left: 10px">{{ scope.row.toId ? scope.row.toId : "--" }}</span>
  111. </template>
  112. </el-table-column>
  113. </template>
  114. <!-- 对象实例表 -->
  115. <template v-else-if="tableName === 'dt_object'">
  116. <el-table-column label="本地名称" >
  117. <template slot-scope="scope">
  118. <span style="margin-left: 10px">{{ scope.row.localName ? scope.row.localName : "--" }}</span>
  119. </template>
  120. </el-table-column>
  121. <el-table-column label="本地编码">
  122. <template slot-scope="scope">
  123. <span style="margin-left: 10px">{{ scope.row.localId ? scope.row.localId : "--" }}</span>
  124. </template>
  125. </el-table-column>
  126. <el-table-column label="对象类型" >
  127. <template slot-scope="scope">
  128. <span style="margin-left: 10px">{{ scope.row.objectType ? OBJ_TYPE[scope.row.objectType] : "--" }}</span>
  129. </template>
  130. </el-table-column>
  131. </template>
  132. <!-- 其他表 -->
  133. <template v-else>
  134. <el-table-column label="编码" >
  135. <template slot-scope="scope">
  136. <span style="margin-left: 10px">{{ scope.row.code ? scope.row.code : "--" }}</span>
  137. </template>
  138. </el-table-column>
  139. </template>
  140. <el-table-column label="状态" >
  141. <template slot-scope="scope">
  142. <span style="margin-left: 10px">{{ scope.row.sign ? (scope.row.sign === 1 ? '失败' : '成功') : "--" }}</span>
  143. </template>
  144. </el-table-column>
  145. <el-table-column label="同步时间" >
  146. <template slot-scope="scope">
  147. <span style="margin-left: 10px">{{ scope.row.creationTime | timeFormat }}</span>
  148. </template>
  149. </el-table-column>
  150. <el-table-column label="错误信息" >
  151. <template slot-scope="scope">
  152. <span style="margin-left: 10px">{{ scope.row.error ? scope.row.error : "--" }}</span>
  153. </template>
  154. </el-table-column>
  155. </el-table>
  156. <!-- {/* 分页 */} -->
  157. <div class="pages">
  158. <el-pagination
  159. layout="total, sizes, prev, pager, next, jumper"
  160. :total="this.pageObj.total"
  161. :pageSizes="[15, 30, 50, 100]"
  162. @size-change="onSizeChange"
  163. @current-change="onCurrentChange"
  164. :pageSize="pageObj.pageSize"
  165. :currentPage="pageObj.pageNumber"
  166. />
  167. </div>
  168. </div>
  169. <div v-else class="no-data">
  170. <img src="@/assets/image/no-data.png" />
  171. </div>
  172. </div>
  173. </div>
  174. </template>
  175. <script>
  176. import { mapGetters } from 'vuex'
  177. import {
  178. queryobjType,
  179. syncDataLogList,
  180. syncData,
  181. queryRecordUpdata,
  182. dHttpExport,
  183. exportSql
  184. } from "@/api/synclog";
  185. import moment from 'moment'
  186. import { ENUM_OBJECT_TABLE, OBJ_TYPE, TABLE_NAME } from './constant'
  187. export default {
  188. data() {
  189. return {
  190. ENUM_OBJECT_TABLE,
  191. OBJ_TYPE,
  192. TABLE_NAME,
  193. groupCode: "", //集团id
  194. isShowTable: false, //是否显示table
  195. data: [],
  196. objClassify: [],
  197. //对象类型
  198. objType: [
  199. {
  200. value: "building",
  201. label: "建筑",
  202. },
  203. {
  204. value: "floor",
  205. label: "楼层",
  206. },
  207. {
  208. value: "equipment",
  209. label: "设备",
  210. },
  211. {
  212. value: "component",
  213. label: "部件",
  214. },
  215. {
  216. value: "space",
  217. label: "空间",
  218. },
  219. {
  220. value: "system",
  221. label: "系统",
  222. },
  223. {
  224. value: "shaft",
  225. label: "竖井",
  226. },
  227. ],
  228. typeObj: { // 操作符类型
  229. create: "创建",
  230. update: "修改",
  231. delete: "删除",
  232. },
  233. //操作下拉框
  234. operation: [
  235. {
  236. value: "create",
  237. label: "创建",
  238. },
  239. {
  240. value: "update",
  241. label: "修改",
  242. },
  243. {
  244. value: "delete",
  245. label: "删除",
  246. },
  247. ],
  248. objClassifyValue: "", //对象分类状态
  249. operationValue: "", //操作符状态
  250. objTypeValue: "", //对象类型状态
  251. sign: 2, //状态(默认成功),1:失败, 2成功
  252. targetId: '', //对象id
  253. tableName: 'dt_object', //对象表
  254. loading: false, //是否加载
  255. order: "creationTime desc", //时间倒序排列
  256. pageObj: {
  257. total: 0, //总计
  258. pageSize: 50, //每页数量
  259. pageNumber: 1, //第几页
  260. },
  261. httpBtnLoading: false, //域名导出按钮状态
  262. httpBtnDisable: true, //域名导出按钮禁用状态
  263. httpValue: '', //域名内容
  264. isExported: false, //是否已导出excel,未导出则不可同步
  265. syncBtnLoading: false, //同步按钮状态
  266. sqlBtnLoading: false, //导出sql文件按钮状态
  267. timeParam: []
  268. }
  269. },
  270. computed: {
  271. ...mapGetters("layout", ["projectId", "projectName"]),
  272. },
  273. filters: {
  274. timeFormat(val) {
  275. if(!val) return '--';
  276. return moment(val).format('YYYY-MM-DD HH:mm:ss')
  277. }
  278. },
  279. methods: {
  280. // 同步数据
  281. syncDataHandle() {
  282. this.$message.closeAll();
  283. this.$confirm('同步前,请确认导出表格数据正确?', '警告', {
  284. confirmButtonText: '确定',
  285. cancelButtonText: '取消',
  286. type: 'warning'
  287. }).then(() => {
  288. this.syncBtnLoading = true;
  289. syncData(
  290. {
  291. targetUrl: this.httpValue
  292. },
  293. res => {
  294. this.pageObj = {
  295. ...this.pageObj,
  296. pageNumber: 1
  297. }
  298. this.syncBtnLoading = false;
  299. this.isExported = false; //同步成功后禁用同步按钮
  300. this.getData();
  301. },
  302. err => {
  303. this.syncBtnLoading = false;
  304. // this.getData();
  305. }
  306. )
  307. }).catch(() => {
  308. this.$message({
  309. type: 'info',
  310. message: '已取消同步操作'
  311. });
  312. });
  313. },
  314. httpInputChange(val) {
  315. this.httpValue = val.trim();
  316. },
  317. httpInputBlur(e) {
  318. const value = e.target.value;
  319. const regExp = /^(?=^.{3,255}$)(http(s)?:\/\/)?(www\.)?[a-zA-Z0-9][-a-zA-Z0-9]{0,62}(\.[a-zA-Z0-9][-a-zA-Z0-9]{0,62})+(:\d+)*(\/\w+\.\w+)*$/ //域名校验正则
  320. this.$message.closeAll();
  321. const { origin } = location;
  322. if ( origin == value) {
  323. this.httpValue = '';
  324. this.$message.warning('不可同步当前域名数据!')
  325. }
  326. if (value && !regExp.test(value)) {
  327. this.httpValue = '';
  328. this.$message.warning('请输入合法的域名')
  329. }
  330. },
  331. httpExportHandle() {
  332. this.httpBtnLoading = true;
  333. dHttpExport(
  334. {
  335. targetUrl: this.httpValue
  336. },
  337. () => {
  338. this.httpBtnLoading = false;
  339. this.isExported = true
  340. }
  341. )
  342. },
  343. /**
  344. * @description: 导出sql文件
  345. * @param {*}
  346. * @return {*}
  347. */
  348. exportSqlHandle() {
  349. this.sqlBtnLoading = true
  350. exportSql({}, res => {
  351. this.sqlBtnLoading = false;
  352. this.$message.success('导出sql文件操作成功!')
  353. })
  354. },
  355. // 项目id请求接口
  356. getData() {
  357. this.getTable();
  358. this.loading = true;
  359. },
  360. // 获取对象类型下拉框
  361. getObjTypeList() {
  362. const data = {
  363. projectId: this.projectId,
  364. objType: this.objTypeValue,
  365. };
  366. queryobjType(data, res => {
  367. const objClassify = res.content.map((item) => {
  368. return {
  369. value: item.code,
  370. label: item.name,
  371. };
  372. });
  373. this.objClassify = objClassify;
  374. });
  375. },
  376. // 对象类型发生变化
  377. objTypeChange(val) {
  378. this.objTypeValue = val;
  379. this.objClassifyValue = "";
  380. // if (val == "equipment" || val == "space" || val == "system" || val == "component") {
  381. // this.getObjTypeList();
  382. // } else {
  383. this.objClassify = [];
  384. // }
  385. this.getTable();
  386. },
  387. // change变化触发获取tablelist
  388. operationChange(val) {
  389. this.operationValue = val;
  390. this.getTable();
  391. },
  392. // 对象类型编号
  393. objClassChange(val) {
  394. this.objClassifyValue = val;
  395. this.getTable();
  396. },
  397. // 状态变化
  398. signChange(val) {
  399. this.sign = val;
  400. this.getTable();
  401. },
  402. // 对象表变化
  403. objTableChange(val) {
  404. this.tableName = val;
  405. },
  406. // 时间变动
  407. timeChange() {
  408. this.getTable();
  409. },
  410. // 对象id变化
  411. objIdChange(val) {
  412. this.targetId = val.trim();
  413. this.getTable();
  414. },
  415. // 请求table
  416. getTable() {
  417. this.loading = true;
  418. if (this.projectId) {
  419. // 请求table以及中台状态接口
  420. //对象类型
  421. const objectType = this.objTypeValue
  422. ? `;objectType='${this.objTypeValue}'`
  423. : "";
  424. // 对象分类
  425. const classCodeName = this.objClassifyValue
  426. ? `;classCode='${this.objClassifyValue}'`
  427. : "";
  428. // 操作符状态
  429. const type = this.operationValue
  430. ? `;type='${this.operationValue}'`
  431. : "";
  432. // 对象表
  433. const tableName = this.tableName ? `;tableName='${this.tableName}'` : ''
  434. // 对象id
  435. const targetId = this.targetId ? `;targetId='${this.targetId}'` : ''
  436. // 时间范围
  437. let creationTime = this.timeParam && this.timeParam.map(item => moment(item).format('YYYYMMDDHHmm'))
  438. creationTime = creationTime && !!creationTime.length ? `;creationTime in [${creationTime}]` : ''
  439. const postParam = {
  440. orders: this.order,
  441. pageNumber: this.pageObj.pageNumber,
  442. pageSize: this.pageObj.pageSize,
  443. filters: `projectId='${this.projectId}';sign=${this.sign}${type}${classCodeName}${objectType}${tableName}${targetId}${creationTime}`,
  444. };
  445. syncDataLogList(postParam, res => {
  446. this.isShowTable = true;
  447. this.data = res.content;
  448. this.loading = false;
  449. this.pageObj = Object.assign(this.pageObj, {
  450. total: res.total,
  451. // pageNumber: res.pageNumber,
  452. // pageSize: res.pageSize,
  453. });
  454. }, () => {
  455. this.isShowTable = false;
  456. this.loading = false;
  457. this.data = [];
  458. })
  459. } else {
  460. this.isShowTable = false;
  461. }
  462. },
  463. // 输入改变输入参数
  464. onChange(key, value) {
  465. this[key] = value;
  466. // this.forceUpdate();
  467. },
  468. // 忽略该条信息
  469. hideMsg(res) {
  470. const data = {
  471. content: [
  472. {
  473. ...Object.assign(res, {
  474. sign: 3,
  475. }),
  476. },
  477. ],
  478. };
  479. this.loading = true;
  480. queryRecordUpdata(data, res => {
  481. if (res.result == "success")
  482. this.$message({
  483. showClose: true,
  484. message: "忽略完成",
  485. type: "success",
  486. duration: 3000,
  487. });
  488. this.getTable();
  489. }, () => {
  490. this.$message({
  491. showClose: true,
  492. message: "忽略失败,请重新同步或联系管理人员!",
  493. type: "error",
  494. duration: 3000,
  495. });
  496. this.loading = false;
  497. })
  498. },
  499. // 改变pageSize
  500. onSizeChange(val) {
  501. this.pageObj = Object.assign(this.pageObj, {
  502. pageSize: val,
  503. pageNumber: 1,
  504. });
  505. this.getTable();
  506. },
  507. // 改变当前页
  508. onCurrentChange(val) {
  509. this.pageObj = Object.assign(this.pageObj, {
  510. pageNumber: val,
  511. });
  512. this.getTable();
  513. },
  514. // 时间排序
  515. handleSort(data) {
  516. if (data.order == "descending") {
  517. this.order = "lastUpdate desc, objId desc";
  518. } else {
  519. this.order = "lastUpdate asc, objId asc";
  520. }
  521. this.getTable();
  522. },
  523. },
  524. mounted() {
  525. this.getData();
  526. // this.ENUM_OBJECT_TABLE = ;
  527. // this. = OBJ_TYPE
  528. },
  529. watch: {
  530. projectId() {
  531. this.getData();
  532. }
  533. }
  534. }
  535. </script>
  536. <style lang="less">
  537. #DataLog {
  538. padding: 20px 20px;
  539. box-sizing: border-box;
  540. }
  541. .pages {
  542. float: right;
  543. margin-top: 12px;
  544. margin-right: 24px;
  545. }
  546. .top {
  547. display: flex;
  548. align-items: center;
  549. justify-content: space-between;
  550. }
  551. .top .serve-updata {
  552. display: flex;
  553. align-items: center;
  554. margin-right: 12px;
  555. }
  556. .top .serve-updata .state {
  557. width: 20px;
  558. height: 20px;
  559. /* background: ; */
  560. border-radius: 50% 50%;
  561. margin-left: 6px;
  562. margin-right: 6px;
  563. }
  564. .status-1 {
  565. background: #19f704;
  566. border-radius: 50% 50%;
  567. width: 12px;
  568. height: 12px;
  569. display: inline-block;
  570. }
  571. .status-2 {
  572. display: inline-block;
  573. width: 12px;
  574. height: 12px;
  575. background: #4a4a4a;
  576. border-radius: 50% 50%;
  577. }
  578. .project {
  579. display: flex;
  580. width: 300px;
  581. align-items: center;
  582. justify-content: space-between;
  583. margin-bottom: 24px;
  584. }
  585. .project p {
  586. width: 90px;
  587. }
  588. .screen {
  589. margin-bottom: 12px;
  590. }
  591. .screen .screen-list {
  592. display: flex;
  593. align-items: center;
  594. justify-content: space-between;
  595. padding: 12px;
  596. li {
  597. width: 25%;
  598. }
  599. }
  600. .screen ul li {
  601. margin-left: 12px;
  602. }
  603. .infomations {
  604. cursor: pointer;
  605. }
  606. .no-data {
  607. width: 100%;
  608. min-height: 600px;
  609. display: flex;
  610. justify-content: center;
  611. align-items: center;
  612. }
  613. .mlr8 {
  614. margin: 0 8px;
  615. }
  616. .el-divider--horizontal {
  617. height: 0.5px;
  618. }
  619. .modify {
  620. display: flex;
  621. justify-content: space-between;
  622. }
  623. </style>