VueTable
This commit is contained in:
		
							
								
								
									
										108
									
								
								vue-table/components/HeaderQuery.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										108
									
								
								vue-table/components/HeaderQuery.vue
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,108 @@
 | 
				
			|||||||
 | 
					<!--
 | 
				
			||||||
 | 
					 * @Author: your name
 | 
				
			||||||
 | 
					 * @Date: 2020-10-21 14:22:25
 | 
				
			||||||
 | 
					 * @LastEditTime: 2021-02-04 15:46:01
 | 
				
			||||||
 | 
					 * @LastEditors: Please set LastEditors
 | 
				
			||||||
 | 
					 * @Description: In User Settings Edit
 | 
				
			||||||
 | 
					 * @FilePath: \dbadmin\src\components\HeaderQueryForm.vue
 | 
				
			||||||
 | 
					-->
 | 
				
			||||||
 | 
					<template>
 | 
				
			||||||
 | 
					  <div class="header-query__component">
 | 
				
			||||||
 | 
					    <el-form
 | 
				
			||||||
 | 
					      :model="form"
 | 
				
			||||||
 | 
					      :rules="rules"
 | 
				
			||||||
 | 
					      label-position="left"
 | 
				
			||||||
 | 
					      :label-width="labelWidth"
 | 
				
			||||||
 | 
					      :size="size"
 | 
				
			||||||
 | 
					      @keydown.enter.native.prevent="request"
 | 
				
			||||||
 | 
					      inline
 | 
				
			||||||
 | 
					      v-bind="$attrs"
 | 
				
			||||||
 | 
					    >
 | 
				
			||||||
 | 
					      <slot></slot>
 | 
				
			||||||
 | 
					      <el-button v-if="btn" type="primary" :size="size" @click="request">
 | 
				
			||||||
 | 
					        {{ queryLabel }}
 | 
				
			||||||
 | 
					      </el-button>
 | 
				
			||||||
 | 
					    </el-form>
 | 
				
			||||||
 | 
					  </div>
 | 
				
			||||||
 | 
					</template>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<script>
 | 
				
			||||||
 | 
					import { Component, Prop, Emit } from 'vue-property-decorator'
 | 
				
			||||||
 | 
					import Vue from 'vue'
 | 
				
			||||||
 | 
					import { getModule } from 'vuex-module-decorators'
 | 
				
			||||||
 | 
					import QueryStore, { DEFAULT_TAG as DEFAULT_QUERY_TAG } from '@/store/modules/query'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import store from '@/store'
 | 
				
			||||||
 | 
					const queryStore = getModule(QueryStore, store)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@Component({
 | 
				
			||||||
 | 
					  name: 'HeaderQuery'
 | 
				
			||||||
 | 
					})
 | 
				
			||||||
 | 
					export default class HeaderQuery extends Vue {
 | 
				
			||||||
 | 
					  @Prop({ type: String, default: DEFAULT_QUERY_TAG })
 | 
				
			||||||
 | 
					  tag
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @Prop({ type: Object, required: true })
 | 
				
			||||||
 | 
					  form
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @Prop({ type: Object, default: () => ({}) })
 | 
				
			||||||
 | 
					  rules
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @Prop({ type: String, default: 'mini' })
 | 
				
			||||||
 | 
					  size
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @Prop({ type: String, default: '查询' })
 | 
				
			||||||
 | 
					  queryLabel
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @Prop({ type: Boolean, default: true })
 | 
				
			||||||
 | 
					  btn
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @Prop({ type: Boolean, default: true })
 | 
				
			||||||
 | 
					  cache
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @Prop({ type: String, default: undefined })
 | 
				
			||||||
 | 
					  labelWidth
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  pageData = null
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  get storeData() {
 | 
				
			||||||
 | 
					    return queryStore.data[this.path][this.tag] || {}
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  set storeData(data) {
 | 
				
			||||||
 | 
					    queryStore.setData({ path: this.path, data, tag: this.tag })
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  get path() {
 | 
				
			||||||
 | 
					    return this.$route.path
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  get fetch() {
 | 
				
			||||||
 | 
					    return queryStore.fetchs[this.path][this.tag]
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  created() {
 | 
				
			||||||
 | 
					    queryStore.init({ tag: this.tag, path: this.path, initData: Object.assign({}, this.form) })
 | 
				
			||||||
 | 
					    this.pageData = queryStore.pageData[this.path][this.tag]
 | 
				
			||||||
 | 
					    this.emitUpdateQuery()
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /**
 | 
				
			||||||
 | 
					   * 触发外部更新值
 | 
				
			||||||
 | 
					   */
 | 
				
			||||||
 | 
					  @Emit('update:form')
 | 
				
			||||||
 | 
					  emitUpdateQuery() {
 | 
				
			||||||
 | 
					    return Object.assign({}, this.storeData)
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @Emit('submit')
 | 
				
			||||||
 | 
					  async request() {
 | 
				
			||||||
 | 
					    this.pageData.page = 1
 | 
				
			||||||
 | 
					    this.storeData = this.form
 | 
				
			||||||
 | 
					    this.fetch()
 | 
				
			||||||
 | 
					    return this.storeData
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					</script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<style lang="scss" scoped></style>
 | 
				
			||||||
							
								
								
									
										556
									
								
								vue-table/components/Table.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										556
									
								
								vue-table/components/Table.vue
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,556 @@
 | 
				
			|||||||
 | 
					<!--
 | 
				
			||||||
 | 
					 * @Author: your name
 | 
				
			||||||
 | 
					 * @Date: 2020-09-08 16:22:26
 | 
				
			||||||
 | 
					 * @LastEditTime: 2021-02-04 16:52:15
 | 
				
			||||||
 | 
					 * @LastEditors: Please set LastEditors
 | 
				
			||||||
 | 
					 * @Description: In User Settings Edit
 | 
				
			||||||
 | 
					 * @FilePath: \dbadmin\src\components\TableForm\Table.vue
 | 
				
			||||||
 | 
					-->
 | 
				
			||||||
 | 
					<template>
 | 
				
			||||||
 | 
					  <div class="table__component" ref="root" :style="rootStyle">
 | 
				
			||||||
 | 
					    <el-button-group>
 | 
				
			||||||
 | 
					      <!-- 普通功能按钮插槽 -->
 | 
				
			||||||
 | 
					      <slot
 | 
				
			||||||
 | 
					        name="btns"
 | 
				
			||||||
 | 
					        :selectable="multiselect && selectedRows.length > 0"
 | 
				
			||||||
 | 
					        :disabled="!multiselect || selectedRows.length === 0"
 | 
				
			||||||
 | 
					        :selectrows="selectedRows"
 | 
				
			||||||
 | 
					        :multiStepAction="multiStepReq"
 | 
				
			||||||
 | 
					      ></slot>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      <!-- 数据导出按钮插槽 -->
 | 
				
			||||||
 | 
					      <slot v-if="allowExport" name="export-btn" :disabled="selectedRows.length === 0" :action="exportData" :loading="exporting"></slot>
 | 
				
			||||||
 | 
					    </el-button-group>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    <el-table
 | 
				
			||||||
 | 
					      :data="list"
 | 
				
			||||||
 | 
					      @selection-change="onSelectionChange"
 | 
				
			||||||
 | 
					      @current-change="$emit('current-change', $event)"
 | 
				
			||||||
 | 
					      ref="table"
 | 
				
			||||||
 | 
					      :height="tableHeight"
 | 
				
			||||||
 | 
					      v-loading="loading"
 | 
				
			||||||
 | 
					      :span-method="SpanMethod"
 | 
				
			||||||
 | 
					      :default-expand-all="expandAll"
 | 
				
			||||||
 | 
					      :class="tableClass"
 | 
				
			||||||
 | 
					      v-bind="tableOptions"
 | 
				
			||||||
 | 
					    >
 | 
				
			||||||
 | 
					      <el-table-column v-if="enableDrag" v-bind="dragColumnOptions">
 | 
				
			||||||
 | 
					        <i slot-scope="{ row }" class="el-icon-s-fold handle" style="font-size: 16px; cursor: move"></i>
 | 
				
			||||||
 | 
					      </el-table-column>
 | 
				
			||||||
 | 
					      <el-table-column type="selection" v-if="multiselect || allowExport" />
 | 
				
			||||||
 | 
					      <slot></slot>
 | 
				
			||||||
 | 
					    </el-table>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    <!-- 分页 -->
 | 
				
			||||||
 | 
					    <div v-if="visiblePage" class="page">
 | 
				
			||||||
 | 
					      <el-pagination
 | 
				
			||||||
 | 
					        :total="total"
 | 
				
			||||||
 | 
					        :page-size="size"
 | 
				
			||||||
 | 
					        background
 | 
				
			||||||
 | 
					        layout="sizes, prev, pager, next"
 | 
				
			||||||
 | 
					        :current-page.sync="currentPage"
 | 
				
			||||||
 | 
					        :page-sizes="[...(isDev ? [1, 2, 5] : []), 10, 20, 50, 100, 200]"
 | 
				
			||||||
 | 
					        @size-change="onSizeChange"
 | 
				
			||||||
 | 
					      ></el-pagination>
 | 
				
			||||||
 | 
					    </div>
 | 
				
			||||||
 | 
					  </div>
 | 
				
			||||||
 | 
					</template>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<script>
 | 
				
			||||||
 | 
					import { get, del as RequestDelete } from '@/utils/request'
 | 
				
			||||||
 | 
					import Vue from 'vue'
 | 
				
			||||||
 | 
					import { Component, Prop, Watch, Ref, ProvideReactive, Provide } from 'vue-property-decorator'
 | 
				
			||||||
 | 
					import { toTime, toDateTime, toDate } from '@/utils/util'
 | 
				
			||||||
 | 
					import { downloadXlsx } from '@/utils/excel'
 | 
				
			||||||
 | 
					import { debounce } from 'underscore'
 | 
				
			||||||
 | 
					import { getModule } from 'vuex-module-decorators'
 | 
				
			||||||
 | 
					import QueryStore, { DEFAULT_TAG as DEFAULT_QUERY_TAG } from '@/store/modules/query'
 | 
				
			||||||
 | 
					import Sortable from 'sortablejs'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Table组件只读取不写vuex里面的查询参数,但会修改分页参数(入currentPage,pageSize)
 | 
				
			||||||
 | 
					import store from '@/store'
 | 
				
			||||||
 | 
					const queryStore = getModule(QueryStore, store)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@Component({
 | 
				
			||||||
 | 
					  name: 'Table'
 | 
				
			||||||
 | 
					})
 | 
				
			||||||
 | 
					export default class Table extends Vue {
 | 
				
			||||||
 | 
					  @Prop({ type: Boolean, default: false })
 | 
				
			||||||
 | 
					  enableDrag
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @Prop({ type: Object, default: () => ({}) })
 | 
				
			||||||
 | 
					  dragColumnOptions
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @Prop({ type: Object, default: () => ({}) })
 | 
				
			||||||
 | 
					  tableOptions
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @Prop({ type: Boolean, default: false })
 | 
				
			||||||
 | 
					  expandAll
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @Prop({ type: String })
 | 
				
			||||||
 | 
					  tableClass
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @Prop({ type: Boolean, default: false })
 | 
				
			||||||
 | 
					  multiselect
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @Prop({ type: Boolean, default: true })
 | 
				
			||||||
 | 
					  visiblePage
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @Prop({ type: Function })
 | 
				
			||||||
 | 
					  responseHandler
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /**
 | 
				
			||||||
 | 
					   * 是否允许导出数据
 | 
				
			||||||
 | 
					   */
 | 
				
			||||||
 | 
					  @Prop({ type: Boolean, default: false })
 | 
				
			||||||
 | 
					  allowExport
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /**
 | 
				
			||||||
 | 
					   * 导出数据时需要特殊处理的字段
 | 
				
			||||||
 | 
					   * {
 | 
				
			||||||
 | 
					   *  [字段名]:处理方式
 | 
				
			||||||
 | 
					   * }
 | 
				
			||||||
 | 
					   */
 | 
				
			||||||
 | 
					  @Prop({ type: Object, default: () => ({}) })
 | 
				
			||||||
 | 
					  exportSpecialField
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @Prop({ type: String, required: true })
 | 
				
			||||||
 | 
					  api
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @Prop({ type: Function })
 | 
				
			||||||
 | 
					  SpanMethod
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @Prop({ type: [String, Number] })
 | 
				
			||||||
 | 
					  height
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @Prop({ type: String, default: DEFAULT_QUERY_TAG })
 | 
				
			||||||
 | 
					  tag
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @Ref('table')
 | 
				
			||||||
 | 
					  tableRef
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @Ref('root')
 | 
				
			||||||
 | 
					  rootRef
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /**
 | 
				
			||||||
 | 
					   * 当前页码
 | 
				
			||||||
 | 
					   */
 | 
				
			||||||
 | 
					  // currentPage = 1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  get currentPage() {
 | 
				
			||||||
 | 
					    if (!this.pageData) return 1
 | 
				
			||||||
 | 
					    if (!this.pageData.page) this.pageData.page = 1
 | 
				
			||||||
 | 
					    return this.pageData.page
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  set currentPage(page) {
 | 
				
			||||||
 | 
					    if (!this.pageData) return
 | 
				
			||||||
 | 
					    this.pageData.page = page
 | 
				
			||||||
 | 
					    return page
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // size = 20
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  get size() {
 | 
				
			||||||
 | 
					    if (!this.pageData) return 20
 | 
				
			||||||
 | 
					    if (!this.pageData.size) this.pageData.size = 20
 | 
				
			||||||
 | 
					    return this.pageData.size
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  set size(size) {
 | 
				
			||||||
 | 
					    if (!this.pageData) return
 | 
				
			||||||
 | 
					    this.pageData.size = size
 | 
				
			||||||
 | 
					    return size
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /**
 | 
				
			||||||
 | 
					   * 列表数据
 | 
				
			||||||
 | 
					   */
 | 
				
			||||||
 | 
					  @ProvideReactive('table_data')
 | 
				
			||||||
 | 
					  list = []
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /**
 | 
				
			||||||
 | 
					   * 列表数据是否加载中
 | 
				
			||||||
 | 
					   */
 | 
				
			||||||
 | 
					  loading = false
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /**
 | 
				
			||||||
 | 
					   * 列表数据总长度
 | 
				
			||||||
 | 
					   */
 | 
				
			||||||
 | 
					  total = 1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /**
 | 
				
			||||||
 | 
					   * 选中的行
 | 
				
			||||||
 | 
					   */
 | 
				
			||||||
 | 
					  selectedRows = []
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /**
 | 
				
			||||||
 | 
					   * 数据导出处理中
 | 
				
			||||||
 | 
					   */
 | 
				
			||||||
 | 
					  exporting = false
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  rootHeight = null
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  tableHeightData = 50
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  get tableHeight() {
 | 
				
			||||||
 | 
					    if (this.propHeightOk) {
 | 
				
			||||||
 | 
					      return this.height
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return this.tableHeightData
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  get propHeightOk() {
 | 
				
			||||||
 | 
					    return ['string', 'number'].includes(typeof this.height)
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  get rootStyle() {
 | 
				
			||||||
 | 
					    const style = {}
 | 
				
			||||||
 | 
					    if (this.rootHeight) {
 | 
				
			||||||
 | 
					      style.height = `${this.rootHeight}px`
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return style
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  pageData = {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  get path() {
 | 
				
			||||||
 | 
					    return this.$route.path
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  async created() {
 | 
				
			||||||
 | 
					    queryStore.init({ path: this.path, tag: this.tag })
 | 
				
			||||||
 | 
					    queryStore.registerFetch({ path: this.path, func: this.fetch, tag: this.tag })
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    this.$set(this, 'pageData', queryStore.pageData[this.$route.path][this.tag])
 | 
				
			||||||
 | 
					    await this.fetch()
 | 
				
			||||||
 | 
					    this.resizeHeight()
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  async mounted() {
 | 
				
			||||||
 | 
					    this.initSortable()
 | 
				
			||||||
 | 
					    window.addEventListener('resize', this.resizeHeight)
 | 
				
			||||||
 | 
					    await this.$nextTick()
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  initSortable() {
 | 
				
			||||||
 | 
					    if (!this.enableDrag) return
 | 
				
			||||||
 | 
					    const tbody = this.tableRef.$el.querySelector('.el-table__body-wrapper table tbody')
 | 
				
			||||||
 | 
					    if (!tbody) return
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const onEnd = async event => {
 | 
				
			||||||
 | 
					      const list = this.list.splice(0)
 | 
				
			||||||
 | 
					      await this.$nextTick()
 | 
				
			||||||
 | 
					      const { oldIndex, newIndex } = event
 | 
				
			||||||
 | 
					      const oldObj = list[oldIndex]
 | 
				
			||||||
 | 
					      const newObj = list[newIndex]
 | 
				
			||||||
 | 
					      oldObj.sort = newIndex
 | 
				
			||||||
 | 
					      newObj.sort = oldIndex
 | 
				
			||||||
 | 
					      list[oldIndex] = newObj
 | 
				
			||||||
 | 
					      list[newIndex] = oldObj
 | 
				
			||||||
 | 
					      this.list.push(...list)
 | 
				
			||||||
 | 
					      this.$emit('sort', this.list)
 | 
				
			||||||
 | 
					      this.$emit('sort-change', { newObj, oldObj })
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    new Sortable(tbody, {
 | 
				
			||||||
 | 
					      group: `TableComponent:${this._uid}`,
 | 
				
			||||||
 | 
					      handle: '.el-icon-s-fold.handle',
 | 
				
			||||||
 | 
					      draggable: 'tr.el-table__row',
 | 
				
			||||||
 | 
					      onEnd
 | 
				
			||||||
 | 
					    })
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @Watch('api')
 | 
				
			||||||
 | 
					  onWatchApiChange(api) {
 | 
				
			||||||
 | 
					    this.currentPage = 1
 | 
				
			||||||
 | 
					    this.fetch()
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  beforeDestroy() {
 | 
				
			||||||
 | 
					    window.removeEventListener('resize', this.resizeHeight)
 | 
				
			||||||
 | 
					    queryStore.unregisterFetch(this.path, this.tag)
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  async setHeight() {
 | 
				
			||||||
 | 
					    if (this.propHeightOk) return
 | 
				
			||||||
 | 
					    if (!this.tableRef) await this.$nextTick()
 | 
				
			||||||
 | 
					    if (!this.tableRef || !this.tableRef.$el) return
 | 
				
			||||||
 | 
					    this.rootHeight = document.body.clientHeight - this.tableRef.$el.offsetTop - 60
 | 
				
			||||||
 | 
					    this.tableHeightData = this.rootHeight - 85
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  resizeHeight = debounce(this.setHeight.bind(this), 300)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @Watch('currentPage')
 | 
				
			||||||
 | 
					  /**
 | 
				
			||||||
 | 
					   * 页码有变化时获取数据
 | 
				
			||||||
 | 
					   */
 | 
				
			||||||
 | 
					  onWatchCurrentPageChange(page) {
 | 
				
			||||||
 | 
					    this.fetch()
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  onSizeChange(size) {
 | 
				
			||||||
 | 
					    this.size = size
 | 
				
			||||||
 | 
					    this.currentPage = 1
 | 
				
			||||||
 | 
					    this.fetch()
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  onSelectionChange(rows) {
 | 
				
			||||||
 | 
					    this.$emit('selection-change', rows)
 | 
				
			||||||
 | 
					    this.$set(this, 'selectedRows', rows)
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /**
 | 
				
			||||||
 | 
					   * 导出数据
 | 
				
			||||||
 | 
					   * @param {string} name 工作薄名
 | 
				
			||||||
 | 
					   * @param {string} filename 文件名
 | 
				
			||||||
 | 
					   * @param {Array} 英文字段-中文转换表
 | 
				
			||||||
 | 
					   */
 | 
				
			||||||
 | 
					  exportData(name, filename, fields) {
 | 
				
			||||||
 | 
					    if (this.exporting) return
 | 
				
			||||||
 | 
					    this.exporting = true
 | 
				
			||||||
 | 
					    const data = this.selectedRows.map(item => {
 | 
				
			||||||
 | 
					      const result = {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      fields.forEach(([en, cn]) => {
 | 
				
			||||||
 | 
					        result[cn] = item[en]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // 特殊处理的字段
 | 
				
			||||||
 | 
					        if (en in this.exportSpecialField) {
 | 
				
			||||||
 | 
					          const type = this.exportSpecialField[en]
 | 
				
			||||||
 | 
					          switch (type) {
 | 
				
			||||||
 | 
					            case 'time':
 | 
				
			||||||
 | 
					              result[cn] = toTime(result[cn])
 | 
				
			||||||
 | 
					              return
 | 
				
			||||||
 | 
					            case 'date-time':
 | 
				
			||||||
 | 
					              result[cn] = toDateTime(result[cn])
 | 
				
			||||||
 | 
					              return
 | 
				
			||||||
 | 
					            case 'date':
 | 
				
			||||||
 | 
					              result[cn] = toDate(result[cn])
 | 
				
			||||||
 | 
					              return
 | 
				
			||||||
 | 
					            default:
 | 
				
			||||||
 | 
					              break
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					        } else if (typeof result[cn] === 'boolean') {
 | 
				
			||||||
 | 
					          result[cn] = result[cn] ? '是' : '否'
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      })
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      return result
 | 
				
			||||||
 | 
					    })
 | 
				
			||||||
 | 
					    downloadXlsx(
 | 
				
			||||||
 | 
					      {
 | 
				
			||||||
 | 
					        [name]: data
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      filename
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					    this.exporting = false
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /**
 | 
				
			||||||
 | 
					   * 获取列表数据
 | 
				
			||||||
 | 
					   */
 | 
				
			||||||
 | 
					  @Provide('fetch')
 | 
				
			||||||
 | 
					  async fetch(query) {
 | 
				
			||||||
 | 
					    if (this.loading) return
 | 
				
			||||||
 | 
					    this.loading = true
 | 
				
			||||||
 | 
					    let data, params
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (query) {
 | 
				
			||||||
 | 
					      this.currentPage = 1
 | 
				
			||||||
 | 
					      params = query
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					      params = queryStore.data[this.path][this.tag]
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Object.entries(params).forEach(([key, value]) => {
 | 
				
			||||||
 | 
					      if ([undefined, NaN, null, ''].includes(value) || key === '__ob__') {
 | 
				
			||||||
 | 
					        delete params[key]
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    })
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const page_params = {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (this.visiblePage) {
 | 
				
			||||||
 | 
					      page_params.limit = this.size
 | 
				
			||||||
 | 
					      page_params.page = this.currentPage
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    try {
 | 
				
			||||||
 | 
					      data = await get(this.api, {
 | 
				
			||||||
 | 
					        params: {
 | 
				
			||||||
 | 
					          ...params,
 | 
				
			||||||
 | 
					          ...page_params
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      })
 | 
				
			||||||
 | 
					      this.$emit('response', data)
 | 
				
			||||||
 | 
					    } catch (err) {
 | 
				
			||||||
 | 
					      this.loading = false
 | 
				
			||||||
 | 
					      return
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    this.total = data.count
 | 
				
			||||||
 | 
					    this.currentPage = data.page || data.currentPage
 | 
				
			||||||
 | 
					    const list = data.results.map(detail => {
 | 
				
			||||||
 | 
					      if (detail.created_time) {
 | 
				
			||||||
 | 
					        detail.created_time = toDateTime(detail.created_time)
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      if (detail.date_joined) {
 | 
				
			||||||
 | 
					        detail.date_joined = toDateTime(detail.date_joined)
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      if (detail.release_time) {
 | 
				
			||||||
 | 
					        detail.release_time = toDateTime(detail.release_time)
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      if (this.responseHandler) return this.responseHandler(detail)
 | 
				
			||||||
 | 
					      return detail
 | 
				
			||||||
 | 
					    })
 | 
				
			||||||
 | 
					    this.$emit('fetch-success', list)
 | 
				
			||||||
 | 
					    this.list.splice(0)
 | 
				
			||||||
 | 
					    this.$set(this, 'list', list)
 | 
				
			||||||
 | 
					    await this.$nextTick()
 | 
				
			||||||
 | 
					    this.$emit('get-table-ref', this.$refs.table)
 | 
				
			||||||
 | 
					    this.loading = false
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /**
 | 
				
			||||||
 | 
					   * 下一页
 | 
				
			||||||
 | 
					   */
 | 
				
			||||||
 | 
					  nextPage() {
 | 
				
			||||||
 | 
					    this.currentPage++
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /**
 | 
				
			||||||
 | 
					   * 上一页
 | 
				
			||||||
 | 
					   */
 | 
				
			||||||
 | 
					  prevPage() {
 | 
				
			||||||
 | 
					    this.currentPage--
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /**
 | 
				
			||||||
 | 
					   * 重置当前页码
 | 
				
			||||||
 | 
					   */
 | 
				
			||||||
 | 
					  resetPage() {
 | 
				
			||||||
 | 
					    this.currentPage = 1
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /**
 | 
				
			||||||
 | 
					   * 切换某行某列的布尔值
 | 
				
			||||||
 | 
					   * @param {number} rowIndex 行
 | 
				
			||||||
 | 
					   * @param {string} name 字段
 | 
				
			||||||
 | 
					   * @param {boolean} status 修改的布尔值
 | 
				
			||||||
 | 
					   */
 | 
				
			||||||
 | 
					  toggleColumnBoolean(rowIndex, name, status) {
 | 
				
			||||||
 | 
					    const detail = this.list[rowIndex]
 | 
				
			||||||
 | 
					    if (!detail) throw new Error(`列${rowIndex}不存在`)
 | 
				
			||||||
 | 
					    if (typeof detail[name] !== 'boolean') throw new Error(`列${rowIndex}-键${name}不是布尔值`)
 | 
				
			||||||
 | 
					    const oldValue = detail[name]
 | 
				
			||||||
 | 
					    detail[name] = status
 | 
				
			||||||
 | 
					    this.$emit('column-bool-change', {
 | 
				
			||||||
 | 
					      row: rowIndex,
 | 
				
			||||||
 | 
					      name,
 | 
				
			||||||
 | 
					      value: status,
 | 
				
			||||||
 | 
					      oldValue
 | 
				
			||||||
 | 
					    })
 | 
				
			||||||
 | 
					    return status
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /**
 | 
				
			||||||
 | 
					   * 设置某行某列的值
 | 
				
			||||||
 | 
					   * @param {number} rowIndex 行
 | 
				
			||||||
 | 
					   * @param {string} name 字段
 | 
				
			||||||
 | 
					   * @param {any} value 修改的值
 | 
				
			||||||
 | 
					   */
 | 
				
			||||||
 | 
					  setColumnValue(rowIndex, name, value) {
 | 
				
			||||||
 | 
					    const detail = this.list[rowIndex]
 | 
				
			||||||
 | 
					    if (!detail) throw new Error(`列${rowIndex}不存在`)
 | 
				
			||||||
 | 
					    const oldValue = detail[name]
 | 
				
			||||||
 | 
					    detail[name] = value
 | 
				
			||||||
 | 
					    this.$emit('column-value-change', {
 | 
				
			||||||
 | 
					      row: rowIndex,
 | 
				
			||||||
 | 
					      name,
 | 
				
			||||||
 | 
					      value,
 | 
				
			||||||
 | 
					      oldValue
 | 
				
			||||||
 | 
					    })
 | 
				
			||||||
 | 
					    return value
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /**
 | 
				
			||||||
 | 
					   * 格式化日期对象
 | 
				
			||||||
 | 
					   * @param {string|Date} date 日期对象/字符串
 | 
				
			||||||
 | 
					   * @returns {string}
 | 
				
			||||||
 | 
					   */
 | 
				
			||||||
 | 
					  formatDate(date, time = true) {
 | 
				
			||||||
 | 
					    return time ? toDateTime(date) : toDate(date)
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /**
 | 
				
			||||||
 | 
					   * 格式化日期对象
 | 
				
			||||||
 | 
					   * @param {string|Date} date 日期对象/字符串
 | 
				
			||||||
 | 
					   * @returns {string}
 | 
				
			||||||
 | 
					   */
 | 
				
			||||||
 | 
					  formatTime(date) {
 | 
				
			||||||
 | 
					    return toTime(date)
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /**
 | 
				
			||||||
 | 
					   * 调用删除接口
 | 
				
			||||||
 | 
					   * @param {string} api 接口地址
 | 
				
			||||||
 | 
					   * @param {string} message 提示消息
 | 
				
			||||||
 | 
					   * @returns {Promise<boolean>} 是否删除成功
 | 
				
			||||||
 | 
					   */
 | 
				
			||||||
 | 
					  async del(api, message = '是否确认删除') {
 | 
				
			||||||
 | 
					    await this.$confirm(message)
 | 
				
			||||||
 | 
					    try {
 | 
				
			||||||
 | 
					      await RequestDelete(api)
 | 
				
			||||||
 | 
					    } catch (err) {
 | 
				
			||||||
 | 
					      console.error(`
 | 
				
			||||||
 | 
					Table组件调用删除接口失败
 | 
				
			||||||
 | 
					接口地址   ${api}
 | 
				
			||||||
 | 
					原因:
 | 
				
			||||||
 | 
					${err.message || err}
 | 
				
			||||||
 | 
					`)
 | 
				
			||||||
 | 
					      return false
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    this.fetch()
 | 
				
			||||||
 | 
					    return true
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  async multiStepReq(ids, req, options = {}) {
 | 
				
			||||||
 | 
					    const baseOptions = {
 | 
				
			||||||
 | 
					      confirmMessage: '是否确认此操作?',
 | 
				
			||||||
 | 
					      successMessage: '批量操作成功'
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    options = Object.assign({}, baseOptions, options)
 | 
				
			||||||
 | 
					    await this.$confirm(options.confirmMessage)
 | 
				
			||||||
 | 
					    for (const id of ids) {
 | 
				
			||||||
 | 
					      await req(id, this.selectedRows)
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    this.$message.success(options.successMessage)
 | 
				
			||||||
 | 
					    this.fetch()
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					</script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<style lang="scss" scoped>
 | 
				
			||||||
 | 
					.page {
 | 
				
			||||||
 | 
					  display: flex;
 | 
				
			||||||
 | 
					  justify-content: center;
 | 
				
			||||||
 | 
					  margin-top: 1em;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					</style>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<style lang="scss">
 | 
				
			||||||
 | 
					.mo3 {
 | 
				
			||||||
 | 
					  overflow: hidden;
 | 
				
			||||||
 | 
					  -webkit-line-clamp: 3;
 | 
				
			||||||
 | 
					  -webkit-box-orient: vertical;
 | 
				
			||||||
 | 
					  display: -webkit-box;
 | 
				
			||||||
 | 
					  text-overflow: ellipsis;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.el-tooltip__popper {
 | 
				
			||||||
 | 
					  max-width: 500px;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					</style>
 | 
				
			||||||
							
								
								
									
										27
									
								
								vue-table/store/index.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								vue-table/store/index.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,27 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * @Author: your name
 | 
				
			||||||
 | 
					 * @Date: 2020-09-07 10:17:01
 | 
				
			||||||
 | 
					 * @LastEditTime: 2021-02-18 14:51:58
 | 
				
			||||||
 | 
					 * @LastEditors: Please set LastEditors
 | 
				
			||||||
 | 
					 * @Description: In User Settings Edit,
 | 
				
			||||||
 | 
					 * @FilePath: \dbadmin\src\store\index.js
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					import Vue from 'vue'
 | 
				
			||||||
 | 
					import Vuex from 'vuex'
 | 
				
			||||||
 | 
					import query from './modules/query'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Vue.use(Vuex)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const store = new Vuex.Store({
 | 
				
			||||||
 | 
					  modules: {
 | 
				
			||||||
 | 
					    app,
 | 
				
			||||||
 | 
					    api,
 | 
				
			||||||
 | 
					    user,
 | 
				
			||||||
 | 
					    tagsView,
 | 
				
			||||||
 | 
					    permission,
 | 
				
			||||||
 | 
					    query
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  getters
 | 
				
			||||||
 | 
					})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default store
 | 
				
			||||||
							
								
								
									
										88
									
								
								vue-table/store/modules/query.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										88
									
								
								vue-table/store/modules/query.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,88 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * @Author: your name
 | 
				
			||||||
 | 
					 * @Date: 2020-10-28 14:40:52
 | 
				
			||||||
 | 
					 * @LastEditTime: 2020-12-29 14:33:05
 | 
				
			||||||
 | 
					 * @LastEditors: Please set LastEditors
 | 
				
			||||||
 | 
					 * @Description: In User Settings Edit
 | 
				
			||||||
 | 
					 * @FilePath: \dbadmin\src\store\modules\query.js
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					import { Module, VuexModule, Mutation } from 'vuex-module-decorators'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export const DEFAULT_TAG = 'default'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function nullObj() {
 | 
				
			||||||
 | 
					  return Object.create(null)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@Module({ name: 'query', namespaced: true })
 | 
				
			||||||
 | 
					class Query extends VuexModule {
 | 
				
			||||||
 | 
					  data = nullObj()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  pageData = nullObj()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  fetchs = nullObj()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @Mutation
 | 
				
			||||||
 | 
					  init(data) {
 | 
				
			||||||
 | 
					    let path = ''
 | 
				
			||||||
 | 
					    let initData = nullObj()
 | 
				
			||||||
 | 
					    let tag = DEFAULT_TAG
 | 
				
			||||||
 | 
					    if (typeof data === 'string') {
 | 
				
			||||||
 | 
					      path = data
 | 
				
			||||||
 | 
					    } else if (typeof data === 'object') {
 | 
				
			||||||
 | 
					      if (data.path) path = data.path
 | 
				
			||||||
 | 
					      if (data.initData) initData = data.initData
 | 
				
			||||||
 | 
					      if (data.tag) tag = data.tag
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if (!path) throw new Error('path不能为空')
 | 
				
			||||||
 | 
					    initPath.call(this, path)
 | 
				
			||||||
 | 
					    if (!this.data[path][tag]) {
 | 
				
			||||||
 | 
					      this.data[path][tag] = initData
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if (!this.pageData[path][tag]) {
 | 
				
			||||||
 | 
					      this.pageData[path][tag] = {
 | 
				
			||||||
 | 
					        page: 1,
 | 
				
			||||||
 | 
					        size: 20
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @Mutation
 | 
				
			||||||
 | 
					  setData({ path, data, tag = DEFAULT_TAG }) {
 | 
				
			||||||
 | 
					    initPath.call(this, path)
 | 
				
			||||||
 | 
					    this.data[path][tag] = data
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @Mutation
 | 
				
			||||||
 | 
					  registerFetch({ path, func, tag = DEFAULT_TAG }) {
 | 
				
			||||||
 | 
					    initPath.call(this, path)
 | 
				
			||||||
 | 
					    this.fetchs[path][tag] = func
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @Mutation
 | 
				
			||||||
 | 
					  unregisterFetch(path, tag = DEFAULT_TAG) {
 | 
				
			||||||
 | 
					    initPath.call(this, path)
 | 
				
			||||||
 | 
					    delete this.fetchs[path][tag]
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function initPath(path) {
 | 
				
			||||||
 | 
					  if (this instanceof Window) {
 | 
				
			||||||
 | 
					    throw new Error('initPath this对象没有绑定')
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  if (!this.data[path]) this.data[path] = nullObj()
 | 
				
			||||||
 | 
					  if (!this.pageData[path]) this.pageData[path] = nullObj()
 | 
				
			||||||
 | 
					  if (!this.fetchs[path]) this.fetchs[path] = nullObj()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// function initTag(path, tag) {
 | 
				
			||||||
 | 
					//   if (this instanceof Window) {
 | 
				
			||||||
 | 
					//     throw new Error('initPath this对象没有绑定')
 | 
				
			||||||
 | 
					//   }
 | 
				
			||||||
 | 
					//   initTag.call(path)
 | 
				
			||||||
 | 
					//   if (!this.data[path][tag]) this.data[path][tag] = nullObj()
 | 
				
			||||||
 | 
					//   if (!this.pageData[path][tag]) this.pageData[path][tag] = nullObj()
 | 
				
			||||||
 | 
					//   if (!this.fetchs[path][tag]) this.fetchs[path][tag] = nullObj()
 | 
				
			||||||
 | 
					// }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default Query
 | 
				
			||||||
		Reference in New Issue
	
	Block a user