Przeglądaj źródła

fix 首页 & 数据管理页面

haveyou 1 rok temu
rodzic
commit
150ef83e45

+ 54 - 0
src/api/dashboard/analysis/index.js

@@ -0,0 +1,54 @@
+import request from '@/utils/request';
+
+/**
+ * 获取支付笔数数据
+ */
+export async function getPayNumList() {
+  const res = await request.get(
+    'https://cdn.eleadmin.com/20200610/analysis-pay-num.json'
+  );
+  if (res.data.code === 0 && res.data.data) {
+    return res.data.data;
+  }
+  return Promise.reject(new Error(res.data.message));
+}
+
+/**
+ * 获取销售量数据
+ */
+export async function getSaleroomList() {
+  const res = await request.get(
+    'https://cdn.eleadmin.com/20200610/analysis-saleroom.json'
+  );
+  if (res.data.code === 0 && res.data.data) {
+    return res.data.data;
+  }
+  return Promise.reject(new Error(res.data.message));
+}
+
+/**
+ * 获取最近 1 小时访问情况数据
+ * @returns {Promise<Object>}
+ */
+export async function getVisitHourList() {
+  const res = await request.get(
+    'https://cdn.eleadmin.com/20200610/analysis-visits.json'
+  );
+  if (res.data.code === 0 && res.data.data) {
+    return res.data.data;
+  }
+  return Promise.reject(new Error(res.data.message));
+}
+
+/**
+ * 获取词云数据
+ */
+export async function getWordCloudList() {
+  const res = await request.get(
+    'https://cdn.eleadmin.com/20200610/analysis-hot-search.json'
+  );
+  if (res.data.code === 0 && res.data.data) {
+    return res.data.data;
+  }
+  return Promise.reject(new Error(res.data.message));
+}

+ 148 - 0
src/components/CommonPage/CommonTable.vue

@@ -0,0 +1,148 @@
+<template>
+  <ele-page flex-table>
+    <!-- 搜索表单 -->
+    <slot name="search"></slot>
+    <ele-card :body-style="{ paddingTop: '8px' }" flex-table>
+      <!-- 表格 -->
+      <ele-pro-table
+        ref="tableRef"
+        row-key="postId"
+        :columns="columns"
+        :datasource="datasource"
+        :show-overflow-tooltip="true"
+        v-model:selections="selections"
+        highlight-current-row
+        :export-config="{ fileName: pageConfig.fileName }"
+        :cache-key="pageConfig.cacheKey"
+        v-bind="$attrs"
+      >
+        <template v-for="(val, key) in slotArray" v-slot:[key]="{ row }">
+          <slot :name="key" :row="row"></slot>
+        </template>
+      </ele-pro-table>
+    </ele-card>
+
+    <slot></slot>
+  </ele-page>
+</template>
+
+<script setup>
+  import { ref, getCurrentInstance, useSlots } from 'vue';
+  import { ElMessageBox } from 'element-plus/es';
+  import { EleMessage } from 'ele-admin-plus/es';
+  import { useDictData } from '@/utils/use-dict-data';
+  import { download, toFormData, checkDownloadRes } from '@/utils/common';
+  const slotArray = useSlots();
+
+  let props = defineProps({
+    pageConfig: {
+      type: Object,
+      default: () => ({
+        cacheKey: 'recycleOrderTable',
+        fileName: '回收订单查询'
+      })
+    },
+    pageUrl: { type: String, default: '/system/post/list' },
+    exportUrl: { type: String, default: '/system/post/export' },
+    columns: { type: Array, default: () => [] }
+  });
+  let { proxy } = getCurrentInstance();
+
+  /** 表格实例 */
+  const tableRef = ref(null);
+
+  /** 表格选中数据 */
+  const selections = ref([]);
+
+  async function queryPage(params) {
+    const res = await proxy.$http.get(props.pageUrl, { params });
+    if (res.data.code === 200) {
+      return res.data;
+    }
+    return Promise.reject(new Error(res.data.msg));
+  }
+
+  /** 表格数据源 */
+  const datasource = ({ pages, where, orders }) => {
+    return queryPage({ ...where, ...orders, ...pages });
+  };
+
+  /** 搜索 */
+  const reload = (where) => {
+    tableRef.value?.reload?.({ page: 1, where });
+  };
+
+  /** 批量操作 */
+  const operatBatch = ({ row, url, title }) => {
+    const rows = row == null ? selections.value : [row];
+    if (!rows.length) {
+      EleMessage.error('请至少选择一条数据');
+      return;
+    }
+    title = title || '是否确认当前操作?';
+    ElMessageBox.confirm(title, '提示', {
+      type: 'warning',
+      draggable: true
+    })
+      .then(() => {
+        const loading = EleMessage.loading({
+          message: '请求中..',
+          plain: true
+        });
+
+        proxy.$http
+          .delete(url)
+          .then(() => {
+            loading.close();
+            EleMessage.success('操作成功');
+            reload();
+          })
+          .catch((e) => {
+            loading.close();
+            EleMessage.error(e.message);
+          });
+      })
+      .catch(() => {});
+  };
+
+  /// 导出数据
+  async function exportPage(params, name) {
+    const res = await proxy.$http({
+      url: props.exportUrl,
+      method: 'POST',
+      data: toFormData(params),
+      responseType: 'blob'
+    });
+    await checkDownloadRes(res);
+    download(
+      res.data,
+      name ? `${name}_${Date.now()}.xlsx` : `post_${Date.now()}.xlsx`
+    );
+  }
+
+  /** 导出数据 */
+  const exportData = (name) => {
+    const loading = EleMessage.loading({
+      message: '请求中..',
+      plain: true
+    });
+    tableRef.value?.fetch?.(({ where, orders }) => {
+      exportPage({ ...where, ...orders }, name)
+        .then(() => {
+          loading.close();
+        })
+        .catch((e) => {
+          loading.close();
+          EleMessage.error(e.message);
+        });
+    });
+  };
+
+  //修改备注
+  const remarksRef = ref(null);
+  function handleRemarks(row) {
+    remarksRef.value?.handleOpen(row);
+  }
+
+  defineExpose({ reload, exportData, operatBatch });
+</script>

+ 0 - 0
src/views/data/books/index.vue


+ 0 - 0
src/views/data/universities/index.vue


+ 0 - 147
src/views/index/components/activities-card.vue

@@ -1,147 +0,0 @@
-<!-- 最新动态 -->
-<template>
-  <ele-card :header="title" :body-style="{ padding: '6px 0', height: '370px' }">
-    <template #extra>
-      <more-icon @command="handleCommand" />
-    </template>
-    <el-scrollbar :view-style="{ padding: '20px 20px 0 20px' }">
-      <el-timeline :reverse="false" class="demo-timeline">
-        <el-timeline-item
-          v-for="item in activities"
-          :key="item.id"
-          :timestamp="item.time"
-          :type="item.type"
-          :hollow="true"
-        >
-          {{ item.title }}
-        </el-timeline-item>
-      </el-timeline>
-    </el-scrollbar>
-  </ele-card>
-</template>
-
-<script setup>
-  import { ref } from 'vue';
-  import MoreIcon from './more-icon.vue';
-
-  defineProps({
-    title: String
-  });
-
-  const emit = defineEmits(['command']);
-
-  /** 最新动态数据 */
-  const activities = ref([]);
-
-  /** 查询最新动态 */
-  const queryActivities = () => {
-    activities.value = [
-      {
-        id: 1,
-        title: 'SunSmile 解决了bug 登录提示操作失败',
-        time: '20:30'
-      },
-      {
-        id: 2,
-        title: 'Jasmine 解决了bug 按钮颜色与设计不符',
-        time: '19:30'
-      },
-      {
-        id: 3,
-        title: '项目经理 指派了任务 解决项目一的bug',
-        time: '18:30',
-        type: 'primary'
-      },
-      {
-        id: 4,
-        title: '项目经理 指派了任务 解决项目二的bug',
-        time: '17:30',
-        type: 'primary'
-      },
-      {
-        id: 5,
-        title: '项目经理 指派了任务 解决项目三的bug',
-        time: '16:30',
-        type: 'primary'
-      },
-      {
-        id: 6,
-        title: '项目经理 指派了任务 解决项目四的bug',
-        time: '15:30'
-      },
-      {
-        id: 7,
-        title: '项目经理 指派了任务 解决项目五的bug',
-        time: '14:30'
-      },
-      {
-        id: 8,
-        title: '项目经理 指派了任务 解决项目六的bug',
-        time: '12:30'
-      },
-      {
-        id: 9,
-        title: '项目经理 指派了任务 解决项目七的bug',
-        time: '11:30',
-        type: 'primary'
-      },
-      {
-        id: 10,
-        title: '项目经理 指派了任务 解决项目八的bug',
-        time: '10:30'
-      },
-      {
-        id: 11,
-        title: '项目经理 指派了任务 解决项目九的bug',
-        time: '09:30',
-        type: 'success'
-      },
-      {
-        id: 12,
-        title: '项目经理 指派了任务 解决项目十的bug',
-        time: '08:30',
-        type: 'danger'
-      }
-    ];
-  };
-
-  const handleCommand = (command) => {
-    emit('command', command);
-  };
-
-  queryActivities();
-</script>
-
-<style lang="scss" scoped>
-  /* 时间轴 */
-  .demo-timeline {
-    padding-left: 0;
-
-    :deep(.el-timeline-item__wrapper) {
-      display: flex;
-
-      .el-timeline-item__timestamp {
-        order: 0;
-        flex-shrink: 0;
-        margin: 0 16px 0 0;
-        height: 22px;
-        line-height: 22px;
-        font-size: 14px;
-      }
-
-      .el-timeline-item__content {
-        order: 1;
-        flex: 1;
-      }
-    }
-
-    :deep(.el-timeline-item__node) {
-      top: 3px;
-      --el-color-white: var(--el-bg-color-overlay);
-    }
-
-    :deep(.el-timeline-item__tail) {
-      top: 3px;
-    }
-  }
-</style>

+ 0 - 65
src/views/index/components/goal-card.vue

@@ -1,65 +0,0 @@
-<!-- 本月目标 -->
-<template>
-  <ele-card :header="title" :body-style="{ height: '370px' }">
-    <template #extra>
-      <more-icon @command="handleCommand" />
-    </template>
-    <div class="workplace-goal">
-      <el-progress
-        :width="180"
-        :percentage="80"
-        color="#1677ff"
-        type="dashboard"
-        :format="() => ''"
-      />
-      <div class="workplace-goal-body">
-        <el-tag
-          size="large"
-          :disable-transitions="true"
-          style="width: 36px; height: 36px; border-radius: 50%; line-height: 0"
-        >
-          <el-icon style="cursor: default; border-radius: 0">
-            <TrophyBase />
-          </el-icon>
-        </el-tag>
-        <div style="font-size: 40px">285</div>
-      </div>
-      <div>恭喜, 本月目标已达标!</div>
-    </div>
-  </ele-card>
-</template>
-
-<script setup>
-  import { TrophyBase } from '@element-plus/icons-vue';
-  import MoreIcon from './more-icon.vue';
-
-  defineProps({
-    title: String
-  });
-
-  const emit = defineEmits(['command']);
-
-  const handleCommand = (command) => {
-    emit('command', command);
-  };
-</script>
-
-<style lang="scss" scoped>
-  .workplace-goal {
-    height: 100%;
-    display: flex;
-    flex-direction: column;
-    justify-content: center;
-    align-items: center;
-    position: relative;
-
-    .workplace-goal-body {
-      position: absolute;
-      top: 50%;
-      left: 50%;
-      width: 180px;
-      margin: -48px 0 0 -90px;
-      text-align: center;
-    }
-  }
-</style>

+ 37 - 0
src/views/index/components/goods-stat.vue

@@ -0,0 +1,37 @@
+<template>
+  <ele-card>
+    <el-row :gutter="24">
+      <el-col :span="8">
+        <div class="flex justify-center items-center">
+          <el-icon size="40" color="#E6A23C"><SoldOut /></el-icon>
+          <div class="flex flex-col ml-6">
+            <div class="text-lg text-theme">待发货订单</div>
+            <div class="text-3xl text-theme">1245</div>
+          </div>
+        </div>
+      </el-col>
+      <el-col :span="8">
+        <div class="flex justify-center items-center border-l">
+          <el-icon size="40" color="#F56C6C"><Wallet /></el-icon>
+          <div class="flex flex-col ml-6">
+            <div class="text-lg text-theme">退款待审核</div>
+            <div class="text-3xl text-theme">1245</div>
+          </div>
+        </div>
+      </el-col>
+      <el-col :span="8">
+        <div class="flex justify-center items-center border-l">
+          <el-icon size="40" color="#409EFF"><ChatDotSquare /></el-icon>
+          <div class="flex flex-col ml-6">
+            <div class="text-lg text-theme">待处理工单</div>
+            <div class="text-3xl text-theme">1245</div>
+          </div>
+        </div>
+      </el-col>
+    </el-row>
+  </ele-card>
+</template>
+
+<script setup>
+  import { SoldOut, Wallet, ChatDotSquare } from '@element-plus/icons-vue';
+</script>

+ 0 - 194
src/views/index/components/link-card.vue

@@ -1,194 +0,0 @@
-<!-- 快捷方式 -->
-<template>
-  <el-row :gutter="16" ref="wrapRef">
-    <el-col v-for="item in data" :key="item.url" :md="3" :sm="6" :xs="12">
-      <ele-card shadow="hover" :body-style="{ padding: 0 }">
-        <router-link :to="item.url" class="app-link">
-          <el-icon class="app-link-icon" :style="{ color: item.color }">
-            <component :is="item.icon" />
-          </el-icon>
-          <div class="app-link-title">{{ item.title }}</div>
-        </router-link>
-      </ele-card>
-    </el-col>
-  </el-row>
-</template>
-
-<script setup>
-  import { ref, onMounted, onBeforeUnmount } from 'vue';
-  import SortableJs from 'sortablejs';
-  import {
-    UserOutlined,
-    AnalysisOutlined,
-    ShoppingOutlined,
-    LogOutlined,
-    CopyOutlined,
-    MailOutlined,
-    TagOutlined,
-    ControlOutlined
-  } from '@/components/icons';
-
-  defineOptions({
-    components: {
-      UserOutlined,
-      AnalysisOutlined,
-      ShoppingOutlined,
-      LogOutlined,
-      CopyOutlined,
-      MailOutlined,
-      TagOutlined,
-      ControlOutlined
-    }
-  });
-
-  const CACHE_KEY = 'workplace-links';
-
-  /** 默认顺序 */
-  const DEFAULT = [
-    {
-      id: 1,
-      icon: 'UserOutlined',
-      title: '用户',
-      url: '/system/user'
-    },
-    {
-      id: 2,
-      icon: 'AnalysisOutlined',
-      title: '分析',
-      url: '/monitor/cache',
-      color: '#95de64'
-    },
-    {
-      id: 3,
-      icon: 'ShoppingOutlined',
-      title: '商品',
-      url: '/system/dict',
-      color: '#ff9c6e'
-    },
-    {
-      id: 4,
-      icon: 'LogOutlined',
-      title: '订单',
-      url: '/system/log/logininfor',
-      color: '#b37feb'
-    },
-    {
-      id: 5,
-      icon: 'CopyOutlined',
-      title: '票据',
-      url: '/monitor/online',
-      color: '#ffd666'
-    },
-    {
-      id: 6,
-      icon: 'MailOutlined',
-      title: '消息',
-      url: '/system/notice',
-      color: '#5cdbd3'
-    },
-    {
-      id: 7,
-      icon: 'TagOutlined',
-      title: '标签',
-      url: '/system/role',
-      color: '#ff85c0'
-    },
-    {
-      id: 8,
-      icon: 'ControlOutlined',
-      title: '配置',
-      url: '/system/config',
-      color: '#ffc069'
-    }
-  ];
-
-  /** 数据 */
-  const data = ref(
-    (() => {
-      try {
-        const str = localStorage.getItem(CACHE_KEY);
-        const temp = str ? JSON.parse(str) : null;
-        if (temp) {
-          const result = [...DEFAULT];
-          result.sort((a, b) => temp.indexOf(a.id) - temp.indexOf(b.id));
-          return result;
-        }
-      } catch (_e) {
-        //
-      }
-      return [...DEFAULT];
-    })()
-  );
-
-  /** 根节点 */
-  const wrapRef = ref(null);
-
-  /** 排序实例 */
-  let sortableIns = null;
-
-  /** 重置布局 */
-  const reset = () => {
-    data.value = [...DEFAULT];
-    localStorage.removeItem(CACHE_KEY);
-  };
-
-  /** 缓存布局 */
-  const cacheData = () => {
-    localStorage.setItem(
-      CACHE_KEY,
-      JSON.stringify(data.value.map((d) => d.id))
-    );
-  };
-
-  onMounted(() => {
-    if ('ontouchstart' in document.documentElement) {
-      return;
-    }
-    sortableIns = new SortableJs(wrapRef.value?.$el, {
-      animation: 300,
-      onUpdate: ({ oldIndex, newIndex }) => {
-        if (typeof oldIndex === 'number' && typeof newIndex === 'number') {
-          const temp = [...data.value];
-          temp.splice(newIndex, 0, temp.splice(oldIndex, 1)[0]);
-          data.value = temp;
-          cacheData();
-        }
-      },
-      setData: () => {}
-    });
-  });
-
-  onBeforeUnmount(() => {
-    if (sortableIns) {
-      sortableIns.destroy();
-      sortableIns = null;
-    }
-  });
-
-  defineExpose({ reset });
-</script>
-
-<style lang="scss" scoped>
-  .app-link {
-    padding: 12px;
-    display: block;
-    text-align: center;
-    text-decoration: none;
-    user-select: none;
-    color: inherit;
-
-    :deep(.app-link-icon) {
-      font-size: 30px;
-      color: #69c0ff;
-      margin: 6px 0 10px 0;
-
-      & > svg {
-        stroke-width: 3;
-      }
-    }
-  }
-
-  .el-col.sortable-ghost {
-    opacity: 0;
-  }
-</style>

+ 0 - 74
src/views/index/components/more-icon.vue

@@ -1,74 +0,0 @@
-<template>
-  <ele-dropdown
-    :items="[
-      {
-        title: '刷新内容',
-        command: 'refresh',
-        icon: ReloadOutlined
-      },
-      {
-        title: '编辑卡片',
-        command: 'edit',
-        icon: EditOutlined
-      },
-      {
-        title: '删除卡片',
-        command: 'remove',
-        icon: DeleteOutlined,
-        danger: true,
-        divided: true
-      }
-    ]"
-    :icon-props="{ size: 15 }"
-    placement="bottom-end"
-    style="cursor: pointer"
-    :popper-options="{
-      strategy: 'fixed',
-      modifiers: [{ name: 'offset', options: { offset: [12, 12] } }]
-    }"
-    @command="handleCommand"
-    class="demo-more-icon"
-  >
-    <el-icon style="outline: none">
-      <MoreOutlined style="transform: scale(1.1)" />
-    </el-icon>
-  </ele-dropdown>
-</template>
-
-<script setup>
-  import {
-    MoreOutlined,
-    ReloadOutlined,
-    EditOutlined,
-    DeleteOutlined
-  } from '@/components/icons';
-
-  const emit = defineEmits(['command']);
-
-  const handleCommand = (command) => {
-    emit('command', command);
-  };
-</script>
-
-<style lang="scss" scoped>
-  .demo-more-icon {
-    display: flex;
-    align-items: center;
-    justify-content: center;
-    color: var(--el-text-color-placeholder);
-    font-size: 14px;
-    border-radius: 6px;
-    margin: 0 -10px 0 0;
-    transition: all 0.2s;
-
-    & > .el-icon {
-      width: 26px;
-      height: 26px;
-    }
-
-    &:hover {
-      color: var(--el-text-color-regular);
-      background: var(--el-fill-color-light);
-    }
-  }
-</style>

+ 53 - 0
src/views/index/components/order-stat.vue

@@ -0,0 +1,53 @@
+<template>
+  <ele-card>
+    <el-row :gutter="24" justify="center">
+      <el-col :span="8">
+        <div class="flex justify-center items-center mb-5 border-b">
+          <div class="flex items-center flex-col flex-1 pb-6">
+            <div class="text-2xl text-theme">0</div>
+            <div class="text-base text-theme">待初审订单</div>
+          </div>
+          <div class="flex items-center flex-col flex-1 border-l">
+            <div class="text-2xl text-theme">6</div>
+            <div class="text-base text-theme">待收货订单</div>
+          </div>
+        </div>
+        <div class="flex justify-center items-center">
+          <div class="flex items-center flex-col flex-1">
+            <div class="text-2xl text-theme">1245</div>
+            <div class="text-base text-theme">待审核订单</div>
+          </div>
+          <div class="flex items-center flex-col flex-1 border-l">
+            <div class="text-2xl text-theme">1245</div>
+            <div class="text-base text-theme">待付款订单</div>
+          </div>
+        </div>
+      </el-col>
+      <el-col :span="3"></el-col>
+      <el-col :span="8">
+        <div class="flex justify-center items-center mb-5 border-b">
+          <div class="flex items-center flex-col flex-1 pb-6">
+            <div class="text-2xl text-theme">0</div>
+            <div class="text-base text-theme">库存预警</div>
+          </div>
+          <div class="flex items-center flex-col flex-1 border-l">
+            <div class="text-2xl text-theme">6</div>
+            <div class="text-base text-theme">库存已满</div>
+          </div>
+        </div>
+        <div class="flex justify-center items-center">
+          <div class="flex items-center flex-col flex-1">
+            <div class="text-2xl text-theme">1245</div>
+            <div class="text-base text-theme">24小时未初审</div>
+          </div>
+          <div class="flex items-center flex-col flex-1 border-l">
+            <div class="text-2xl text-theme">1245</div>
+            <div class="text-base text-theme">回收价>出售价(中等)</div>
+          </div>
+        </div>
+      </el-col>
+    </el-row>
+  </ele-card>
+</template>
+
+<script setup></script>

+ 0 - 148
src/views/index/components/profile-card.vue

@@ -1,148 +0,0 @@
-<!-- 用户信息 -->
-<template>
-  <ele-card :body-style="{ padding: '20px' }">
-    <div class="profile-wrapper">
-      <div class="profile-main">
-        <el-avatar :size="68" :src="loginUser.avatar" class="profile-avatar" />
-        <div class="profile-body">
-          <ele-text size="xl" type="heading" style="font-weight: normal">
-            早安, {{ loginUser.nickName }}, 开始您一天的工作吧!
-          </ele-text>
-          <ele-text type="placeholder" :icon="PartlyCloudy">
-            今日多云转阴, 18℃ ~ 22℃, 出门记得穿外套哦~
-          </ele-text>
-        </div>
-      </div>
-      <div class="profile-count">
-        <div class="profile-count-item">
-          <div class="profile-count-header">
-            <el-tag size="large" :disable-transitions="true">
-              <el-icon>
-                <Briefcase />
-              </el-icon>
-            </el-tag>
-            <span class="profile-count-name">项目数</span>
-          </div>
-          <ele-text size="xl" type="heading" style="font-weight: normal">
-            3
-          </ele-text>
-        </div>
-        <div class="profile-count-item">
-          <div class="profile-count-header">
-            <el-tag size="large" type="warning" :disable-transitions="true">
-              <el-icon>
-                <Checked />
-              </el-icon>
-            </el-tag>
-            <span class="profile-count-name">待办项</span>
-          </div>
-          <ele-text size="xl" type="heading" style="font-weight: normal">
-            6 / 24
-          </ele-text>
-        </div>
-        <div class="profile-count-item">
-          <div class="profile-count-header">
-            <el-tag size="large" type="success" :disable-transitions="true">
-              <el-icon>
-                <BellFilled />
-              </el-icon>
-            </el-tag>
-            <span class="profile-count-name">消息</span>
-          </div>
-          <ele-text size="xl" type="heading" style="font-weight: normal">
-            1,689
-          </ele-text>
-        </div>
-      </div>
-    </div>
-  </ele-card>
-</template>
-
-<script setup>
-  import { computed } from 'vue';
-  import {
-    PartlyCloudy,
-    Briefcase,
-    Checked,
-    BellFilled
-  } from '@element-plus/icons-vue';
-  import { useUserStore } from '@/store/modules/user';
-
-  const userStore = useUserStore();
-
-  /** 当前登录用户信息 */
-  const loginUser = computed(() => userStore.info ?? {});
-</script>
-
-<style lang="scss" scoped>
-  .profile-wrapper {
-    display: flex;
-    align-items: center;
-
-    .profile-main {
-      flex: 1;
-      display: flex;
-      align-items: center;
-      overflow: hidden;
-
-      .profile-avatar {
-        flex-shrink: 0;
-      }
-
-      .profile-body {
-        flex: 1;
-        padding-left: 12px;
-        box-sizing: border-box;
-      }
-
-      h4 {
-        margin-bottom: 6px;
-      }
-    }
-  }
-
-  .profile-count {
-    flex-shrink: 0;
-    text-align: right;
-    white-space: nowrap;
-
-    .profile-count-item {
-      display: inline-block;
-      margin: 0 4px 0 24px;
-
-      .el-tag {
-        width: 26px;
-        height: 26px;
-        border-radius: 50%;
-        line-height: 0;
-        padding: 0;
-      }
-
-      .profile-count-name {
-        margin-left: 8px;
-      }
-
-      .profile-count-header {
-        display: flex;
-        align-items: center;
-        margin-bottom: 4px;
-      }
-    }
-  }
-
-  @media screen and (max-width: 992px) {
-    .profile-count .profile-count-item {
-      margin: 0 2px 0 12px;
-    }
-  }
-
-  @media screen and (max-width: 768px) {
-    .profile-wrapper {
-      display: block;
-
-      .profile-count {
-        margin-top: 14px;
-      }
-    }
-  }
-</style>

+ 0 - 162
src/views/index/components/project-card.vue

@@ -1,162 +0,0 @@
-<!-- 项目进度 -->
-<template>
-  <ele-card :header="title" :body-style="{ padding: '10px', height: '370px' }">
-    <template #extra>
-      <more-icon @command="handleCommand" />
-    </template>
-    <ele-pro-table
-      :height="352"
-      row-key="id"
-      :columns="columns"
-      :datasource="projectList"
-      :show-overflow-tooltip="true"
-      highlight-current-row
-      :pagination="false"
-      :toolbar="false"
-      :bottom-line="false"
-      size="large"
-      class="project-table"
-    >
-      <template #projectName="{ row }">
-        <el-link type="primary" :underline="false">
-          {{ row.projectName }}
-        </el-link>
-      </template>
-      <template #status="{ row }">
-        <ele-text v-if="row.status === 0" type="success">进行中</ele-text>
-        <ele-text v-else-if="row.status === 1" type="danger">已延期</ele-text>
-        <ele-text v-else-if="row.status === 2" type="warning">
-          未开始
-        </ele-text>
-        <ele-text v-else-if="row.status === 3" type="info">已结束</ele-text>
-      </template>
-      <template #progress="{ row }">
-        <el-progress :percentage="row.progress" />
-      </template>
-    </ele-pro-table>
-  </ele-card>
-</template>
-
-<script setup>
-  import { ref } from 'vue';
-  import MoreIcon from './more-icon.vue';
-
-  defineProps({
-    title: String
-  });
-
-  const emit = defineEmits(['command']);
-
-  /** 表格列配置 */
-  const columns = ref([
-    {
-      type: 'index',
-      columnKey: 'index',
-      width: 50,
-      align: 'center',
-      fixed: 'left'
-    },
-    {
-      prop: 'projectName',
-      label: '项目名称',
-      slot: 'projectName',
-      minWidth: 110
-    },
-    {
-      prop: 'startDate',
-      label: '开始时间',
-      align: 'center',
-      minWidth: 110
-    },
-    {
-      prop: 'endDate',
-      label: '结束时间',
-      align: 'center',
-      minWidth: 110
-    },
-    {
-      prop: 'status',
-      label: '状态',
-      slot: 'status',
-      align: 'center',
-      width: 90
-    },
-    {
-      prop: 'progress',
-      label: '进度',
-      width: 180,
-      align: 'center',
-      slot: 'progress',
-      showOverflowTooltip: false
-    }
-  ]);
-
-  /** 项目进度数据 */
-  const projectList = ref([]);
-
-  /** 查询项目进度 */
-  const queryProjectList = () => {
-    projectList.value = [
-      {
-        id: 1,
-        projectName: '项目000000001',
-        status: 0,
-        startDate: '2020-03-01',
-        endDate: '2020-06-01',
-        progress: 30
-      },
-      {
-        id: 2,
-        projectName: '项目000000002',
-        status: 0,
-        startDate: '2020-03-01',
-        endDate: '2020-08-01',
-        progress: 10
-      },
-      {
-        id: 3,
-        projectName: '项目000000003',
-        status: 1,
-        startDate: '2020-01-01',
-        endDate: '2020-05-01',
-        progress: 60
-      },
-      {
-        id: 4,
-        projectName: '项目000000004',
-        status: 1,
-        startDate: '2020-06-01',
-        endDate: '2020-10-01',
-        progress: 0
-      },
-      {
-        id: 5,
-        projectName: '项目000000005',
-        status: 2,
-        startDate: '2020-03-01',
-        endDate: '2020-07-01',
-        progress: 100
-      },
-      {
-        id: 6,
-        projectName: '项目000000006',
-        status: 3,
-        startDate: '2020-02-01',
-        endDate: '2020-06-01',
-        progress: 100
-      }
-    ];
-  };
-
-  const handleCommand = (command) => {
-    emit('command', command);
-  };
-
-  queryProjectList();
-</script>
-
-<style lang="scss" scoped>
-  .project-table :deep(.el-progress__text) {
-    font-size: 12px !important;
-  }
-</style>

+ 138 - 0
src/views/index/components/sale-card.vue

@@ -0,0 +1,138 @@
+<template>
+  <ele-card
+    header="订单趋势"
+    :header-style="{ padding: '0 24px' }"
+    :body-style="{ padding: 0 }"
+  >
+    <template #extra>
+      <div
+        class="hidden-xs-only"
+        style="display: flex; align-items: center; margin: 16px 0"
+      >
+        <el-radio-group v-model="saleSearch.dateType">
+          <el-radio-button label="1">今天</el-radio-button>
+          <el-radio-button label="2">本周</el-radio-button>
+          <el-radio-button label="3">本月</el-radio-button>
+          <el-radio-button label="4">本年</el-radio-button>
+        </el-radio-group>
+        <div class="hidden-md-and-down" style="width: 320px; margin-left: 12px">
+          <el-date-picker
+            unlink-panels
+            type="datetimerange"
+            v-model="saleSearch.datetime"
+            range-separator="-"
+            format="YYYY-MM-DD HH:mm"
+            value-format="YYYY-MM-DD HH:mm"
+            start-placeholder="开始时间"
+            end-placeholder="结束时间"
+            class="ele-fluid"
+          />
+        </div>
+      </div>
+    </template>
+    <div class="sale-body">
+      <v-chart
+        ref="saleChartRef"
+        :option="saleChartOption"
+        style="height: 400px"
+      />
+    </div>
+  </ele-card>
+</template>
+
+<script setup>
+  import { ref, reactive } from 'vue';
+  import { EleMessage } from 'ele-admin-plus/es';
+  import { use } from 'echarts/core';
+  import { CanvasRenderer } from 'echarts/renderers';
+  import { BarChart } from 'echarts/charts';
+  import { GridComponent, TooltipComponent } from 'echarts/components';
+  import VChart from 'vue-echarts';
+  import { useEcharts } from '@/utils/use-echarts';
+  import { getSaleroomList } from '@/api/dashboard/analysis';
+
+  use([CanvasRenderer, BarChart, GridComponent, TooltipComponent]);
+
+  const saleChartRef = ref(null);
+
+  useEcharts([saleChartRef]);
+
+  /** 销售额柱状图配置 */
+  const saleChartOption = reactive({});
+
+  /** 销售量趋势数据 */
+  const saleroomData1 = ref([]);
+
+  /** 访问量趋势数据 */
+  const saleroomData2 = ref([]);
+
+  /** 销售量搜索参数 */
+  const saleSearch = reactive({
+    type: 'saleroom',
+    dateType: '1',
+    datetime: ['2022-01-01 10:44', '2022-01-03 13:00']
+  });
+
+  /** 获取销售量数据 */
+  const getSaleroomData = () => {
+    getSaleroomList()
+      .then((data) => {
+        saleroomData1.value = data.list1;
+        onSaleTypeChange();
+      })
+      .catch((e) => {
+        EleMessage.error(e.message);
+      });
+  };
+
+  getSaleroomData();
+
+  /** 销售量tab选择改变事件 */
+  const onSaleTypeChange = () => {
+    Object.assign(saleChartOption, {
+      tooltip: {
+        trigger: 'axis'
+      },
+      xAxis: [
+        {
+          type: 'category',
+          data: saleroomData1.value.map((d) => d.month)
+        }
+      ],
+      yAxis: [
+        {
+          type: 'value'
+        }
+      ],
+      series: [
+        {
+          type: 'bar',
+          data: saleroomData1.value.map((d) => d.value)
+        }
+      ]
+    });
+  };
+</script>
+
+<style lang="scss" scoped>
+  .sale-body {
+    padding: 16px 0 10px 0;
+  }
+
+  .sale-body-title {
+    padding: 6px 20px;
+  }
+
+  .sale-rank-item {
+    display: flex;
+    align-items: center;
+    padding: 0 20px;
+    margin-top: 18px;
+    box-sizing: border-box;
+
+    .sale-rank-item-text {
+      flex: 1;
+      padding-left: 12px;
+    }
+  }
+</style>

+ 0 - 232
src/views/index/components/task-card.vue

@@ -1,232 +0,0 @@
-<!-- 我的任务 -->
-<template>
-  <ele-card
-    :header="title"
-    :body-style="{ height: '370px', padding: '7px 8px 6px 8px' }"
-  >
-    <template #extra>
-      <more-icon @command="handleCommand" />
-    </template>
-    <el-scrollbar
-      :wrap-style="{ position: 'relative', zIndex: 1 }"
-      @scroll="handleTaskTableScroll"
-    >
-      <ele-table
-        size="large"
-        :class="['task-table', { 'is-ping-left': isPingLeft }]"
-      >
-        <thead style="position: sticky; top: 0; z-index: 2">
-          <tr>
-            <th
-              style="position: sticky; left: 0; z-index: 1; width: 38px"
-              class="task-table-index"
-            ></th>
-            <th style="text-align: center; width: 78px">优先级</th>
-            <th>任务名称</th>
-            <th style="text-align: center; width: 80px">状态</th>
-          </tr>
-        </thead>
-        <vue-draggable
-          tag="tbody"
-          item-key="id"
-          v-model="taskList"
-          handle=".sort-handle"
-          :animation="300"
-          :set-data="() => void 0"
-          :force-fallback="true"
-        >
-          <template #item="{ element }">
-            <tr>
-              <td
-                :style="{
-                  textAlign: 'center',
-                  paddingLeft: 0,
-                  paddingRight: 0,
-                  position: 'sticky',
-                  left: 0,
-                  zIndex: 1,
-                  width: '38px'
-                }"
-                class="task-table-index"
-              >
-                <ele-text
-                  :icon="DragOutlined"
-                  :icon-style="{ transform: 'scale(1.15)' }"
-                  type="placeholder"
-                  class="sort-handle"
-                />
-              </td>
-              <td style="text-align: center; width: 78px">
-                <el-tag
-                  v-if="element.priority === 1"
-                  type="danger"
-                  :disable-transitions="true"
-                >
-                  {{ element.priority }}
-                </el-tag>
-                <el-tag
-                  v-else-if="element.priority === 2"
-                  type="warning"
-                  :disable-transitions="true"
-                >
-                  {{ element.priority }}
-                </el-tag>
-                <el-tag v-else :disable-transitions="true">
-                  {{ element.priority }}
-                </el-tag>
-              </td>
-              <td>
-                <ele-ellipsis style="line-height: 20px">
-                  <el-link type="primary" :underline="false">
-                    {{ element.taskName }}
-                  </el-link>
-                </ele-ellipsis>
-              </td>
-              <td style="text-align: center; width: 80px">
-                <ele-text v-if="element.status === 0" type="warning">
-                  未开始
-                </ele-text>
-                <ele-text v-else-if="element.status === 1" type="success">
-                  进行中
-                </ele-text>
-                <ele-text v-else-if="element.status === 2" type="info" deleted>
-                  已完成
-                </ele-text>
-              </td>
-            </tr>
-          </template>
-        </vue-draggable>
-      </ele-table>
-    </el-scrollbar>
-  </ele-card>
-</template>
-
-<script setup>
-  import { ref } from 'vue';
-  import VueDraggable from 'vuedraggable';
-  import { DragOutlined } from '@/components/icons';
-  import MoreIcon from './more-icon.vue';
-
-  defineProps({
-    title: String
-  });
-
-  const emit = defineEmits(['command']);
-
-  /** 我的任务数据 */
-  const taskList = ref([]);
-
-  /** 查询我的任务 */
-  const queryTaskList = () => {
-    taskList.value = [
-      {
-        id: 1,
-        priority: 1,
-        taskName: '解决项目一的bug',
-        status: 0
-      },
-      {
-        id: 2,
-        priority: 2,
-        taskName: '解决项目二的bug',
-        status: 0
-      },
-      {
-        id: 3,
-        priority: 2,
-        taskName: '解决项目三的bug',
-        status: 1
-      },
-      {
-        id: 4,
-        priority: 3,
-        taskName: '解决项目四的bug',
-        status: 1
-      },
-      {
-        id: 5,
-        priority: 3,
-        taskName: '解决项目五的bug',
-        status: 2
-      },
-      {
-        id: 6,
-        priority: 3,
-        taskName: '解决项目六的bug',
-        status: 2
-      }
-    ];
-  };
-
-  const handleCommand = (command) => {
-    emit('command', command);
-  };
-
-  queryTaskList();
-
-  /** 我的任务表格左侧列是否固定状态 */
-  const isPingLeft = ref(false);
-
-  /** 我的任务表格滚动事件 */
-  const handleTaskTableScroll = ({ scrollLeft }) => {
-    isPingLeft.value = scrollLeft > 1;
-  };
-</script>
-
-<style lang="scss" scoped>
-  .task-table {
-    table-layout: fixed;
-    min-width: 300px;
-
-    .sort-handle {
-      cursor: move;
-    }
-
-    .el-tag {
-      width: 20px;
-      height: 20px;
-      border-radius: 50%;
-    }
-
-    td,
-    th {
-      box-sizing: border-box;
-    }
-
-    tr.sortable-chosen {
-      user-select: none;
-    }
-
-    tr.sortable-ghost {
-      opacity: 0;
-    }
-
-    tr.sortable-fallback {
-      opacity: 1 !important;
-      display: table !important;
-      table-layout: fixed !important;
-
-      td {
-        background: var(--el-color-primary-light-8);
-      }
-    }
-  }
-
-  .task-table.is-ping-left :deep(.task-table-index) {
-    &::before {
-      content: '';
-      width: 10px;
-      position: absolute;
-      top: 0;
-      bottom: -1px;
-      right: -10px;
-      box-shadow: var(--ele-table-fixed-left-shadow);
-      transition: box-shadow 0.2s;
-      pointer-events: none;
-    }
-
-    &::after {
-      display: none;
-    }
-  }
-</style>

+ 0 - 124
src/views/index/components/user-list.vue

@@ -1,124 +0,0 @@
-<!-- 小组成员 -->
-<template>
-  <ele-card
-    :header="title"
-    :body-style="{ padding: '8px 0px', height: '370px' }"
-  >
-    <template #extra>
-      <more-icon @command="handleCommand" />
-    </template>
-    <div v-for="item in userList" :key="item.id" class="user-list-item">
-      <el-avatar :size="46" :src="item.avatar" style="flex-shrink: 0" />
-      <div class="user-list-item-body">
-        <div>{{ item.name }}</div>
-        <ele-ellipsis type="placeholder" size="sm">
-          {{ item.introduction }}
-        </ele-ellipsis>
-      </div>
-      <div style="flex-shrink: 0">
-        <el-tag
-          v-if="item.status === 0"
-          size="small"
-          type="success"
-          :disable-transitions="true"
-        >
-          在线
-        </el-tag>
-        <el-tag v-else size="small" type="danger" :disable-transitions="true">
-          离线
-        </el-tag>
-      </div>
-    </div>
-  </ele-card>
-</template>
-
-<script setup>
-  import { ref } from 'vue';
-  import MoreIcon from './more-icon.vue';
-
-  defineProps({
-    title: String
-  });
-
-  const emit = defineEmits(['command']);
-
-  /** 小组成员数据 */
-  const userList = ref([]);
-
-  /** 查询小组成员 */
-  const queryUserList = () => {
-    userList.value = [
-      {
-        id: 1,
-        name: 'SunSmile',
-        introduction: 'UI设计师、交互专家',
-        status: 0,
-        avatar:
-          'https://cdn.eleadmin.com/20200609/c184eef391ae48dba87e3057e70238fb.jpg'
-      },
-      {
-        id: 2,
-        name: '你的名字很好听',
-        introduction: '前端工程师',
-        status: 0,
-        avatar:
-          'https://cdn.eleadmin.com/20200609/b6a811873e704db49db994053a5019b2.jpg'
-      },
-      {
-        id: 3,
-        name: '全村人的希望',
-        introduction: '前端工程师',
-        status: 0,
-        avatar:
-          'https://cdn.eleadmin.com/20200609/948344a2a77c47a7a7b332fe12ff749a.jpg'
-      },
-      {
-        id: 4,
-        name: 'Jasmine',
-        introduction: '产品经理、项目经理',
-        status: 1,
-        avatar:
-          'https://cdn.eleadmin.com/20200609/f6bc05af944a4f738b54128717952107.jpg'
-      },
-      {
-        id: 5,
-        name: '酷酷的大叔',
-        introduction: '组长、后端工程师',
-        status: 1,
-        avatar:
-          'https://cdn.eleadmin.com/20200609/2d98970a51b34b6b859339c96b240dcd.jpg'
-      }
-    ];
-  };
-
-  const handleCommand = (command) => {
-    emit('command', command);
-  };
-
-  queryUserList();
-</script>
-
-<style lang="scss" scoped>
-  .user-list-item {
-    display: flex;
-    align-items: center;
-    padding: 12px 18px;
-    transition: background-color 0.2s;
-    cursor: pointer;
-
-    .user-list-item-body {
-      flex: 1;
-      overflow: hidden;
-      padding-left: 12px;
-      box-sizing: border-box;
-    }
-
-    & + .user-list-item {
-      border-top: 1px solid hsla(0, 0%, 60%, 0.2);
-    }
-
-    &:hover {
-      background: hsla(0, 0%, 60%, 0.08);
-    }
-  }
-</style>

+ 9 - 282
src/views/index/index.vue

@@ -1,296 +1,23 @@
 <template>
   <ele-page class="workplace-page">
-    <profile-card />
-    <link-card ref="linkCardRef" />
-    <el-row :gutter="16" ref="wrapRef">
-      <el-col
-        v-for="(item, index) in data"
-        :key="item.name"
-        :md="item.md"
-        :sm="item.sm"
-        :xs="item.xs"
-      >
-        <component
-          :is="item.name"
-          :title="item.title"
-          @command="(command) => handleCommand(command, index)"
-        />
-      </el-col>
-    </el-row>
-    <ele-card :body-style="{ padding: 0 }">
-      <div class="workplace-bottom">
-        <el-link
-          type="primary"
-          :icon="PlusCircleOutlined"
-          :underline="false"
-          class="workplace-button"
-          @click="add"
-        >
-          添加卡片
-        </el-link>
-        <el-divider direction="vertical" style="margin: 0" />
-        <el-link
-          type="primary"
-          :icon="UndoOutlined"
-          :underline="false"
-          class="workplace-button"
-          @click="reset"
-        >
-          重置布局
-        </el-link>
-      </div>
-    </ele-card>
-    <!-- 添加卡片弹窗 -->
-    <ele-modal :width="680" v-model="visible" title="未添加的卡片">
-      <el-row :gutter="16" style="margin-top: -16px">
-        <el-col
-          v-for="item in notAddedData"
-          :key="item.name"
-          :md="8"
-          :sm="12"
-          :xs="24"
-        >
-          <ele-card
-            bordered
-            :header="item.title"
-            :header-style="{ padding: '8px 14px', fontSize: '14px' }"
-            :body-style="{ padding: '32px 0', textAlign: 'center' }"
-            style="margin-top: 16px"
-          >
-            <el-button
-              plain
-              round
-              size="small"
-              type="primary"
-              @click="addView(item)"
-            >
-              添加
-            </el-button>
-          </ele-card>
-        </el-col>
-      </el-row>
-      <el-empty
-        v-if="!notAddedData.length"
-        description="已添加所有视图"
-        :image-size="80"
-      />
-    </ele-modal>
+    <goodsStat />
+    <orderStat />
+    <saleCard />
   </ele-page>
 </template>
 
 <script setup>
   import { ref, computed, onMounted, onBeforeUnmount } from 'vue';
-  import SortableJs from 'sortablejs';
   import { ElMessageBox } from 'element-plus/es';
   import { EleMessage } from 'ele-admin-plus/es';
   import { PlusCircleOutlined, UndoOutlined } from '@/components/icons';
-  import ProfileCard from './components/profile-card.vue';
-  import LinkCard from './components/link-card.vue';
-  import ActivitiesCard from './components/activities-card.vue';
-  import TaskCard from './components/task-card.vue';
-  import GoalCard from './components/goal-card.vue';
-  import ProjectCard from './components/project-card.vue';
-  import UserList from './components/user-list.vue';
+  import goodsStat from '@/views/index/components/goods-stat.vue';
+  import orderStat from '@/views/index/components/order-stat.vue';
+  import saleCard from '@/views/index/components/sale-card.vue';
 
-  defineOptions({
-    name: 'Index',
-    components: {
-      ActivitiesCard,
-      TaskCard,
-      GoalCard,
-      ProjectCard,
-      UserList
-    }
-  });
+  onMounted(() => {});
 
-  const CACHE_KEY = 'workplace-layout';
-
-  /** 默认布局 */
-  const DEFAULT = [
-    {
-      name: 'activities-card',
-      title: '最新动态',
-      md: 8,
-      sm: 24,
-      xs: 24
-    },
-    {
-      name: 'task-card',
-      title: '我的任务',
-      md: 8,
-      sm: 24,
-      xs: 24
-    },
-    {
-      name: 'goal-card',
-      title: '本月目标',
-      md: 8,
-      sm: 24,
-      xs: 24
-    },
-    {
-      name: 'project-card',
-      title: '项目进度',
-      md: 16,
-      sm: 24,
-      xs: 24
-    },
-    {
-      name: 'user-list',
-      title: '小组成员',
-      md: 8,
-      sm: 24,
-      xs: 24
-    }
-  ];
-
-  /** 获取缓存的数据 */
-  const getCacheData = () => {
-    const str = localStorage.getItem(CACHE_KEY);
-    try {
-      return str ? JSON.parse(str) : null;
-    } catch (e) {
-      return null;
-    }
-  };
-
-  /** 卡片数据 */
-  const data = ref([...(getCacheData() ?? DEFAULT)]);
-
-  /** 弹窗是否打开 */
-  const visible = ref(false);
-
-  /** 快捷方式卡片 */
-  const linkCardRef = ref(null);
-
-  /** 容器 */
-  const wrapRef = ref(null);
-
-  /** 拖拽排序实例 */
-  let sortableIns = null;
-
-  /** 未添加的数据 */
-  const notAddedData = computed(() => {
-    return DEFAULT.filter((d) => !data.value.some((t) => t.name === d.name));
-  });
-
-  /** 添加 */
-  const add = () => {
-    visible.value = true;
-  };
-
-  /** 重置布局 */
-  const reset = () => {
-    data.value = [...DEFAULT];
-    cacheData();
-    linkCardRef.value?.reset?.();
-    EleMessage.success('已重置');
-  };
-
-  /** 缓存布局 */
-  const cacheData = () => {
-    localStorage.setItem(CACHE_KEY, JSON.stringify(data.value));
-  };
-
-  /** 编辑卡片 */
-  const handleCommand = (command, index) => {
-    switch (command) {
-      case 'refresh': // 刷新
-        EleMessage.info({ message: '点击了刷新', plain: true });
-        break;
-      case 'edit': // 编辑
-        EleMessage.info({ message: '点击了编辑', plain: true });
-        break;
-      case 'remove': // 删除
-        ElMessageBox.confirm(
-          `确定要删除“${data.value[index].title}”卡片吗?`,
-          '系统提示',
-          { type: 'warning', draggable: true }
-        )
-          .then(() => {
-            data.value = data.value.filter((_d, i) => i !== index);
-            cacheData();
-          })
-          .catch(() => {});
-        break;
-    }
-  };
-
-  /** 添加视图 */
-  const addView = (item) => {
-    data.value.push(item);
-    cacheData();
-    EleMessage.success('已添加');
-  };
-
-  onMounted(() => {
-    // 卡片支持拖动排序
-    if ('ontouchstart' in document.documentElement) {
-      return;
-    }
-    sortableIns = new SortableJs(wrapRef.value?.$el, {
-      handle: '.ele-card-header',
-      filter: '.demo-more-icon',
-      animation: 300,
-      onUpdate: ({ oldIndex, newIndex }) => {
-        if (typeof oldIndex === 'number' && typeof newIndex === 'number') {
-          const temp = [...data.value];
-          temp.splice(newIndex, 0, temp.splice(oldIndex, 1)[0]);
-          data.value = temp;
-          cacheData();
-        }
-      },
-      setData: () => {},
-      forceFallback: true
-    });
-  });
-
-  onBeforeUnmount(() => {
-    sortableIns && sortableIns.destroy();
-    sortableIns = null;
-  });
+  onBeforeUnmount(() => {});
 </script>
 
-<style lang="scss" scoped>
-  .workplace-page {
-    :deep(.ele-card-header) {
-      user-select: none;
-      cursor: move;
-    }
-
-    :deep(.el-col) {
-      &.sortable-chosen > .ele-card {
-        box-shadow: 0 2px 16px 0 rgba(0, 0, 0, 0.2);
-      }
-
-      &.sortable-ghost {
-        opacity: 0;
-      }
-
-      &.sortable-fallback {
-        opacity: 1 !important;
-      }
-    }
-  }
-
-  /* 底部按钮 */
-  .workplace-bottom {
-    display: flex;
-    align-items: center;
-
-    .workplace-button {
-      flex: 1;
-      padding: 10px 0;
-      transition: background-color 0.2s;
-
-      &:hover {
-        background: hsla(0, 0%, 60%, 0.05);
-      }
-
-      :deep(.el-icon) {
-        font-size: 15px;
-        margin: -1px 6px 0 0;
-      }
-    }
-  }
-</style>
+<style lang="scss" scoped></style>