YY 2 gadi atpakaļ
vecāks
revīzija
28a158771e
1 mainītis faili ar 174 papildinājumiem un 301 dzēšanām
  1. 174 301
      src/components/frame/c-table.vue

+ 174 - 301
src/components/frame/c-table.vue

@@ -1,341 +1,214 @@
 <template>
-  <div id="c-table">
-    <el-table
-      ref="table"
-      :row-key="rowKey"
-      :data="data"
-      border
-      stripe
-      :max-height="height !== null ? height : ''"
-      @select="handleSelectionChange"
-      @select-all="handleSelectAll"
-      :show-summary="useSum"
-      @row-click="rowClick"
-      :summary-method="computedSum"
-      :header-cell-style="{ background: '#F5F7FA' }"
-    >
-      <el-table-column type="selection" width="55" v-if="select" :prop="rowKey" :reserve-selection="true"> </el-table-column>
-      <template v-for="(item, index) in fields">
-        <template v-if="item.custom">
-          <el-table-column :key="index" align="center" :label="item.label" v-bind="item.options" :show-overflow-tooltip="item.showTip || true">
-            <template v-slot="{ row }">
-              <slot :name="item.model" v-bind="{ item, row }"></slot>
-            </template>
-          </el-table-column>
-        </template>
-        <template v-else>
-          <el-table-column
-            :key="index"
-            align="center"
-            :label="item.label"
-            :prop="item.model"
-            :formatter="toFormatter"
-            :sortable="true"
-            v-bind="item.options"
-            :show-overflow-tooltip="item.showTip === false ? item.showTip : true"
-          >
-          </el-table-column>
-        </template>
+  <el-table :data="list" border stripe @selection-change="toSelect">
+    <el-table-column type="selection" width="55" v-if="select"> </el-table-column>
+    <template v-for="(item, index) in fields">
+      <template v-if="item.custom">
+        <el-table-column :key="index" :label="item.label" v-bind="item.options" align="center" :show-overflow-tooltip="item.showTip || true">
+          <template v-slot="{ row }">
+            <slot :name="item.model" v-bind="{ item, row }"></slot>
+          </template>
+        </el-table-column>
       </template>
-      <template v-if="opera.length > 0">
-        <el-table-column label="操作" align="center" :width="operaWidth">
-          <template v-slot="{ row, $index }">
-            <template v-for="(item, index) in opera">
-              <template v-if="display(item, row)">
-                <template v-if="vOpera">
-                  <el-link
-                    v-opera="item.method"
-                    :key="`${item.model}-column-${index}`"
-                    :type="item.type || 'primary'"
-                    :icon="item.icon || ''"
-                    size="small"
-                    style="padding-right: 10px"
-                    :underline="false"
-                    @click="handleOpera(row, item.method, item.confirm, item.methodZh, item.label, $index, item.confirmWord)"
-                  >
-                    {{ item.label }}
-                  </el-link>
-                </template>
-                <template v-else>
-                  <el-link
-                    :key="`${item.model}-column-${index}`"
-                    :type="item.type || 'primary'"
-                    :icon="item.icon || ''"
-                    size="small"
-                    style="padding-right: 10px"
-                    :underline="false"
-                    @click="handleOpera(row, item.method, item.confirm, item.methodZh, item.label, $index, item.confirmWord)"
-                  >
-                    {{ item.label }}
-                  </el-link>
-                </template>
+      <template v-else>
+        <el-table-column
+          :key="index"
+          :label="item.label"
+          :prop="item.model"
+          :formatter="toFormatter"
+          v-bind="item.options"
+          :sortable="true"
+          align="center"
+          :show-overflow-tooltip="item.showTip === false ? item.showTip : true"
+        ></el-table-column>
+      </template>
+    </template>
+    <template v-if="opera.length > 0">
+      <el-table-column label="操作" fixed="right" width="110" align="center">
+        <template v-slot="{ row, $index }">
+          <template v-for="(item, index) in opera">
+            <template v-if="display(item, row)">
+              <template v-if="vOpera">
+                <el-link
+                  :key="`${item.model}-column-${index}`"
+                  :type="item.type || 'primary'"
+                  size="small"
+                  :underline="false"
+                  class="link"
+                  v-opera="item.method"
+                  @click="handleOpera(row, item.method, item.confirm, item.methodZh, item.label, $index, item.confirmWord)"
+                >
+                  {{ item.label }}
+                </el-link>
+              </template>
+              <template v-else>
+                <el-link
+                  :key="`${item.model}-column-${index}`"
+                  :type="item.type || 'primary'"
+                  size="small"
+                  :underline="false"
+                  class="link"
+                  @click="handleOpera(row, item.method, item.confirm, item.methodZh, item.label, $index, item.confirmWord)"
+                >
+                  {{ item.label }}
+                </el-link>
               </template>
             </template>
           </template>
-        </el-table-column>
-      </template>
-    </el-table>
-    <el-row type="flex" align="middle" justify="end" v-if="usePage">
-      <el-col :span="24" class="page">
-        <el-pagination
-          background
-          layout="sizes,total, prev, pager, next"
-          :page-sizes="[10, 20, 50, 100, 200]"
-          :total="total"
-          :page-size="limit"
-          v-model:current-page="currentPage"
-          @current-change="changePage"
-          @size-change="sizeChange"
-        >
-        </el-pagination>
-      </el-col>
-    </el-row>
-  </div>
+        </template>
+      </el-table-column>
+    </template>
+  </el-table>
+  <el-row justify="end" class="page" v-if="usePage">
+    <el-pagination
+      background
+      layout="sizes,total, prev, pager, next"
+      :page-sizes="[10, 20, 50, 100, 200]"
+      :total="total"
+      :page-size="limit"
+      v-model:current-page="currentPage"
+      @current-change="changePage"
+      @size-change="sizeChange"
+    >
+    </el-pagination>
+  </el-row>
 </template>
-<script setup lang="ts">
-import type { Ref } from 'vue';
-import { ref, toRefs, nextTick, getCurrentInstance } from 'vue';
-import { ElMessageBox } from 'element-plus';
-
-import _ from 'lodash';
-const { proxy } = getCurrentInstance() as any;
 
-// #region 传递
+<script setup lang="ts">
+// 基础
+import _ from 'lodash'
+import type { Ref } from 'vue'
+import { onMounted, toRefs, getCurrentInstance, ref } from 'vue'
+import { ElMessageBox } from 'element-plus'
+const { proxy } = getCurrentInstance() as any
+const emit = defineEmits(['toSelect', 'query'])
 
+// 参数
 interface fieldsItem {
-  custom: string;
-  label: string;
-  options: string;
-  showTip: boolean;
-  model: string;
+  // 是否自定义
+  custom: string
+  // 名称
+  label: string
+  // 绑定键值
+  model: string
+  // 其他
+  options: string
+  // 是否超出隐藏
+  showTip: boolean
 }
 interface operaItem {
-  method: string;
-  model: string;
-  type: string;
-  icon: string;
-  confirmWord: string;
-  label: string;
-  confirm: boolean;
-  methodZh: string;
+  // 名称
+  label: string
+  model: string
+  // 绑定键值
+  method: string
+  // 颜色
+  type: string
+  // 是否开启弹框
+  confirm: boolean
+  // 是否自定义文字说明
+  confirmWord: string
+  // 简短文字
+  methodZh: string
 }
 interface dataItem {
-  _id?: string;
+  _id?: string
 }
 
 const props = defineProps({
+  // 列表配置
   fields: { type: Array<fieldsItem>, required: true },
-  data: { type: Array<dataItem>, required: true },
-  opera: { type: Array<operaItem>, default: () => [] },
-  rowKey: { type: String, default: '_id' },
-  select: { type: Boolean, default: false },
-  selected: { type: Array, default: () => [] },
+  // 操作配置
+  opera: { type: Array<operaItem>, required: true },
+  // 列表数据
+  list: { type: Array<dataItem>, required: true },
+  // 是否开启多选
+  select: { type: Boolean, default: true },
+  // selected: { type: Array, default: () => [] },
+  vOpera: { type: Boolean, default: false },
+  // 分页
   usePage: { type: Boolean, default: true },
-  total: { type: Number, default: 0 },
-  useSum: { type: Boolean, default: false },
-  sumcol: { type: Array, default: () => [] },
-  sumres: { type: String, default: 'total' },
-  // limit: { type: Number, default: 10 },
-  height: null,
-  operaWidth: { type: Number, default: 200 },
-  vOpera: { type: Boolean, default: false }
-});
-const { fields } = toRefs(props);
-const { data } = toRefs(props);
-const { opera } = toRefs(props);
-const { rowKey } = toRefs(props);
-const { select } = toRefs(props);
-const { selected } = toRefs(props);
-const { usePage } = toRefs(props);
-const { total } = toRefs(props);
-const { useSum } = toRefs(props);
-const { sumcol } = toRefs(props);
-const { sumres } = toRefs(props);
-// const { limit } = toRefs(props);
-const { height } = toRefs(props);
-const { operaWidth } = toRefs(props);
-const { vOpera } = toRefs(props);
-// #endregion
-const emit = defineEmits(['method', 'handleSelect', 'query', 'rowClick']);
-
-let pageSelected: Ref<any[]> = ref([]);
-let currentPage: Ref<number> = ref(1);
+  total: { type: Number, default: 0 }
+})
+const { fields } = toRefs(props)
+const { opera } = toRefs(props)
+const { list } = toRefs(props)
+const { select } = toRefs(props)
+// const { selected } = toRefs(props);
+const { vOpera } = toRefs(props)
+const { usePage } = toRefs(props)
+const { total } = toRefs(props)
 
-let limit: number = proxy.$limit;
-const toFormatter = (row: any, column: { property: string }, cellValue: string, index: string) => {
-  let this_fields = fields.value.filter((fil) => fil.model === column.property);
+let limit: number = proxy.$limit
+let currentPage: Ref<number> = ref(1)
+// 请求
+onMounted(async () => {})
+// 多选
+const toSelect = (val: Array<[]>) => {
+  emit(`toSelect`, val)
+}
+// 格式化内容
+const toFormatter = (row: any, column: { property: string }, cellValue: string) => {
+  let this_fields = fields.value.filter((fil) => fil.model === column.property)
   if (this_fields.length > 0) {
-    let format: any = _.get(this_fields[0], `format`, false);
+    let format: any = _.get(this_fields[0], `format`, false)
     if (format) {
-      let res;
+      let res
       if (_.isFunction(format)) {
-        res = format(cellValue);
+        res = format(cellValue)
       } else {
-        res = toFormat({
-          model: this_fields[0].model,
-          value: cellValue
-        });
+        res = toFormat({ model: this_fields[0].model, value: cellValue })
       }
-      return res;
+      return res
     } else {
-      return cellValue;
+      return cellValue
     }
   }
-};
-const toFormat = (e: { model: string; value: string }) => {};
+}
+const toFormat = (e: { model: string; value: string }) => {
+  console.log(e)
+}
+// 过滤
+const display = (item: operaItem, row: any) => {
+  let display: any = _.get(item, `display`, true)
+  if (display === true) return true
+  else {
+    let res = display(row)
+    return res
+  }
+}
+// 操作
 const handleOpera = (data: string, method: any, confirm = false, methodZh: string, label: string, index: string, confirmWord: string) => {
-  let self = true;
-  if (_.isFunction(methodZh)) methodZh = methodZh(data);
+  let self = true
+  if (_.isFunction(methodZh)) methodZh = methodZh(data)
   else if (!_.isString(methodZh)) {
-    methodZh = label;
-    self = false;
+    methodZh = label
+    self = false
   }
   if (confirm) {
-    let word = self ? methodZh : `您确认${methodZh}该数据?`;
-    if (confirmWord) word = confirmWord;
+    let word = self ? methodZh : `您确认${methodZh}该数据?`
+    if (confirmWord) word = confirmWord
     ElMessageBox.confirm(word, '提示', { confirmButtonText: '确定', cancelButtonText: '取消', type: 'warning' })
       .then(() => {
-        emit(method, data, index);
+        emit(method, data, index)
       })
-      .catch(() => {});
-  } else emit(method, data, index);
-};
-const handleSelectionChange = (selection: string, row: never) => {
-  //根据row是否再pageSelected中,判断是添加还是删除
-  let isSelecteds = _.cloneDeep(pageSelected);
-  const is_has = isSelecteds.value.findIndex((f) => f[rowKey.value] === row[rowKey.value]);
-  if (is_has <= -1) {
-    // 没有找到,属于添加
-    isSelecteds.value.push(row);
-  } else {
-    // 找到了,删除
-    isSelecteds.value.splice(is_has, 1);
-  }
-  pageSelected.value = isSelecteds.value;
-  emit(`handleSelect`, isSelecteds);
-};
-const handleSelectAll = (selection: any) => {
-  //处于没全选状态,选择之后一定是全选,只有处于全选状态时,才会反选(全取消)
-  let res: any = [];
-  if (selection.length > 0) {
-    //全选
-    res = _.uniqBy(pageSelected.value.concat(selection), rowKey.value);
-  } else {
-    //全取消
-    res = _.differenceBy(pageSelected.value, data.value, rowKey.value);
-  }
-  pageSelected.value = res;
-  emit(`handleSelect`, res);
-};
-
-const table = ref<any>();
-
-const initSelection = (select: any, data: any) => {
-  nextTick(() => {
-    table.value.clearSelection();
-    select.forEach((info: any) => {
-      let d = data.find((p: any) => p._id == info._id);
-      console.log(d);
-      if (d) table.value.toggleRowSelection(d);
-    });
-  });
-};
-
-const selectReset = () => {
-  table.value.clearSelection();
-};
-defineExpose({ initSelection });
-
+      .catch(() => {})
+  } else emit(method, data, index)
+}
+// 分页
 const changePage = (page: number = currentPage.value) => {
-  emit('query', { skip: (page - 1) * limit, limit: limit });
-};
+  emit('query', { skip: (page - 1) * limit, limit: limit })
+}
 const sizeChange = (limits: number) => {
-  limit = limits;
-  currentPage.value = 1;
-  emit('query', { skip: 0, limit: limit });
-};
-const rowClick = (row: any, column: string, event: string) => {
-  emit(`rowClick`, row);
-};
-const display = (item: operaItem, row: any) => {
-  let display: any = _.get(item, `display`, true);
-  if (display === true) return true;
-  else {
-    let res = display(row);
-    return res;
-  }
-};
-// 计算合计
-const computedSum = (e: { columns: any; data: any }) => {
-  const { columns, data } = e;
-
-  if (columns.length <= 0 || data.length <= 0) return '';
-  const result = [];
-  const reg = new RegExp(/^\d+$/);
-  for (const column of columns) {
-    // 判断有没有prop属性
-    const prop = _.get(column, 'property');
-    if (!prop) {
-      result.push('');
-      continue;
-    }
-    // 判断是否需要计算
-    const inlist = sumcol.value.find((f) => f == prop);
-    if (!inlist) {
-      result.push('');
-      continue;
-    }
-    let res: number | unknown = 0;
-    // 整理出要计算的属性(只取出数字或者可以为数字的值)
-    const resetList = data.map((i: any) => {
-      const d = _.get(i, prop);
-      return d * 1;
-    });
-    let p1: any;
-    if (sumres.value === 'total') {
-      res = totalComputed(p1, resetList);
-    } else if (sumres.value === 'avg') {
-      res = avgComputed(resetList);
-    } else if (sumres.value === 'max') {
-      res = maxComputed(resetList);
-    } else if (sumres.value === 'min') {
-      res = minComputed(resetList);
-    }
-    result.push(res);
-  }
-  result[0] = '合计';
-  return result;
-};
-// 合计计算
-const totalComputed = (columns: any, data: any) => {
-  const total = data.reduce((p: number, n: string) => p + parseFloat(n), 0);
-  return total;
-};
-// 平均值计算
-const avgComputed = (data: any) => {
-  let p1: any;
-  const total = totalComputed(p1, data);
-  return _.round(_.divide(total, data.length), 2);
-};
-// 最大值计算
-const maxComputed = (data: any) => {
-  return _.max(data);
-};
-// 最小值计算
-const minComputed = (data: any) => {
-  return _.min(data);
-};
+  limit = limits
+  currentPage.value = 1
+  emit('query', { skip: 0, limit: limit })
+}
 </script>
-
-<style scoped>
-.page {
-  background-color: #fff;
-  padding: 8px;
-  height: 50px;
+<style scoped lang="scss">
+.link {
+  padding: 0 5px 0 0;
 }
-.el-pagination {
-  position: absolute;
-  right: 10px;
-  background-color: #fff;
+.page {
+  margin: 10px 0 0 0;
 }
 </style>