index.vue 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618
  1. <template>
  2. <div class="newRole">
  3. <div class="newRole-content flex-wrap">
  4. <div class="newRole-content-left">
  5. <div class="newRole-content-left-top">
  6. <div class="flex head">
  7. <div class="title">账号列表</div>
  8. <!-- <el-button @click="handleAdd" class="serButton" size="small">新增</el-button> -->
  9. </div>
  10. <div class="search">
  11. <el-input size="small" placeholder="请输入内容" clearable prefix-icon="el-icon-search" :filter-node-method="filterArrNode" v-model="search">
  12. </el-input>
  13. </div>
  14. </div>
  15. <div v-loading="loading" element-loading-text="拼命加载中" element-loading-spinner="el-icon-loading" element-loading-background="rgba(0, 0, 0, 0.8)" class="newRole-content-left-bottom">
  16. <el-scrollbar ref="scroll" style="height: 100%">
  17. <div class="treeArr">
  18. <el-tree ref="treeArr" :data="arrs" :props="defaultArrProps" highlight-current :filter-node-method="filterArrNode" default-expand-all node-key="user_group_id" @node-click="handleClick" :expand-on-click-node="false">
  19. <span class="custom-tree-node" slot-scope="{ node,data }">
  20. <div class="flex">
  21. <div :class="!data.user_id ? 'bigText':''">
  22. <span class="customTxt">{{ node.label }}</span>
  23. </div>
  24. </div>
  25. </span>
  26. </el-tree>
  27. </div>
  28. </el-scrollbar>
  29. </div>
  30. </div>
  31. <div class="newRole-content-right">
  32. <div style="height: 100%" class="flex newRole-content-right-new">
  33. <div class="newRole-content-right-bottom contents1 flex1">
  34. <div class="newRole-content-left-top">
  35. <div class="flex head">
  36. <div class="title">功能授权</div>
  37. </div>
  38. <div class="search">
  39. <el-input size="small" placeholder="请输入内容" clearable prefix-icon="el-icon-search" :filter-node-method="filterNode" v-model="filterText">
  40. </el-input>
  41. </div>
  42. </div>
  43. <div class="newRole-content-left-bottom">
  44. <el-scrollbar ref="scroll" style="height: 100%">
  45. <div class="newRole-content-left-bottom-tree">
  46. <el-tree ref="tree" show-checkbox :data="treeData" :props="defaultProps" highlight-current :filter-node-method="filterNode" default-expand-all node-key="auth_id" @check="checkChange" @node-click="handleNodeClick" :expand-on-click-node="false">
  47. <span class="custom-tree-node" slot-scope="{ node, data }">
  48. <span class="customTxt">{{ node.label }}</span>
  49. <span v-show="treeCheckId == data.auth_id" class="customBtn">
  50. <span @click.stop="setItem(node,data)" v-if="data.auth_id != 0 && (data.auth_type == 4 || data.auth_type == 5)" class="ym">列授权</span>
  51. </span>
  52. </span>
  53. </el-tree>
  54. </div>
  55. </el-scrollbar>
  56. </div>
  57. </div>
  58. <div class="newRole-content-right-bottom contents2 flex1">
  59. <div class="newRole-content-left-top">
  60. <div class="flex head">
  61. <div class="title">数据授权</div>
  62. <el-button type="primary" @click="handleColSave" class="bcButton" size="small">保存</el-button>
  63. </div>
  64. </div>
  65. <div class="newRole-content-left-bottom">
  66. <el-table ref="multipleTable" class="multipleTable" :data="checkArrs" border height="100%" stripe tooltip-effect="dark" style="width: 100%;" @selection-change="handleSelectionChange">
  67. <el-table-column label-class-name="DisabledSelection" type="selection" width="100">
  68. </el-table-column>
  69. <el-table-column prop="columnLabel" label="列名">
  70. </el-table-column>
  71. <el-table-column v-if="isAuth" label="行授权">
  72. <template slot-scope="scope">
  73. <el-input size="small" placeholder="请输入内容" v-model="scope.row.row_auth" clearable>
  74. </el-input>
  75. </template>
  76. </el-table-column>
  77. </el-table>
  78. </div>
  79. </div>
  80. </div>
  81. </div>
  82. </div>
  83. <Dialog :flag="rmFlag">
  84. <div class="airportInfoDialog">
  85. <div class="title del-title">删除</div>
  86. <div class="content del-content">
  87. <span class="el-icon-error error r10"></span>您是否确认删除<span class="error l10">{{ dataObj.user_group_name }}</span>
  88. </div>
  89. <div class="foot right Delfoot">
  90. <el-button size="medium" class="r24" @click="tableRemove" type="danger">删除</el-button>
  91. <el-button size="medium" @click="rmFlag = false">取消</el-button>
  92. </div>
  93. </div>
  94. </Dialog>
  95. </div>
  96. </template>
  97. <script>
  98. import Table from '@/views/newTable/index.vue'
  99. import Dialog from "@/layout/components/Dialog/index.vue"
  100. import { setTree, listToTree } from '@/utils/validate'
  101. import { getToken } from '@/utils/auth'
  102. import pf from '@/layout/mixin/publicFunc'
  103. import * as _ from 'lodash'
  104. export default {
  105. name: 'NewService',
  106. components: { Table, Dialog },
  107. mixins: [pf],
  108. data () {
  109. return {
  110. title: '服务设置',
  111. search: '',
  112. filterText: '',
  113. arrs: [
  114. {
  115. "user_group_id": 0,
  116. "user_group_name": "默认用户组",
  117. "up_user_group_id": -1,
  118. "user_group_status": null,
  119. "user_group_comment": null,
  120. children: []
  121. }
  122. ],
  123. flag: true,
  124. formInline: {
  125. role_name: '',
  126. comment: ''
  127. },
  128. activeIndex: null,
  129. pageIndex: 0,
  130. pageSize: 9999,
  131. dataContent: {},
  132. queryId: '',
  133. dataObj: {},
  134. dataType: 'edit',
  135. noMore: false,
  136. loading: false,
  137. treeData: [
  138. {
  139. auth_name: '所有权限',
  140. auth_id: 0,
  141. children: [],
  142. up_auth_id: -1
  143. }
  144. ],
  145. treeCheckId: '',
  146. treeCheckObj: {},
  147. defaultProps: {
  148. children: 'children',
  149. label: 'auth_name'
  150. },
  151. defaultArrProps: {
  152. children: 'children',
  153. label: 'user_group_name'
  154. },
  155. checkGroup: [],
  156. checkArrs: [],
  157. checkDatas: [],
  158. checkGroups: [],
  159. multipleTable: [],
  160. rmFlag: false,
  161. msgUserId: '',
  162. userId: getToken('userid')
  163. }
  164. },
  165. watch: {
  166. filterText (val) {
  167. this.$refs.tree.filter(val);
  168. },
  169. search (val) {
  170. this.$refs.treeArr.filter(val);
  171. },
  172. treeCheckId () {
  173. this.checkArrs = []
  174. }
  175. },
  176. computed: {
  177. isAuth () {
  178. if (this.userId == 1 || this.userId == 99999 || this.userId == 9999) {
  179. return true
  180. } else {
  181. return false
  182. }
  183. }
  184. },
  185. created () {
  186. const { title, qid } = this.$route.meta
  187. this.title = title
  188. this.queryId = qid
  189. this.getQueryListCo(qid)
  190. this.setTreeData()
  191. },
  192. updated () {
  193. this.scrollDown()
  194. },
  195. methods: {
  196. //获取tree数据
  197. async setTreeData () {
  198. const { code, returnData } = await this.getQueryList(SERVICE_ID.sysAuthId)
  199. if (code == 0) {
  200. const treeMenu = listToTree(returnData, 'up_auth_id', 'auth_id')
  201. this.treeData[0].children = treeMenu
  202. }
  203. },
  204. filterNode (value, data) {
  205. if (!value) return true;
  206. return data.auth_name.indexOf(value) !== -1;
  207. },
  208. filterArrNode (value, data) {
  209. if (!value) return true;
  210. return data.user_group_name.indexOf(value) !== -1;
  211. },
  212. async getQueryListCo (id) {
  213. try {
  214. this.loading = true;
  215. const { code, returnData } = await this.getQueryList(SERVICE_ID.userListId)
  216. if (code == 0 && returnData && returnData.length) {
  217. const result = await this.getQueryList(SERVICE_ID.getUserTableId)
  218. if (result.code == 0 && result.returnData && result.returnData.length) {
  219. result.returnData.forEach(item => {
  220. if (item.hasOwnProperty('user_name') || item.hasOwnProperty('user_group_id')) {
  221. item.user_group_name = item.user_name
  222. item.user_group_id = item.user_id
  223. }
  224. })
  225. const menus = [...returnData, ...result.returnData]
  226. const treeMenu = listToTree(menus, 'up_user_group_id', 'user_group_id')
  227. this.arrs = treeMenu
  228. }
  229. this.loading = false;
  230. } else {
  231. this.loading = false;
  232. }
  233. } catch (error) {
  234. this.loading = false;
  235. }
  236. },
  237. load () {
  238. if (!this.noMore) {
  239. this.getQueryListCo(this.queryId);
  240. }
  241. },
  242. scrollDown () {
  243. if (this.$refs['scroll'] && this.dataType == 'add') {
  244. this.$refs['scroll'].wrap.scrollTop = this.$refs['scroll'].wrap.scrollHeight
  245. }
  246. },
  247. resetTable () {
  248. this.pageIndex = 0;
  249. this.noMore = false;
  250. this.arrs = [];
  251. },
  252. //服务列表-新增
  253. handleAdd () {
  254. const datas = this.arrs.filter(item => item.role_name == '新建角色')
  255. if (datas && datas.length) {
  256. return
  257. }
  258. this.dataType = 'add'
  259. this.flag = false
  260. this.dataObj.role_name = '新建角色'
  261. this.arrs.push({ role_name: '新建角色' })
  262. this.activeIndex = this.arrs.length - 1
  263. for (const key in this.formInline) {
  264. if (Object.hasOwnProperty.call(this.formInline, key)) {
  265. this.formInline[key] = null
  266. }
  267. }
  268. },
  269. //获取角色已有权限
  270. async getRoleQuth (item) {
  271. console.log(item)
  272. this.$refs.tree.setCheckedKeys([])
  273. const newItem = _.cloneDeep(item)
  274. const newObj = {}
  275. if (newItem.hasOwnProperty('user_id')) {
  276. newObj.user_id = newItem.user_id
  277. } else {
  278. newObj.user_group_id = newItem.user_group_id
  279. }
  280. const { code, returnData } = await this.getQueryList(SERVICE_ID.userAuthorizationId, newObj)
  281. if (code == 0) {
  282. const result = returnData
  283. if (result && result.length) {
  284. const datas = []
  285. result.forEach(item => {
  286. datas.push(item.auth_id)
  287. })
  288. this.$refs.tree.setCheckedKeys(datas)
  289. const treeDatas = this.$refs.tree.getCheckedNodes().concat(this.$refs.tree.getHalfCheckedNodes())
  290. const res = [...treeDatas, ...result].filter((item) => !(treeDatas.some((p) => item.auth_id == p.auth_id) && result.some((c) => item.auth_id == c.auth_id)))
  291. setTimeout(() => {
  292. res.forEach((item) => {
  293. if (item.auth_id) {
  294. this.$refs.tree.setChecked(item.auth_id, false, false);
  295. }
  296. });
  297. }, 50);
  298. setTimeout(() => {
  299. const newTreeDatas = this.$refs.tree.getCheckedNodes().concat(this.$refs.tree.getHalfCheckedNodes())
  300. const arrs = newTreeDatas.filter(item => item.auth_id != 0)
  301. this.checkDatas.push(arrs)
  302. }, 70);
  303. }
  304. }
  305. },
  306. removeClass (elements) {
  307. elements.className = '';
  308. },
  309. //服务列表-点击
  310. handleClick (item) {
  311. this.dataType = 'edit'
  312. this.dataObj = _.cloneDeep(item)
  313. this.formInline = _.cloneDeep(item)
  314. this.activeIndex = item.user_group_id
  315. this.flag = false
  316. this.treeCheckId = null
  317. this.$refs.tree.setCurrentKey(null)
  318. this.msgUserId = null
  319. this.getRoleQuth(item)
  320. },
  321. //服务列表-保存
  322. async handleSave () {
  323. if (this.dataObj.role_ID && this.dataType == 'edit') {
  324. const { code } = await this.getChangeList(this.queryId, this.formInline, 2, 'role_ID')
  325. if (code == 0) {
  326. this.resetTable()
  327. this.getQueryListCo(this.queryId)
  328. }
  329. this.tipMsg(code)
  330. } else if (this.dataType == 'add' && this.arrs[this.arrs.length - 1].role_ID) {
  331. this.formInline.role_ID = this.arrs[this.arrs.length - 1].role_ID
  332. const { code } = await this.getChangeList(this.queryId, this.formInline, 2, 'role_ID')
  333. if (code == 0) {
  334. this.resetTable()
  335. this.getQueryListCo(this.queryId)
  336. }
  337. this.tipMsg(code)
  338. } else if (this.dataType == 'add') {
  339. const { code } = await this.getChangeList(this.queryId, this.formInline, 1)
  340. if (code == 0) {
  341. this.resetTable()
  342. this.getQueryListCo(this.queryId)
  343. }
  344. this.tipMsg(code)
  345. }
  346. else {
  347. this.$message.error('请先选中服务后再操作')
  348. }
  349. },
  350. async tableRemove () {
  351. if (this.dataObj.role_ID && this.dataType == 'edit') {
  352. const { code } = await this.getChangeList(this.queryId, this.dataObj, 3)
  353. if (code == 0) {
  354. this.resetTable()
  355. this.getQueryListCo(this.queryId)
  356. this.activeIndex = null;
  357. this.dataObj = {};
  358. for (const key in this.formInline) {
  359. if (Object.hasOwnProperty.call(this.formInline, key)) {
  360. this.formInline[key] = null
  361. }
  362. }
  363. this.flag = true
  364. }
  365. this.tipMsg(code)
  366. } else if (this.dataType == 'add' && this.arrs[this.arrs.length - 1].role_ID) {
  367. const { code } = await this.getChangeList(this.queryId, this.arrs[this.arrs.length - 1], 3)
  368. if (code == 0) {
  369. this.resetTable()
  370. this.getQueryListCo(this.queryId)
  371. this.activeIndex = null;
  372. this.dataObj = {};
  373. for (const key in this.formInline) {
  374. if (Object.hasOwnProperty.call(this.formInline, key)) {
  375. this.formInline[key] = null
  376. }
  377. }
  378. this.flag = true
  379. this.dataType = 'edit'
  380. }
  381. this.tipMsg(code)
  382. }
  383. else {
  384. this.arrs.splice(this.activeIndex, 1)
  385. this.activeIndex = null
  386. this.flag = true
  387. this.dataObj = {}
  388. }
  389. this.rmFlag = false
  390. },
  391. //服务列表-删除
  392. handleError () {
  393. this.rmFlag = true
  394. },
  395. handleNodeClick (data) {
  396. this.msgUserId = null
  397. this.treeCheckId = data.auth_id
  398. this.treeCheckObj = data
  399. // this.treeCheckId = null
  400. // this.checkArrs = []
  401. },
  402. async checkChange () {
  403. if (this.dataObj.user_group_id) {
  404. const datas = this.$refs.tree.getCheckedNodes().concat(this.$refs.tree.getHalfCheckedNodes());
  405. const arrs = datas.filter(item => item.auth_id != 0)
  406. this.checkDatas.push(arrs)
  407. if (this.checkDatas.length == 1) {
  408. const res = this.checkDatas[this.checkDatas.length - 1]; //最后一条数据
  409. const addRes = []
  410. const newDatas = []
  411. const newItem = _.cloneDeep(this.dataObj)
  412. res.forEach(item => {
  413. if (item.children) {
  414. delete item.children
  415. }
  416. if (newItem.hasOwnProperty('user_id')) {
  417. item.user_id = newItem.user_id
  418. } else {
  419. item.user_group_id = newItem.user_group_id
  420. }
  421. addRes.push(item)
  422. })
  423. const newMsgs = _.cloneDeep(addRes)
  424. newMsgs.forEach(item => {
  425. const { auth_id, auth_type, queryTemplateColumnSetID, row_auth, user_group_id, user_id } = item
  426. const newObj = { auth_id, auth_type, queryTemplateColumnSetID, row_auth, user_group_id, user_id }
  427. newDatas.push(newObj)
  428. })
  429. const { code } = await this.getChangeList(SERVICE_ID.userAuthorizationId, newDatas, 1)
  430. if (code == 0) {
  431. setTimeout(() => {
  432. this.getRoleQuth(this.dataObj)
  433. }, 100);
  434. }
  435. this.tipMsg(code)
  436. } else {
  437. const data1 = this.checkDatas[this.checkDatas.length - 1]; //最后一条数据
  438. const data2 = this.checkDatas[this.checkDatas.length - 2]; //倒数第二条数据
  439. if (data1.length > data2.length) {
  440. this.checksBoxTs(data1, data2, "add");
  441. } else {
  442. this.checksBoxTs(data2, data1, "del");
  443. }
  444. }
  445. } else {
  446. this.$message.error('请选中账号后再操作');
  447. this.$refs.tree.setCheckedKeys([]);
  448. }
  449. },
  450. async checksBoxTs (datas, arr, type) {
  451. const res = [...datas, ...arr].filter((item) => !(datas.some((p) => item.auth_id == p.auth_id) && arr.some((c) => item.auth_id == c.auth_id)));
  452. const addRes = []
  453. const newDatas = []
  454. const newItem = _.cloneDeep(this.dataObj)
  455. res.forEach(item => {
  456. if (item.children) {
  457. delete item.children
  458. }
  459. if (newItem.hasOwnProperty('user_id')) {
  460. item.user_id = newItem.user_id
  461. } else {
  462. item.user_group_id = newItem.user_group_id
  463. }
  464. addRes.push(item)
  465. })
  466. const newMsgs = _.cloneDeep(addRes)
  467. newMsgs.forEach(item => {
  468. const { auth_id, auth_type, queryTemplateColumnSetID, row_auth, user_group_id, user_id } = item
  469. const newObj = { auth_id, auth_type, queryTemplateColumnSetID, row_auth, user_group_id, user_id }
  470. newDatas.push(newObj)
  471. })
  472. if (type == 'add') {
  473. const { code } = await this.getChangeList(SERVICE_ID.userAuthorizationId, newDatas, 1)
  474. if (code == 0) {
  475. setTimeout(() => {
  476. this.getRoleQuth(this.dataObj)
  477. }, 100);
  478. }
  479. this.tipMsg(code)
  480. } else {
  481. const { code } = await this.getChangeList(SERVICE_ID.userAuthorizationId, newDatas, 3)
  482. if (code == 0) {
  483. this.msgUserId = null
  484. this.checkArrs = []
  485. setTimeout(() => {
  486. this.getRoleQuth(this.dataObj)
  487. }, 100);
  488. }
  489. this.tipMsg(code)
  490. }
  491. // this.checkArrs = []
  492. },
  493. async setItem (node, data) {
  494. if (this.dataObj.user_id || this.dataObj.user_group_id) {
  495. this.msgUserId = data.auth_id
  496. const newItem = _.cloneDeep(this.dataObj)
  497. const newObj = {}
  498. if (newItem.hasOwnProperty('user_id')) {
  499. newObj.user_id = newItem.user_id
  500. } else {
  501. newObj.user_group_id = newItem.user_group_id
  502. }
  503. newObj.auth_id = data.auth_id
  504. const { code, returnData } = await this.getQueryList(SERVICE_ID.userColAuthId, { auth_id: data.auth_id, user_id: getToken('userid') })
  505. if (code == 0) {
  506. const result = returnData
  507. if (result && result.length) {
  508. result.map(item => {
  509. item.row_auth = null
  510. })
  511. this.checkArrs = [...result]
  512. const { code, returnData } = await this.getQueryList(SERVICE_ID.userAuthorizationId, newObj)
  513. if (code == 0 && returnData && returnData.length) {
  514. const res = returnData.filter(item => item.queryTemplateColumnSetID)
  515. if (res && res.length) {
  516. // const caps = _.intersectionBy([result, res], 'queryTemplateColumnSetID')
  517. // console.log(caps)
  518. const resmsg = []
  519. result.forEach((item) => {
  520. res.forEach(p => {
  521. if (item.queryTemplateColumnSetID == p.queryTemplateColumnSetID) {
  522. item.row_auth = p.row_auth
  523. resmsg.push(item)
  524. }
  525. })
  526. })
  527. if (resmsg && resmsg.length) {
  528. resmsg.forEach(row => {
  529. this.$refs.multipleTable.toggleRowSelection(row);
  530. });
  531. }
  532. this.multipleTable = resmsg
  533. }
  534. }
  535. }
  536. }
  537. } else {
  538. this.$message.error('请选中账号后再操作');
  539. }
  540. },
  541. sendCheckData (arr, type = false) {
  542. const newData = []
  543. const newItem = _.cloneDeep(this.dataObj)
  544. arr.forEach(item => {
  545. if (type) {
  546. const newObj = {
  547. "auth_id": this.treeCheckObj.auth_id,
  548. "queryTemplateColumnSetID": item.queryTemplateColumnSetID,
  549. }
  550. if (newItem.hasOwnProperty('user_id')) {
  551. newObj.user_id = newItem.user_id
  552. } else {
  553. newObj.user_group_id = newItem.user_group_id
  554. }
  555. newData.push(newObj)
  556. } else {
  557. const obj = {
  558. "auth_id": this.treeCheckObj.auth_id,
  559. "auth_type": this.treeCheckObj.auth_type,
  560. "queryTemplateColumnSetID": item.queryTemplateColumnSetID,
  561. "columnLabel": item.columnLabel,
  562. "columnname": item.columnName,
  563. "row_auth": item.row_auth
  564. }
  565. if (newItem.hasOwnProperty('user_id')) {
  566. obj.user_id = newItem.user_id
  567. } else {
  568. obj.user_group_id = newItem.user_group_id
  569. }
  570. newData.push(obj)
  571. }
  572. })
  573. return newData
  574. },
  575. getColName (arr) {
  576. const res = []
  577. this.checkArrs.forEach(item => {
  578. arr.forEach(p => {
  579. if (item.columnName == p) {
  580. res.push(item)
  581. }
  582. })
  583. })
  584. return res
  585. },
  586. handleSelectionChange (val) {
  587. this.multipleTable = val
  588. },
  589. async handleColSave () {
  590. if (this.treeCheckObj.auth_id && this.dataObj.user_group_id && this.msgUserId) {
  591. const newItem = _.cloneDeep(this.dataObj)
  592. const newObj = {
  593. "auth_id": this.treeCheckObj.auth_id,
  594. }
  595. if (newItem.hasOwnProperty('user_id')) {
  596. newObj.user_id = newItem.user_id
  597. } else {
  598. newObj.user_group_id = newItem.user_group_id
  599. }
  600. const result = this.sendCheckData(this.multipleTable)
  601. const tes = await this.getChangeList(SERVICE_ID.userAuthorizationId, [newObj], 3)
  602. if (tes.code == 0) {
  603. const { code } = await this.getChangeList(SERVICE_ID.userAuthorizationId, result, 1)
  604. this.tipMsg(code)
  605. }
  606. } else {
  607. this.$message.error('请先选中用户和权限后再操作列设置后保存数据')
  608. }
  609. }
  610. }
  611. }
  612. </script>
  613. <style lang="scss" scoped>
  614. @import "./css/index.scss";
  615. </style>