浏览代码

更新表格

fxs 1 年之前
父节点
当前提交
509d99e976

+ 5 - 0
.env

@@ -0,0 +1,5 @@
+# 测试服和本地开发
+# VITE_API_URL_TEST='http://server.ichunhao.cn'
+VITE_API_URL_TEST='http://127.0.0.1:8003/mock'
+# 线上
+VITE_API_URL_PRODUCT=''

+ 4 - 3
components.d.ts

@@ -12,20 +12,21 @@ declare module 'vue' {
     ElConfigProvider: typeof import('element-plus/es')['ElConfigProvider']
     ElDatePicker: typeof import('element-plus/es')['ElDatePicker']
     ElDivider: typeof import('element-plus/es')['ElDivider']
+    ElForm: typeof import('element-plus/es')['ElForm']
+    ElFormItem: typeof import('element-plus/es')['ElFormItem']
     ElIcon: typeof import('element-plus/es')['ElIcon']
     ElImage: typeof import('element-plus/es')['ElImage']
     ElInput: typeof import('element-plus/es')['ElInput']
-    ElMenItem: typeof import('element-plus/es')['ElMenItem']
     ElMenu: typeof import('element-plus/es')['ElMenu']
     ElMenuItem: typeof import('element-plus/es')['ElMenuItem']
-    ElMenuItemGroup: typeof import('element-plus/es')['ElMenuItemGroup']
     ElOption: typeof import('element-plus/es')['ElOption']
     ElPopover: typeof import('element-plus/es')['ElPopover']
     ElRow: typeof import('element-plus/es')['ElRow']
     ElSelect: typeof import('element-plus/es')['ElSelect']
     ElStatistic: typeof import('element-plus/es')['ElStatistic']
     ElSubMenu: typeof import('element-plus/es')['ElSubMenu']
-    ElTooltip: typeof import('element-plus/es')['ElTooltip']
+    ElTable: typeof import('element-plus/es')['ElTable']
+    ElTableColumn: typeof import('element-plus/es')['ElTableColumn']
     IconIcBaselineVisibility: typeof import('~icons/ic/baseline-visibility')['default']
     IconIcBaselineVisibilityOff: typeof import('~icons/ic/baseline-visibility-off')['default']
     IconMaterialSymbolsLightLogout: typeof import('~icons/material-symbols-light/logout')['default']

+ 13 - 0
config/api.ts

@@ -0,0 +1,13 @@
+let BASE_URL: string = ''
+
+switch (import.meta.env.MODE) {
+  case 'production':
+    BASE_URL = import.meta.env.VITE_API_URL_PRODUCT
+    break
+  case 'test':
+    BASE_URL = import.meta.env.VITE_API_URL_TEST
+    break
+  default:
+    BASE_URL = import.meta.env.VITE_API_URL_TEST // 默认为开发环境
+}
+export default BASE_URL

+ 3 - 0
package.json

@@ -5,7 +5,10 @@
   "type": "module",
   "scripts": {
     "dev": "vite",
+    "test": "vite --mode test",
     "build": "run-p type-check \"build-only {@}\" --",
+    "build:test": "vite build --mode test",
+    "build:prod": "vite build --mode production",
     "preview": "vite preview",
     "build-only": "vite build",
     "type-check": "vue-tsc --build --force",

+ 77 - 6
src/assets/base.css

@@ -1,6 +1,3 @@
-::-webkit-scrollbar {
-  display: none;
-}
 html,
 body,
 ul,
@@ -19,17 +16,91 @@ h6,
 form,
 fieldset,
 legend,
-img {
+img,
+div {
   margin: 0;
   padding: 0;
   box-sizing: border-box;
 }
 
-.el-button + .el-button {
-  margin-left: 0 !important;
+div {
+  background-color: white;
+}
+
+/* 字节的样式 */
+.el-button {
+  /* display: inline-block; */
+  line-height: 1;
+  white-space: nowrap;
+  cursor: pointer;
+  background: #fff;
+  border: 1px solid #dcdfe6;
+  color: #606266;
+
+  text-align: center;
+  box-sizing: border-box;
+  outline: 0;
+  margin: 0;
+  transition: 0.1s;
+
+  padding: 12px 20px;
+  font-size: 14px;
+  border-radius: 3px;
+  font-weight: 200 !important;
 }
 
 body {
   font-family: 'Helvetica Neue', Helvetica, 'PingFang SC', 'Hiragino Sans GB',
     'Microsoft YaHei', 微软雅黑, Arial, sans-serif;
 }
+
+::-webkit-scrollbar {
+  width: 8px;
+  height: 8px;
+}
+
+::-webkit-scrollbar-thumb:hover {
+  background-color: #666;
+}
+
+::-webkit-scrollbar-thumb {
+  background-color: #dcdee2;
+  border-radius: 4px;
+}
+
+::-webkit-scrollbar-track-piece {
+  background-color: #f8f8f9;
+  border-radius: 4px;
+}
+
+::-webkit-scrollbar-corner {
+  display: block;
+}
+
+/* ::-webkit-scrollbar {
+  width: 8px;
+  height: 8px;
+}
+
+
+::-webkit-scrollbar-track-piece {
+  background-color: transparent;
+  border-radius: 5px;
+}
+
+
+::-webkit-scrollbar-thumb {
+  cursor: pointer;
+  background-color: red;
+  border-radius: 5px;
+}
+
+
+::-webkit-scrollbar-thumb:hover {
+  background-color: #999999;
+}
+
+
+::-webkit-scrollbar-corner {
+  display: block; 
+} */

+ 26 - 9
src/components/navigation/Menu.vue

@@ -38,9 +38,10 @@ initDefaultActive()
 <template>
   <div
     class="menuContainer"
-    :class="
-      $attrs.mode === 'vertical' ? 'verticalContainer' : 'horizontalContainer'
-    "
+    :class="[
+      $attrs.mode === 'vertical' ? 'verticalContainer' : 'horizontalContainer',
+      $attrs.mode === 'vertical' ? 'borderR' : '',
+    ]"
   >
     <el-menu
       v-bind="$attrs"
@@ -110,29 +111,45 @@ initDefaultActive()
       v-if="$attrs.mode === 'vertical'"
       class="sideBarFold"
       @click="isCollapse = !isCollapse"
+      :style="{ textAlign: isCollapse ? 'center' : 'right' }"
     >
-      <el-icon :size="20"><Fold /></el-icon>
+      <el-icon class="icon" :size="20"><Fold /></el-icon>
     </div>
   </div>
 </template>
 
 <style scoped>
+div {
+  background-color: white;
+}
 .menuContainer {
   position: relative;
+  height: 100%;
+}
+
+.borderR {
+  border-right: 1px solid #e8eaec;
 }
 
 /* 垂直样式 */
 .verticalContainer {
   .menu {
-    height: 93vh;
-    min-width: 180px;
+    position: relative;
+    height: calc(100% - 40px);
+    /* min-width: 180px; */
+    border-right: none;
   }
 
   .sideBarFold {
-    position: absolute;
-    right: 20px;
-    bottom: 20px;
+    position: relative;
+    bottom: 0px;
+    /* width: 100%; */
+    height: 40px;
+    line-height: 40px;
+    margin-right: 6px;
     cursor: pointer;
+    background-color: white;
+    /* text-align: right; */
   }
 }
 

+ 331 - 84
src/components/table/Table.vue

@@ -1,20 +1,57 @@
 <script setup lang="ts">
 import type { TableProps } from '@/types/Tables/table'
+import type { FormInstance } from 'element-plus'
 import { TableFilterType } from '@/types/Tables/table'
 
-import { computed, reactive, ref } from 'vue'
+import { nextTick, onMounted, reactive, ref } from 'vue'
 import { Search } from '@element-plus/icons-vue'
+import { Plus, Operation } from '@element-plus/icons-vue'
+import { useRequest } from '@/hooks/useRequest'
 
+import axiosInstance from '@/utils/axios/axiosInstance'
+
+interface AccountData {
+  accountBalance: number // 账户余额
+  accountFlow: number // 账户流动
+  accountName: string // 账户名
+  accountStatus: string // 账户状态
+  action: string // 操作
+  adAccountCount: number // 广告账户数量
+  dailyBudget: number // 每日预算
+  loginEmail: string // 登录邮箱
+  mediaId: string // 媒体ID
+}
+
+type AccountKeys = keyof AccountData
+
+const { AllApi } = useRequest()
 const props = withDefaults(defineProps<TableProps>(), {})
+const tableFieldLWidth = 200
+const tableFieldSWidth = 150
+const xScrollBaseOffset = 100
+
+// 表格字段
+const accountFields: AccountKeys[] = [
+  'accountName',
+  'accountBalance',
+  'accountFlow',
 
-// 过滤表单的数据
+  'accountStatus',
+  'action',
+  'adAccountCount',
+  'dailyBudget',
+  'loginEmail',
+  'mediaId',
+]
+
+// 表单数据
 const filterFormData = reactive<{
-  [key: string]: {
-    state: boolean
-    value: any
-  }
+  [key: string]: any
 }>({})
 
+// 表单ref
+const filterFormRef = ref<FormInstance>()
+
 // 过滤表单字段的状态信息
 const filterFieldsStateList = reactive<
   Array<{
@@ -27,16 +64,41 @@ const filterFieldsStateList = reactive<
 // 当前已经选中的展示的过滤字段
 const filterFields = ref<Array<any>>([])
 
+// 批量操作选中的值
+const batchOper = ref<string>()
+
+// 批量操作的选项数组
+const batchOperList = reactive<
+  Array<{
+    label: string
+    value: string
+  }>
+>([
+  {
+    label: '删除',
+    value: 'delete',
+  },
+  {
+    label: '新增',
+    value: 'add',
+  },
+])
+
+// 表格数据
+const tableData = reactive<Array<any>>([])
+
+// 需要横向固定的字段
+const fixedFields: Array<string> = ['action', 'accountName']
+
 /**
  * @description: 初始化查询表单
  * @return {*}
  */
 const initfilterForm = () => {
   for (let [k, v] of Object.entries(props.filtersInfo)) {
-    filterFormData[k] = {
-      state: true,
-      value: v.value,
-    }
+    // 表单给初始值
+    filterFormData[k] = v.value ? v.value : ''
+
     // 初始化过滤表单字段的状态信息
     filterFieldsStateList.push({
       label: v.label,
@@ -57,100 +119,250 @@ const initFilterFields = () => {
 }
 
 /**
- * @description: 当查询字段改变的时候,查询表单的数据也需要同步的增删
- * @param {*} val
+ * @description: 重置查询表单
  * @return {*}
  */
-const changeFilterFields = (val: Array<any>) => {
-  for (let item in filterFormData) {
-    if (!val.includes(item)) filterFormData[item].state = false
-  }
+const resetFilterForm = () => {
+  filterFormRef.value?.resetFields()
   console.log(filterFormData)
 }
 
+/**
+ * @description:根据现有的筛选字段重新生成查询参数
+ * @return {[key: string]: any}  查询参数
+ */
+const createQueryParams = (): {
+  [key: string]: any
+} => {
+  let queryParams: {
+    [key: string]: any
+  } = {}
+  for (let i in filterFormData) {
+    // 当前字段没有被隐藏,则加入查询参数
+    if (filterFields.value.includes(i)) {
+      queryParams[i] = filterFormData[i]
+    }
+  }
+  return queryParams
+}
+
+/**
+ * @description: 查询表格
+ * @return {*}
+ */
+const queryTable = () => {
+  let queryParams: {
+    [key: string]: any
+  } = createQueryParams()
+}
+
+const xScrollBox = ref<HTMLElement>()
+const xScroll = ref<HTMLElement>()
+const tableContent = ref<HTMLElement>()
+// const scrollView = ref<Element>()
+
+/**
+ * @description: 判断表格横向是否满足滚动条的生成条件
+ * @param {*} boolean
+ * @return {*}
+ */
+const canCreateTableXScroll = (): boolean => {
+  if (!xScrollBox.value || !tableContent.value || !xScroll.value) {
+    return false
+  }
+  return true
+}
+
+const initScroll = () => {
+  let scrViw = document.querySelector('.el-scrollbar__view') // 找到表格的实际容器
+  let lastColumn = document.getElementsByClassName('.el-table__cell')
+  console.log(lastColumn)
+  if (!scrViw || !canCreateTableXScroll()) return
+
+  let scrViewWidth = scrViw.clientWidth // 实际容器的宽度
+  let tableWidth = tableContent.value!.offsetWidth // 表格宽度
+  let residueClientWidth = tableWidth - fixedFields.length * tableFieldLWidth // 表格余下的可视宽度
+  let residueActualWidth = scrViewWidth - fixedFields.length * tableFieldLWidth // 表格余下的实际宽度
+
+  let scrOffsetLeft: number =
+    xScrollBaseOffset + fixedFields.length * tableFieldLWidth // 滑块box的偏移量
+  let scrBoxWidth: number = tableWidth - fixedFields.length * tableFieldLWidth // 滑块box的宽度
+  let xScrollWidth: number =
+    (residueClientWidth / residueActualWidth) * scrBoxWidth
+
+  xScrollBox.value!.style.left = `${scrOffsetLeft}px`
+  xScrollBox.value!.style.width = `${scrBoxWidth}px`
+  xScroll.value!.style.width = `${xScrollWidth}px`
+  console.log(scrOffsetLeft, scrBoxWidth, xScrollWidth)
+}
+
 initfilterForm()
 initFilterFields()
+
+onMounted(() => {
+  axiosInstance.get(AllApi.mockData).then(res => {
+    console.log(res)
+    tableData.splice(0, tableData.length, ...res.data)
+    initScroll()
+  })
+})
 </script>
 
 <template>
   <div class="tableContainer">
     <div class="filterContainer">
       <div class="filterContent">
-        <div class="filterFields">
-          <el-input
-            :readonly="true"
-            placeholder="筛选字段"
-            prefix-icon="Filter"
-            style="width: 112px"
-          >
-            <template #append>
+        <el-form
+          :model="filterFormData"
+          label-width="auto"
+          ref="filterFormRef"
+          :inline="true"
+        >
+          <!-- <div class="filterFields"> -->
+          <el-form-item>
+            <el-input
+              :readonly="true"
+              placeholder="筛选字段"
+              prefix-icon="Filter"
+              style="width: 200px; margin-bottom: 10px"
+            >
+              <template #append>
+                <el-select
+                  v-model="filterFields"
+                  multiple
+                  collapse-tags
+                  collapse-tags-tooltip
+                  placeholder="Select"
+                  style="width: 100px"
+                >
+                  <el-option
+                    v-for="item in filterFieldsStateList"
+                    :key="item.value"
+                    :label="item.label"
+                    :value="item.value"
+                  />
+                </el-select>
+              </template>
+            </el-input>
+          </el-form-item>
+          <!-- </div> -->
+          <template v-for="item in filtersInfo" :key="item.name">
+            <el-form-item :prop="item.name">
+              <el-input
+                class="filterItem"
+                v-if="
+                  filterFields.includes(item.name) &&
+                  item.type === TableFilterType.Search
+                "
+                v-model="filterFormData[item.name]"
+                style="width: 240px"
+                placeholder="Please Input"
+                :suffix-icon="Search"
+              />
+
               <el-select
-                v-model="filterFields"
-                multiple
-                collapse-tags
-                collapse-tags-tooltip
+                class="filterItem"
+                v-if="
+                  filterFields.includes(item.name) &&
+                  item.type === TableFilterType.Select
+                "
+                v-model="filterFormData[item.name]"
                 placeholder="Select"
-                style="width: 180px"
-                @change="changeFilterFields"
+                style="width: 240px"
               >
+                <template #label="{ label, value }">
+                  <span>{{ item.label }}: </span>
+                  <span style="margin-left: 10px">{{ value }}</span>
+                </template>
                 <el-option
-                  v-for="item in filterFieldsStateList"
-                  :key="item.value"
-                  :label="item.label"
-                  :value="item.value"
+                  v-for="option in item.options"
+                  :key="option.value"
+                  :label="option.label"
+                  :value="option.value"
                 />
               </el-select>
-            </template>
-          </el-input>
-        </div>
-
-        <template v-for="item in filtersInfo" :key="item.name">
-          <el-input
-            class="filterItem"
-            v-if="
-              filterFields.includes(item.name) &&
-              item.type === TableFilterType.Search
-            "
-            v-model="filterFormData[item.name].value"
-            style="width: 240px"
-            placeholder="Please Input"
-            :suffix-icon="Search"
-          />
-
+            </el-form-item>
+          </template>
+        </el-form>
+      </div>
+      <div class="filterButtonContainer">
+        <el-button class="queryBtn" color="#197afb" @click="queryTable"
+          >查询</el-button
+        >
+        <el-button
+          class="queryBtn"
+          color="#626aef"
+          plain
+          @click="resetFilterForm"
+          >重置</el-button
+        >
+      </div>
+    </div>
+    <div class="operationContainer">
+      <div class="tableOperationLeft">
+        <slot name="addItem">
+          <el-button class="addItem w120" plain :icon="Plus"
+            >添加账户</el-button
+          >
+        </slot>
+        <slot name="batchOper">
           <el-select
-            class="filterItem"
-            v-if="
-              filterFields.includes(item.name) &&
-              item.type === TableFilterType.Select
-            "
-            v-model="filterFormData[item.name].value"
-            placeholder="Select"
-            style="width: 240px"
+            class="batchOper w120"
+            v-model="batchOper"
+            placeholder="批量操作"
           >
-            <template #label="{ label, value }">
-              <span>{{ item.label }}: </span>
-              <span style="margin-left: 10px">{{ value }}</span>
-            </template>
             <el-option
-              v-for="option in item.options"
-              :key="option.value"
-              :label="option.label"
-              :value="option.value"
+              v-for="item in batchOperList"
+              :key="item.value"
+              :label="item.label"
+              :value="item.value"
             />
           </el-select>
-        </template>
+        </slot>
       </div>
-      <div class="filterButtonContainer">
-        <el-button class="queryBtn" color="#197afb">查询</el-button>
-        <el-button class="queryBtn" color="#626aef" plain>重置</el-button>
+      <div class="tableOperationRight">
+        <slot name="exportData">
+          <el-button class="exportData w120 ml16" plain>导出数据</el-button>
+        </slot>
+        <slot name="customIndicator">
+          <el-button class="customIndicator w120 ml16" plain :icon="Operation"
+            >自定义指标</el-button
+          >
+        </slot>
+      </div>
+    </div>
+    <div class="tableContent" ref="tableContent">
+      <!-- height="250" -->
+      <el-table
+        v-bind="{ ...$attrs, data: tableData }"
+        style="width: 100%"
+        border
+        :scrollbar-always-on="true"
+      >
+        <el-table-column
+          :width="fixedFields.includes(k) ? tableFieldLWidth : tableFieldSWidth"
+          v-for="k in accountFields"
+          :fixed="k === 'action'"
+          :prop="k"
+          :label="k"
+        />
+      </el-table>
+      <div class="xScrollBox" ref="xScrollBox">
+        <div class="xScroll" ref="xScroll"></div>
       </div>
     </div>
-    <div class="operationContainer"></div>
-    <div class="tableContent"></div>
   </div>
 </template>
 
 <style scoped>
+.w120 {
+  width: 120px;
+}
+
+.ml16 {
+  margin-left: 16px;
+}
+
 .tableContainer {
   width: 100%;
 }
@@ -166,25 +378,15 @@ initFilterFields()
 .filterContent {
   width: 90%;
   display: flex;
-  /* align-items: center; */
-  /* flex-direction: column; */
-  /* display: flex; */
-  /* justify-content: space-between; */
-  /* flex-wrap: wrap; */
 }
 
 .filterButtonContainer {
   width: 10%;
   height: 100%;
   display: flex;
-  /* flex-direction: column; */
-  align-items: center;
-  justify-content: center;
 }
 
 .queryBtn {
-  /* width: 50%; */
-  /* padding-bottom: 8px; */
   margin-right: 8px;
 }
 
@@ -194,6 +396,51 @@ initFilterFields()
 }
 
 .filterFields {
-  margin-right: 150px;
+  width: 112px;
+}
+
+.operationContainer {
+  position: -webkit-sticky;
+  position: sticky;
+  width: 100%;
+  padding: 10px 20px;
+  display: flex;
+  justify-content: space-between;
+  border: 1px solid #e8eaec;
+}
+
+.tableOperationLeft,
+.tableOperationRight {
+  display: flex;
+  align-items: center;
+  justify-content: flex-start;
+}
+.batchOper {
+  margin: 0 12px;
+}
+
+.tableContent {
+  width: 100%;
+  position: relative;
+  /* padding: 10px 20px; */
+}
+
+.xScrollBox {
+  width: 811px;
+  position: fixed;
+  top: unset;
+  bottom: 0px;
+  left: 626px;
+  right: unset;
+  display: block;
+}
+
+.xScroll {
+  width: 257.698px;
+  transform: translateX(0px);
+  box-sizing: border-box;
+  height: 10px;
+  background-color: #c1c1c1;
+  border-radius: 3px;
 }
 </style>

+ 15 - 0
src/directive/scrollbar.ts

@@ -0,0 +1,15 @@
+import type { Directive, DirectiveBinding } from 'vue'
+
+const scrollbar: Directive = {
+  mounted(el: HTMLElement, binding: DirectiveBinding) {
+    if (binding.value) {
+      const bar = el?.querySelector('.el-scrollbar__bar')
+      if (bar && el) {
+        bar?.classList?.add('v-scroll__el-scrollbar__bar')
+        el?.appendChild(bar)
+      }
+    }
+  },
+}
+
+export default scrollbar

+ 3 - 44
src/hooks/useRequest.ts

@@ -2,8 +2,8 @@
  * @Author: fxs bjnsfxs@163.com
  * @Date: 2024-08-20 17:24:06
  * @LastEditors: fxs bjnsfxs@163.com
- * @LastEditTime: 2024-10-10 12:08:47
- * @FilePath: \Game-Backstage-Management-System\src\hooks\useRequest.ts
+ * @LastEditTime: 2024-10-17 12:13:39
+ * @FilePath: \Quantity-Creation-Management-System\src\hooks\useRequest.ts
  * @Description:
  *
  */
@@ -26,48 +26,7 @@ export function useRequest() {
   }
 
   const AllApi = {
-    // mock: `http://127.0.0.1:8003/mock`,
-    mockEvent: `http://127.0.0.1:8003/mockEvent`,
-    mockTest: `http://127.0.0.1:8003/test`,
-
-    getGameTable: `/user/getGidConfig`, // 获取游戏列表
-    getUserTable: `/user/userList`, // 获取用户列表
-    addGame: `/user/addGidConfig`, // 添加/修改 游戏配置
-    userLogin: `/user/login`, // 登录
-    addOption: `/user/addUserOption`, // 添加/修改 权限
-    addUserToBlack: `/user/addUserToBlackList`, // 封禁用户
-    deleteUserToBlack: `/user/deleteUserToBlackList`, // 解封用户
-    getInterfaceInfo: `/user/getInterfaceInfo`, // 拿到所有接口的信息
-    getInterfaceDataByDay: `/user/getInterfaceDataByDay`, //获取接口的请求频次 (按天)
-    getRefreshToken: `/user/refreshToken`, // 刷新token
-    getOverViewData: `/user/overview`, // 总览数据
-
-    // 数据分析相关URL
-    timeDistributionData: `/user/timeDistributionData`, //用户概览 -时段分布
-    userSummary: `/user/summary`, //用户概览 -总览
-    userMouthDistributionData: `/user/mouthDistributionData`, //用户概览 -30日趋势
-    userTrendsOverview: `/user/userTrendsOverview`, //用户趋势 -总览
-    userDataTrades: `/user/dataTrades`, //用户趋势 -数据趋势
-    userDataTradesDetail: `/user/dataTradesDetail`, //用户趋势 -数据趋势详情
-    userRemainDataBydDay: `/user/remainDataBydDay`, //用户留存数据
-
-    // 事件相关
-    // 事件
-    gameActionList: `/user/gameActionList`, // 游戏事件列表
-    gameActionDetail: `/user/gameActionDetail`, // 事件详情
-    updateGameAction: `/user/updateGameAction`, // 更新游戏事件
-    setGameAction: `/user/setGameAction`, // 新增事件
-
-    // 事件参数
-    gameActionOptionList: `/user/gameActionOptionList`, // 获取事件参数列表
-    addGameActionOption: `/user/addGameActionOption`, // 新增事件参数
-    updateGameActionOption: `/user/updateGameActionOption`, // 更新事件参数
-    deleteGameActionOption: `/user/deleteGameActionOption`, // 删除事件参数
-
-    // 事件分析
-    userActionDetailDistribution: `/user/userActionDetailDistribution`, // 事件统计趋势图
-    userActionDetail: `/user/userActionDetail`, // 事件统计详情
-    userActionList: `/user/userActionList`, // 游戏事件统计列表
+    mockData: `http://127.0.0.1:8003/mock/ad/ttacc`,
   }
 
   /**

+ 1 - 1
src/main.ts

@@ -5,7 +5,7 @@ import App from './App.vue'
 import router from './router'
 
 import * as ElementPlusIconsVue from '@element-plus/icons-vue'
-import './assets/base.css'
+import '@/assets/base.css'
 
 const app = createApp(App)
 

+ 2 - 1
src/types/Tables/table.ts

@@ -13,9 +13,10 @@ interface SelectFilterOptions {
 // 筛选条件的基础信息
 interface BaseFilterItem {
   type: TableFilterType
+  label: string
   name: string
   value: any
-  placeholder: string
+  placeholder?: string
 }
 
 // 搜索框

+ 8 - 7
src/views/Index.vue

@@ -183,7 +183,7 @@ onMounted(() => {
 <style scoped>
 .body {
   width: 100%;
-  display: flex;
+
   height: 100vh;
 }
 
@@ -213,12 +213,13 @@ onMounted(() => {
 }
 
 .navBarBox {
-  position: fixed;
+  position: -webkit-sticky;
+  position: sticky;
   display: flex;
   align-items: center;
   width: 100vw;
   z-index: 2;
-  height: 7vh;
+  height: 64px;
   top: 0;
   background-color: white;
   right: 0;
@@ -292,11 +293,11 @@ onMounted(() => {
 .content {
   /* flex-grow: 1; */
   /* position: absolute; */
-
+  position: relative;
   width: 100%;
-  /* height: 93%; */
-  margin-top: 7vh;
-  overflow: scroll;
+  height: calc(100% - 64px);
+  overflow: auto;
+
   background-color: #f2f3f5;
 
   right: 0vw;

+ 4 - 0
src/views/Promotion/adManage/ttad.vue

@@ -146,6 +146,10 @@ const dateChange = (val: Array<Date>) => {
 
 .ttAdContent {
   width: 96%;
+  height: 100%;
+  background-color: white;
+  margin: 0 auto;
+  overflow: scroll;
 }
 
 .datePickerBox {

+ 7 - 4
src/views/Promotion/promotion.vue

@@ -96,7 +96,6 @@ const menu: Array<BaseMenu> = [
         :menu-list="menu"
         :default-active="defaultActive"
         :router="true"
-        :menu-style="'min-width: 180px'"
       ></Menu>
     </div>
     <div class="promotionContent">
@@ -108,11 +107,13 @@ const menu: Array<BaseMenu> = [
 <style scoped>
 .promotionContainer {
   width: 100%;
+  height: 100%;
   display: flex;
 }
 
 .promotionSiderBar {
-  width: 180px;
+  /* width: 180px; */
+  height: 100%;
   position: relative;
 }
 
@@ -128,8 +129,10 @@ const menu: Array<BaseMenu> = [
 }
 
 .promotionContent {
-  width: calc(100% - 180px);
-
+  width: 100%;
+  height: 100%;
+  /* height: calc(100% - 64px); */
+  overflow: scroll;
   /* padding: 20px; */
 }
 </style>