|
@@ -40,6 +40,9 @@ export default {
|
|
|
const innerColumns = stroage && !!loaclColumns ? loaclColumns : columns;
|
|
|
return {
|
|
|
drawer: false,
|
|
|
+ visible: false,
|
|
|
+ top: 0,
|
|
|
+ left: 0,
|
|
|
stroageKey: stroageKey,
|
|
|
innerColumns: innerColumns,
|
|
|
};
|
|
@@ -62,13 +65,57 @@ export default {
|
|
|
},
|
|
|
},
|
|
|
},
|
|
|
- watch: {},
|
|
|
+ watch: {
|
|
|
+ visible(value) {
|
|
|
+ if (value) {
|
|
|
+ document.body.addEventListener("click", this.hideContextmenu);
|
|
|
+ document.body.addEventListener("keydown", this.hideContextmenu);
|
|
|
+ } else {
|
|
|
+ document.body.removeEventListener("click", this.hideContextmenu);
|
|
|
+ document.body.removeEventListener("keydown", this.hideContextmenu);
|
|
|
+ }
|
|
|
+ },
|
|
|
+ },
|
|
|
methods: {
|
|
|
changeColumns() {
|
|
|
const { stroageKey, innerColumns } = this;
|
|
|
this.$refs.superTable.doLayout();
|
|
|
localStorage.setItem(stroageKey, JSON.stringify(innerColumns));
|
|
|
},
|
|
|
+ openContextmenu(row, column, event) {
|
|
|
+ this.visible = true;
|
|
|
+ this.$nextTick(() => {
|
|
|
+ // 鼠标坐标
|
|
|
+ const { x, y } = event;
|
|
|
+ // 侧边栏宽度
|
|
|
+ const [{ clientWidth: sideWidth }] =
|
|
|
+ document.getElementsByClassName("sidebar-container");
|
|
|
+ // 导航栏宽度
|
|
|
+ const { clientHeight: navHeight } =
|
|
|
+ document.getElementsByClassName("main-container")[0].firstChild;
|
|
|
+ // 菜单宽度
|
|
|
+ const [{ clientWidth: contextmenuWidth }] =
|
|
|
+ document.getElementsByClassName("el-super-table_contextmenu");
|
|
|
+ // 最大Y轴偏差
|
|
|
+ const maxLeft = this.$el.offsetWidth - contextmenuWidth;
|
|
|
+ if (x > maxLeft) {
|
|
|
+ this.left = maxLeft + 10;
|
|
|
+ } else {
|
|
|
+ this.left = x - sideWidth;
|
|
|
+ }
|
|
|
+ this.top = y - navHeight;
|
|
|
+ });
|
|
|
+ },
|
|
|
+ hideContextmenu(event) {
|
|
|
+ const { type } = event;
|
|
|
+ if (type === "click") {
|
|
|
+ this.visible = false;
|
|
|
+ }
|
|
|
+ if (type === "keydown") {
|
|
|
+ const { keyCode } = event;
|
|
|
+ if (keyCode === 27) this.visible = false;
|
|
|
+ }
|
|
|
+ },
|
|
|
},
|
|
|
created() {},
|
|
|
mounted() {},
|
|
@@ -77,151 +124,184 @@ export default {
|
|
|
</script>
|
|
|
|
|
|
<template>
|
|
|
- <el-table
|
|
|
- v-bind="$attrs"
|
|
|
- v-on="$listeners"
|
|
|
- :data="innerValue"
|
|
|
- border
|
|
|
- ref="superTable"
|
|
|
- class="el-super-table"
|
|
|
- >
|
|
|
- <slot></slot>
|
|
|
- <el-table-column
|
|
|
- v-for="({ item, attr }, index) in showColumns"
|
|
|
- :key="index"
|
|
|
- :prop="item.key"
|
|
|
- :label="item.title"
|
|
|
- :fixed="item.fixed"
|
|
|
- :width="item.width || 250"
|
|
|
- show-overflow-tooltip
|
|
|
- >
|
|
|
- <template slot-scope="scope">
|
|
|
- <slot :name="item.key" v-bind="scope" :item="item" :attr="attr">
|
|
|
- <template v-if="attr.is">
|
|
|
- <component
|
|
|
- v-if="attr.is === 'el-dict-tag'"
|
|
|
- v-bind="attr"
|
|
|
- :size="$attrs.size"
|
|
|
- :value="scope.row[item.key]"
|
|
|
- :options="dict.type[attr.dictName]"
|
|
|
- ></component>
|
|
|
- <component
|
|
|
- v-else-if="attr.is === 'el-popover-select-v2'"
|
|
|
- v-bind="attr"
|
|
|
- v-model="scope.row[item.key]"
|
|
|
- :size="$attrs.size"
|
|
|
- :source.sync="scope.row"
|
|
|
- >
|
|
|
- </component>
|
|
|
- <component
|
|
|
- v-else-if="attr.is === 'el-select'"
|
|
|
- v-bind="attr"
|
|
|
- v-model="scope.row[item.key]"
|
|
|
- :size="$attrs.size"
|
|
|
- >
|
|
|
- <template>
|
|
|
- <el-option
|
|
|
- v-for="item in dict.type[attr.dictName]"
|
|
|
- :key="item.value"
|
|
|
- :label="item.label"
|
|
|
- :value="item.value"
|
|
|
- >
|
|
|
- </el-option>
|
|
|
- </template>
|
|
|
- </component>
|
|
|
- <component
|
|
|
- v-else
|
|
|
- v-bind="attr"
|
|
|
- v-model="scope.row[item.key]"
|
|
|
- :size="$attrs.size"
|
|
|
- >
|
|
|
- </component
|
|
|
- ></template>
|
|
|
- <template v-else>
|
|
|
- <component v-if="attr.formatter" is="span">{{
|
|
|
- attr.formatter(scope.row)
|
|
|
- }}</component>
|
|
|
- <component v-else is="span">{{
|
|
|
- scope.row[item.key] || "--"
|
|
|
- }}</component>
|
|
|
- </template>
|
|
|
- </slot>
|
|
|
- </template>
|
|
|
- </el-table-column>
|
|
|
- <el-table-column
|
|
|
- v-if="hideOperationColumns"
|
|
|
- width="50"
|
|
|
- fixed="right"
|
|
|
- align="center"
|
|
|
+ <div class="el-super-table" @contextmenu.prevent.stop>
|
|
|
+ <el-table
|
|
|
+ v-bind="$attrs"
|
|
|
+ v-on="$listeners"
|
|
|
+ :data="innerValue"
|
|
|
+ border
|
|
|
+ ref="superTable"
|
|
|
+ @row-contextmenu="openContextmenu"
|
|
|
>
|
|
|
- <template slot="header" slot-scope="scope">
|
|
|
- <i
|
|
|
- class="el-icon-setting"
|
|
|
- style="cursor: pointer"
|
|
|
- @click="drawer = true"
|
|
|
- ></i>
|
|
|
- <el-drawer
|
|
|
- size="25%"
|
|
|
- title="操作列"
|
|
|
- append-to-body
|
|
|
- :visible.sync="drawer"
|
|
|
- >
|
|
|
- <el-row :gutter="20" style="margin: 0">
|
|
|
- <el-draggable
|
|
|
- v-model="innerColumns"
|
|
|
- :group="{ item: 'key' }"
|
|
|
- @change="changeColumns"
|
|
|
- >
|
|
|
- <el-col
|
|
|
- v-for="({ item }, index) in innerColumns"
|
|
|
- :key="index"
|
|
|
- :span="24"
|
|
|
- style="
|
|
|
- display: flex;
|
|
|
- justify-content: space-between;
|
|
|
- padding: 15px 20px;
|
|
|
- "
|
|
|
+ <slot></slot>
|
|
|
+ <el-table-column
|
|
|
+ v-for="({ item, attr }, index) in showColumns"
|
|
|
+ :key="index"
|
|
|
+ :prop="item.key"
|
|
|
+ :label="item.title"
|
|
|
+ :fixed="item.fixed"
|
|
|
+ :width="item.width || 250"
|
|
|
+ show-overflow-tooltip
|
|
|
+ >
|
|
|
+ <template slot-scope="scope">
|
|
|
+ <slot :name="item.key" v-bind="scope" :item="item" :attr="attr">
|
|
|
+ <template v-if="attr.is">
|
|
|
+ <component
|
|
|
+ v-if="attr.is === 'el-dict-tag'"
|
|
|
+ v-bind="attr"
|
|
|
+ :size="$attrs.size"
|
|
|
+ :value="scope.row[item.key]"
|
|
|
+ :options="dict.type[attr.dictName]"
|
|
|
+ ></component>
|
|
|
+ <component
|
|
|
+ v-else-if="attr.is === 'el-popover-select-v2'"
|
|
|
+ v-bind="attr"
|
|
|
+ v-model="scope.row[item.key]"
|
|
|
+ :size="$attrs.size"
|
|
|
+ :source.sync="scope.row"
|
|
|
>
|
|
|
- <span style="cursor: move">
|
|
|
- <i class="el-icon-rank"></i>
|
|
|
- {{ item.title }}
|
|
|
- </span>
|
|
|
- <div>
|
|
|
- <el-radio-group
|
|
|
- v-model="item.hidden"
|
|
|
- :size="$attrs.size"
|
|
|
- style="margin: 0 15px 0 0"
|
|
|
- @change="changeColumns"
|
|
|
- >
|
|
|
- <el-radio-button :label="true">显</el-radio-button>
|
|
|
- <el-radio-button :label="false">隐</el-radio-button>
|
|
|
- </el-radio-group>
|
|
|
- <el-radio-group
|
|
|
- v-model="item.fixed"
|
|
|
- :size="$attrs.size"
|
|
|
- @change="changeColumns"
|
|
|
+ </component>
|
|
|
+ <component
|
|
|
+ v-else-if="attr.is === 'el-select'"
|
|
|
+ v-bind="attr"
|
|
|
+ v-model="scope.row[item.key]"
|
|
|
+ :size="$attrs.size"
|
|
|
+ >
|
|
|
+ <template>
|
|
|
+ <el-option
|
|
|
+ v-for="item in dict.type[attr.dictName]"
|
|
|
+ :key="item.value"
|
|
|
+ :label="item.label"
|
|
|
+ :value="item.value"
|
|
|
>
|
|
|
- <el-radio-button :label="false">不</el-radio-button>
|
|
|
- <el-radio-button label="left">左</el-radio-button>
|
|
|
- <el-radio-button label="right">右</el-radio-button>
|
|
|
- </el-radio-group>
|
|
|
- </div>
|
|
|
- </el-col>
|
|
|
- </el-draggable>
|
|
|
- </el-row>
|
|
|
- </el-drawer>
|
|
|
- </template>
|
|
|
+ </el-option>
|
|
|
+ </template>
|
|
|
+ </component>
|
|
|
+ <component
|
|
|
+ v-else
|
|
|
+ v-bind="attr"
|
|
|
+ v-model="scope.row[item.key]"
|
|
|
+ :size="$attrs.size"
|
|
|
+ >
|
|
|
+ </component
|
|
|
+ ></template>
|
|
|
+ <template v-else>
|
|
|
+ <component v-if="attr.formatter" is="span">{{
|
|
|
+ attr.formatter(scope.row)
|
|
|
+ }}</component>
|
|
|
+ <component v-else is="span">{{
|
|
|
+ scope.row[item.key] || "--"
|
|
|
+ }}</component>
|
|
|
+ </template>
|
|
|
+ </slot>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column
|
|
|
+ v-if="hideOperationColumns"
|
|
|
+ width="50"
|
|
|
+ fixed="right"
|
|
|
+ align="center"
|
|
|
+ >
|
|
|
+ <template slot="header" slot-scope="scope">
|
|
|
+ <i
|
|
|
+ class="el-icon-setting"
|
|
|
+ style="cursor: pointer"
|
|
|
+ @click="drawer = true"
|
|
|
+ ></i>
|
|
|
+ </template>
|
|
|
|
|
|
- <template slot-scope="scope">
|
|
|
- <slot name="operation" v-bind="scope">
|
|
|
- <el-tag :size="$attrs.size" type="info">
|
|
|
- {{ scope.row.$index || scope.$index }}
|
|
|
- </el-tag>
|
|
|
- </slot>
|
|
|
- </template>
|
|
|
- </el-table-column>
|
|
|
- <slot v-else name="operation"> </slot>
|
|
|
- </el-table>
|
|
|
+ <template slot-scope="scope">
|
|
|
+ <slot name="operation" v-bind="scope">
|
|
|
+ <el-tag :size="$attrs.size" type="info">
|
|
|
+ {{ scope.row.$index || scope.$index + 1 }}
|
|
|
+ </el-tag>
|
|
|
+ </slot>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ <slot v-else name="operation"> </slot>
|
|
|
+ </el-table>
|
|
|
+ <el-drawer :visible.sync="drawer" size="25%" title="操作列" append-to-body>
|
|
|
+ <el-row :gutter="20" style="margin: 0">
|
|
|
+ <el-draggable
|
|
|
+ v-model="innerColumns"
|
|
|
+ :group="{ item: 'key' }"
|
|
|
+ @change="changeColumns"
|
|
|
+ >
|
|
|
+ <el-col
|
|
|
+ v-for="({ item }, index) in innerColumns"
|
|
|
+ :key="index"
|
|
|
+ :span="24"
|
|
|
+ style="
|
|
|
+ display: flex;
|
|
|
+ justify-content: space-between;
|
|
|
+ padding: 15px 20px;
|
|
|
+ "
|
|
|
+ >
|
|
|
+ <span style="cursor: move">
|
|
|
+ <i class="el-icon-rank"></i>
|
|
|
+ {{ item.title }}
|
|
|
+ </span>
|
|
|
+ <div>
|
|
|
+ <el-radio-group
|
|
|
+ v-model="item.hidden"
|
|
|
+ :size="$attrs.size"
|
|
|
+ style="margin: 0 15px 0 0"
|
|
|
+ @change="changeColumns"
|
|
|
+ >
|
|
|
+ <el-radio-button :label="true">显</el-radio-button>
|
|
|
+ <el-radio-button :label="false">隐</el-radio-button>
|
|
|
+ </el-radio-group>
|
|
|
+ <el-radio-group
|
|
|
+ v-model="item.fixed"
|
|
|
+ :size="$attrs.size"
|
|
|
+ @change="changeColumns"
|
|
|
+ >
|
|
|
+ <el-radio-button :label="false">不</el-radio-button>
|
|
|
+ <el-radio-button label="left">左</el-radio-button>
|
|
|
+ <el-radio-button label="right">右</el-radio-button>
|
|
|
+ </el-radio-group>
|
|
|
+ </div>
|
|
|
+ </el-col>
|
|
|
+ </el-draggable>
|
|
|
+ </el-row>
|
|
|
+ </el-drawer>
|
|
|
+ <transition name="el-fade-in-linear">
|
|
|
+ <ul
|
|
|
+ v-show="visible"
|
|
|
+ :style="{ left: left + 'px', top: top + 'px' }"
|
|
|
+ class="el-super-table_contextmenu"
|
|
|
+ >
|
|
|
+ <li><i class="el-icon-refresh-right"></i> 刷新页面</li>
|
|
|
+ <li><i class="el-icon-close"></i> 关闭当前</li>
|
|
|
+ <li><i class="el-icon-circle-close"></i> 关闭其他</li>
|
|
|
+ <li><i class="el-icon-back"></i> 关闭左侧</li>
|
|
|
+ <li><i class="el-icon-right"></i> 关闭右侧</li>
|
|
|
+ <li><i class="el-icon-circle-close"></i> 全部关闭</li>
|
|
|
+ </ul>
|
|
|
+ </transition>
|
|
|
+ </div>
|
|
|
</template>
|
|
|
|
|
|
-<style scoped></style>
|
|
|
+<style lang="scss" scoped>
|
|
|
+.el-super-table_contextmenu {
|
|
|
+ margin: 0;
|
|
|
+ background: #fff;
|
|
|
+ z-index: 3000;
|
|
|
+ position: absolute;
|
|
|
+ list-style-type: none;
|
|
|
+ padding: 5px 0;
|
|
|
+ border-radius: 4px;
|
|
|
+ font-size: 12px;
|
|
|
+ font-weight: 400;
|
|
|
+ color: #333;
|
|
|
+ box-shadow: 2px 2px 3px 0 rgba(0, 0, 0, 0.3);
|
|
|
+ li {
|
|
|
+ margin: 0;
|
|
|
+ padding: 7px 16px;
|
|
|
+ cursor: pointer;
|
|
|
+ &:hover {
|
|
|
+ background: #eee;
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+</style>
|