batchMoveDialog.vue 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592
  1. <template>
  2. <el-dialog
  3. :visible.sync="show"
  4. :close-on-click-modal="false"
  5. :modal-append-to-body="false"
  6. @close="handleClose"
  7. custom-class="batch-move-dialog fit-screen-dialog"
  8. center
  9. top="2vh"
  10. v-dialogDrag
  11. :title="`批量移动${sourceLabel}`"
  12. >
  13. <div class="list-wrap">
  14. <div class="filter-wrap">
  15. <div>
  16. <el-cascader
  17. style="width: 240px"
  18. v-model="filterObj.classify"
  19. :options="classifyOption"
  20. clearable
  21. collapse-tags
  22. placeholder="选择分类"
  23. @change="handleFilter"
  24. :props="cascaderProps"
  25. :show-all-levels="false"
  26. :key="cascaderKey"
  27. ref="classifyRef"
  28. />
  29. <div>
  30. 关联子分类
  31. <el-switch
  32. v-model="filterObj.relevanceChild"
  33. :active-value="true"
  34. :inactive-value="false"
  35. style="margin-left: 5px;"
  36. @change="cascaderKey++"
  37. />
  38. </div>
  39. <el-select
  40. v-if="source==='edb'"
  41. v-model="filterObj.source"
  42. style="width: 200px"
  43. placeholder="请选择计算方式"
  44. clearable
  45. multiple
  46. collapse-tags
  47. @change="handleFilter"
  48. >
  49. <el-option
  50. v-for="item in sourceOption"
  51. :key="item.type"
  52. :label="item.name"
  53. :value="item.type"
  54. >
  55. </el-option>
  56. </el-select>
  57. <el-select
  58. v-if="source==='chart'"
  59. v-model="filterObj.chartTypes"
  60. style="width: 200px"
  61. placeholder="图表类型"
  62. clearable
  63. multiple
  64. collapse-tags
  65. @change="handleFilter"
  66. >
  67. <el-option
  68. v-for="item in sourceOption"
  69. :key="item.value"
  70. :label="item.label"
  71. :value="item.value"
  72. >
  73. </el-option>
  74. </el-select>
  75. <el-input
  76. v-model="filterObj.keyWord"
  77. :placeholder="`${sourceLabel}名称`"
  78. style="width: 200px;"
  79. @change="handleFilter"
  80. clearable
  81. >
  82. <i slot="prefix" class="el-input__icon el-icon-search"/>
  83. </el-input>
  84. <el-checkbox
  85. label="列表全选"
  86. v-model="filterObj.checkAll"
  87. :indeterminate="filterObj.checkSome"
  88. style="margin-left:10px"
  89. @change="listCheckAllChange"
  90. />
  91. </div>
  92. </div>
  93. <div class="table-wrap">
  94. <el-table
  95. :data="list"
  96. border
  97. ref="table"
  98. height="50vh"
  99. v-loading="listLoading"
  100. @selection-change="selectionChange"
  101. @select="selectHandle"
  102. @select-all="selectAllPageHandle"
  103. >
  104. <el-table-column type="selection" min-width="50" align="center" :selectable="filterEdbAuth"/>
  105. <el-table-column
  106. :label="item.label"
  107. align="center"
  108. v-for="item in tableColumns"
  109. :key="item.key"
  110. :width="item.widthsty"
  111. :min-width="item.minwidthsty"
  112. >
  113. <template slot-scope="{row}">
  114. <!-- 公开状态 -->
  115. <span v-if="item.key==='PublicStatus'">
  116. {{ publicStatusLabel.get(row.PublicStatus) }}
  117. </span>
  118. <span v-else>{{ row[item.key] }}</span>
  119. </template>
  120. </el-table-column>
  121. </el-table>
  122. <div style="height:40px;margin:20px 0;">
  123. <m-page
  124. class="table-page"
  125. :total="total"
  126. :pageSize="pageSize"
  127. :page_no="pageNo"
  128. @handleCurrentChange="pageChange"
  129. />
  130. </div>
  131. </div>
  132. <div class="type-wrap">
  133. <label class="el-form-item__label">移动至新分类</label>
  134. <cascader
  135. v-model="filterObj.newClassify"
  136. :options="classifyOption"
  137. clearable
  138. placeholder="选择新分类"
  139. style="width: 240px"
  140. :config="{ checkStrictly: true,emitPath:false }"
  141. />
  142. </div>
  143. <div class="bot">
  144. <el-button type="primary" plain @click="handleClose">取消</el-button>
  145. <el-button type="primary" @click="handleConfirm">确定</el-button>
  146. </div>
  147. </div>
  148. </el-dialog>
  149. </template>
  150. <script>
  151. import mPage from '@/components/mPage.vue'
  152. import { dataBaseInterface } from '@/api/api.js';
  153. import { edbBaseV2Interface,chartBaseV2Interface } from '@/api/modules/chartApi';
  154. import { getComputedTypes } from '../databaseComponents/util';
  155. export default {
  156. components:{ mPage, },
  157. props:{
  158. show:{
  159. type: Boolean
  160. },
  161. source: { //指标或图库
  162. type: String,
  163. default: 'edb'
  164. },
  165. type: { //设置类型 设置共享shared 设置公开public
  166. type: Number
  167. },
  168. classifyShowType: { //分类类型 own public
  169. type: String
  170. }
  171. },
  172. computed:{
  173. // 最大添加指标的上限
  174. MAXAddNUM(){
  175. let num=100
  176. return num
  177. },
  178. tableColumns() {
  179. let columns = [
  180. {
  181. label: '指标名称',
  182. key: 'EdbName',
  183. minwidthsty: '250px',
  184. show: this.source==='edb'
  185. },
  186. {
  187. label: '图表名称',
  188. key: 'ChartName',
  189. minwidthsty: '250px',
  190. show: this.source==='chart'
  191. },
  192. {
  193. label: '分类',
  194. key: 'ClassifyName',
  195. show: true
  196. },
  197. {
  198. label: '图表类型',
  199. key: 'Source',
  200. show: this.source==='chart'
  201. },
  202. {
  203. label: '计算方式',
  204. key: 'SourceName',
  205. widthsty:'100px',
  206. show: this.source==='edb'
  207. },
  208. ]
  209. let filterColumns = columns.filter(_ => _.show);
  210. return filterColumns;
  211. },
  212. sourceLabel() {
  213. return this.source==='edb'?'指标':'图表';
  214. },
  215. cascaderProps() {
  216. return {
  217. label: 'ClassifyName',
  218. value: 'ClassifyId',
  219. children: 'Children',
  220. multiple: true,
  221. emitPath: false,
  222. checkStrictly: !this.filterObj.relevanceChild
  223. }
  224. },
  225. Idkey() {
  226. return this.source==='edb'?'EdbInfoId':'ChartInfoId';
  227. },
  228. },
  229. watch: {
  230. show(n){
  231. if(!n) return
  232. this.getClassifyOpts();
  233. this.$nextTick(() => {
  234. this.getList('init');
  235. })
  236. }
  237. },
  238. data() {
  239. return {
  240. filterObj: {
  241. classify: [],
  242. relevanceChild:true,
  243. pageNo: 1,
  244. pageSize: 20,
  245. source: [],
  246. chartTypes: [],
  247. keyWord: '',
  248. checkAll: false, //控制全选显示状态
  249. checkSome: false,
  250. newClassify: ''
  251. },
  252. sourceOption: getComputedTypes(),
  253. classifyOption: [],
  254. cascaderKey:0,
  255. list: [],
  256. isSelectAll: false, //真正意义上的全选或不全选
  257. checkedList: [], //不全选勾选中的 或 全选取消勾的项
  258. selectionReactCancel:false,//手动设置选中中
  259. }
  260. },
  261. methods: {
  262. //目录 指标/图库
  263. async getClassifyOpts() {
  264. let res;
  265. if(this.source === 'edb') { //指标
  266. res = this.classifyShowType==='own'
  267. ? await dataBaseInterface.menuListV3({ClassifyType: 2})
  268. : await edbBaseV2Interface.getPublicClassifyBase()
  269. }else {//图库
  270. res = this.classifyShowType==='own'
  271. ? await dataBaseInterface.chartClassify()
  272. : await chartBaseV2Interface.getPublicClassifyBase()
  273. }
  274. if(res.Ret!==200) return
  275. this.classifyOption = res.Data.AllNodes || [];
  276. this.filterNodes(this.classifyOption)
  277. },
  278. filterNodes(arr) {
  279. arr.length && arr.forEach(item => {
  280. item.Children && item.Children.length && this.filterNodes(item.Children)
  281. if(!item.Children.length) {
  282. delete item.Children
  283. }
  284. })
  285. },
  286. async getList(type='pageChange') {
  287. let apiMap = {
  288. 'edb': this.getEdbList,
  289. 'chart': this.getChartList
  290. }
  291. apiMap[this.source](type)
  292. },
  293. //指标列表
  294. async getEdbList(type) {
  295. const {
  296. pageNo,
  297. pageSize,
  298. source,
  299. keyWord,
  300. } = this.filterObj;
  301. let checkedClassify = this.$refs.classifyRef.getCheckedNodes();
  302. let ClassifyIdList = checkedClassify.length
  303. ? checkedClassify.map(_ => _.data.ClassifyId)
  304. : []
  305. const res = this.classifyShowType === 'own'
  306. ? await dataBaseInterface.targetSearchByPage({
  307. PageSize:pageSize,
  308. Source: source.join(','),
  309. CurrentIndex:pageNo,
  310. ClassifyId:ClassifyIdList.join(','),
  311. KeyWord: keyWord,
  312. EdbType: 2,
  313. EdbAuth: 1
  314. })
  315. : await edbBaseV2Interface.getPublicSearchList({
  316. EdbPublicList: [3],
  317. SourceList:source,
  318. Keyword: keyWord,
  319. ClassifyIdList,
  320. CurrentIndex: pageNo,
  321. PageSize: pageSize
  322. })
  323. if(res.Ret !== 200) return
  324. this.list = res.Data.List||[];
  325. this.total = res.Data.Paging.Totals;
  326. if(type==='filter'){
  327. this.listCheckAllChange(true)
  328. }else {
  329. //页码变化 选中项不做清空
  330. this.checkedSomeSelection()
  331. }
  332. },
  333. //图表列表
  334. async getChartList() {
  335. },
  336. handleFilter(val) {
  337. this.filterObj.pageNo = 1;
  338. if(!val||!val.length) {
  339. this.isSelectAll = false;
  340. this.checkedList = [];
  341. this.filterObj.checkAll = false;
  342. this.filterObj.checkSome = false;
  343. }
  344. this.getList((val.length)?'filter':'');
  345. },
  346. async handleConfirm() {
  347. const {
  348. source,
  349. keyWord,
  350. newClassify
  351. } = this.filterObj;
  352. let checkedClassify = this.$refs.classifyRef.getCheckedNodes();
  353. let ClassifyIdList = checkedClassify.length
  354. ? checkedClassify.map(_ => _.data.ClassifyId)
  355. : [];
  356. let res;
  357. if(this.source === 'edb') { //指标
  358. let params = {
  359. SourceList:source,
  360. Keyword: keyWord,
  361. ClassifyIdList,
  362. IsSelectAll: this.isSelectAll,
  363. NoEdbIdList: this.isSelectAll ? this.checkedList.map(_ =>_.EdbInfoId) : [],
  364. EdbIdList: this.isSelectAll ? [] : this.checkedList.map(_ =>_.EdbInfoId),
  365. NewClassifyId: newClassify
  366. }
  367. res = this.classifyShowType==='own'
  368. ? await edbBaseV2Interface.moveOwnBatch(params)
  369. : await edbBaseV2Interface.movePublicBatch(params)
  370. }else {//图库
  371. let params = {
  372. Keyword: keyWord,
  373. ClassifyIdList,
  374. IsSelectAll: this.isSelectAll,
  375. NoChartIdList: this.isSelectAll ? this.checkedList.map(_ =>_.ChartInfoId) : [],
  376. ChartIdList: this.isSelectAll ? [] : this.checkedList.map(_ =>_.ChartInfoId),
  377. NewClassifyId: newClassify
  378. }
  379. res = this.classifyShowType==='own'
  380. ? await chartBaseV2Interface.moveOwnBatch(params)
  381. : await chartBaseV2Interface.movePublicBatch(params)
  382. }
  383. if(res.Ret!==200) return
  384. this.$message.success('移动成功')
  385. this.handleClose();
  386. this.$emit('confirm')
  387. },
  388. /* 设置当页数据勾选状态 */
  389. checkedSomeSelection() {
  390. this.selectionReactCancel=true
  391. if(!this.isSelectAll){
  392. this.checkedList.map(_ =>{
  393. let row = this.list.find(item => item[this.Idkey]==_[this.Idkey])
  394. if(row){ //设置部分选中
  395. setTimeout(()=>{
  396. this.$refs.table.toggleRowSelection(row,true)
  397. },20)
  398. }
  399. })
  400. }else{
  401. this.$refs.table &&this.$refs.table.toggleAllSelection()
  402. this.checkedList.map(_ =>{
  403. let row = this.list.find(item => item[this.Idkey]==_[this.Idkey])
  404. if(row){ //设置部分不勾选
  405. setTimeout(()=>{
  406. this.$refs.table.toggleRowSelection(row,false)
  407. },20)
  408. }
  409. })
  410. }
  411. setTimeout(()=>{
  412. this.selectionReactCancel=false
  413. },30)
  414. },
  415. //列表全选或全不选
  416. listCheckAllChange(value){
  417. this.checkedList = []
  418. this.isSelectAll = value
  419. this.$refs.table && this.$refs.table.clearSelection()
  420. value && this.$refs.table && this.$refs.table.toggleAllSelection()
  421. },
  422. selectionChange() {
  423. if(this.selectionReactCancel) return
  424. //设置全选框状态 选中 半选 不选
  425. setTimeout(()=>{
  426. let filterChecked = Array.from(new Set(this.checkedList))
  427. //全选
  428. if(
  429. (filterChecked.length===this.total&&this.total>0 && (!this.isSelectAll))
  430. || (filterChecked.length === 0 && this.isSelectAll)
  431. ){
  432. this.filterObj.checkAll = true
  433. this.filterObj.checkSome = false
  434. //不选
  435. }else if(
  436. (filterChecked.length === 0 && (!this.isSelectAll))
  437. || (filterChecked.length === this.total && this.isSelectAll)
  438. ){
  439. this.filterObj.checkAll = false
  440. this.filterObj.checkSome = false
  441. //半选
  442. }else{
  443. this.filterObj.checkAll = false
  444. this.filterObj.checkSome=true
  445. }
  446. },1)
  447. },
  448. //单选
  449. selectHandle(selection,row){ //当前选中的项是进选中还是取消选中中
  450. if(this.selectionReactCancel) return
  451. //当前项是选中还是取消选
  452. let haveChecked = selection.some(_ => _[this.Idkey] === row[this.Idkey]);
  453. //全选取消选和不全选选中才有意义
  454. if((haveChecked&&!this.isSelectAll) || (!haveChecked&&this.isSelectAll)) {
  455. this.checkedList.push(row)
  456. }else {
  457. this.checkedList=this.checkedList.filter(_ => _[this.Idkey]!==row[this.Idkey])
  458. }
  459. },
  460. //整列选
  461. selectAllPageHandle(selection){
  462. if(this.selectionReactCancel) return
  463. //当前页是选中还是取消
  464. let haveChecked = selection && selection.length>0;
  465. //全选取消选和不全选选中才有意义
  466. if((haveChecked&&!this.isSelectAll) || (!haveChecked&&this.isSelectAll)) {
  467. this.checkedList = [...this.checkedList,...this.list]
  468. }else {
  469. let pageIds = this.list.map(_ => _[this.Idkey]);
  470. this.checkedList = this.checkedList.filter(_ => !pageIds.includes(_[this.Idkey]))
  471. }
  472. },
  473. // 页码改变
  474. pageChange(page) {
  475. this.filterObj.pageNo = page;
  476. this.getList('pageChange')
  477. },
  478. handleClose() {
  479. this.filterObj = {
  480. classify: [],
  481. relevanceChild:true,
  482. pageNo: 1,
  483. pageSize: 10,
  484. source: [],
  485. chartTypes: [],
  486. keyWord: '',
  487. checkAll: false, //控制全选显示状态
  488. checkSome: false,
  489. newClassify:''
  490. }
  491. this.list = [];
  492. this.isSelectAll = false;
  493. this.checkedList = [];
  494. this.selectionReactCancel =false;
  495. this.$emit('update:show',false)
  496. }
  497. },
  498. }
  499. </script>
  500. <style lang="scss" scoped>
  501. .batch-move-dialog{
  502. max-width: 1200px;
  503. width:90vw;
  504. overflow: hidden;
  505. }
  506. .list-wrap{
  507. .type-wrap{
  508. display: flex;
  509. }
  510. .table-wrap{
  511. margin-top: 20px;
  512. }
  513. .filter-wrap {
  514. margin-top: 20px;
  515. display: flex;
  516. justify-content: space-between;
  517. align-items: center;
  518. flex-wrap: wrap;
  519. gap: 10px;
  520. >div {
  521. display: flex;
  522. align-items: center;
  523. gap: 10px;
  524. }
  525. }
  526. .bot {
  527. margin: 50px 0;
  528. display: flex;
  529. justify-content: center;
  530. align-items: center;
  531. gap: 30px;
  532. .el-button {
  533. width: 120px;
  534. }
  535. }
  536. }
  537. </style>