Browse Source

feat(table): add vxe-table

xiaoxian521 4 years ago
parent
commit
2de43ef859
6 changed files with 218 additions and 383 deletions
  1. 5 0
      package-lock.json
  2. 1 0
      package.json
  3. 5 4
      src/layout/components/AppMain.vue
  4. 1 0
      src/main.ts
  5. 2 2
      src/style/index.scss
  6. 204 377
      src/views/user.vue

+ 5 - 0
package-lock.json

@@ -760,6 +760,11 @@
       "resolved": "http://192.168.250.101:4873/follow-redirects/-/follow-redirects-1.13.2.tgz",
       "integrity": "sha1-3XPI7/wScoulz0JZ12DqX7g+MUc="
     },
+    "font-awesome": {
+      "version": "4.7.0",
+      "resolved": "http://192.168.250.101:4873/font-awesome/-/font-awesome-4.7.0.tgz",
+      "integrity": "sha1-j6jPBBGhoxr9B7BtKQK7n8gVoTM="
+    },
     "fraction.js": {
       "version": "4.0.13",
       "resolved": "http://192.168.250.101:4873/fraction.js/-/fraction.js-4.0.13.tgz",

+ 1 - 0
package.json

@@ -12,6 +12,7 @@
     "axios": "^0.21.1",
     "dotenv": "^8.2.0",
     "element-plus": "^1.0.2-beta.36",
+    "font-awesome": "^4.7.0",
     "mitt": "^2.1.0",
     "mockjs": "^1.1.0",
     "nprogress": "^0.2.0",

+ 5 - 4
src/layout/components/AppMain.vue

@@ -1,5 +1,5 @@
 <template>
-  <section class="app-main">
+  <section class="app-main" :style="{'margin': appMargin}">
     <router-view :key="key" v-slot="{ Component }">
       <transition appear name="fade-transform" mode="out-in">
         <keep-alive>
@@ -13,24 +13,25 @@
 <script>
 import { computed, defineComponent } from "vue";
 import { useRoute } from "vue-router";
+import { deviceDetection } from "../../utils/deviceDetection";
 export default defineComponent({
   name: "AppMain",
   setup() {
     const route = useRoute();
     const key = computed(() => route.path);
+    const appMargin = computed(() => (deviceDetection() ? 0 : "10px"));
 
-    return { key };
+    return { key, appMargin };
   },
 });
 </script>
 
 <style scoped>
 .app-main {
-  min-height: calc(100vh - 50px);
+  /* min-height: calc(100vh - 50px); */
   width: 100%;
   position: relative;
   overflow-x: hidden;
-  margin: 10px;
 }
 .fixed-header + .app-main {
   padding-top: 50px;

+ 1 - 0
src/main.ts

@@ -9,6 +9,7 @@ import ElementPlus from 'element-plus'
 import 'element-plus/lib/theme-chalk/index.css'
 
 // 内置vxe-table
+import "font-awesome/css/font-awesome.css"
 import VXETable from 'vxe-table'
 import 'vxe-table/lib/style.css'
 

+ 2 - 2
src/style/index.scss

@@ -20,7 +20,7 @@ label {
 }
 
 html {
-  overflow: hidden;
+  overflow-x: hidden;
   width: 100%;
   height: 100%;
   box-sizing: border-box;
@@ -29,7 +29,7 @@ html {
 #app {
   width: 100%;
   height: 100%;
-  overflow: hidden;
+  overflow-x: hidden;
 }
 
 *,

+ 204 - 377
src/views/user.vue

@@ -1,421 +1,248 @@
 <template>
-  <vxe-grid ref="xGrid" v-bind="gridOptions" style="width:98%"></vxe-grid>
+  <vxe-grid v-bind="gridOptions" style="width:98%"></vxe-grid>
 </template>
 
 <script lang='ts'>
-import { defineComponent, onMounted, reactive, ref, Ref } from "vue";
-import { VXETable, VxeGridInstance, VxeGridProps } from "vxe-table";
-import XEUtils from "xe-utils";
-import XEAjax from "xe-ajax";
+import { reactive } from "vue";
+import { VxeGridProps } from "vxe-table";
 export default {
   name: "user",
   setup() {
-    const xGrid = ref({} as VxeGridInstance);
-
     const gridOptions = reactive({
       border: true,
       resizable: true,
-      showHeaderOverflow: true,
-      showOverflow: true,
-      highlightHoverRow: true,
       keepSource: true,
-      id: "full_edit_1",
-      height: 600,
-      rowId: "id",
-      customConfig: {
-        storage: true,
-        checkMethod({ column }) {
-          if (["nickname", "role"].includes(column.property)) {
-            return false;
-          }
-          return true;
-        },
-      },
-      printConfig: {
-        columns: [
-          { field: "name" },
-          { field: "email" },
-          { field: "nickname" },
-          { field: "age" },
-          { field: "amount" },
-        ],
-      },
-      sortConfig: {
-        trigger: "cell",
-        remote: true,
-      },
-      filterConfig: {
-        remote: true,
-      },
+      height: 500,
+      printConfig: {},
+      importConfig: {},
+      exportConfig: {},
       pagerConfig: {
-        pageSize: 10,
-        pageSizes: [5, 10, 15, 20, 50, 100, 200, 500, 1000],
+        perfect: true,
+        pageSize: 15,
       },
-      formConfig: {
-        titleWidth: 100,
-        titleAlign: "right",
-        items: [
-          {
-            field: "name",
-            title: "app.body.label.name",
-            span: 8,
-            titlePrefix: {
-              message: "app.body.valid.rName",
-              icon: "fa fa-exclamation-circle",
-            },
-            itemRender: {
-              name: "$input",
-              props: { placeholder: "请输入名称" },
-            },
-          },
-          {
-            field: "email",
-            title: "邮件",
-            span: 8,
-            itemRender: {
-              name: "$input",
-              props: { placeholder: "请输入邮件" },
-            },
-          },
-          {
-            field: "nickname",
-            title: "昵称",
-            span: 8,
-            itemRender: {
-              name: "$input",
-              props: { placeholder: "请输入昵称" },
-            },
-          },
-          {
-            field: "role",
-            title: "角色",
-            span: 8,
-            folding: true,
-            itemRender: {
-              name: "$input",
-              props: { placeholder: "请输入角色" },
-            },
-          },
-          {
-            field: "sex",
-            title: "性别",
-            span: 8,
-            folding: true,
-            titleSuffix: {
-              message: "注意,必填信息!",
-              icon: "fa fa-info-circle",
-            },
-            itemRender: { name: "$select", options: [] },
-          },
+      editConfig: {
+        trigger: "click",
+        mode: "row",
+        showStatus: true,
+      },
+      toolbarConfig: {
+        buttons: [
           {
-            field: "age",
-            title: "年龄",
-            span: 8,
-            folding: true,
-            itemRender: {
-              name: "$input",
-              props: {
-                type: "number",
-                min: 1,
-                max: 120,
-                placeholder: "请输入年龄",
-              },
-            },
+            code: "insert_actived",
+            name: "新增",
+            status: "perfect",
+            icon: "fa fa-plus",
           },
           {
-            span: 24,
-            align: "center",
-            collapseNode: true,
-            itemRender: {
-              name: "$buttons",
-              children: [
-                {
-                  props: {
-                    type: "submit",
-                    content: "app.body.label.search",
-                    status: "primary",
-                  },
-                },
-                { props: { type: "reset", content: "app.body.label.reset" } },
-              ],
-            },
+            code: "mark_cancel",
+            name: "标记/取消",
+            status: "perfect",
+            icon: "fa fa-trash-o",
           },
-        ],
-      },
-      toolbarConfig: {
-        buttons: [
-          { code: "insert_actived", name: "新增", icon: "fa fa-plus" },
-          { code: "delete", name: "直接删除", icon: "fa fa-trash-o" },
-          { code: "mark_cancel", name: "删除/取消", icon: "fa fa-trash-o" },
           {
             code: "save",
-            name: "app.body.button.save",
+            name: "保存",
+            status: "perfect",
             icon: "fa fa-save",
-            status: "success",
           },
         ],
-        refresh: true,
-        import: true,
-        export: true,
-        print: true,
-        zoom: true,
-        custom: true,
+        perfect: true,
+        refresh: {
+          icon: "fa fa-refresh",
+          iconLoading: "fa fa-spinner fa-spin",
+        },
+        import: {
+          icon: "fa fa-upload",
+        },
+        export: {
+          icon: "fa fa-download",
+        },
+        print: {
+          icon: "fa fa-print",
+        },
+        // zoom: {
+        //   iconIn: "fa fa-arrows-alt",
+        //   iconOut: "fa fa-expand",
+        // },
+        custom: {
+          icon: "fa fa-cog",
+        },
       },
       proxyConfig: {
-        seq: true, // 启用动态序号代理
-        sort: true, // 启用排序代理
-        filter: true, // 启用筛选代理
-        form: true, // 启用表单代理
         props: {
           result: "result",
           total: "page.total",
         },
         ajax: {
           // 接收 Promise
-          query: ({ page, sorts, filters, form }) => {
-            const queryParams: any = Object.assign({}, form);
-            // 处理排序条件
-            const firstSort = sorts[0];
-            if (firstSort) {
-              queryParams.sort = firstSort.property;
-              queryParams.order = firstSort.order;
-            }
-            // 处理筛选条件
-            filters.forEach(({ property, values }) => {
-              queryParams[property] = values.join(",");
+          query: ({ page }) => {
+            return new Promise((resolve) => {
+              setTimeout(() => {
+                const list = [
+                  {
+                    id: 10001,
+                    name: "Test1",
+                    nickname: "T1",
+                    role: "Develop",
+                    sex: "Man",
+                    age: 28,
+                    address: "Shenzhen",
+                  },
+                  {
+                    id: 10002,
+                    name: "Test2",
+                    nickname: "T2",
+                    role: "Test",
+                    sex: "Women",
+                    age: 22,
+                    address: "Guangzhou",
+                  },
+                  {
+                    id: 10003,
+                    name: "Test3",
+                    nickname: "T3",
+                    role: "PM",
+                    sex: "Man",
+                    age: 32,
+                    address: "Shanghai",
+                  },
+                  {
+                    id: 10004,
+                    name: "Test4",
+                    nickname: "T4",
+                    role: "Designer",
+                    sex: "Women ",
+                    age: 23,
+                    address: "Shenzhen",
+                  },
+                  {
+                    id: 10005,
+                    name: "Test5",
+                    nickname: "T5",
+                    role: "Develop",
+                    sex: "Women ",
+                    age: 30,
+                    address: "Shanghai",
+                  },
+                  {
+                    id: 10006,
+                    name: "Test6",
+                    nickname: "T6",
+                    role: "Designer",
+                    sex: "Women ",
+                    age: 21,
+                    address: "Shenzhen",
+                  },
+                  {
+                    id: 10007,
+                    name: "Test7",
+                    nickname: "T7",
+                    role: "Test",
+                    sex: "Man ",
+                    age: 29,
+                    address: "vxe-table 从入门到放弃",
+                  },
+                  {
+                    id: 10008,
+                    name: "Test8",
+                    nickname: "T8",
+                    role: "Develop",
+                    sex: "Man ",
+                    age: 35,
+                    address: "Shenzhen",
+                  },
+                  {
+                    id: 10009,
+                    name: "Test9",
+                    nickname: "T9",
+                    role: "Develop",
+                    sex: "Man ",
+                    age: 35,
+                    address: "Shenzhen",
+                  },
+                  {
+                    id: 100010,
+                    name: "Test10",
+                    nickname: "T10",
+                    role: "Develop",
+                    sex: "Man ",
+                    age: 35,
+                    address: "Guangzhou",
+                  },
+                  {
+                    id: 100011,
+                    name: "Test11",
+                    nickname: "T11",
+                    role: "Test",
+                    sex: "Women ",
+                    age: 26,
+                    address: "vxe-table 从入门到放弃",
+                  },
+                  {
+                    id: 100012,
+                    name: "Test12",
+                    nickname: "T12",
+                    role: "Develop",
+                    sex: "Man ",
+                    age: 34,
+                    address: "Guangzhou",
+                  },
+                  {
+                    id: 100013,
+                    name: "Test13",
+                    nickname: "T13",
+                    role: "Test",
+                    sex: "Women ",
+                    age: 22,
+                    address: "Shenzhen",
+                  },
+                ];
+                resolve({
+                  page: {
+                    total: list.length,
+                  },
+                  result: list.slice(
+                    (page.currentPage - 1) * page.pageSize,
+                    page.currentPage * page.pageSize
+                  ),
+                });
+              }, 100);
             });
-            return XEAjax.get(
-              `https://api.xuliangzhan.com:10443/api/pub/page/list/${page.pageSize}/${page.currentPage}`,
-              queryParams
-            );
           },
-          delete: ({ body }) =>
-            XEAjax.post("https://api.xuliangzhan.com:10443/api/pub/save", body),
-          save: ({ body }) =>
-            XEAjax.post("https://api.xuliangzhan.com:10443/api/pub/save", body),
-        },
-      },
-      columns: [
-        { type: "checkbox", title: "ID", width: 120 },
-        {
-          field: "name",
-          title: "Name",
-          sortable: true,
-          titleHelp: { message: "名称必须填写!" },
-          editRender: { name: "input", attrs: { placeholder: "请输入名称" } },
-        },
-        {
-          field: "role",
-          title: "Role",
-          sortable: true,
-          filters: [
-            { label: "前端开发", value: "前端" },
-            { label: "后端开发", value: "后端" },
-            { label: "测试", value: "测试" },
-            { label: "程序员鼓励师", value: "程序员鼓励师" },
-          ],
-          filterMultiple: false,
-          editRender: { name: "input", attrs: { placeholder: "请输入角色" } },
-        },
-        {
-          field: "email",
-          title: "Email",
-          width: 160,
-          editRender: { name: "$input", props: { placeholder: "请输入邮件" } },
-        },
-        {
-          field: "nickname",
-          title: "Nickname",
-          editRender: { name: "input", attrs: { placeholder: "请输入昵称" } },
-        },
-        {
-          field: "sex",
-          title: "Sex",
-          editRender: {
-            name: "$select",
-            options: [],
-            props: { placeholder: "请选择性别" },
-          },
-        },
-        {
-          field: "age",
-          title: "Age",
-          visible: false,
-          sortable: true,
-          editRender: {
-            name: "$input",
-            props: { type: "number", min: 1, max: 120 },
-          },
-        },
-        {
-          field: "amount",
-          title: "Amount",
-          formatter({ cellValue }) {
-            return cellValue
-              ? `¥${XEUtils.commafy(XEUtils.toNumber(cellValue), {
-                  digits: 2,
-                })}`
-              : "";
-          },
-          editRender: {
-            name: "$input",
-            props: { type: "float", digits: 2, placeholder: "请输入数值" },
+          // body 对象: { removeRecords }
+          delete: () => {
+            return new Promise((resolve) => {
+              setTimeout(() => {
+                resolve({});
+              }, 100);
+            });
           },
-        },
-        {
-          field: "updateDate",
-          title: "Update Date",
-          width: 160,
-          visible: false,
-          sortable: true,
-          formatter({ cellValue }) {
-            return XEUtils.toDateString(cellValue, "yyyy-MM-dd HH:ss:mm");
+          // body 对象: { insertRecords, updateRecords, removeRecords, pendingRecords }
+          save: () => {
+            return new Promise((resolve) => {
+              setTimeout(() => {
+                resolve({});
+              }, 100);
+            });
           },
         },
+      },
+      columns: [
+        { type: "checkbox", width: 50 },
+        { type: "seq", width: 60 },
+        { field: "name", title: "Name", editRender: { name: "input" } },
+        { field: "nickname", title: "Nickname", editRender: { name: "input" } },
+        { field: "role", title: "Role", editRender: { name: "input" } },
         {
-          field: "createDate",
-          title: "Create Date",
-          width: 160,
-          visible: false,
-          sortable: true,
-          formatter({ cellValue }) {
-            return XEUtils.toDateString(cellValue, "yyyy-MM-dd");
-          },
+          field: "address",
+          title: "Address",
+          showOverflow: true,
+          editRender: { name: "input" },
         },
       ],
-      importConfig: {
-        remote: true,
-        types: ["xlsx"],
-        modes: ["insert"],
-        // 自定义服务端导入
-        importMethod({ file }) {
-          const $grid = xGrid.value;
-          const formBody = new FormData();
-          formBody.append("file", file);
-          return XEAjax.post(
-            "https://api.xuliangzhan.com:10443/api/pub/import",
-            formBody
-          )
-            .then((data) => {
-              VXETable.modal.message({
-                message: `成功导入 ${data.result.insertRows} 条记录!`,
-                status: "success",
-              });
-              // 导入完成,刷新表格
-              $grid.commitProxy("query");
-            })
-            .catch(() => {
-              VXETable.modal.message({
-                message: "导入失败,请检查数据是否正确!",
-                status: "error",
-              });
-            });
-        },
-      },
-      exportConfig: {
-        remote: true,
-        types: ["xlsx"],
-        modes: ["current", "selected", "all"],
-        // 自定义服务端导出
-        exportMethod({ options }) {
-          const $grid = xGrid.value;
-          const proxyInfo = $grid.getProxyInfo();
-          // 传给服务端的参数
-          const body = {
-            filename: options.filename,
-            sheetName: options.sheetName,
-            isHeader: options.isHeader,
-            original: options.original,
-            mode: options.mode,
-            pager: proxyInfo ? proxyInfo.pager : null,
-            ids:
-              options.mode === "selected"
-                ? options.data.map((item) => item.id)
-                : [],
-            fields: options.columns.map((column) => {
-              return {
-                field: column.property,
-                title: column.title,
-              };
-            }),
-          };
-          // 开始服务端导出
-          return XEAjax.post(
-            "https://api.xuliangzhan.com:10443/api/pub/export",
-            body
-          )
-            .then((data) => {
-              if (data.id) {
-                VXETable.modal.message({
-                  message: "导出成功,开始下载",
-                  status: "success",
-                });
-                // 读取路径,请求文件
-                XEAjax.fetch(
-                  `https://api.xuliangzhan.com:10443/api/pub/export/download/${data.id}`
-                ).then((response) => {
-                  response.blob().then((blob) => {
-                    // 开始下载
-                    VXETable.saveFile({
-                      filename: "导出数据",
-                      type: "xlsx",
-                      content: blob,
-                    });
-                  });
-                });
-              }
-            })
-            .catch(() => {
-              VXETable.modal.message({
-                message: "导出失败!",
-                status: "error",
-              });
-            });
-        },
-      },
-      checkboxConfig: {
-        labelField: "id",
-        reserve: true,
-        highlight: true,
-        range: true,
-      },
-      editRules: {
-        name: [
-          { required: true, message: "app.body.valid.rName" },
-          { min: 3, max: 50, message: "名称长度在 3 到 50 个字符" },
-        ],
-        email: [{ required: true, message: "邮件必须填写" }],
-        role: [{ required: true, message: "角色必须填写" }],
-      },
-      editConfig: {
-        trigger: "click",
-        mode: "row",
-        showStatus: true,
-      },
     } as VxeGridProps);
 
-    onMounted(() => {
-      const sexList = [
-        { label: "女", value: "0" },
-        { label: "男", value: "1" },
-      ];
-      const { formConfig, columns } = gridOptions;
-      if (columns) {
-        const sexColumn = columns[5];
-        if (sexColumn && sexColumn.editRender) {
-          sexColumn.editRender.options = sexList;
-        }
-      }
-      if (formConfig && formConfig.items) {
-        const sexItem = formConfig.items[4];
-        if (sexItem && sexItem.itemRender) {
-          sexItem.itemRender.options = sexList;
-        }
-      }
-    });
-
     return {
-      xGrid,
       gridOptions,
     };
   },