asd26269546 vor 2 Jahren
Ursprung
Commit
9e993f70b3

BIN
src/assets/shibei.png


+ 552 - 0
src/components/byTable/index copy.vue

@@ -0,0 +1,552 @@
+<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"
+            >
+              全部
+            </li>
+            <li
+              v-for="j in i.data"
+              :key="j.value"
+              @click="searchItemSelct(j, i)"
+            >
+              {{ j.label }}
+            </li>
+          </ul>
+        </div>
+      </div>
+
+      <div style="display: flex">
+        <el-input
+          placeholder="请输入关键字"
+          suffix-icon="search"
+          size="mini"
+          v-model="keywrod"
+          @keyup.enter="searchFn"
+        >
+        </el-input>
+        <el-button
+          type="primary"
+          style="margin-left: 10px"
+          size="default"
+          @click="searchFn"
+          >搜索</el-button
+        >
+
+        <div class="more-icon"><i class="el-icon-wind-power"></i></div>
+        <div class="more-icon">
+          <i class="el-icon-notebook-2"></i>
+        </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' }"
+      >
+        <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 [];
+      },
+    },
+    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 keywrod = ref("");
+    const selectConfigCopy = computed(() => {
+      return props.selectConfig.map((item) => {
+        if(!item.labelCopy) item.labelCopy = {...item}.label;
+        return item;
+      });
+    });
+    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]: keywrod.value })
+      );
+    };
+    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") {
+        console.log(props.selectConfig)
+        i.label = {...props.selectConfig[index]}.labelCopy
+        proxy.$emit(
+          "getList",
+          Object.assign(props.filterParams, { [i.prop]: "" })
+        );
+        return;
+      }
+      i.label = item.label;
+      console.log(item, i);
+      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,
+      keywrod,
+      searchFn,
+      searchItemSelct,
+      selectConfigCopy,
+      isSelectable,
+    };
+  },
+});
+</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;
+}
+</style>
+  <style lang="scss" scoped>
+.by-search {
+  display: flex;
+  justify-content: space-between;
+  margin-bottom: 10px;
+}
+.by-dropdown {
+  position: relative;
+  text-align: left;
+  height: 32px;
+  z-index: 100;
+  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: 101;
+}
+
+.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;
+    }
+  }
+}
+</style>

+ 41 - 0
src/views/process/processConfig/endBtn.vue

@@ -0,0 +1,41 @@
+<template>
+    <div class="end-btn">
+        <div class="icon">
+            <div class="fan"></div>
+        </div>
+        <div class="text">结束</div>
+    </div>
+</template>
+<style lang="scss">
+    .end-btn{
+        height: 90px;
+        width: 150px;
+        background: #fff;
+        text-align: center;
+        box-shadow: 0px 2px 10px 1px rgba(51,51,51,0.1);
+        border-radius: 10px 10px 10px 10px;
+        padding: 10px 0;
+        .icon {
+            height: 40px;
+            width: 40px;
+            background: #FF655B;
+            border-radius: 20px;
+            margin: 0 auto;
+            padding: 12px;
+            //画一个三角形
+            .fan {
+                height: 16px;
+                height: 16px;
+                border-radius: 2px;
+                background: #fff;
+                
+            }
+            
+        }
+        .text{
+            color: #333;
+            font-size: 14px;
+            margin-top: 10px; 
+        }
+    }
+</style>

+ 69 - 0
src/views/process/processConfig/handleBtn.vue

@@ -0,0 +1,69 @@
+<template>
+    <div class="handle-btn">
+        <div class="icon-box">
+            <div class="icon">
+                <i class="iconfont icon-icomx_banli"></i>
+            </div>
+            <div class="icon-text">办理</div>
+        </div>
+        <div class="title">{{title || '待配置'}}</div>
+    </div>
+</template>
+<script setup>
+    import { defineProps, inject, ref } from 'vue'
+    
+    let title = ref('')
+    let getNode = inject('getNode')
+    const node = getNode()
+    console.log(node)
+    node.on('change:data', ({current}) => {
+        title.value = current.title
+    })
+
+</script>
+<style lang="scss">
+    .handle-btn{
+        height: 90px;
+        width: 150px;
+        background: #fff;
+        text-align: center;
+        box-shadow: 0px 2px 10px 1px rgba(51,51,51,0.1);
+        border-radius: 10px 10px 10px 10px;
+        padding: 10px;
+        .title {
+            width: 100%;
+            height: 40px;
+            line-height: 40px;
+            padding: 0 20px;
+            text-align: left;
+            background: #eee;
+            border-radius: 10px;
+            margin-top: 10px;
+            //文字一行多余省略
+            white-space: nowrap;
+            overflow: hidden;
+            text-overflow: ellipsis;
+        }
+        .icon-box{
+            display: flex;
+            height: 20px;
+            line-height: 20px;
+            color: #333;
+            font-size: 14px;
+            .icon{
+                height: 20px;
+                width: 20px;
+                border-radius: 10px;
+                background: #FF9315;
+                color: #fff;
+                i{
+                    color: #fff;
+                    font-size: 12px;
+                }
+            }
+            .icon-text{
+                margin-left:10px;
+            }
+        }
+    }
+</style>

+ 57 - 0
src/views/process/processConfig/startBtn.vue

@@ -0,0 +1,57 @@
+<template>
+    <div class="start-btn"  @click="formTableChange">
+        <div class="icon">
+            <div class="sanjiao"></div>
+        </div>
+        <div class="text">开始{{title}}</div>
+    </div>
+</template>
+<script setup>
+    import { defineProps, inject, ref } from 'vue'
+    
+    let title = ref('')
+    let getNode = inject('getNode')
+    const node = getNode()
+    console.log(node)
+    node.on('change:data', ({current}) => {
+        title.value = current.title
+    })
+
+</script>
+<style lang="scss">
+    .start-btn{
+        height: 90px;
+        width: 150px;
+        background: #fff;
+        text-align: center;
+        box-shadow: 0px 2px 10px 1px rgba(51,51,51,0.1);
+        border-radius: 10px 10px 10px 10px;
+        padding: 10px 0;
+        .icon {
+            height: 40px;
+            width: 40px;
+            background: #39C55A;
+            border-radius: 20px;
+            margin: 0 auto;
+            //画一个三角形
+            .sanjiao {
+                width: 0;
+                height: 0;
+                border-left: 10px solid transparent;
+                border-right: 10px solid transparent;
+                border-bottom: 10px solid #fff;
+                margin: 0 auto;
+                position: relative;
+                top: 15px;
+                left: 2px;
+                transform: rotate(90deg);
+            }
+            
+        }
+        .text{
+            color: #333;
+            font-size: 14px;
+            margin-top: 10px; 
+        }
+    }
+</style>