|
@@ -1,585 +0,0 @@
|
|
|
-<template>
|
|
|
- <div class="header-actions" v-if="getActionList.length != 0">
|
|
|
- <div class="overflow-box">
|
|
|
- <el-button
|
|
|
- v-for="(item, index) in getActionList"
|
|
|
- :key="index"
|
|
|
- :type="item.type || 'primary'"
|
|
|
- :plain="item.plain || false"
|
|
|
- v-bind="getHeaderActions(item)"
|
|
|
- @click="item.action"
|
|
|
- :disabled="item.disabled || false"
|
|
|
- >
|
|
|
- {{ item.text }}
|
|
|
- </el-button>
|
|
|
- </div>
|
|
|
- </div>
|
|
|
- <div class="table-list-container by-table">
|
|
|
- <!-- v-if="!hideHeader" -->
|
|
|
- <header v-if="false" class="header">
|
|
|
- <h2>{{ title }}</h2>
|
|
|
- </header>
|
|
|
- <div class="by-search" v-if="!hideSearch">
|
|
|
- <div style="display: flex">
|
|
|
- <div
|
|
|
- class="by-dropdown"
|
|
|
- v-for="(i, index) in selectConfigCopy"
|
|
|
- :key="i.prop"
|
|
|
- style="margin-right: 10px"
|
|
|
- >
|
|
|
- <div class="by-dropdown-title">
|
|
|
- {{ i.label || i.labelCopy
|
|
|
- }}<i
|
|
|
- style="margin-left: 5px"
|
|
|
- class="iconfont icon-iconm_xialan1"
|
|
|
- ></i>
|
|
|
- </div>
|
|
|
- <ul class="by-dropdown-lists">
|
|
|
- <li
|
|
|
- @click="searchItemSelct('all', i, index)"
|
|
|
- v-if="i.isShowAll === false ? i.isShowAll : true"
|
|
|
- style="
|
|
|
- display: flex;
|
|
|
- align-items: center;
|
|
|
- justify-content: center;
|
|
|
- "
|
|
|
- >
|
|
|
- {{ $t("common.all") }}
|
|
|
- </li>
|
|
|
- <li
|
|
|
- v-for="j in i.data"
|
|
|
- :key="j.value"
|
|
|
- @click="searchItemSelct(j, i)"
|
|
|
- style="
|
|
|
- display: flex;
|
|
|
- align-items: center;
|
|
|
- justify-content: center;
|
|
|
- "
|
|
|
- >
|
|
|
- {{ j.label }}
|
|
|
- </li>
|
|
|
- </ul>
|
|
|
- </div>
|
|
|
- </div>
|
|
|
-
|
|
|
- <div style="display: flex">
|
|
|
- <el-input
|
|
|
- :placeholder="$t('common.pleaseEnterKeywords')"
|
|
|
- suffix-icon="search"
|
|
|
- size="mini"
|
|
|
- v-model="pagination.keyword"
|
|
|
- @keyup.enter="searchFn"
|
|
|
- >
|
|
|
- </el-input>
|
|
|
- <el-button
|
|
|
- type="primary"
|
|
|
- style="margin-left: 10px"
|
|
|
- size="default"
|
|
|
- @click="searchFn"
|
|
|
- >{{ $t("common.search") }}</el-button
|
|
|
- >
|
|
|
- <div class="more-icon" @click="retrievalModalFn">
|
|
|
- <img src="@/assets/images/iconm_xiangyzk.png" alt="" />
|
|
|
- </div>
|
|
|
- </div>
|
|
|
- </div>
|
|
|
- <component :is="containerTag">
|
|
|
- <div class="filter-form-container">
|
|
|
- <slot />
|
|
|
- </div>
|
|
|
-
|
|
|
- <el-table
|
|
|
- ref="hocElTable"
|
|
|
- v-loading="loading"
|
|
|
- :data="source"
|
|
|
- v-if="!hideTable"
|
|
|
- style="width: 100%"
|
|
|
- v-bind="$attrs"
|
|
|
- v-on="tableEvents"
|
|
|
- row-key="id"
|
|
|
- :tree-props="{ children: 'children', hasChildren: 'hasChildren' }"
|
|
|
- :height="tableHeight"
|
|
|
- >
|
|
|
- <el-table-column
|
|
|
- v-for="(item, index) in config"
|
|
|
- :key="index"
|
|
|
- v-bind="getAttrsValue(item)"
|
|
|
- :type="item.type || ''"
|
|
|
- :selectable="
|
|
|
- (rowData, rowIndex) => isSelectable(rowData, rowIndex, item)
|
|
|
- "
|
|
|
- >
|
|
|
- <template #default="scope" v-if="!item.type">
|
|
|
- <slot
|
|
|
- :name="item.attrs.slot"
|
|
|
- :item="scope.row"
|
|
|
- v-if="item.attrs.slot"
|
|
|
- >
|
|
|
- 插槽占位符
|
|
|
- </slot>
|
|
|
- <div v-else-if="isFunction(getValue(scope, item))">
|
|
|
- <component
|
|
|
- :is="renderTypeList[getMatchRenderFunction(item)].target"
|
|
|
- :cell-list="getValue(scope, item)()"
|
|
|
- :row="scope.row"
|
|
|
- :parent="getParent"
|
|
|
- @click="
|
|
|
- ($event) => {
|
|
|
- handleNativeClick(getAttrsValue(item), $event, item);
|
|
|
- }
|
|
|
- "
|
|
|
- />
|
|
|
- </div>
|
|
|
- <div v-else>
|
|
|
- {{ getValue(scope, item) }}
|
|
|
- </div>
|
|
|
- </template>
|
|
|
- </el-table-column>
|
|
|
- </el-table>
|
|
|
-
|
|
|
- <el-row
|
|
|
- v-if="!hidePagination"
|
|
|
- class="table-pagination"
|
|
|
- justify="end"
|
|
|
- type="flex"
|
|
|
- >
|
|
|
- <el-pagination
|
|
|
- background
|
|
|
- layout="total, sizes, prev, pager, next, jumper"
|
|
|
- :current-page="getPagination.pageNum"
|
|
|
- :page-size="getPagination.pageSize"
|
|
|
- :total="getPagination.total"
|
|
|
- @size-change="handleSizeChange"
|
|
|
- @current-change="handlePageChange"
|
|
|
- />
|
|
|
- </el-row>
|
|
|
- </component>
|
|
|
- </div>
|
|
|
-</template>
|
|
|
-
|
|
|
- <script>
|
|
|
-import { isFunction as isFn, isBoolean } from "./type";
|
|
|
-import ElementsMapping from "./ElementsMapping";
|
|
|
-import ComponentsMapping from "./ComponentsMapping";
|
|
|
-import { computed, defineComponent, getCurrentInstance, ref } from "vue";
|
|
|
-import expand from "./expand";
|
|
|
-export default defineComponent({
|
|
|
- name: "Table",
|
|
|
- components: {
|
|
|
- ElementsMapping,
|
|
|
- ComponentsMapping,
|
|
|
- },
|
|
|
- props: {
|
|
|
- hideSearch: {
|
|
|
- type: Boolean,
|
|
|
- default: false,
|
|
|
- },
|
|
|
- hideTable: {
|
|
|
- type: Boolean,
|
|
|
- default: false,
|
|
|
- },
|
|
|
- //顶部搜索下拉配置
|
|
|
- selectConfig: {
|
|
|
- type: Array,
|
|
|
- default() {
|
|
|
- return [];
|
|
|
- },
|
|
|
- },
|
|
|
- // 获取表格元数据时携带的参数
|
|
|
- filterParams: {
|
|
|
- type: Object,
|
|
|
- default() {
|
|
|
- return {};
|
|
|
- },
|
|
|
- },
|
|
|
- // 表格加载 loading
|
|
|
- loading: {
|
|
|
- type: Boolean,
|
|
|
- default: false,
|
|
|
- },
|
|
|
- // 表格名称
|
|
|
- title: {
|
|
|
- type: String,
|
|
|
- default: "",
|
|
|
- },
|
|
|
- // 表格元数据
|
|
|
- source: {
|
|
|
- type: Array,
|
|
|
- required: true,
|
|
|
- default() {
|
|
|
- return [];
|
|
|
- },
|
|
|
- },
|
|
|
- tableHeight: {
|
|
|
- type: Number,
|
|
|
- required: false,
|
|
|
- },
|
|
|
- searchConfig: {
|
|
|
- type: Object,
|
|
|
- default() {
|
|
|
- return {
|
|
|
- keyword: "",
|
|
|
- };
|
|
|
- },
|
|
|
- },
|
|
|
- // 指定外层容器的渲染组件
|
|
|
- containerTag: {
|
|
|
- type: String,
|
|
|
- default: "div",
|
|
|
- },
|
|
|
- // 是否隐藏表头
|
|
|
- hideHeader: {
|
|
|
- type: Boolean,
|
|
|
- default: false,
|
|
|
- },
|
|
|
- // 是否隐藏分页
|
|
|
- hidePagination: {
|
|
|
- type: Boolean,
|
|
|
- default: false,
|
|
|
- },
|
|
|
- // 分页配置
|
|
|
- pagination: {
|
|
|
- type: Object,
|
|
|
- default() {
|
|
|
- return {};
|
|
|
- },
|
|
|
- },
|
|
|
- // 表格配置文件
|
|
|
- config: {
|
|
|
- type: Array,
|
|
|
- default() {
|
|
|
- return [];
|
|
|
- },
|
|
|
- },
|
|
|
- // 表头右上方的按钮组
|
|
|
- actionList: {
|
|
|
- type: Array,
|
|
|
- default() {
|
|
|
- return [{ text: "", action: () => {} }];
|
|
|
- },
|
|
|
- },
|
|
|
- // element table 原生事件
|
|
|
- tableEvents: {
|
|
|
- type: Object,
|
|
|
- default() {
|
|
|
- return {};
|
|
|
- },
|
|
|
- },
|
|
|
- searchKey: {
|
|
|
- type: String,
|
|
|
- default: "keyword",
|
|
|
- },
|
|
|
- // 是否显示过滤的全部选项
|
|
|
- // isShowAll: {
|
|
|
- // type: Boolean,
|
|
|
- // default: true,
|
|
|
- // },
|
|
|
- },
|
|
|
- setup(props) {
|
|
|
- const { proxy } = getCurrentInstance();
|
|
|
- const selectConfigCopy = computed(() => {
|
|
|
- return props.selectConfig.map((item) => {
|
|
|
- if (!item.labelCopy) item.labelCopy = { ...item }.label;
|
|
|
- return item;
|
|
|
- });
|
|
|
- });
|
|
|
- const retrievalModal = ref(false);
|
|
|
- console.log(selectConfigCopy);
|
|
|
- const getAttrsValue = (item) => {
|
|
|
- const { attrs } = item;
|
|
|
- const result = {
|
|
|
- ...attrs,
|
|
|
- };
|
|
|
- delete result.prop;
|
|
|
- return result;
|
|
|
- };
|
|
|
- const renderTypeList = ref({
|
|
|
- render: {},
|
|
|
- renderHTML: {
|
|
|
- target: "elements-mapping",
|
|
|
- },
|
|
|
- renderComponent: {
|
|
|
- target: "components-mapping",
|
|
|
- },
|
|
|
- });
|
|
|
- const getParent = computed(() => {
|
|
|
- return proxy.$parent;
|
|
|
- });
|
|
|
- const getPagination = computed(() => {
|
|
|
- const params = {
|
|
|
- pageNum: 1,
|
|
|
- pageSize: 10,
|
|
|
- total: 0,
|
|
|
- };
|
|
|
- return Object.assign({}, params, props.pagination);
|
|
|
- });
|
|
|
- const getActionList = computed(() => {
|
|
|
- return props.actionList
|
|
|
- .slice()
|
|
|
- .reverse()
|
|
|
- .filter((it) => it.text);
|
|
|
- });
|
|
|
- const getValue = (scope, configItem) => {
|
|
|
- const prop = configItem.attrs.prop;
|
|
|
- const renderName = getMatchRenderFunction(configItem);
|
|
|
- const renderObj = renderTypeList.value[renderName];
|
|
|
- if (renderObj && isFunction(configItem[renderName])) {
|
|
|
- return renderObj.target
|
|
|
- ? getRenderValue(scope, configItem, {
|
|
|
- name: renderName,
|
|
|
- type: "bind",
|
|
|
- })
|
|
|
- : getRenderValue(scope, configItem);
|
|
|
- }
|
|
|
- return scope.row[prop];
|
|
|
- };
|
|
|
- const getRenderValue = (
|
|
|
- scope,
|
|
|
- item,
|
|
|
- fn = { name: "render", type: "call" }
|
|
|
- ) => {
|
|
|
- const prop = item.attrs.prop;
|
|
|
- const propValue = prop && scope.row[prop];
|
|
|
- scope.row.$index = scope.$index;
|
|
|
- const args = propValue !== undefined ? propValue : scope.row;
|
|
|
-
|
|
|
- return item[fn.name][fn.type](getParent.value, args);
|
|
|
- };
|
|
|
- // 匹配 render 开头的函数
|
|
|
- const getMatchRenderFunction = (obj) => {
|
|
|
- return Object.keys(obj).find((key) => {
|
|
|
- const matchRender = key.match(/^render.*/);
|
|
|
- return matchRender && matchRender[0];
|
|
|
- });
|
|
|
- };
|
|
|
- const isFunction = (fn) => {
|
|
|
- return isFn(fn);
|
|
|
- };
|
|
|
- const searchFn = (val) => {
|
|
|
- console.log(props);
|
|
|
- proxy.$emit(
|
|
|
- "getList",
|
|
|
- Object.assign(props.filterParams, {
|
|
|
- [props.searchKey]: props.pagination.keyword,
|
|
|
- })
|
|
|
- );
|
|
|
- };
|
|
|
- const retrievalModalFn = () => {
|
|
|
- proxy.$emit("moreSearch", "");
|
|
|
- };
|
|
|
- const handlePageChange = (val) => {
|
|
|
- proxy.$emit(
|
|
|
- "getList",
|
|
|
- Object.assign(props.filterParams, { pageNum: val })
|
|
|
- );
|
|
|
- };
|
|
|
- const handleSizeChange = (val) => {
|
|
|
- proxy.$emit(
|
|
|
- "getList",
|
|
|
- Object.assign(props.filterParams, { pageSize: val })
|
|
|
- );
|
|
|
- };
|
|
|
- const getHeaderActions = (item) => {
|
|
|
- return {
|
|
|
- ...item.attrs,
|
|
|
- };
|
|
|
- };
|
|
|
- const stopBubbles = (e) => {
|
|
|
- const event = e || window.event;
|
|
|
- if (event && event.stopPropagation) {
|
|
|
- event.stopPropagation();
|
|
|
- } else {
|
|
|
- event.cancelBubble = true;
|
|
|
- }
|
|
|
- };
|
|
|
- const handleNativeClick = ({ isBubble }, e, item) => {
|
|
|
- // 考虑到单元格内渲染了组件,并且组件自身可能含有点击事件,故添加了阻止冒泡机制
|
|
|
- // 若指定 isBubble 为 false,则当前单元格恢复冒泡机制
|
|
|
- if (isBoolean(isBubble) && !isBubble) return;
|
|
|
- stopBubbles(e);
|
|
|
- };
|
|
|
- //下拉搜索相关
|
|
|
-
|
|
|
- const searchItemSelct = (item, i, index) => {
|
|
|
- if (item == "all") {
|
|
|
- i.label = { ...props.selectConfig[index] }.labelCopy;
|
|
|
- proxy.$emit(
|
|
|
- "getList",
|
|
|
- Object.assign(props.filterParams, { [i.prop]: "" })
|
|
|
- );
|
|
|
- return;
|
|
|
- }
|
|
|
- i.label = item.label;
|
|
|
- proxy.$emit(
|
|
|
- "getList",
|
|
|
- Object.assign(props.filterParams, { [i.prop]: item.value })
|
|
|
- );
|
|
|
- };
|
|
|
-
|
|
|
- const isSelectable = (row, index, item) => {
|
|
|
- if (item.type === "selection") {
|
|
|
- if (item.attrs && item.attrs.checkAtt) {
|
|
|
- if (row[item.attrs.checkAtt]) {
|
|
|
- return row[item.attrs.checkAtt];
|
|
|
- }
|
|
|
- } else {
|
|
|
- return true;
|
|
|
- }
|
|
|
- }
|
|
|
- };
|
|
|
-
|
|
|
- return {
|
|
|
- getParent,
|
|
|
- getPagination,
|
|
|
- renderTypeList,
|
|
|
- getActionList,
|
|
|
- getAttrsValue,
|
|
|
- getValue,
|
|
|
- getRenderValue,
|
|
|
- getMatchRenderFunction,
|
|
|
- isFunction,
|
|
|
- handlePageChange,
|
|
|
- handleSizeChange,
|
|
|
- getHeaderActions,
|
|
|
- stopBubbles,
|
|
|
- handleNativeClick,
|
|
|
- searchFn,
|
|
|
- searchItemSelct,
|
|
|
- selectConfigCopy,
|
|
|
- isSelectable,
|
|
|
- retrievalModal,
|
|
|
- retrievalModalFn,
|
|
|
- };
|
|
|
- },
|
|
|
-});
|
|
|
-</script>
|
|
|
- <style>
|
|
|
-.table-list-container th {
|
|
|
- color: #333 !important;
|
|
|
-}
|
|
|
-.by-table td .el-button + .el-button {
|
|
|
- margin-left: 0 !important;
|
|
|
-}
|
|
|
-.by-table td .el-button {
|
|
|
- background: none !important;
|
|
|
- margin: 0 !important;
|
|
|
- padding: 8px 6px !important;
|
|
|
-}
|
|
|
-.el-checkbox__input.is-disabled .el-checkbox__inner {
|
|
|
- background-color: #dee1e6;
|
|
|
- border-color: #b2b4b9;
|
|
|
-}
|
|
|
-.el-table .cell {
|
|
|
- line-height: 34px;
|
|
|
-}
|
|
|
-</style>
|
|
|
- <style lang="scss" scoped>
|
|
|
-.by-search {
|
|
|
- display: flex;
|
|
|
- justify-content: space-between;
|
|
|
- margin-bottom: 10px;
|
|
|
- .more-icon {
|
|
|
- float: right;
|
|
|
- cursor: pointer;
|
|
|
- }
|
|
|
-}
|
|
|
-.by-dropdown {
|
|
|
- position: relative;
|
|
|
- text-align: left;
|
|
|
- height: 32px;
|
|
|
- z-index: 1010;
|
|
|
- padding: 0 10px;
|
|
|
- transition: all 0.5s ease;
|
|
|
- cursor: pointer;
|
|
|
- line-height: 32px;
|
|
|
-
|
|
|
- .by-dropdown-title {
|
|
|
- font-size: 14px;
|
|
|
- background-color: #fff;
|
|
|
- }
|
|
|
- ul {
|
|
|
- position: absolute;
|
|
|
- left: 0;
|
|
|
-
|
|
|
- top: 32px;
|
|
|
- padding: 0;
|
|
|
- margin: 0;
|
|
|
- z-index: 100;
|
|
|
- display: none;
|
|
|
- white-space: nowrap;
|
|
|
- li {
|
|
|
- list-style: none;
|
|
|
- font-size: 12px;
|
|
|
- height: 30px;
|
|
|
- padding: 0 10px;
|
|
|
- }
|
|
|
- li:hover {
|
|
|
- background-color: #eff6ff;
|
|
|
- color: #0084ff;
|
|
|
- }
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-.by-dropdown::before {
|
|
|
- display: block;
|
|
|
- width: 1px;
|
|
|
- content: " ";
|
|
|
- position: absolute;
|
|
|
- height: 14px;
|
|
|
- top: 8px;
|
|
|
- background-color: #ddd;
|
|
|
- right: 0;
|
|
|
- z-index: 1011;
|
|
|
-}
|
|
|
-
|
|
|
-.by-dropdown:hover {
|
|
|
- background: #ffffff;
|
|
|
-
|
|
|
- border-radius: 2px 2px 2px 2px;
|
|
|
- opacity: 1;
|
|
|
- ul {
|
|
|
- background: #ffffff;
|
|
|
- box-shadow: 0px 2px 16px 1px rgba(0, 0, 0, 0.06);
|
|
|
- border-radius: 2px 2px 2px 2px;
|
|
|
- opacity: 1;
|
|
|
- display: block;
|
|
|
- text-align: left;
|
|
|
- }
|
|
|
-}
|
|
|
-.header-actions {
|
|
|
- flex: 1;
|
|
|
- overflow-x: auto;
|
|
|
- padding: 20px;
|
|
|
- background: #fff;
|
|
|
- margin-bottom: 20px;
|
|
|
- .overflow-box {
|
|
|
- :deep() .el-button:nth-child(1) {
|
|
|
- margin-left: 10px;
|
|
|
- }
|
|
|
- }
|
|
|
-}
|
|
|
-.table-list-container {
|
|
|
- background: #fff;
|
|
|
- padding: 13px 20px 20px;
|
|
|
- .table-pagination {
|
|
|
- padding-top: 20px;
|
|
|
- }
|
|
|
- .header {
|
|
|
- display: flex;
|
|
|
- padding-bottom: 20px;
|
|
|
- }
|
|
|
- .el-table {
|
|
|
- :deep() th {
|
|
|
- font-size: 14px;
|
|
|
- }
|
|
|
- :deep() td {
|
|
|
- font-size: 14px;
|
|
|
- }
|
|
|
- }
|
|
|
-}
|
|
|
-.by-dropdown-lists {
|
|
|
- max-height: 50vh;
|
|
|
- overflow-y: auto;
|
|
|
- line-height: 1;
|
|
|
-}
|
|
|
-</style>
|