index.vue 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694
  1. <template>
  2. <div id="deviceList">
  3. <el-row class="left">
  4. <span style="float: left">当前选择的部件类型:{{ category.name }}</span>
  5. <!-- <div style="width:200px;display:inline-block;text-align:left;color:gray;">
  6. <span>隐藏自动填充的信息</span>
  7. <el-checkbox v-model="isWatch" @change="getTableHeader"></el-checkbox>
  8. </div> -->
  9. <span style="float: right">
  10. <el-select
  11. v-model="showType"
  12. @change="initTable"
  13. style="width: 140px; margin-right: 10px; vertical-align: bottom"
  14. >
  15. <el-option
  16. v-for="item in showTypes"
  17. :key="item.value"
  18. :label="item.label"
  19. :value="item.value"
  20. >
  21. </el-option>
  22. </el-select>
  23. <span>增加</span>
  24. <el-input-number
  25. v-model="addNum"
  26. :controls="false"
  27. style="width: 50px"
  28. :min="1"
  29. :max="50"
  30. ></el-input-number>
  31. <span>个{{ category.name }}</span>
  32. <el-button @click="handleAddTableRow">增加</el-button>
  33. </span>
  34. </el-row>
  35. <div class="tableBox">
  36. <div
  37. class="center middle_sty"
  38. style="flex: 2"
  39. v-show="tableData && !tableData.length"
  40. >
  41. <p>
  42. <i class="icon-wushuju iconfont"></i>
  43. 暂无数据
  44. </p>
  45. </div>
  46. <div class="tableLeft" v-show="tableData && tableData.length">
  47. <handson-table ref="table"></handson-table>
  48. </div>
  49. </div>
  50. <el-row class="center">
  51. <el-button
  52. type="primary"
  53. size="medium"
  54. @click="handleCreateTableData"
  55. class="create_button"
  56. :disabled="createDisable"
  57. >创建部件</el-button
  58. >
  59. </el-row>
  60. <!-- 二维码弹窗 -->
  61. <qrcode
  62. :dialog="myDialog"
  63. :qrcodeUrl="qrcodeUrl"
  64. :addBody="true"
  65. ref="qrcode"
  66. ></qrcode>
  67. <upload-files-dialog
  68. :read="onlyRead ? true : false"
  69. ref="upload"
  70. @changeFile="fileChange"
  71. :keysArr="filesArr"
  72. :dialog="myDialog"
  73. >
  74. </upload-files-dialog>
  75. <upload-img-dialog
  76. :read="onlyRead ? true : false"
  77. @changeFile="imgChange"
  78. :keysArr="imgsArr"
  79. :dialog="myDialog"
  80. ></upload-img-dialog>
  81. <pic-dialog
  82. :read="onlyRead ? true : false"
  83. :dialog="myDialog"
  84. :keysArr="picsArr"
  85. @change="changePics"
  86. ></pic-dialog>
  87. <details-dialog
  88. :iframeSrc="iframeSrc"
  89. v-if="myDialog.details"
  90. :dialog="myDialog"
  91. ></details-dialog>
  92. <!-- 多选枚举类型维护 -->
  93. <menum
  94. :dialog="myDialog"
  95. :updateInfoData="updateInfoData"
  96. :updateInput="updateInput"
  97. @change="handleChangeMenum"
  98. ></menum>
  99. <!-- 不支持的输入方式 -->
  100. <el-dialog
  101. title="临时维护信息点"
  102. :visible.sync="myDialog.update"
  103. @close="handleCloseUpdate"
  104. width="670px"
  105. >
  106. <el-row>
  107. 该信息点未定义对应组件,现在维护数据不确定后续是否可用。如确实需要维护,请点击
  108. <el-link
  109. @click="updateInputShow = true"
  110. type="primary"
  111. :underline="false"
  112. >继续维护</el-link
  113. >
  114. </el-row>
  115. <el-row style="margin-top: 20px" v-show="updateInputShow">
  116. <el-input
  117. type="textarea"
  118. :autosize="{ minRows: 4, maxRows: 8 }"
  119. placeholder="请输入内容"
  120. v-model="updateInput"
  121. ></el-input>
  122. </el-row>
  123. <span slot="footer" class="dialog-footer">
  124. <el-button @click="myDialog.update = false">取 消</el-button>
  125. <el-button type="primary" @click="handleClickUpdate">确 认</el-button>
  126. </span>
  127. </el-dialog>
  128. </div>
  129. </template>
  130. <script>
  131. import tools from "@/utils/old-adm/scan/tools";
  132. import handsonUtils from "@/utils/old-adm/hasontableUtils";
  133. import showTools from "@/utils/handsontable/notShow";
  134. import text from "@/utils/handsontable/mainText";
  135. import session from "@/framework/utils/storage";
  136. import handsonTable from "@/components/old-adm/common/handsontable";
  137. import {
  138. // getDataDictionary,
  139. createPart,
  140. createPropertyData,
  141. getEquipBelongs,
  142. } from "@/api/scan/request";
  143. import { getDataDictionary } from "@/api/dict";
  144. import { mapGetters, mapActions } from "vuex";
  145. import qrcode from "@/components/old-adm/ledger/lib/qrcode";
  146. import uploadFilesDialog from "@/components/old-adm/dialogs/list/filesDialog";
  147. import uploadImgDialog from "@/components/old-adm/dialogs/list/uploadImgDialog";
  148. import picDialog from "@/components/old-adm/dialogs/list/picDialog";
  149. import menum from "@/components/old-adm/dialogs/list/menum";
  150. export default {
  151. components: {
  152. qrcode, //二维码页面
  153. uploadFilesDialog,
  154. uploadImgDialog,
  155. picDialog,
  156. handsonTable,
  157. menum,
  158. },
  159. data() {
  160. return {
  161. addNum: 1,
  162. onlyRead: false,
  163. tableHeader: [],
  164. // tableData: session.get("partsAddData")
  165. // ? session.get("partsAddData").length
  166. // ? session.get("partsAddData")
  167. // : [{ Checked: 1 }]
  168. // : [{ Checked: 1 }],
  169. tableData: session.get("partsAddData")
  170. ? session.get("partsAddData").length
  171. ? session.get("partsAddData")
  172. : [{}]
  173. : [{}],
  174. showTypes: [
  175. // { value: "partInfo", label: '隐藏信息点' },
  176. { value: "Visible", label: "只看需交付的" },
  177. { value: "all", label: "全部" },
  178. ],
  179. showType: this.$route.query.showType,
  180. copyTableData: [],
  181. category: "", //当前设备类
  182. myDialog: {
  183. qrcode: false, //二维码弹窗
  184. uploadFiles: false, //上传文件
  185. uploadImgs: false, //上传单个图片
  186. pic: false, //多个图片
  187. addDevice: false,
  188. systemType: false,
  189. details: false, //详情页
  190. changeRea: false,
  191. lookPic: false, //图片查看
  192. update: false, //临时维护信息点
  193. menum: false, //临时多选枚举类型信息点
  194. },
  195. inputMap: {
  196. flowBuild: {
  197. editable: true,
  198. code: "flowBuild",
  199. name: "建筑楼层",
  200. path: "flowBuild",
  201. category: "STATIC",
  202. dataType: "ENUM",
  203. },
  204. }, //信息点和输入方式映射表
  205. updateInputShow: false, //是否显示临时维护输入框
  206. updateInfoData: {}, //当前信息点信息
  207. updateInfoPoint: "", //临时维护信息点
  208. updateInput: "", //临时维护信息点值
  209. qrcodeUrl: "", //二维码图片地址
  210. filesArr: [], //保存临时的文件key
  211. imgsArr: [], //临时保存的图片key数组
  212. picsArr: [], //临时设备图片keys数组
  213. systemId: null,
  214. graphyId: null,
  215. id: 0,
  216. EquipmentList: [],
  217. firmId: "", //品牌型号所需字段--族id三位编码(传设备类id或部件类id)
  218. createDisable: false,
  219. };
  220. },
  221. computed: {
  222. ...mapGetters("layout", ["projectId", "secret", "userId"]),
  223. },
  224. created() {
  225. this.category = this.$route.query;
  226. this.category.parentId = this.category.code.substr(
  227. 0,
  228. this.category.code.length - 2
  229. );
  230. this.getBelongs();
  231. this.getTableHeader();
  232. },
  233. methods: {
  234. //查询部件类对应的 族
  235. getBelongs() {
  236. let params = {
  237. data: {
  238. filters: `equipCode='${this.category.code}'`,
  239. pageNumber: 1,
  240. pageSize: 50,
  241. },
  242. };
  243. getEquipBelongs(params, (res) => {
  244. if (res.content.length) {
  245. this.firmId = res.content[0].family;
  246. }
  247. });
  248. },
  249. // 获取表头数据(初始化表格)
  250. async getTableHeader() {
  251. let params = {
  252. orders: "sort asc, name desc",
  253. pageNumber: 1,
  254. pageSize: 1000,
  255. type: this.category.code,
  256. // Filters: `type='Equipment' or type='${this.category.Code}'`
  257. };
  258. await getDataDictionary(params, (res) => {
  259. this.tableHeader = res.content;
  260. this.tableHeader.forEach((item) => {
  261. if (item.path) {
  262. this.inputMap[item.path] = item;
  263. }
  264. });
  265. this.initTable();
  266. });
  267. },
  268. // 创建部件数据
  269. async handleCreateTableData() {
  270. let newData = this.tableData.filter((item) => {
  271. let keys = Object.keys(item);
  272. keys.map((key) => {
  273. //将值为空字符串的属性删除
  274. if (item[key] == "") {
  275. delete item[key];
  276. }
  277. });
  278. let newK = Object.keys(item);
  279. if (
  280. (item.Checked && newK.length > 1) ||
  281. (!item.Checked && newK.length)
  282. ) {
  283. return item;
  284. }
  285. });
  286. if (!newData.length) {
  287. this.$message("创建信息为空,请录入信息后再创建!");
  288. return;
  289. }
  290. let flag = false;
  291. newData.map((item) => {
  292. if (!item.localName || !item.localId) {
  293. flag = true;
  294. }
  295. });
  296. if (flag) {
  297. this.$message.info("存在设备的本地名称或本地编码为空,请检查");
  298. return;
  299. }
  300. for (let i = 0; i < newData.length; i++) {
  301. newData[i].parentId = this.category.deviceId; //当前设备id
  302. newData[i].classCode = this.category.code; //当前部件分类
  303. newData[i].family = this.firmId;
  304. //待接口修改为关联创建
  305. let param = {
  306. cascade: [],
  307. content: [newData[i]],
  308. };
  309. this.createDisable = true;
  310. await createPart(param, async (res) => {
  311. // if (newData[i].Checked) {
  312. // //同时创建资产
  313. // param.content[0].equipmentId = res.entityList[0].id;
  314. // await createPropertyData(param, (res) => {
  315. // // todo 创建资产
  316. // });
  317. // }
  318. if (i == newData.length - 1) {
  319. this.createDisable = false;
  320. this.$message.success("创建成功");
  321. session.remove("partsAddData");
  322. this.$router.push({
  323. path: "/ledger/partsmanage",
  324. query: {
  325. deviceId: this.category.deviceId,
  326. typeId: this.category.parentId,
  327. pageNo: this.category.pageNo,
  328. pageSize: this.category.pageSize,
  329. },
  330. });
  331. }
  332. });
  333. }
  334. },
  335. // 删除表格行
  336. handleDeleteTableRow(a, b, c, d) {
  337. if (d && d === "ContextMenu.removeRow") {
  338. this.$message.success("删除成功");
  339. this.formaTableData();
  340. }
  341. },
  342. // 添加行
  343. handleAddTableRow() {
  344. let addRowLength = this.addNum;
  345. for (let i = 0; i < addRowLength; i++) {
  346. // this.tableData.push({ Checked: 1 });
  347. this.tableData.push({});
  348. }
  349. this.initTable();
  350. this.formaTableData();
  351. },
  352. //修改
  353. handleUpdataTable(changeData, source) {
  354. if (!this.onlyRead && source != "ObserveChanges.change") {
  355. this.formaTableData();
  356. }
  357. },
  358. //保存去掉空字段的新增数据
  359. formaTableData() {
  360. let newData = this.tableData.filter((item) => {
  361. let keys = Object.keys(item);
  362. keys.map((key) => {
  363. //将值为空字符串的属性删除
  364. if (item[key] == "") {
  365. delete item[key];
  366. }
  367. });
  368. if (keys.length && Object.keys(item).length) {
  369. return item;
  370. }
  371. });
  372. session.set("partsAddData", newData);
  373. },
  374. //格式化表头显示的数据
  375. formatHeaderData(list) {
  376. let arr = tools.copyArr(list);
  377. let data = showTools.headerTextFilter(
  378. arr,
  379. "parts",
  380. this.onlyRead,
  381. this.showType,
  382. true
  383. );
  384. // data.unshift("同时创建资产");
  385. return data;
  386. },
  387. formatHeaderType(list) {
  388. //格式化表头头映射的数据
  389. let arr = tools.copyArr(list);
  390. let data = showTools.headerTypeFilter(
  391. arr,
  392. "parts",
  393. this.onlyRead,
  394. this.showType,
  395. true
  396. );
  397. // data.unshift({
  398. // type: "checkbox",
  399. // checkedTemplate: 1,
  400. // uncheckedTemplate: 0,
  401. // data: "Checked",
  402. // label: {
  403. // position: "after",
  404. // },
  405. // });
  406. return data;
  407. },
  408. initTable() {
  409. //实例化表格
  410. let settings = {
  411. data: this.tableData,
  412. colHeaders: this.formatHeaderData(this.tableHeader),
  413. columns: this.formatHeaderType(this.tableHeader),
  414. rowHeights: 30,
  415. fillHandle: "vertical", //允许纵向填充
  416. maxRows: this.tableData.length,
  417. contextMenu: this.onlyRead
  418. ? false
  419. : {
  420. items: {
  421. remove_row: {
  422. name: "删除部件",
  423. },
  424. },
  425. },
  426. // 事件
  427. afterChange: this.handleUpdataTable, //修改后
  428. afterFilter: this.trimmedRows, //排序前
  429. afterRemoveRow: this.handleDeleteTableRow, //右键删除
  430. afterOnCellMouseDown: this.handleTdClick, //鼠标点击
  431. };
  432. this.$nextTick(() => {
  433. this.tableExample = this.$refs.table.init(settings);
  434. });
  435. },
  436. //去除数组中相同的元素
  437. array_diff(a, b) {
  438. for (var i = 0; i < b.length; i++) {
  439. for (var j = 0; j < a.length; j++) {
  440. if (a[j] == b[i]) {
  441. a.splice(j, 1);
  442. j = j - 1;
  443. }
  444. }
  445. }
  446. return a;
  447. },
  448. //上传文件弹窗触发事件
  449. fileChange(keys) {
  450. this.setDataToMain(keys, this.messKey, this.row);
  451. },
  452. //上传图片弹窗触发事件
  453. imgChange(keys) {
  454. this.setDataToMain(keys, this.messKey, this.row);
  455. },
  456. //设备图片弹窗改变事件
  457. changePics(keys) {
  458. this.setDataToMain(keys, this.messKey, this.row);
  459. },
  460. //表格点击事件
  461. handleTdClick(el, rowArr) {
  462. //点击的是表头
  463. if (rowArr.row < 0) {
  464. return;
  465. }
  466. //被筛选过后的数组
  467. let trimmedArr = this.trimmedRows();
  468. //是否启用了排序
  469. let isSort = this.tableExample.getPlugin("columnSorting").isSorted();
  470. if (trimmedArr.length && isSort) {
  471. let sortArr =
  472. this.myHotArr.getPlugin("columnSorting").rowsMapper.__arrayMap;
  473. let infos = this.tableData[trimmedArr[sortArr[rowArr.row]]];
  474. this.getInfors(infos, { row: sortArr[rowArr.row], col: rowArr.col });
  475. } else if (isSort) {
  476. //排序后的数组
  477. let sortArr =
  478. this.tableExample.getPlugin("columnSorting").rowsMapper.__arrayMap;
  479. let infos = this.tableData[sortArr[rowArr.row]];
  480. this.getInfors(infos, { row: sortArr[rowArr.row], col: rowArr.col });
  481. } else if (trimmedArr.length) {
  482. let infos = this.tableData[trimmedArr[rowArr.row]];
  483. this.getInfors(infos, { row: trimmedArr[rowArr.row], col: rowArr.col });
  484. } else {
  485. let infos = this.tableData[rowArr.row];
  486. this.getInfors(infos, rowArr);
  487. }
  488. },
  489. //获取被筛选掉的行号
  490. trimmedRows() {
  491. var plugin = this.tableExample.getPlugin("trimRows").trimmedRows;
  492. let dataLength = this.tableData.length;
  493. let dataArr = new Array();
  494. for (let i = 0; i < dataLength; i++) {
  495. dataArr.push(i);
  496. }
  497. if (plugin.length <= 0) {
  498. dataArr = undefined;
  499. } else {
  500. dataArr = this.array_diff(dataArr, plugin);
  501. }
  502. return dataArr || [];
  503. },
  504. getInfors(infos, row) {
  505. //其他的开始判断
  506. let val = this.tableExample.colToProp(row.col);
  507. let inputData = this.inputMap[val];
  508. this.row = row.row;
  509. this.messKey = val;
  510. //设备二维码图片
  511. if (val == "defaultQRCode") {
  512. this.myDialog.qrcode = true;
  513. this.$refs.qrcode.getCanvas(1111);
  514. }
  515. // if (
  516. // val == "flowBuild" || //所属建筑楼层
  517. // val == "infos.productDate" || //生产日期
  518. // val == "infos.serialNum" || //出厂编号
  519. // val == "infos.assetID" || //资产编号
  520. // val == "infos.purchasePrice" || //采购价格
  521. // val == "infos.insuranceNum" || //保险单号
  522. // val == "infos.insuranceFile" //保险文件
  523. // ) {
  524. // const propertyId = this.tableData[row.row].propertyId;
  525. // if (!propertyId) { //未关联资产
  526. // this.$confirm('您暂未关联设备对应的资产,该信息点不可编辑', '提示', {
  527. // confirmButtonText: '我知道了',
  528. // showCancelButton: false,
  529. // type: 'warning',
  530. // center: true
  531. // }).then(() => {
  532. // return false;
  533. // });
  534. // }
  535. // return false
  536. // }
  537. //保险文件--设备文档--安装质检报告
  538. if (
  539. val == "infos.insuranceFile" || //保险文件
  540. val == "infos.archive" || //设备文档
  541. val == "infos.checkReport" || //安装质检报告
  542. val == "infos.maintainManual" || //维修保养手册
  543. val == "infos.approachingAcceptance" || //进场验收单
  544. val == "infos.acceptanceReport" || //验收报告
  545. val == "infos.operationManual" || //操作说明书
  546. val == "infos.originalCertificate" || //原厂证明
  547. val == "infos.testReport" || //检测报告
  548. val == "infos.productCertification" || //产品合格证
  549. val == "infos.installInstruction" || //
  550. val == "infos.supplierContract" || //供应合同
  551. val == "infos.drawing" || //设备图纸
  552. val == "infos.installDrawing" //安装图纸
  553. ) {
  554. let data = tools.dataForKey(this.tableData[row.row], val);
  555. this.filesArr = data ? data : [];
  556. this.myDialog.uploadFiles = true;
  557. }
  558. //安装照片--设备铭牌照片
  559. if (val == "infos.installPic" || val == "infos.nameplate") {
  560. let data = tools.dataForKey(this.tableData[row.row], val);
  561. this.imgsArr = data ? data : [];
  562. this.myDialog.uploadImgs = true;
  563. }
  564. //设备照片
  565. if (val == "infos.pic") {
  566. let data = tools.dataForKey(this.tableData[row.row], val);
  567. this.picsArr = data ? data : [];
  568. this.myDialog.pic = true;
  569. }
  570. if (!this.onlyRead && !inputData.editable) {
  571. this.$confirm("该信息点的值为自动生成,不可人工维护!", "提示", {
  572. confirmButtonText: "我知道了",
  573. showCancelButton: false,
  574. type: "warning",
  575. center: true,
  576. }).then(() => {
  577. return false;
  578. });
  579. }
  580. // 维护多选枚举值
  581. if (!this.onlyRead && inputData.dataType == "MENUM") {
  582. this.updateInfoData = inputData;
  583. this.updateInfoPoint = val;
  584. this.updateInput = tools.dataForKey(this.tableData[row.row], val);
  585. this.myDialog.menum = true;
  586. return false;
  587. }
  588. if (
  589. !this.onlyRead &&
  590. showTools.inputModeArr.indexOf(inputData.dataType) == "-1"
  591. ) {
  592. this.updateInfoPoint = val;
  593. this.updateInput = tools.dataForKey(this.tableData[row.row], val);
  594. this.myDialog.update = true;
  595. return false;
  596. }
  597. },
  598. //关闭临时维护弹窗回调
  599. handleCloseUpdate() {
  600. this.updateInputShow = false;
  601. this.updateInfoPoint = "";
  602. this.updateInput = "";
  603. },
  604. //更新临时维护信息点
  605. handleClickUpdate() {
  606. tools.setDataForKey(
  607. this.tableData[this.row],
  608. this.updateInfoPoint,
  609. this.updateInput
  610. );
  611. this.handleUpdataTable(
  612. [[this.row, this.updateInfoPoint, null, this.updateInput]],
  613. "edit"
  614. );
  615. this.updateInputShow = false;
  616. this.myDialog.update = false;
  617. this.updateInput = "";
  618. },
  619. //多选枚举类型值修改
  620. handleChangeMenum(newValue) {
  621. tools.setDataForKey(
  622. this.tableData[this.row],
  623. this.updateInfoPoint,
  624. newValue
  625. );
  626. this.handleUpdataTable(
  627. [[this.row, this.updateInfoPoint, null, newValue]],
  628. "edit"
  629. );
  630. this.myDialog.menum = false;
  631. this.updateInput = "";
  632. },
  633. utilToKey(key, name, data, messName) {
  634. if (key == name) {
  635. this.setDataToMain(data[key], messName, this.row);
  636. }
  637. },
  638. //判断是否有值,有值赋值
  639. setDataToMain(data, key, row) {
  640. if (!!data && data != "--") {
  641. if (!!this.tableData[row]) {
  642. //铭牌照片特殊处理
  643. tools.setDataForKey(this.tableData[row], key, data);
  644. // this.tableData[row][key] = data;
  645. } else {
  646. this.tableData[row] = {};
  647. tools.setDataForKey(this.tableData[row], key, data);
  648. }
  649. } else {
  650. tools.setDataForKey(this.tableData[row], key, "");
  651. }
  652. },
  653. },
  654. };
  655. </script>
  656. <style lang="less" scoped>
  657. #deviceList {
  658. overflow: hidden;
  659. height: 100%;
  660. background-color: #fff;
  661. padding: 10px;
  662. position: relative;
  663. .right {
  664. background: #fff;
  665. }
  666. .search-header {
  667. overflow: hidden;
  668. padding: 0 10px 10px 10px;
  669. border-bottom: 1px solid #bcbcbc;
  670. }
  671. .tableBox {
  672. display: flex;
  673. height: calc(100% - 100px);
  674. margin-top: 10px;
  675. .tableLeft {
  676. flex: 1;
  677. }
  678. }
  679. .create_button {
  680. margin-top: 10px;
  681. }
  682. }
  683. </style>