Procházet zdrojové kódy

feat(PromotionTable、DrawerBaseInfo): 素材总览表格新增预览功能;新增表格字段筛选功能;修复表格横向滚动条的BUG;

fxs před 8 měsíci
rodič
revize
f669519dcb
52 změnil soubory, kde provedl 816 přidání a 266 odebrání
  1. 3 0
      components.d.ts
  2. 3 1
      src/assets/defaultGame.svg
  3. 4 1
      src/assets/icon/file/folder-active.svg
  4. 4 1
      src/assets/icon/file/folder-default.svg
  5. 4 1
      src/assets/icon/file/project-active.svg
  6. 4 1
      src/assets/icon/file/project-default.svg
  7. 3 1
      src/assets/icon/header/defaultGame.svg
  8. 0 0
      src/assets/icon/logo/logo.svg
  9. 0 0
      src/assets/icon/promotion/acc-manage-active.svg
  10. 0 0
      src/assets/icon/promotion/acc-manage-default.svg
  11. 3 1
      src/assets/icon/promotion/ad-manage-active.svg
  12. 3 1
      src/assets/icon/promotion/ad-manage-default.svg
  13. 0 0
      src/assets/icon/promotion/ad-tencent.svg
  14. 3 1
      src/assets/icon/promotion/ad-tt.svg
  15. 0 0
      src/assets/logo.svg
  16. 1 2
      src/components/animationNumber/AnimationNumber.vue
  17. 2 10
      src/components/echarts/TimeLineChart.vue
  18. 6 6
      src/components/echarts/index.ts
  19. 16 11
      src/components/form/MyInput.vue
  20. 2 3
      src/components/navigation/Menu.vue
  21. 0 4
      src/components/promotion/MenuTable.vue
  22. 157 43
      src/components/table/PromotionTable.vue
  23. 17 11
      src/hooks/useCustomIndicatorDialog.ts
  24. 7 10
      src/hooks/useDate.ts
  25. 15 19
      src/hooks/useDialogDrag.ts
  26. 2 1
      src/hooks/useMenu.ts
  27. 41 18
      src/hooks/useMenuTable.ts
  28. 3 3
      src/hooks/useNumber.ts
  29. 2 2
      src/hooks/useTable.ts
  30. 33 9
      src/hooks/useTableScroll.ts
  31. 1 1
      src/main.ts
  32. 2 2
      src/router/home.ts
  33. 2 1
      src/router/login.ts
  34. 1 1
      src/router/material.ts
  35. 1 0
      src/types/Tables/MenuTable/menuTableReq.ts
  36. 1 0
      src/types/Tables/Operations/operations.ts
  37. 5 7
      src/types/Tables/table.ts
  38. 1 0
      src/types/Tables/tableData/tencentAcc.ts
  39. 1 0
      src/types/Tables/tableData/ttAcc.ts
  40. 5 4
      src/types/Tables/tablePageData.ts
  41. 3 3
      src/utils/axios/auth.ts
  42. 6 7
      src/utils/axios/axiosInstance.ts
  43. 8 9
      src/utils/localStorage/tableCustomIndicatorController.ts
  44. 4 4
      src/utils/token/token.ts
  45. 279 0
      src/views/Material/DrawerTagsView/DrawerBaseInfo.vue
  46. 130 50
      src/views/Material/FilmLibrary.vue
  47. 9 3
      src/views/Material/config/FimLibraryConfig.ts
  48. 3 3
      src/views/Promotion/accManage/accTencentAd.vue
  49. 3 3
      src/views/Promotion/accManage/accTtAd.vue
  50. 3 3
      src/views/Promotion/adManage/tencentAd.vue
  51. 3 3
      src/views/Promotion/adManage/ttad.vue
  52. 7 1
      tsconfig.json

+ 3 - 0
components.d.ts

@@ -21,6 +21,7 @@ declare module 'vue' {
     ElDatePicker: typeof import('element-plus/es')['ElDatePicker']
     ElDialog: typeof import('element-plus/es')['ElDialog']
     ElDivider: typeof import('element-plus/es')['ElDivider']
+    ElDrawer: typeof import('element-plus/es')['ElDrawer']
     ElForm: typeof import('element-plus/es')['ElForm']
     ElFormItem: typeof import('element-plus/es')['ElFormItem']
     ElIcon: typeof import('element-plus/es')['ElIcon']
@@ -40,6 +41,8 @@ declare module 'vue' {
     ElSubMenu: typeof import('element-plus/es')['ElSubMenu']
     ElTable: typeof import('element-plus/es')['ElTable']
     ElTableColumn: typeof import('element-plus/es')['ElTableColumn']
+    ElTabPane: typeof import('element-plus/es')['ElTabPane']
+    ElTabs: typeof import('element-plus/es')['ElTabs']
     ElTag: typeof import('element-plus/es')['ElTag']
     ElText: typeof import('element-plus/es')['ElText']
     ElUpload: typeof import('element-plus/es')['ElUpload']

+ 3 - 1
src/assets/defaultGame.svg

@@ -1 +1,3 @@
-<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1725591308908" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4433" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M704.32 974.4H321.81333333c-77.54666667 0-150.61333333-30.4-205.76-85.54666667S30.50666667 760.64 30.50666667 683.2v-0.42666667c0-77.54666667 30.4-150.61333333 85.54666666-205.76C171.2 421.86666667 244.26666667 391.46666667 321.81333333 391.46666667h382.61333334c77.54666667 0 150.61333333 30.4 205.76 85.54666666 55.14666667 55.14666667 85.54666667 128.21333333 85.54666666 205.76v0.42666667c0 77.54666667-30.4 150.61333333-85.54666666 205.76s-128.32 85.44-205.86666667 85.44zM321.81333333 466.24c-119.36 0-216.53333333 97.17333333-216.53333333 216.53333333v0.42666667c0 119.36 97.17333333 216.53333333 216.53333333 216.53333333h382.61333334c119.36 0 216.53333333-97.17333333 216.53333333-216.53333333v-0.42666667c0-119.36-97.17333333-216.53333333-216.53333333-216.53333333H321.81333333z" fill="#ac4cfd" p-id="4434"></path><path d="M263.89333333 655.68H412.8v57.38666667H263.89333333z" fill="#ac4cfd" p-id="4435"></path><path d="M311.11466667 756.24106667l0.35093333-148.90666667 57.38666667 0.1344-0.352 148.90666667zM682.77333333 764.69333333c-45.65333333 0-82.88-37.12-82.88-82.88s37.12-82.88 82.88-82.88 82.88 37.12 82.88 82.88-37.12 82.88-82.88 82.88z m0-117.65333333c-19.2 0-34.88 15.68-34.88 34.88s15.68 34.88 34.88 34.88 34.88-15.68 34.88-34.88-15.57333333-34.88-34.88-34.88zM545.70666667 463.78666667L488.53333333 432.74666667l100.05333334-184.42666667H385.81333333l-27.84-49.38666667 86.4-143.36 55.78666667 33.49333334-56.74666667 94.18666666h199.89333334l28.58666666 48z" fill="#ac4cfd" p-id="4436"></path></svg>
+<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg t="1725591308908" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4433"
+     width="200" height="200"><path d="M704.32 974.4H321.81333333c-77.54666667 0-150.61333333-30.4-205.76-85.54666667S30.50666667 760.64 30.50666667 683.2v-0.42666667c0-77.54666667 30.4-150.61333333 85.54666666-205.76C171.2 421.86666667 244.26666667 391.46666667 321.81333333 391.46666667h382.61333334c77.54666667 0 150.61333333 30.4 205.76 85.54666666 55.14666667 55.14666667 85.54666667 128.21333333 85.54666666 205.76v0.42666667c0 77.54666667-30.4 150.61333333-85.54666666 205.76s-128.32 85.44-205.86666667 85.44zM321.81333333 466.24c-119.36 0-216.53333333 97.17333333-216.53333333 216.53333333v0.42666667c0 119.36 97.17333333 216.53333333 216.53333333 216.53333333h382.61333334c119.36 0 216.53333333-97.17333333 216.53333333-216.53333333v-0.42666667c0-119.36-97.17333333-216.53333333-216.53333333-216.53333333H321.81333333z" fill="#ac4cfd" p-id="4434"></path><path d="M263.89333333 655.68H412.8v57.38666667H263.89333333z" fill="#ac4cfd" p-id="4435"></path><path d="M311.11466667 756.24106667l0.35093333-148.90666667 57.38666667 0.1344-0.352 148.90666667zM682.77333333 764.69333333c-45.65333333 0-82.88-37.12-82.88-82.88s37.12-82.88 82.88-82.88 82.88 37.12 82.88 82.88-37.12 82.88-82.88 82.88z m0-117.65333333c-19.2 0-34.88 15.68-34.88 34.88s15.68 34.88 34.88 34.88 34.88-15.68 34.88-34.88-15.57333333-34.88-34.88-34.88zM545.70666667 463.78666667L488.53333333 432.74666667l100.05333334-184.42666667H385.81333333l-27.84-49.38666667 86.4-143.36 55.78666667 33.49333334-56.74666667 94.18666666h199.89333334l28.58666666 48z" fill="#ac4cfd" p-id="4436"></path></svg>

+ 4 - 1
src/assets/icon/file/folder-active.svg

@@ -1 +1,4 @@
-<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1742787869354" class="icon" viewBox="0 0 1204 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="16052" xmlns:xlink="http://www.w3.org/1999/xlink" width="235.15625" height="200"><path d="M561.63235285 164.57352927h335.01838211c27.29779432 0 49.63235285 22.33455854 49.63235366 49.63235284v62.04044147c0 27.29779432-22.33455854 49.63235285-49.63235366 49.63235284H561.63235285c-27.29779432 0-49.63235285-22.33455854-49.63235285-49.63235284v-62.04044147c0-27.29779432 22.33455854-49.63235285 49.63235285-49.63235284z" fill="#AFFCFE" p-id="16053"></path><path d="M983.50735284 933.875H189.38970568c-54.59558862 0-99.26470568-44.66911789-99.26470568-99.26470568V189.38970568c0-54.59558862 44.66911789-99.26470568 99.26470568-99.26470568h285.38602928c68.24448496 18.61213211 54.59558862 53.35477927 99.2647065 99.26470568l31.02021992 49.63235286H983.50735284c54.59558862 0 99.26470568 44.66911789 99.26470569 99.2647065v496.32352928c0 54.59558862-44.66911789 99.26470568-99.26470569 99.26470568z" fill="#2F77F1" p-id="16054"></path></svg>
+<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg t="1742787869354" class="icon" viewBox="0 0 1204 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"
+     p-id="16052"
+     width="235.15625" height="200"><path d="M561.63235285 164.57352927h335.01838211c27.29779432 0 49.63235285 22.33455854 49.63235366 49.63235284v62.04044147c0 27.29779432-22.33455854 49.63235285-49.63235366 49.63235284H561.63235285c-27.29779432 0-49.63235285-22.33455854-49.63235285-49.63235284v-62.04044147c0-27.29779432 22.33455854-49.63235285 49.63235285-49.63235284z" fill="#AFFCFE" p-id="16053"></path><path d="M983.50735284 933.875H189.38970568c-54.59558862 0-99.26470568-44.66911789-99.26470568-99.26470568V189.38970568c0-54.59558862 44.66911789-99.26470568 99.26470568-99.26470568h285.38602928c68.24448496 18.61213211 54.59558862 53.35477927 99.2647065 99.26470568l31.02021992 49.63235286H983.50735284c54.59558862 0 99.26470568 44.66911789 99.26470569 99.2647065v496.32352928c0 54.59558862-44.66911789 99.26470568-99.26470569 99.26470568z" fill="#2F77F1" p-id="16054"></path></svg>

+ 4 - 1
src/assets/icon/file/folder-default.svg

@@ -1 +1,4 @@
-<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1742787843454" class="icon" viewBox="0 0 1204 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="15793" xmlns:xlink="http://www.w3.org/1999/xlink" width="235.15625" height="200"><path d="M561.63235285 164.57352927h335.01838211c27.29779432 0 49.63235285 22.33455854 49.63235366 49.63235284v62.04044147c0 27.29779432-22.33455854 49.63235285-49.63235366 49.63235284H561.63235285c-27.29779432 0-49.63235285-22.33455854-49.63235285-49.63235284v-62.04044147c0-27.29779432 22.33455854-49.63235285 49.63235285-49.63235284z" fill="#8a8a8a" p-id="15794"></path><path d="M983.50735284 933.875H189.38970568c-54.59558862 0-99.26470568-44.66911789-99.26470568-99.26470568V189.38970568c0-54.59558862 44.66911789-99.26470568 99.26470568-99.26470568h285.38602928c68.24448496 18.61213211 54.59558862 53.35477927 99.2647065 99.26470568l31.02021992 49.63235286H983.50735284c54.59558862 0 99.26470568 44.66911789 99.26470569 99.2647065v496.32352928c0 54.59558862-44.66911789 99.26470568-99.26470569 99.26470568z" fill="#8a8a8a" p-id="15795"></path></svg>
+<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg t="1742787843454" class="icon" viewBox="0 0 1204 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"
+     p-id="15793"
+     width="235.15625" height="200"><path d="M561.63235285 164.57352927h335.01838211c27.29779432 0 49.63235285 22.33455854 49.63235366 49.63235284v62.04044147c0 27.29779432-22.33455854 49.63235285-49.63235366 49.63235284H561.63235285c-27.29779432 0-49.63235285-22.33455854-49.63235285-49.63235284v-62.04044147c0-27.29779432 22.33455854-49.63235285 49.63235285-49.63235284z" fill="#8a8a8a" p-id="15794"></path><path d="M983.50735284 933.875H189.38970568c-54.59558862 0-99.26470568-44.66911789-99.26470568-99.26470568V189.38970568c0-54.59558862 44.66911789-99.26470568 99.26470568-99.26470568h285.38602928c68.24448496 18.61213211 54.59558862 53.35477927 99.2647065 99.26470568l31.02021992 49.63235286H983.50735284c54.59558862 0 99.26470568 44.66911789 99.26470569 99.2647065v496.32352928c0 54.59558862-44.66911789 99.26470568-99.26470569 99.26470568z" fill="#8a8a8a" p-id="15795"></path></svg>

+ 4 - 1
src/assets/icon/file/project-active.svg

@@ -1 +1,4 @@
-<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1742785436544" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="12527" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M505.6 477.952c-12.288 0-24.32-2.304-35.84-7.168L67.328 305.92c-11.264-4.608-18.944-15.616-18.944-27.904s6.912-23.552 17.92-28.672l400.128-183.296c26.368-12.032 56.32-12.032 82.688-0.256l398.08 179.2c11.264 5.12 18.176 16.128 18.176 28.416s-7.68 23.296-18.944 27.904l-404.224 169.216c-11.776 4.864-24.064 7.424-36.608 7.424z" fill="#5396FF" p-id="12528"></path><path d="M490.496 523.264c0.256 0.256 0.512 0.256 1.024 0.512 8.96 4.608 19.712 4.608 28.672 0 0.256-0.256 0.512-0.256 1.024-0.512l181.248-72.96 65.536-28.672 73.728-30.976 112.384 65.536c9.984 5.632 15.872 16.384 15.36 27.904-0.512 11.52-7.168 21.504-17.664 26.624L547.84 701.44c-13.056 6.656-27.648 9.984-41.984 9.984-14.336 0-28.672-3.328-41.728-9.728L64.256 514.56c-10.496-4.864-17.152-15.104-17.664-26.624s5.632-22.272 15.616-27.904l113.92-64 78.08 32.512" fill="#5396FF" p-id="12529"></path><path d="M489.984 768.768c11.264 5.632 24.576 5.632 35.584 0l146.944-75.008 77.056-39.68 65.024-33.024h0.256l140.8 80.64c11.264 6.4 17.408 19.456 14.848 32.768-1.792 9.472-8.448 17.408-16.896 21.76l-399.872 205.568c-14.336 7.424-30.208 11.008-46.08 11.008-15.616 0-31.488-3.584-45.568-11.008l-396.8-202.24c-9.984-5.12-16.384-15.36-16.64-26.624-0.256-11.264 5.632-21.76 15.616-27.392l133.888-76.288h0.256l70.144 32.512" fill="#5396FF" p-id="12530"></path></svg>
+<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg t="1742785436544" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"
+     p-id="12527"
+     width="200" height="200"><path d="M505.6 477.952c-12.288 0-24.32-2.304-35.84-7.168L67.328 305.92c-11.264-4.608-18.944-15.616-18.944-27.904s6.912-23.552 17.92-28.672l400.128-183.296c26.368-12.032 56.32-12.032 82.688-0.256l398.08 179.2c11.264 5.12 18.176 16.128 18.176 28.416s-7.68 23.296-18.944 27.904l-404.224 169.216c-11.776 4.864-24.064 7.424-36.608 7.424z" fill="#5396FF" p-id="12528"></path><path d="M490.496 523.264c0.256 0.256 0.512 0.256 1.024 0.512 8.96 4.608 19.712 4.608 28.672 0 0.256-0.256 0.512-0.256 1.024-0.512l181.248-72.96 65.536-28.672 73.728-30.976 112.384 65.536c9.984 5.632 15.872 16.384 15.36 27.904-0.512 11.52-7.168 21.504-17.664 26.624L547.84 701.44c-13.056 6.656-27.648 9.984-41.984 9.984-14.336 0-28.672-3.328-41.728-9.728L64.256 514.56c-10.496-4.864-17.152-15.104-17.664-26.624s5.632-22.272 15.616-27.904l113.92-64 78.08 32.512" fill="#5396FF" p-id="12529"></path><path d="M489.984 768.768c11.264 5.632 24.576 5.632 35.584 0l146.944-75.008 77.056-39.68 65.024-33.024h0.256l140.8 80.64c11.264 6.4 17.408 19.456 14.848 32.768-1.792 9.472-8.448 17.408-16.896 21.76l-399.872 205.568c-14.336 7.424-30.208 11.008-46.08 11.008-15.616 0-31.488-3.584-45.568-11.008l-396.8-202.24c-9.984-5.12-16.384-15.36-16.64-26.624-0.256-11.264 5.632-21.76 15.616-27.392l133.888-76.288h0.256l70.144 32.512" fill="#5396FF" p-id="12530"></path></svg>

+ 4 - 1
src/assets/icon/file/project-default.svg

@@ -1 +1,4 @@
-<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1742785436544" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="12527" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M505.6 477.952c-12.288 0-24.32-2.304-35.84-7.168L67.328 305.92c-11.264-4.608-18.944-15.616-18.944-27.904s6.912-23.552 17.92-28.672l400.128-183.296c26.368-12.032 56.32-12.032 82.688-0.256l398.08 179.2c11.264 5.12 18.176 16.128 18.176 28.416s-7.68 23.296-18.944 27.904l-404.224 169.216c-11.776 4.864-24.064 7.424-36.608 7.424z" fill="#8a8a8a" p-id="12528"></path><path d="M490.496 523.264c0.256 0.256 0.512 0.256 1.024 0.512 8.96 4.608 19.712 4.608 28.672 0 0.256-0.256 0.512-0.256 1.024-0.512l181.248-72.96 65.536-28.672 73.728-30.976 112.384 65.536c9.984 5.632 15.872 16.384 15.36 27.904-0.512 11.52-7.168 21.504-17.664 26.624L547.84 701.44c-13.056 6.656-27.648 9.984-41.984 9.984-14.336 0-28.672-3.328-41.728-9.728L64.256 514.56c-10.496-4.864-17.152-15.104-17.664-26.624s5.632-22.272 15.616-27.904l113.92-64 78.08 32.512" fill="#8a8a8a" p-id="12529"></path><path d="M489.984 768.768c11.264 5.632 24.576 5.632 35.584 0l146.944-75.008 77.056-39.68 65.024-33.024h0.256l140.8 80.64c11.264 6.4 17.408 19.456 14.848 32.768-1.792 9.472-8.448 17.408-16.896 21.76l-399.872 205.568c-14.336 7.424-30.208 11.008-46.08 11.008-15.616 0-31.488-3.584-45.568-11.008l-396.8-202.24c-9.984-5.12-16.384-15.36-16.64-26.624-0.256-11.264 5.632-21.76 15.616-27.392l133.888-76.288h0.256l70.144 32.512" fill="#8a8a8a" p-id="12530"></path></svg>
+<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg t="1742785436544" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"
+     p-id="12527"
+     width="200" height="200"><path d="M505.6 477.952c-12.288 0-24.32-2.304-35.84-7.168L67.328 305.92c-11.264-4.608-18.944-15.616-18.944-27.904s6.912-23.552 17.92-28.672l400.128-183.296c26.368-12.032 56.32-12.032 82.688-0.256l398.08 179.2c11.264 5.12 18.176 16.128 18.176 28.416s-7.68 23.296-18.944 27.904l-404.224 169.216c-11.776 4.864-24.064 7.424-36.608 7.424z" fill="#8a8a8a" p-id="12528"></path><path d="M490.496 523.264c0.256 0.256 0.512 0.256 1.024 0.512 8.96 4.608 19.712 4.608 28.672 0 0.256-0.256 0.512-0.256 1.024-0.512l181.248-72.96 65.536-28.672 73.728-30.976 112.384 65.536c9.984 5.632 15.872 16.384 15.36 27.904-0.512 11.52-7.168 21.504-17.664 26.624L547.84 701.44c-13.056 6.656-27.648 9.984-41.984 9.984-14.336 0-28.672-3.328-41.728-9.728L64.256 514.56c-10.496-4.864-17.152-15.104-17.664-26.624s5.632-22.272 15.616-27.904l113.92-64 78.08 32.512" fill="#8a8a8a" p-id="12529"></path><path d="M489.984 768.768c11.264 5.632 24.576 5.632 35.584 0l146.944-75.008 77.056-39.68 65.024-33.024h0.256l140.8 80.64c11.264 6.4 17.408 19.456 14.848 32.768-1.792 9.472-8.448 17.408-16.896 21.76l-399.872 205.568c-14.336 7.424-30.208 11.008-46.08 11.008-15.616 0-31.488-3.584-45.568-11.008l-396.8-202.24c-9.984-5.12-16.384-15.36-16.64-26.624-0.256-11.264 5.632-21.76 15.616-27.392l133.888-76.288h0.256l70.144 32.512" fill="#8a8a8a" p-id="12530"></path></svg>

+ 3 - 1
src/assets/icon/header/defaultGame.svg

@@ -1 +1,3 @@
-<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1725591308908" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4433" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M704.32 974.4H321.81333333c-77.54666667 0-150.61333333-30.4-205.76-85.54666667S30.50666667 760.64 30.50666667 683.2v-0.42666667c0-77.54666667 30.4-150.61333333 85.54666666-205.76C171.2 421.86666667 244.26666667 391.46666667 321.81333333 391.46666667h382.61333334c77.54666667 0 150.61333333 30.4 205.76 85.54666666 55.14666667 55.14666667 85.54666667 128.21333333 85.54666666 205.76v0.42666667c0 77.54666667-30.4 150.61333333-85.54666666 205.76s-128.32 85.44-205.86666667 85.44zM321.81333333 466.24c-119.36 0-216.53333333 97.17333333-216.53333333 216.53333333v0.42666667c0 119.36 97.17333333 216.53333333 216.53333333 216.53333333h382.61333334c119.36 0 216.53333333-97.17333333 216.53333333-216.53333333v-0.42666667c0-119.36-97.17333333-216.53333333-216.53333333-216.53333333H321.81333333z" fill="#ac4cfd" p-id="4434"></path><path d="M263.89333333 655.68H412.8v57.38666667H263.89333333z" fill="#ac4cfd" p-id="4435"></path><path d="M311.11466667 756.24106667l0.35093333-148.90666667 57.38666667 0.1344-0.352 148.90666667zM682.77333333 764.69333333c-45.65333333 0-82.88-37.12-82.88-82.88s37.12-82.88 82.88-82.88 82.88 37.12 82.88 82.88-37.12 82.88-82.88 82.88z m0-117.65333333c-19.2 0-34.88 15.68-34.88 34.88s15.68 34.88 34.88 34.88 34.88-15.68 34.88-34.88-15.57333333-34.88-34.88-34.88zM545.70666667 463.78666667L488.53333333 432.74666667l100.05333334-184.42666667H385.81333333l-27.84-49.38666667 86.4-143.36 55.78666667 33.49333334-56.74666667 94.18666666h199.89333334l28.58666666 48z" fill="#ac4cfd" p-id="4436"></path></svg>
+<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg t="1725591308908" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4433"
+     width="200" height="200"><path d="M704.32 974.4H321.81333333c-77.54666667 0-150.61333333-30.4-205.76-85.54666667S30.50666667 760.64 30.50666667 683.2v-0.42666667c0-77.54666667 30.4-150.61333333 85.54666666-205.76C171.2 421.86666667 244.26666667 391.46666667 321.81333333 391.46666667h382.61333334c77.54666667 0 150.61333333 30.4 205.76 85.54666666 55.14666667 55.14666667 85.54666667 128.21333333 85.54666666 205.76v0.42666667c0 77.54666667-30.4 150.61333333-85.54666666 205.76s-128.32 85.44-205.86666667 85.44zM321.81333333 466.24c-119.36 0-216.53333333 97.17333333-216.53333333 216.53333333v0.42666667c0 119.36 97.17333333 216.53333333 216.53333333 216.53333333h382.61333334c119.36 0 216.53333333-97.17333333 216.53333333-216.53333333v-0.42666667c0-119.36-97.17333333-216.53333333-216.53333333-216.53333333H321.81333333z" fill="#ac4cfd" p-id="4434"></path><path d="M263.89333333 655.68H412.8v57.38666667H263.89333333z" fill="#ac4cfd" p-id="4435"></path><path d="M311.11466667 756.24106667l0.35093333-148.90666667 57.38666667 0.1344-0.352 148.90666667zM682.77333333 764.69333333c-45.65333333 0-82.88-37.12-82.88-82.88s37.12-82.88 82.88-82.88 82.88 37.12 82.88 82.88-37.12 82.88-82.88 82.88z m0-117.65333333c-19.2 0-34.88 15.68-34.88 34.88s15.68 34.88 34.88 34.88 34.88-15.68 34.88-34.88-15.57333333-34.88-34.88-34.88zM545.70666667 463.78666667L488.53333333 432.74666667l100.05333334-184.42666667H385.81333333l-27.84-49.38666667 86.4-143.36 55.78666667 33.49333334-56.74666667 94.18666666h199.89333334l28.58666666 48z" fill="#ac4cfd" p-id="4436"></path></svg>

Rozdílová data souboru nebyla zobrazena, protože soubor je příliš velký
+ 0 - 0
src/assets/icon/logo/logo.svg


Rozdílová data souboru nebyla zobrazena, protože soubor je příliš velký
+ 0 - 0
src/assets/icon/promotion/acc-manage-active.svg


Rozdílová data souboru nebyla zobrazena, protože soubor je příliš velký
+ 0 - 0
src/assets/icon/promotion/acc-manage-default.svg


+ 3 - 1
src/assets/icon/promotion/ad-manage-active.svg

@@ -1 +1,3 @@
-<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1729041716770" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="6002" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M854.528 34.816H172.032c-79.36 0-143.36 64.512-143.36 143.872v441.344c0 22.016 17.92 39.424 39.424 39.424h752.64c22.016 0 39.424-17.92 39.424-39.424 0-22.016-17.92-39.424-39.424-39.424H107.52V178.688c0-35.328 28.672-64.512 64.512-64.512h682.496c35.328 0 64.512 28.672 64.512 64.512v345.6c0 22.016 17.92 39.424 39.424 39.424s39.424-17.92 39.424-39.424V178.688c0.512-79.36-64-143.872-143.36-143.872zM958.976 747.008h-890.88c-22.016 0-39.424 17.92-39.424 39.424s17.92 39.424 39.424 39.424h407.04c-1.024 3.072-1.536 6.656-1.536 9.728v138.752c0 22.016 17.92 39.424 39.424 39.424s39.424-17.92 39.424-39.424v-138.752c0-3.584-0.512-6.656-1.536-9.728h407.04c22.016 0 39.424-17.92 39.424-39.424s-16.896-39.424-38.4-39.424z" fill="#197afb" p-id="6003"></path><path d="M406.016 207.36c-18.944 1.024-32.768 11.776-40.96 31.744L286.72 449.536v3.072c-1.024 4.096-1.536 7.68-1.536 10.752 1.024 16.384 10.24 24.064 27.136 24.064 14.336 0 23.552-6.144 28.672-17.92l12.288-36.352h107.52l10.752 36.352c5.12 12.288 14.848 17.92 28.672 17.92 17.408 0 26.112-7.68 27.136-22.528 0-4.096-1.024-9.216-3.072-15.36L448.512 239.104c-9.216-21.504-23.04-31.744-42.496-31.744z m-36.352 172.544l36.352-112.128 36.352 112.128H369.664zM574.464 211.968c-17.92 1.024-27.648 10.752-28.672 28.672v218.112c1.024 17.92 11.264 27.648 30.208 28.672h66.56c84.992-4.096 129.024-49.152 133.12-134.656-3.072-90.624-48.64-137.728-136.192-140.8h-65.024z m140.8 139.264c-2.048 53.248-26.112 81.408-72.704 83.456h-39.424V264.704h34.816c50.176 1.024 76.288 29.696 77.312 86.528z" fill="#197afb" p-id="6004"></path></svg>
+<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg t="1729041716770" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="6002"
+     width="200" height="200"><path d="M854.528 34.816H172.032c-79.36 0-143.36 64.512-143.36 143.872v441.344c0 22.016 17.92 39.424 39.424 39.424h752.64c22.016 0 39.424-17.92 39.424-39.424 0-22.016-17.92-39.424-39.424-39.424H107.52V178.688c0-35.328 28.672-64.512 64.512-64.512h682.496c35.328 0 64.512 28.672 64.512 64.512v345.6c0 22.016 17.92 39.424 39.424 39.424s39.424-17.92 39.424-39.424V178.688c0.512-79.36-64-143.872-143.36-143.872zM958.976 747.008h-890.88c-22.016 0-39.424 17.92-39.424 39.424s17.92 39.424 39.424 39.424h407.04c-1.024 3.072-1.536 6.656-1.536 9.728v138.752c0 22.016 17.92 39.424 39.424 39.424s39.424-17.92 39.424-39.424v-138.752c0-3.584-0.512-6.656-1.536-9.728h407.04c22.016 0 39.424-17.92 39.424-39.424s-16.896-39.424-38.4-39.424z" fill="#197afb" p-id="6003"></path><path d="M406.016 207.36c-18.944 1.024-32.768 11.776-40.96 31.744L286.72 449.536v3.072c-1.024 4.096-1.536 7.68-1.536 10.752 1.024 16.384 10.24 24.064 27.136 24.064 14.336 0 23.552-6.144 28.672-17.92l12.288-36.352h107.52l10.752 36.352c5.12 12.288 14.848 17.92 28.672 17.92 17.408 0 26.112-7.68 27.136-22.528 0-4.096-1.024-9.216-3.072-15.36L448.512 239.104c-9.216-21.504-23.04-31.744-42.496-31.744z m-36.352 172.544l36.352-112.128 36.352 112.128H369.664zM574.464 211.968c-17.92 1.024-27.648 10.752-28.672 28.672v218.112c1.024 17.92 11.264 27.648 30.208 28.672h66.56c84.992-4.096 129.024-49.152 133.12-134.656-3.072-90.624-48.64-137.728-136.192-140.8h-65.024z m140.8 139.264c-2.048 53.248-26.112 81.408-72.704 83.456h-39.424V264.704h34.816c50.176 1.024 76.288 29.696 77.312 86.528z" fill="#197afb" p-id="6004"></path></svg>

+ 3 - 1
src/assets/icon/promotion/ad-manage-default.svg

@@ -1 +1,3 @@
-<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1729041826578" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="859" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M854.528 34.816H172.032c-79.36 0-143.36 64.512-143.36 143.872v441.344c0 22.016 17.92 39.424 39.424 39.424h752.64c22.016 0 39.424-17.92 39.424-39.424 0-22.016-17.92-39.424-39.424-39.424H107.52V178.688c0-35.328 28.672-64.512 64.512-64.512h682.496c35.328 0 64.512 28.672 64.512 64.512v345.6c0 22.016 17.92 39.424 39.424 39.424s39.424-17.92 39.424-39.424V178.688c0.512-79.36-64-143.872-143.36-143.872zM958.976 747.008h-890.88c-22.016 0-39.424 17.92-39.424 39.424s17.92 39.424 39.424 39.424h407.04c-1.024 3.072-1.536 6.656-1.536 9.728v138.752c0 22.016 17.92 39.424 39.424 39.424s39.424-17.92 39.424-39.424v-138.752c0-3.584-0.512-6.656-1.536-9.728h407.04c22.016 0 39.424-17.92 39.424-39.424s-16.896-39.424-38.4-39.424z" fill="#333333" p-id="860"></path><path d="M406.016 207.36c-18.944 1.024-32.768 11.776-40.96 31.744L286.72 449.536v3.072c-1.024 4.096-1.536 7.68-1.536 10.752 1.024 16.384 10.24 24.064 27.136 24.064 14.336 0 23.552-6.144 28.672-17.92l12.288-36.352h107.52l10.752 36.352c5.12 12.288 14.848 17.92 28.672 17.92 17.408 0 26.112-7.68 27.136-22.528 0-4.096-1.024-9.216-3.072-15.36L448.512 239.104c-9.216-21.504-23.04-31.744-42.496-31.744z m-36.352 172.544l36.352-112.128 36.352 112.128H369.664zM574.464 211.968c-17.92 1.024-27.648 10.752-28.672 28.672v218.112c1.024 17.92 11.264 27.648 30.208 28.672h66.56c84.992-4.096 129.024-49.152 133.12-134.656-3.072-90.624-48.64-137.728-136.192-140.8h-65.024z m140.8 139.264c-2.048 53.248-26.112 81.408-72.704 83.456h-39.424V264.704h34.816c50.176 1.024 76.288 29.696 77.312 86.528z" fill="#333333" p-id="861"></path></svg>
+<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg t="1729041826578" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="859"
+     width="200" height="200"><path d="M854.528 34.816H172.032c-79.36 0-143.36 64.512-143.36 143.872v441.344c0 22.016 17.92 39.424 39.424 39.424h752.64c22.016 0 39.424-17.92 39.424-39.424 0-22.016-17.92-39.424-39.424-39.424H107.52V178.688c0-35.328 28.672-64.512 64.512-64.512h682.496c35.328 0 64.512 28.672 64.512 64.512v345.6c0 22.016 17.92 39.424 39.424 39.424s39.424-17.92 39.424-39.424V178.688c0.512-79.36-64-143.872-143.36-143.872zM958.976 747.008h-890.88c-22.016 0-39.424 17.92-39.424 39.424s17.92 39.424 39.424 39.424h407.04c-1.024 3.072-1.536 6.656-1.536 9.728v138.752c0 22.016 17.92 39.424 39.424 39.424s39.424-17.92 39.424-39.424v-138.752c0-3.584-0.512-6.656-1.536-9.728h407.04c22.016 0 39.424-17.92 39.424-39.424s-16.896-39.424-38.4-39.424z" fill="#333333" p-id="860"></path><path d="M406.016 207.36c-18.944 1.024-32.768 11.776-40.96 31.744L286.72 449.536v3.072c-1.024 4.096-1.536 7.68-1.536 10.752 1.024 16.384 10.24 24.064 27.136 24.064 14.336 0 23.552-6.144 28.672-17.92l12.288-36.352h107.52l10.752 36.352c5.12 12.288 14.848 17.92 28.672 17.92 17.408 0 26.112-7.68 27.136-22.528 0-4.096-1.024-9.216-3.072-15.36L448.512 239.104c-9.216-21.504-23.04-31.744-42.496-31.744z m-36.352 172.544l36.352-112.128 36.352 112.128H369.664zM574.464 211.968c-17.92 1.024-27.648 10.752-28.672 28.672v218.112c1.024 17.92 11.264 27.648 30.208 28.672h66.56c84.992-4.096 129.024-49.152 133.12-134.656-3.072-90.624-48.64-137.728-136.192-140.8h-65.024z m140.8 139.264c-2.048 53.248-26.112 81.408-72.704 83.456h-39.424V264.704h34.816c50.176 1.024 76.288 29.696 77.312 86.528z" fill="#333333" p-id="861"></path></svg>

Rozdílová data souboru nebyla zobrazena, protože soubor je příliš velký
+ 0 - 0
src/assets/icon/promotion/ad-tencent.svg


+ 3 - 1
src/assets/icon/promotion/ad-tt.svg

@@ -1 +1,3 @@
-<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1729042167533" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2214" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M751.84 328.88L611.472 83.04l-166.2 41.144 188.536 322.152z" fill="#01C6D2" p-id="2215"></path><path d="M195.024 212.424l-48.48 158.272h369.88l-47.824-158.272z" fill="#76E4D9" p-id="2216"></path><path d="M231.584 397.92L96 636.48 205.248 754.48l184.208-319.096z" fill="#3468D4" p-id="2217"></path><path d="M385.184 576.192L273.16 695.888l136.896 238.896 160.296-37.856z" fill="#3058B0" p-id="2218"></path><path d="M505.288 651.128l45.712 157.816h275.848l48.12-157.816z" fill="#3568D5" p-id="2219"></path><path d="M814.544 263.76l-183.52 321.968L786.96 623.76 928 385.496z" fill="#3C8BFF" p-id="2220"></path></svg>
+<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg t="1729042167533" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2214"
+     width="200" height="200"><path d="M751.84 328.88L611.472 83.04l-166.2 41.144 188.536 322.152z" fill="#01C6D2" p-id="2215"></path><path d="M195.024 212.424l-48.48 158.272h369.88l-47.824-158.272z" fill="#76E4D9" p-id="2216"></path><path d="M231.584 397.92L96 636.48 205.248 754.48l184.208-319.096z" fill="#3468D4" p-id="2217"></path><path d="M385.184 576.192L273.16 695.888l136.896 238.896 160.296-37.856z" fill="#3058B0" p-id="2218"></path><path d="M505.288 651.128l45.712 157.816h275.848l48.12-157.816z" fill="#3568D5" p-id="2219"></path><path d="M814.544 263.76l-183.52 321.968L786.96 623.76 928 385.496z" fill="#3C8BFF" p-id="2220"></path></svg>

Rozdílová data souboru nebyla zobrazena, protože soubor je příliš velký
+ 0 - 0
src/assets/logo.svg


+ 1 - 2
src/components/animationNumber/AnimationNumber.vue

@@ -44,8 +44,7 @@ const formatNumber = computed(() => {
 
 /**
  * @description: 更新数字
- * @param {*} nowNumber 当前数字
- * @return {*}
+ * @param newVal 当前数字
  */
 const updateNumber = (newVal: number) => {
   nowNumber.value = backupNumber.value

+ 2 - 10
src/components/echarts/TimeLineChart.vue

@@ -1,8 +1,7 @@
 <script setup lang="ts">
 import type { OptionsProps } from '@/types/echarts/timeLineChart'
 
-import { onMounted, ref, shallowRef, watch, useAttrs } from 'vue'
-import { nextTick } from 'vue'
+import { nextTick, onMounted, ref, shallowRef, useAttrs, watch } from 'vue'
 import { debounceFunc } from '@/utils/common'
 
 import echarts from '.'
@@ -203,11 +202,4 @@ onMounted(() => {
   <div class="chart" ref="chart" style="width: 100%; height: 365px"></div>
 </template>
 
-<style scoped>
-.t {
-  color: red;
-  display: inline-block;
-  box-sizing: border-box;
-  padding-right: 20px;
-}
-</style>
+<style scoped></style>

+ 6 - 6
src/components/echarts/index.ts

@@ -2,17 +2,17 @@
 import * as echarts from 'echarts/core'
 
 // 引入柱状图和饼状图图表,图表后缀都为 Chart,具体为 图标名称+Chart (注意图标名称为首字母大写)
-import { BarChart, PieChart, LineChart } from 'echarts/charts'
+import { BarChart, LineChart, PieChart } from 'echarts/charts'
 
 // 引入提示框,标题,直角坐标系,数据集,内置数据转换器组件,组件后缀都为 Component
 import {
-  TitleComponent,
-  TooltipComponent,
+  DatasetComponent,
   GridComponent,
-  ToolboxComponent,
   LegendComponent,
-  DatasetComponent,
-  TransformComponent
+  TitleComponent,
+  ToolboxComponent,
+  TooltipComponent,
+  TransformComponent,
 } from 'echarts/components'
 // 标签自动布局,全局过渡动画等特性
 import { LabelLayout, UniversalTransition } from 'echarts/features'

+ 16 - 11
src/components/form/MyInput.vue

@@ -4,8 +4,8 @@
  * @LastEditors: fxs bjnsfxs@163.com
  * @LastEditTime: 2024-10-14 17:04:09
  * @FilePath: \Game-Backstage-Management-System\src\components\form\MyInput.vue
- * @Description: 
- * 
+ * @Description:
+ *
 -->
 <script setup lang="ts">
 import type { RuleInfo } from '@/types/input'
@@ -51,13 +51,12 @@ const changeVisible = () => {
 
 /**
  * @description: 验证input框是否符合规则
- * @param {*} let
- * @return {*}
+ * @return
  */
 const verifyIpt = () => {
   let rulesInfo = props.pinputRules
   if (rulesInfo) {
-    let vaild = rulesInfo.rules.every((item) => {
+    let vaild = rulesInfo.rules.every(item => {
       errorMsg.value = item.errMsg
 
       return item.validator()
@@ -70,8 +69,7 @@ const verifyIpt = () => {
 
 /**
  * @description: 同步input框数据
- * @param {*} val
- * @return {*}
+ * @param  val 输入框的值
  */
 const updateValue = (val: any) => {
   emits('update:modelValue', val.target.value)
@@ -79,7 +77,7 @@ const updateValue = (val: any) => {
 
 onMounted(() => {
   // 点击输入框则聚焦,并给边框
-  document.addEventListener('click', (e) => {
+  document.addEventListener('click', e => {
     // 如果点击的地方不在 div 内部,则移除 active-class
     if (inputDivRef.value && !inputDivRef.value.contains(e.target)) {
       activeClass.value = false
@@ -98,7 +96,11 @@ onMounted(() => {
 
 <template>
   <div class="body">
-    <div class="inputBox" ref="inputDivRef" :class="{ activeInput: activeClass }">
+    <div
+      class="inputBox"
+      ref="inputDivRef"
+      :class="{ activeInput: activeClass }"
+    >
       <div class="inputIconBox">
         <div class="icon">
           <el-icon class="iconItem">
@@ -116,7 +118,11 @@ onMounted(() => {
           />
         </div>
 
-        <div class="inputVisble" v-if="props.pInputType === 'password'" @click="changeVisible">
+        <div
+          class="inputVisble"
+          v-if="props.pInputType === 'password'"
+          @click="changeVisible"
+        >
           <el-icon v-if="passwordVisiable" class="iconItem">
             <icon-ic-baseline-visibility></icon-ic-baseline-visibility>
           </el-icon>
@@ -144,7 +150,6 @@ onMounted(() => {
   cursor: text;
   border: 1px solid transparent;
   display: flex;
-  align-items: center;
   box-sizing: border-box;
   transition: background-color 0.2s;
 }

+ 2 - 3
src/components/navigation/Menu.vue

@@ -1,9 +1,8 @@
 <script setup lang="ts">
 import type { BaseMenu } from '@/types/Promotion/Menu'
 
-import { computed, nextTick, ref, watch } from 'vue'
+import { computed, nextTick, ref, useAttrs, watch } from 'vue'
 import { useRoute } from 'vue-router'
-import { useAttrs } from 'vue'
 
 // import CIcon from '../cIcon/CIcon.vue'
 
@@ -202,7 +201,7 @@ const routerDefaultActive = computed(() => {
 
   .sideBarFold {
     position: relative;
-    bottom: 0px;
+    bottom: 0;
     /* width: 100%; */
     height: 40px;
     line-height: 40px;

+ 0 - 4
src/components/promotion/MenuTable.vue

@@ -38,8 +38,6 @@ const props = withDefaults(defineProps<MenuTableProps>(), {
   excludeFields: () => ({}),
 })
 
-const tableContainer = ref<HTMLElement | null>(null)
-
 // 表格ref
 const tableRef = ref<TableType | null>(null)
 
@@ -118,7 +116,6 @@ const emits = defineEmits(['changeDate'])
 
 onMounted(async () => {
   await initData()
-  console.log(props.tablePaginationConfig)
 })
 </script>
 
@@ -153,7 +150,6 @@ onMounted(async () => {
     <div class="menuTableContent">
       <PromotionTable
         ref="tableRef"
-        :table-container="tableContainer"
         :active-menu="activeMenu"
         :pagination-config="tablePaginationConfig"
         :table-fields="tableInfo[activeMenu].fields"

+ 157 - 43
src/components/table/PromotionTable.vue

@@ -13,7 +13,16 @@ import { generateUniqueFilename } from '@/utils/common'
 
 import { Operation, Plus } from '@element-plus/icons-vue'
 
-import { computed, nextTick, onMounted, reactive, ref, watch } from 'vue'
+import {
+  computed,
+  type DirectiveBinding,
+  nextTick,
+  onMounted,
+  onUnmounted,
+  reactive,
+  ref,
+  watch,
+} from 'vue'
 
 import customIndicatorDialog from '../dialog/customIndicatorDialog.vue'
 import TableQueryForm from './TableQueryForm.vue'
@@ -69,13 +78,14 @@ const {
   exportDataToExcel,
 } = useTable()
 
-const { initScroll, setScrollAndHeader, obScroll } = useTableScroll(
-  elScrollBarH,
-  tableContent,
-  tableContainer,
-  tableHeaderRef,
-  isFixed,
-)
+const { initScroll, setScrollAndHeader, obScroll, findScrollParent } =
+  useTableScroll(
+    elScrollBarH,
+    tableContent,
+    tableContainer,
+    tableHeaderRef,
+    isFixed,
+  )
 
 const rowHeight = 56 // 表格行高
 const tableFieldLWidth = 200 // 长单元格的宽度
@@ -143,25 +153,25 @@ const sortInfo = reactive<{
   order: null,
 })
 
-// // 批量操作选中的值
-// const batchOper = ref<string>()
-//
-// // 批量操作的选项数组
-// const batchOperList = reactive<
-//   Array<{
-//     label: string
-//     value: string
-//   }>
-// >([
-//   {
-//     label: '删除',
-//     value: 'delete',
-//   },
-//   {
-//     label: '新增',
-//     value: 'add',
-//   },
-// ])
+// 批量操作选中的值
+const batchOper = ref<string>()
+
+// 批量操作的选项数组
+const batchOperList = reactive<
+  Array<{
+    label: string
+    value: string
+  }>
+>([
+  {
+    label: '删除',
+    value: 'delete',
+  },
+  {
+    label: '新增',
+    value: 'add',
+  },
+])
 
 // 导出对话框的可见性
 const exportDialogVisble = ref<boolean>(false)
@@ -261,6 +271,7 @@ const showCustomIndicator = () => {
 /**
  * @description: 应用自定义指标
  * @param newTableFieldsInfo 新的表格字段信息
+ * @param schemeName 方案名
  */
 const applyCustomIndicator = (
   newTableFieldsInfo: Array<TableFields>,
@@ -410,13 +421,114 @@ if (!props.activeMenu) {
   watchActiveMenu()
 }
 
+interface ScrollHandler {
+  cleanup: () => void
+  rafId?: number
+}
+
+// 使用 WeakMap 自动管理清理函数
+const scrollHandlers = new WeakMap<HTMLElement, ScrollHandler>()
+
+// 自定义指令
+const vScrollParent = {
+  mounted(
+    el: HTMLElement,
+    binding: DirectiveBinding<(container: HTMLElement | Window) => () => void>,
+  ) {
+    // 获取最近的滚动容器
+    const scrollContainer = findScrollParent(el)
+
+    // 执行回调获取清理函数
+    const cleanup = binding.value(scrollContainer)
+
+    // 关联清理函数到元素
+    scrollHandlers.set(el, { cleanup })
+  },
+
+  beforeUnmount(el: HTMLElement) {
+    // 执行清理操作
+    const handler = scrollHandlers.get(el)
+    handler?.cleanup()
+    scrollHandlers.delete(el)
+  },
+}
+
+// 滚动处理函数
+const handleScrollParent = (scrollContainer: HTMLElement) => {
+  // 清理旧的监听(当容器变化时)
+  const prevContainer = tableContainer.value
+  if (prevContainer && prevContainer !== scrollContainer) {
+    const prevHandler = scrollHandlers.get(prevContainer)
+    prevHandler?.cleanup()
+    scrollHandlers.delete(prevContainer)
+  }
+
+  // 如果已经是当前容器,直接返回
+  if (tableContainer.value === scrollContainer) {
+    return () => {}
+  }
+
+  // 节流控制
+  let ticking = false
+  let rafId: number
+
+  // 事件处理器
+  const handler = () => {
+    if (!ticking) {
+      ticking = true
+      rafId = window.requestAnimationFrame(() => {
+        setScrollAndHeader()
+        ticking = false
+      })
+    }
+  }
+
+  // 清理函数
+  const cleanup = () => {
+    scrollContainer.removeEventListener('scroll', handler)
+    if (rafId) window.cancelAnimationFrame(rafId)
+    if (tableContainer.value === scrollContainer) {
+      tableContainer.value = null
+    }
+  }
+
+  // 绑定事件
+  scrollContainer.addEventListener('scroll', handler, { passive: true })
+  tableContainer.value = scrollContainer
+
+  // 保存引用
+  scrollHandlers.set(scrollContainer, { cleanup })
+
+  return cleanup
+}
+
 onMounted(() => {
   initScroll()
   initPagination()
   tableVisOb.observe(tableContent.value as HTMLElement)
-
   tableSizeOb.observe(tableContainer.value as HTMLElement)
-  // setScrollAndHeader()
+})
+
+// 清理逻辑
+const cleanup = () => {
+  // 1. 移除 IntersectionObserver
+  if (tableContent.value) {
+    tableVisOb.unobserve(tableContent.value)
+  }
+  if (tableContainer.value) {
+    tableSizeOb.unobserve(tableContainer.value)
+  }
+
+  // 2. 完全断开观察器(可选)
+  tableVisOb.disconnect()
+  tableSizeOb.disconnect()
+
+  // 3. 清理其他资源
+  // window.removeEventListener('scroll', handleScroll)
+}
+
+onUnmounted(() => {
+  cleanup()
 })
 
 defineExpose({
@@ -427,7 +539,9 @@ defineExpose({
 </script>
 
 <template>
-  <div class="tableContainer" ref="tableContainer" @scroll="setScrollAndHeader">
+  <!--  ref="tableContainer"-->
+  <!--  @scroll="setScrollAndHeader"-->
+  <div class="tableContainer" v-scroll-parent="handleScrollParent">
     <div class="testContainer">
       <TableQueryForm
         ref="tableQueryFormRef"
@@ -442,19 +556,19 @@ defineExpose({
             </el-button>
           </slot>
           <slot name="batchOper">
-            <!--            <el-select-->
-            <!--              class="batchOper w120"-->
-            <!--              v-model="batchOper"-->
-            <!--              placeholder="批量操作"-->
-            <!--              :disabled="tableLoading"-->
-            <!--            >-->
-            <!--              <el-option-->
-            <!--                v-for="item in batchOperList"-->
-            <!--                :key="item.value"-->
-            <!--                :label="item.label"-->
-            <!--                :value="item.value"-->
-            <!--              />-->
-            <!--            </el-select>-->
+            <el-select
+              class="batchOper w120"
+              v-model="batchOper"
+              placeholder="批量操作"
+              :disabled="tableLoading"
+            >
+              <el-option
+                v-for="item in batchOperList"
+                :key="item.value"
+                :label="item.label"
+                :value="item.value"
+              />
+            </el-select>
           </slot>
         </div>
         <div class="tableOperationRight">

+ 17 - 11
src/hooks/useCustomIndicatorDialog.ts

@@ -4,7 +4,8 @@ import type { Ref } from 'vue'
 export function useCustomIndicatorDialog() {
   /**
    * @description: 初始化一下被排序过的表格字段信息,这里要注意深拷贝
-   * @return {*}
+   * @param sortedTableFieldsInfo 被排序过的表格字段信息
+   * @param propsTableFieldsInfo 传递进来的字段信息
    */
   const initSortedTableFieldsInfo = (
     sortedTableFieldsInfo: Array<TableFields>,
@@ -19,10 +20,9 @@ export function useCustomIndicatorDialog() {
 
   /**
    * @description: 验证自定义指标名称
-   * @param {*} _rule 规则
-   * @param {*} value 值
-   * @param {*} callback 回调
-   * @return {*}
+   * @param  _rule 规则
+   * @param  value 值
+   * @param  callback 回调
    */
   const validCustomName = (_rule: any, value: any, callback: any) => {
     const regex = new RegExp(
@@ -39,7 +39,8 @@ export function useCustomIndicatorDialog() {
 
   /**
    * @description: 更新固定指标的框的值
-   * @return {*}
+   * @param propIndicator 自定义指标
+   * @param fixedIndicator 固定指标
    */
   const updateFixedIndicator = (
     propIndicator: Array<BaseFieldItem<TableFields>>,
@@ -58,9 +59,8 @@ export function useCustomIndicatorDialog() {
 
   /**
    * @description: 同步右侧栏目和表格字段的顺序
-   * @param {Array<TableFields>} propsTableFields 表格字段
-   * @param {Array<string>} allSelected 所有目前选中的字段名
-   * @return {*}
+   * @param  propsTableFields 表格字段
+   * @param  allSelected 所有目前选中的字段名
    */
   const syncTableField = (
     propsTableFields: Array<TableFields>,
@@ -76,7 +76,10 @@ export function useCustomIndicatorDialog() {
 
   /**
    * @description: 更新不固定框的状态和顺序
-   * @return {*}
+   * @param  propIndicator 自定义指标
+   * @param  isFirstShow 是否是第一次打开对话框
+   * @param  propsTableFields 表格字段
+   * @param  unFixedIndicator 不固定指标
    */
   const updateUnfixedIndicator = (
     propIndicator: Array<BaseFieldItem<TableFields>>,
@@ -120,7 +123,10 @@ export function useCustomIndicatorDialog() {
 
   /**
    * @description: 更新一下排序后的表格字段信息
-   * @return {*}
+   * @param  sortedTableFieldsInfo 排序后的表格字段信息
+   * @param  dragContentRef 拖拽的容器
+   * @param  unFixedIndicator 不固定指标
+   * @param  fixedIndicator 固定指标
    */
   const updateSortedTableFieldsInfo = (
     sortedTableFieldsInfo: Array<TableFields>,

+ 7 - 10
src/hooks/useDate.ts

@@ -15,9 +15,8 @@ export function useDate() {
    * @description: 创建一个日期范围
    * 如-7,1表示从今天开始往前推7天,到昨天结束
    * -1,-1,表示昨天,0,0表示今天,1,1,也表示昨天
-   * @param {number} startDay 开始的日期,可正可负,均表示距离今天的天数
-   * @param {number} endDay 结束日期,可正可负,也表示距离今天的天数,如不传则为开始日期,表示同一天
-   * @return {*}
+   * @param startDay 开始的日期,可正可负,均表示距离今天的天数
+   * @param endDay 结束日期,可正可负,也表示距离今天的天数,如不传则为开始日期,表示同一天
    */
   const createDateRange = (startDay: number, endDay?: number) => {
     if (endDay === undefined) endDay = startDay
@@ -34,9 +33,9 @@ export function useDate() {
 
   /**
    * @description: 根据type值来获取指定count之前的日期范围
-   * @param {*} type 类型
-   * @param {number} count 往前推的周数、月数、年数
-   * @return {date[]} 开始日期和结束日期
+   * @param type 类型
+   * @param count 往前推的周数、月数、年数
+   * @return 开始日期和结束日期
    */
   const getRangeForPeriod = (
     type: 'week' | 'month' | 'year',
@@ -148,8 +147,7 @@ export function useDate() {
 
   /**
    * @description: 生成日期选择器所需要的options
-   * @param {*} Array
-   * @return {*}
+   * @return options
    */
   const createSelectDateOption = (): Array<DateOption> => {
     return shortcuts.map(item => {
@@ -166,8 +164,7 @@ export function useDate() {
 
   /**
    * @description: 禁止选取今天之后的日期
-   * @param {*} date
-   * @return {*}
+   * @param time 传入的日期
    */
   const disableDate = (time: Date) => {
     return time.getTime() > Date.now()

+ 15 - 19
src/hooks/useDialogDrag.ts

@@ -11,56 +11,53 @@
 import type { Ref } from 'vue'
 
 export function useDialogDrag(
-  dragingRef: Ref<HTMLElement | null>,
+  dragRef: Ref<HTMLElement | null>,
   dragContentRef: Ref<HTMLElement | null>,
 ) {
   /**
    * @description: 判断当前是否可以插入
-   * @param {*} e 触发事件的事件对象
-   * @return {*}
+   * @param  e 触发事件的事件对象
    */
   const canInsert = (e: DragEvent): boolean => {
     return !(
       !e.target ||
-      !dragingRef.value ||
+      !dragRef.value ||
       !dragContentRef.value ||
-      dragingRef.value === e.target ||
+      dragRef.value === e.target ||
       e.target === dragContentRef.value
     )
   }
 
   /**
    * @description: 拖动开始
-   * @param {*} e 拖动事件对象
-   * @return {*}
+   * @param  e 拖动事件对象
    */
   const dragStart = (e: DragEvent) => {
     if (!dragContentRef.value || !e.target || !e.dataTransfer) return
     e.dataTransfer.effectAllowed = 'move' // 设置拖拽类型
-    dragingRef.value = e.target as HTMLElement // 获取当前拖拽的元素
-    dragingRef.value.classList.add('dragMove') // 添加拖拽样式
+    dragRef.value = e.target as HTMLElement // 获取当前拖拽的元素
+    dragRef.value.classList.add('dragMove') // 添加拖拽样式
   }
 
   /**
    * @description: 进入拖拽元素触发
-   * @param {*} e 拖拽事件对象
-   * @return {*}
+   * @param  e 拖拽事件对象
    */
   const dragEnter = (e: DragEvent) => {
     e.preventDefault()
     if (!canInsert(e)) return
     let listArray = Array.from(dragContentRef.value!.childNodes) // 整个可拖动的列表
-    let curIndex = listArray.indexOf(dragingRef.value!) // 当前拖动元素在整个列表中的文职
+    let curIndex = listArray.indexOf(dragRef.value!) // 当前拖动元素在整个列表中的文职
     let targeIndex = listArray.indexOf(e.target as HTMLElement) // 目前拖动到的元素在整个列表中的位置
 
     if (curIndex < targeIndex) {
       dragContentRef.value!.insertBefore(
-        dragingRef.value!,
+        dragRef.value!,
         (e.target as HTMLElement).nextSibling,
       )
     } else {
       dragContentRef.value!.insertBefore(
-        dragingRef.value!,
+        dragRef.value!,
         e.target as HTMLElement,
       )
     }
@@ -68,8 +65,7 @@ export function useDialogDrag(
 
   /**
    * @description: 在目标元素上拖动
-   * @param {*} e 拖拽对象
-   * @return {*}
+   * @param  e 拖拽对象
    */
   const dragOver = (e: DragEvent) => {
     e.preventDefault()
@@ -78,12 +74,12 @@ export function useDialogDrag(
 
   /**
    * @description: 拖拽结束
-   * @param {DragEvent} e 拖拽对象
-   * @return {*}
+   * @param  e 拖拽对象
+
    */
   const dragEnd = (e: DragEvent) => {
     if (!e.target) return
-    dragingRef.value?.classList.remove('dragMove')
+    dragRef.value?.classList.remove('dragMove')
   }
 
   return {

+ 2 - 1
src/hooks/useMenu.ts

@@ -5,7 +5,8 @@ import router from '@/router'
 export function useMenu() {
   /**
    * @description: 设置默认激活的菜单,根据当前路由匹配到对应的菜单
-   * @return {*}
+   * @param defaultActive 默认激活的菜单
+   * @param navBarMenuList 菜单列表
    */
   const setRouterDefaultActive = (
     defaultActive: Ref<string>,

+ 41 - 18
src/hooks/useMenuTable.ts

@@ -10,11 +10,11 @@ import type {
 } from '@/types/Tables/table'
 import type { BaseTableInfo } from '@/types/Tables/tablePageData'
 import TableCustomIndicatorController from '@/utils/localStorage/tableCustomIndicatorController'
-import type { ComputedRef, Reactive, Ref } from 'vue'
+import { type ComputedRef, type Reactive, type Ref } from 'vue'
 
 import { useTable } from './useTable'
 
-type TableType = InstanceType<typeof PromotionTable>
+export type TableType = InstanceType<typeof PromotionTable>
 
 export function useMenuTable(
   saveName: string, // 保存的文件名
@@ -34,6 +34,20 @@ export function useMenuTable(
   const { tableReqList, getData, updateTableFields } = useTable()
 
   /**
+   * 获取所有需要固定的字段
+   */
+  const getFixedFields = (): string[] => {
+    const field = tableInfo[activeMenu.value].fields
+    const fixedFields: string[] = []
+    field.forEach(item => {
+      item.children.forEach(field => {
+        if (field.fixed) fixedFields.push(field.name)
+      })
+    })
+    return fixedFields
+  }
+
+  /**
    * @description: 更新表格数据
    */
   const updateTableData = async () => {
@@ -52,9 +66,7 @@ export function useMenuTable(
             tableInfo[activeMenu.value].data.length,
             ...res,
           )
-          console.log(res)
           tablePaginationConfig.total = res.length
-          console.log(tablePaginationConfig)
         },
       )
     } catch (err) {
@@ -68,8 +80,7 @@ export function useMenuTable(
 
   /**
    * @description: 切换菜单
-   * @param {*} val 新菜单名
-   * @return {*}
+   * @param val 新菜单名
    */
   const menuActiveChange = (val: string) => {
     activeMenu.value = val
@@ -80,7 +91,7 @@ export function useMenuTable(
 
   /**
    * @description: 更新表格的字段信息
-   * @return {*}
+   * @param customName 自定义指标的名字
    */
   const updateTableInfo = (customName: string = '默认') => {
     if (!customName) customName = '默认'
@@ -94,22 +105,23 @@ export function useMenuTable(
 
   /**
    * @description: 更新自定义指标和表格字段
-   * @param {*} newIndicator  新的指标信息
-   * @param {*} newSortedTablefileds 新的表格字段信息
-   * @return {*}
+   * @param  newIndicator  新的指标信息
+   * @param  newSortedTableFields 新的表格字段信息
+   * @param  customSaveName  自定义指标的保存名
    */
   const updateCustomIndicator = (
     newIndicator: Array<BaseFieldItem<TableFields>>,
-    newSortedTablefileds: Array<TableFields>,
+    newSortedTableFields: Array<TableFields>,
     customSaveName: string,
   ) => {
     updateTableFields(
       tableInfo,
       activeMenu.value,
       newIndicator,
-      newSortedTablefileds,
+      newSortedTableFields,
     )
       .then(() => {
+        console.log(tableControllers)
         tableControllers[fileName.value].saveCustomScheme(
           JSON.parse(JSON.stringify(tableInfo[activeMenu.value])),
           customSaveName,
@@ -118,7 +130,8 @@ export function useMenuTable(
         customIndicatorScheme.value =
           tableControllers[fileName.value].getSchemeList()
       })
-      .catch(() => {
+      .catch(err => {
+        console.log(err)
         ElMessage.error('更新失败')
       })
     // saveTableInfo()
@@ -126,8 +139,7 @@ export function useMenuTable(
 
   /**
    * @description: 改变方案,要去更新一下表格字段
-   * @param {*} schemeName 新的方案名
-   * @return {*}
+   * @param  schemeName 新的方案名
    */
   const changeScheme = (schemeName: string) => {
     updateTableInfo(schemeName)
@@ -136,9 +148,15 @@ export function useMenuTable(
 
   /**
    * @description: 初始化表格的保存和读取文件的控制器
-   * @return {*}
    */
   const initTableController = () => {
+    if (!menuList || menuList.length === 0) {
+      tableControllers[fileName.value] = new TableCustomIndicatorController(
+        fileName.value,
+        tableInfo[activeMenu.value],
+      )
+      return
+    }
     menuList.forEach(item => {
       let tableName = `${saveName}-${item.name}`
       tableControllers[tableName] = new TableCustomIndicatorController(
@@ -150,10 +168,14 @@ export function useMenuTable(
 
   /**
    * @description: 初始化数据
+   * @param needGetData 是否需要获取数据
    */
-  const initData = async () => {
+  const initData = async (needGetData: boolean = true) => {
     initTableController()
-    await updateTableData()
+    tableInfo[activeMenu.value].fixedFields = getFixedFields()
+    if (needGetData) {
+      await updateTableData()
+    }
     customIndicatorScheme.value =
       tableControllers[fileName.value].getSchemeList()
   }
@@ -166,5 +188,6 @@ export function useMenuTable(
     updateCustomIndicator,
     initTableController,
     initData,
+    getFixedFields,
   }
 }

+ 3 - 3
src/hooks/useNumber.ts

@@ -1,9 +1,9 @@
 export function useNumber() {
   /**
    * @description: 按分隔符格式化数字
-   * @param {number} number 要格式化的数字
-   * @param {string} separator  分隔符
-   * @return {*}
+   * @param  number 要格式化的数字
+   * @param  separator  分隔符
+   * @return 格式化后的数字
    */
   const formatterNumberGroup = (number: number, separator: string = ',') => {
     return number.toString().replace(/\B(?=(\d{3})+(?!\d))/g, separator)

+ 2 - 2
src/hooks/useTable.ts

@@ -120,8 +120,8 @@ export function useTable() {
    * @param indicatorFields 自定义指标字段信息
    */
   const initTableFields = (
-    tableFieldsInfo: Array<TableFields>,
-    sortedTableFields: Array<TableFields> | undefined,
+    tableFieldsInfo: Array<BaseFieldInfo>,
+    sortedTableFields: Array<BaseFieldInfo> | undefined,
     indicatorFields: Array<BaseFieldItem<TableFields>>,
   ) => {
     resetReactive(tableFieldsInfo)

+ 33 - 9
src/hooks/useTableScroll.ts

@@ -41,13 +41,12 @@ export function useTableScroll(
   /**
    * @description: 判定当前横向滑动条是否在表格内
    * 滑动距离加可见区域高度不大于表格总高度,则说明在表格内
-   * @return {*}
+   * @return 是否在表格内
    */
-  const isIntable = () => {
+  const isInTable = () => {
     if (!tableContent.value || !tableContainer.value) return false
     const { scrollTop, offsetHeight, scrollHeight } =
       tableContainer.value as HTMLElement
-    // console.log(scrollTop, offsetHeight, scrollHeight)
     let result = scrollTop + offsetHeight < scrollHeight
     isFixed.value = result
     return result
@@ -55,7 +54,6 @@ export function useTableScroll(
 
   /**
    * @description: 初始化滑动条
-   * @return {*}
    */
   const initScroll = () => {
     let sc = document.querySelector('.el-scrollbar__bar') as HTMLElement
@@ -72,20 +70,18 @@ export function useTableScroll(
    * @description: 设置横向滑动条的位置和表头的位置
    * 只有滑动位置到达表格内部时,才需要固定横向滑动条,否则让滚动条回到原来的初始位置,即表格的底部
    * 只有滚动条超出表头的原本位置时,才固定表头
-   * @return {*}
    */
   const setScrollAndHeader = () => {
-    setScrollPos(isIntable())
+    setScrollPos(isInTable())
     if (tableHeaderRef.value) {
       const { scrollTop } = tableContainer.value as HTMLElement
       let contentOffsetTop = tableContent.value!.offsetTop // 父容器距离顶部的高度
-      let contentScollHeight = tableContent.value!.scrollHeight // 整个父容器的高度
+      let contentScrollHeight = tableContent.value!.scrollHeight // 整个父容器的高度
       // 超出表头原本位置时且小于整个表的高度,则固定表头
       if (
         scrollTop >= contentOffsetTop &&
-        scrollTop <= contentOffsetTop + contentScollHeight
+        scrollTop <= contentOffsetTop + contentScrollHeight
       ) {
-        console.log()
         tableHeaderRef.value.style.position = 'fixed'
         tableHeaderRef.value.style.top = `${tableContainer.value?.getBoundingClientRect().top}px`
         tableHeaderRef.value.style.zIndex = '666'
@@ -98,10 +94,38 @@ export function useTableScroll(
     }
   }
 
+  const findScrollParent = (el: HTMLElement): HTMLElement | Window => {
+    let parent = el.parentElement
+
+    while (parent) {
+      const style = window.getComputedStyle(parent)
+      const overflowY = style.overflowY
+
+      // 判断标准:
+      // 1. 是可见容器(高度不为0)
+      // 2. 包含滚动条(内容溢出或强制显示)
+      if (
+        parent.clientHeight > 0 &&
+        (overflowY === 'scroll' ||
+          overflowY === 'auto' ||
+          (overflowY === 'visible' &&
+            parent.scrollHeight > parent.clientHeight))
+      ) {
+        return parent
+      }
+
+      parent = parent.parentElement
+    }
+
+    // 未找到则返回window
+    return window
+  }
+
   return {
     initScroll,
     setScrollAndHeader,
     obScroll,
     setScrollPos,
+    findScrollParent,
   }
 }

+ 1 - 1
src/main.ts

@@ -2,7 +2,7 @@ import { createApp } from 'vue'
 import { createPinia } from 'pinia'
 
 import App from './App.vue'
-import router from './router'
+import router from '@/router'
 
 import * as ElementPlusIconsVue from '@element-plus/icons-vue'
 import '@/assets/base.css'

+ 2 - 2
src/router/home.ts

@@ -4,7 +4,7 @@ export default [
     name: 'Home',
     component: () => import('@/views/Home/Home.vue'),
     meta: {
-      needKeepAlive: true,
+      needKeepAlive: false,
     },
   },
   {
@@ -13,7 +13,7 @@ export default [
     redirect: '/promotion/ttAd',
     component: () => import('@/views/Promotion/promotion.vue'),
     meta: {
-      needKeepAlive: true,
+      needKeepAlive: false,
     },
     children: [
       {

+ 2 - 1
src/router/login.ts

@@ -1,6 +1,7 @@
-import type { RouteLocationNormalized, NavigationGuardNext } from 'vue-router'
+import type { NavigationGuardNext, RouteLocationNormalized } from 'vue-router'
 
 import { getLoginState } from '@/utils/localStorage/localStorage'
+
 export default [
   {
     path: '/login',

+ 1 - 1
src/router/material.ts

@@ -7,7 +7,7 @@ export default [
     redirect: '/material/filmLibrary',
     component: () => import('@/views/Material/Material.vue'),
     meta: {
-      needKeepAlive: true,
+      needKeepAlive: false,
     },
     children: [
       {

+ 1 - 0
src/types/Tables/MenuTable/menuTableReq.ts

@@ -1,4 +1,5 @@
 import type { AxiosRequestConfig } from 'axios'
+
 interface TableReq {
   url: string
   config: AxiosRequestConfig

+ 1 - 0
src/types/Tables/Operations/operations.ts

@@ -1,4 +1,5 @@
 import { EleBtnType } from '@/types/Button/buttonType'
+
 interface OperationItem {
   label: string
   type: EleBtnType

+ 5 - 7
src/types/Tables/table.ts

@@ -16,7 +16,6 @@ import type {
   AllTtAccMgeTablesData,
 } from './tableData/ttAcc'
 import type { AllAdmgeTtFields, AllAdMgeTtTablesData } from './tableData/ttAd'
-import type { Ref } from 'vue' // 表格查询表单中表单项的类型
 
 // 表格查询表单中表单项的类型
 enum TableFilterType {
@@ -161,7 +160,6 @@ interface FilterInfo {
 
 // 表格的props
 interface TableProps {
-  tableContainer: Ref<HTMLElement | null> // 表格容器
   filtersInfo: {
     [key: string]: TableFilterItem
   }
@@ -170,7 +168,7 @@ interface TableProps {
   // tableFields: Array<TableFields>
   tableFields: Array<BaseFieldItem<BaseFieldInfo>> // 表格字段信息,分段展示
   // tableFields: Array<BaseFieldItem<any>> // 表格字段信息,分段展示
-  sortedTableFields?: Array<TableFields> // 排序过后的表格字段,整体的
+  sortedTableFields?: Array<BaseFieldInfo> // 排序过后的表格字段,整体的
   // sortedTableFields?: Array<any> // 排序过后的表格字段,整体的
   fixedFields?: Array<string> // 需要固定显示的字段
   remotePagination?: boolean // 是否需要远程分页
@@ -185,8 +183,8 @@ interface TableProps {
 interface SaveFields {
   name: string // 这个是文件的标识名,也是这个文件的索引键
   label: string // 这个是用户自定义的文件名
-  fields: BaseFieldItem<TableFields>[] // 分组后的字段信息
-  tableSortedFields: TableFields[] // 排序过后的表格字段
+  fields: BaseFieldItem<BaseFieldInfo>[] // 分组后的字段信息
+  tableSortedFields: BaseFieldInfo[] // 排序过后的表格字段
 }
 
 // 保存的自定义方案格式
@@ -204,11 +202,11 @@ interface CustomIndicatorScheme {
 // 每个表格需要的信息格式,包含通用的属性
 interface TableInfoItem<
   TData extends TableData, // 数据必须来自所有表格数据类型
-  TFields extends BaseFieldItem<TableFields>, // 字段必须来自被basefieldItem包装过得所有表格字段
+  TFields extends BaseFieldItem<BaseFieldInfo>, // 字段必须来自被basefieldItem包装过得所有表格字段
 > {
   data: TData[] // 数据数组
   fields: TFields[] // 字段数组
-  tableSortedFields: TableFields[] // 排序过后的表格字段,仅用于展示表格字段
+  tableSortedFields: BaseFieldInfo[] // 排序过后的表格字段,仅用于展示表格字段
   filters: FilterInfo // 过滤信息
   fixedFields: string[] // 固定字段
   remote: boolean // 是否需要远程分页

+ 1 - 0
src/types/Tables/tableData/tencentAcc.ts

@@ -1,4 +1,5 @@
 import type { BaseFieldInfo } from '../table'
+
 // 广告主表格数据
 interface AdvertiserData {
   accountBalance: number

+ 1 - 0
src/types/Tables/tableData/ttAcc.ts

@@ -1,4 +1,5 @@
 import type { BaseFieldInfo } from '../table'
+
 // 广告主账户表格数据
 interface AdvertiserAccData {
   accountBalance: number

+ 5 - 4
src/types/Tables/tablePageData.ts

@@ -1,15 +1,16 @@
 // 保存一个包含表格的页面所需要的表格信息
 import type {
-  TableInfoItem,
-  TableData,
+  BaseFieldInfo,
   BaseFieldItem,
-  TableFields,
   FilterInfo,
+  TableData,
+  TableFields,
+  TableInfoItem,
 } from './table'
 
 //表格基本信息
 interface BaseTableInfo {
-  [key: string]: TableInfoItem<TableData, BaseFieldItem<TableFields>>
+  [key: string]: TableInfoItem<TableData, BaseFieldItem<BaseFieldInfo>>
 }
 
 // 所有字段的数据

+ 3 - 3
src/utils/axios/auth.ts

@@ -8,9 +8,9 @@
  *
  */
 
-import { ElMessage } from 'element-plus'
-import { MessageType } from '@/types/axios'
-import { getLoginState } from '../localStorage/localStorage'
+import {ElMessage} from 'element-plus'
+import {MessageType} from '@/types/axios'
+import {getLoginState} from '../localStorage/localStorage'
 
 export const authLogin = (): boolean => {
   const state = getLoginState()

+ 6 - 7
src/utils/axios/axiosInstance.ts

@@ -15,8 +15,8 @@ import { MessageType } from '@/types/axios'
 import {
   getToken,
   refreshToken,
-  setToken,
   removeAllToeken,
+  setToken,
 } from '../token/token'
 import { setLoginState } from '../localStorage/localStorage'
 
@@ -44,10 +44,9 @@ let requestQueue: any[] = [] // 存储请求队列
 
 /**
  * @description: 未登录的情况下展示的信息
- * @param {*} ElMessage
- * @return {*}
+ * @param msg 提示的消息
  */
-const showUnloginInfo = (msg: string = '请先登录') => {
+const showUnLoginInfo = (msg: string = '请先登录') => {
   ElMessage({
     type: MessageType.Warning,
     message: msg,
@@ -65,7 +64,7 @@ axiosInstance.interceptors.response.use(
 
     // -2是token为空的情况
     if (code === -2) {
-      showUnloginInfo()
+      showUnLoginInfo()
     }
     // -1是token过期的情况
     if (code === -1) {
@@ -83,12 +82,12 @@ axiosInstance.interceptors.response.use(
               requestQueue = []
               return axiosInstance(config)
             } else {
-              showUnloginInfo('登录已过期,请重新登陆')
+              showUnLoginInfo('登录已过期,请重新登陆')
             }
           })
           .catch(err => {
             console.log(err)
-            showUnloginInfo('登录已过期,请重新登陆')
+            showUnLoginInfo('登录已过期,请重新登陆')
           })
           .finally(() => {
             isRefreshing = false

+ 8 - 9
src/utils/localStorage/tableCustomIndicatorController.ts

@@ -1,10 +1,10 @@
 import type {
+  BaseFieldInfo,
   BaseFieldItem,
   CustomIndicatorScheme,
   SaveCustomIncicatorScheme,
   SaveFields,
   TableData,
-  TableFields,
   TableInfoItem,
 } from '@/types/Tables/table'
 
@@ -14,7 +14,7 @@ class TableCustomIndicatorController {
 
   constructor(
     tableName: string,
-    tableInfo: TableInfoItem<TableData, BaseFieldItem<TableFields>>,
+    tableInfo: TableInfoItem<TableData, BaseFieldItem<BaseFieldInfo>>,
   ) {
     this.#tableName = tableName
     let schemes = localStorage.getItem(this.#tableName)
@@ -45,12 +45,11 @@ class TableCustomIndicatorController {
 
   /**
    * @description: 保存新方案
-   * @param {string} schemeName 用户的自定义方案名,如果没输入就是默认
-   * @param {TableInfoItem} tableInfo 表格信息
-   * @return {*}
+   * @param schemeName 用户的自定义方案名,如果没输入就是默认
+   * @param tableInfo 表格信息
    */
   saveCustomScheme(
-    tableInfo: TableInfoItem<TableData, BaseFieldItem<TableFields>>,
+    tableInfo: TableInfoItem<TableData, BaseFieldItem<BaseFieldInfo>>,
     schemeName: string = '默认',
   ) {
     try {
@@ -77,8 +76,8 @@ class TableCustomIndicatorController {
 
   /**
    * @description: 获取自定义方案
-   * @param {string} schemeName 方案名,不传则是直接返回所有方案,传了就是具体的某一种方案
-   * @return {SaveFields} 方案
+   * @param schemeName 方案名,不传则是直接返回所有方案,传了就是具体的某一种方案
+   * @return  方案
    */
   getCustomScheme(schemeName: string): SaveFields | undefined
   getCustomScheme(): SaveCustomIncicatorScheme | undefined
@@ -93,7 +92,7 @@ class TableCustomIndicatorController {
 
   /**
    * @description: 获取所有的自定义方案列表
-   * @return {Array<CustomIndicatorScheme>} 所有的自定义方案
+   * @return 所有的自定义方案
    */
   getSchemeList(): Array<CustomIndicatorScheme> {
     let info = this.getCustomScheme()

+ 4 - 4
src/utils/token/token.ts

@@ -52,9 +52,9 @@ const refreshToken = async () => {
     {},
     {
       headers: {
-        Authorization: `${getrefreshToken()}`
-      }
-    }
+        Authorization: `${getrefreshToken()}`,
+      },
+    },
   )
 }
 
@@ -91,5 +91,5 @@ export {
   refreshToken,
   removeToken,
   removeRefreshToken,
-  removeAllToeken
+  removeAllToeken,
 }

+ 279 - 0
src/views/Material/DrawerTagsView/DrawerBaseInfo.vue

@@ -0,0 +1,279 @@
+<script setup lang="ts">
+import { computed, ref } from 'vue'
+
+const imgFieldName = {
+  id: 'ID',
+  name: '图片名称',
+  gid: '游戏ID',
+  pid: '游戏父级ID',
+  wx_id: '微信资源ID',
+  image_width: '图片宽度',
+  image_height: '图片高度',
+  image_file_size: '图片大小',
+  image_type: '图片类型',
+  isImg9: '是否为九宫格',
+  resolution: '分辨率',
+  createdAt: '创建时间',
+  updatedAt: '更新时间',
+  tag: '标签列表',
+}
+
+const videoFieldName = {
+  id: 'ID',
+  name: '视频名称',
+  gid: '游戏ID',
+  pid: '游戏父级ID',
+  wx_id: '微信资源ID',
+  video_type: '视频类型',
+  resolution: '分辨率',
+  createdAt: '创建时间',
+  updatedAt: '更新时间',
+  tag: '标签列表',
+}
+
+const props = defineProps<{
+  info: any
+}>()
+
+const isVideo = ref(false)
+const baseInfo = computed(() => {
+  const fieldData = isVideo.value ? videoFieldName : imgFieldName
+  return Object.entries(fieldData).map(([key, label]) => ({
+    name: key,
+    label,
+    value: props.info[key],
+  }))
+})
+
+interface DataOverViewItemConfig {
+  type: 'percent' | 'default'
+}
+
+interface DataOverViewItem {
+  name: string
+  label: string
+  value: number
+  backgroundColor?: string
+  color?: string
+  config?: DataOverViewItemConfig
+}
+
+const dataOverview = ref<DataOverViewItem[]>([
+  {
+    name: 'consume',
+    label: '消耗',
+    value: 100,
+    backgroundColor: '#e5f6ff',
+    color: '#1f6de4',
+  },
+  {
+    name: 'cost',
+    label: '转化成本',
+    value: 0,
+    color: '#279d55',
+    backgroundColor: '#eaf8f1',
+  },
+  {
+    name: 'clickRate',
+    label: '点击率',
+    value: 100,
+    config: {
+      type: 'percent',
+    },
+  },
+  {
+    name: 'convertRate',
+    label: '转化率',
+    value: 100,
+    config: {
+      type: 'percent',
+    },
+  },
+  {
+    name: 'convertNum',
+    label: '转化数',
+    value: 0,
+  },
+])
+
+const formatOverviewValue = (val: number, config?: DataOverViewItemConfig) => {
+  if (!val) return '--'
+  if (!config) return val
+  const { type } = config
+
+  if (type === 'percent') {
+    return `${val}%`
+  }
+}
+
+console.log(props.info)
+</script>
+
+<template>
+  <div class="baseInfoContainer">
+    <div class="baseInfo">
+      <p class="baseInfoTitle">基本信息</p>
+      <div class="mediaPreview">
+        <video v-if="isVideo"></video>
+        <img
+          alt=""
+          class="previewImg"
+          v-else
+          src="http://localhost:8113/img/head/head-boy.png"
+        />
+      </div>
+
+      <div class="infoDisplay">
+        <div v-for="item in baseInfo">
+          <div class="infoItem" v-if="item.name !== 'tag'">
+            <span class="infoItemLabel">{{ item.label }}</span>
+            <span class="infoItemValue">{{ item.value }}</span>
+          </div>
+          <div class="infoTags" v-else>
+            <p class="infoItemLabel tagLabel">标签</p>
+            <div>
+              <el-tag
+                style="margin-right: 5px"
+                type="primary"
+                v-for="tag in item.value"
+                >{{ tag.name === '' ? '默认' : tag.name }}
+              </el-tag>
+            </div>
+          </div>
+        </div>
+      </div>
+    </div>
+    <div class="overview">
+      <p class="baseInfoTitle">数据概览</p>
+      <div class="overviewData">
+        <div
+          class="overviewItem"
+          v-for="item in dataOverview"
+          :key="'overviewItem' + item.name"
+          :style="{
+            color: item.color ?? '#000',
+            backgroundColor: item.backgroundColor ?? '#fff',
+          }"
+        >
+          <span class="overviewItemLabel">{{ item.label }}</span>
+          <span class="overviewItemValue">{{
+            formatOverviewValue(item.value, item.config)
+          }}</span>
+        </div>
+      </div>
+    </div>
+  </div>
+</template>
+
+<style scoped>
+.baseInfoContainer {
+  width: 100%;
+  height: 100%;
+
+  display: flex;
+  justify-content: space-between;
+}
+
+.baseInfo {
+  width: 300px;
+  min-height: calc(100vh - 82px);
+
+  display: flex;
+  flex-direction: column;
+  align-items: flex-start;
+}
+
+.overview {
+  width: 804px;
+  padding: 16px;
+  overflow-x: hidden;
+  overflow-y: auto;
+  background-color: #fff;
+  border-radius: 8px;
+}
+
+.baseInfoTitle {
+  font-size: 16px;
+  font-weight: 700;
+  margin-bottom: 24px;
+}
+
+.mediaPreview {
+  width: 100%;
+  margin-top: 12px;
+}
+
+.previewImg {
+  display: block;
+  min-width: 100%;
+  max-width: 100%;
+}
+
+.infoDisplay {
+  width: 100%;
+  padding-bottom: 12px;
+  margin-top: 16px;
+  border-bottom: 1px dotted #d0d0d0;
+  display: flex;
+  flex-direction: column;
+  /*align-items: space-betwee;*/
+}
+
+.infoItem {
+  width: 100%;
+  display: flex;
+  justify-content: space-between;
+  padding: 5px 10px;
+}
+
+.infoItemLabel {
+  width: 85px;
+  color: #999;
+  font-size: 12px;
+}
+
+.tagLabel {
+  margin-bottom: 10px;
+}
+
+.infoItemValue {
+  width: 183px;
+  color: #323335;
+  text-align: right;
+  overflow-wrap: break-word;
+}
+
+.overviewData {
+  display: flex;
+  justify-content: space-between;
+}
+
+.overviewItem {
+  display: flex;
+  flex-direction: column;
+  justify-content: space-around;
+  width: 142px;
+  height: 86px;
+  padding: 16px 8px 16px 12px;
+  margin-right: 16px;
+  border-radius: 8px;
+  background-color: rgb(229, 246, 255);
+}
+
+.overviewItemLabel {
+  font-size: 14px;
+  font-weight: 700;
+}
+
+.overviewItemValue {
+  display: flex;
+  align-items: center;
+  font-size: 18px;
+  font-weight: 700;
+}
+
+.infoTags {
+  width: 100%;
+  padding: 5px 10px;
+}
+</style>

+ 130 - 50
src/views/Material/FilmLibrary.vue

@@ -4,9 +4,11 @@ import { MaterialAPI } from '@/config/API.ts'
 import { useMaterial } from '@/hooks/Material/useMaterial.ts'
 import router from '@/router'
 import type { ResponseInfo } from '@/types/axios.ts'
-import type { BaseMenu } from '@/types/Promotion/Menu.ts'
 import type { TablePaginationProps } from '@/types/Tables/pagination.ts'
-import { type SelectFilterOptions } from '@/types/Tables/table.ts'
+import {
+  type CustomIndicatorScheme,
+  type SelectFilterOptions,
+} from '@/types/Tables/table.ts'
 import axiosInstance from '@/utils/axios/axiosInstance.ts'
 import {
   imgFields,
@@ -16,17 +18,64 @@ import {
 } from '@/views/Material/config/FimLibraryConfig.ts'
 import { Plus } from '@element-plus/icons-vue'
 
-import { nextTick, onMounted, reactive, ref } from 'vue'
-
-type PromotionTableType = InstanceType<typeof PromotionTable>
+import { computed, nextTick, onMounted, reactive, ref } from 'vue'
+import DrawerBaseInfo from '@/views/Material/DrawerTagsView/DrawerBaseInfo.vue'
+import type { BaseTableInfo } from '@/types/Tables/tablePageData.ts'
+import { type TableType, useMenuTable } from '@/hooks/useMenuTable.ts'
+import type TableCustomIndicatorController from '@/utils/localStorage/tableCustomIndicatorController.ts'
 
 const { getGameInfo, getAllTags } = useMaterial()
 
 // const defaultActive = ref<string>('filmLibrary')
-const menuList = reactive<BaseMenu[]>([])
-const listRef = ref<PromotionTableType>()
+// const menuList = reactive<BaseMenu[]>([])
+const listRef = ref<TableType | null>(null)
 const isVideo = ref<boolean>(false)
-const tableContainer = ref<HTMLElement | null>(null)
+
+const assetTypeName = computed(() => {
+  return isVideo.value ? 'img' : 'video'
+})
+
+const tableInfo = reactive<BaseTableInfo>({
+  img: {
+    data: [],
+    fields: imgFields,
+    tableSortedFields: [],
+    filters: imgFilterInfo,
+    fixedFields: [],
+    remote: true,
+  },
+  video: {
+    data: [],
+    fields: videoFields,
+    tableSortedFields: [],
+    filters: videoFilterInfo,
+    fixedFields: [],
+    remote: true,
+  },
+})
+
+const drawerVisible = ref(false)
+
+const drawerTagConfig = [
+  {
+    name: 'base',
+    label: '基本信息',
+    component: DrawerBaseInfo,
+  },
+  {
+    name: 'other',
+    label: '占位信息',
+    component: DrawerBaseInfo,
+  },
+]
+
+const activeName = ref(drawerTagConfig[0].name)
+
+// 自定义指标保存的方案
+const customIndicatorScheme = ref<Array<CustomIndicatorScheme>>([])
+
+const selectRowInfo = ref<any>()
+
 /**
  * 跳转上传页面
  */
@@ -43,7 +92,7 @@ const updateGameInfo = async () => {
     ElMessage.error('获取游戏信息失败')
     return
   }
-  const filterInfo = isVideo.value ? videoFilterInfo : imgFilterInfo
+  const filterInfo = tableInfo[assetTypeName.value].filters
   const pidInfo: SelectFilterOptions[] = []
   const gidInfo: SelectFilterOptions[] = []
   const filterInfoPid = (filterInfo as any)['pid']
@@ -79,37 +128,11 @@ const updateTags = async () => {
       value: item.id,
     }
   })
-  const filterInfo = isVideo.value ? videoFilterInfo : imgFilterInfo
+  const filterInfo = tableInfo[assetTypeName.value].filters
   const filterTag = (filterInfo as any)['tags']
   filterTag['options'] = options
 }
 
-const createMenu = async () => {
-  const info = await getGameInfo()
-  if (info === null) {
-    ElMessage.error('游戏信息获取失败')
-    return
-  }
-  menuList.splice(0, menuList.length)
-  for (let [k, v] of Object.entries(info)) {
-    menuList.push({
-      name: k,
-      title: k === '' ? '默认' : k,
-      iconDefault: '/file/project-default.svg',
-      iconActive: '/file/project-active.svg',
-      children: [],
-    })
-    for (let item of v) {
-      menuList[menuList.length - 1].children?.push({
-        name: item.gid,
-        title: item.gameName,
-        iconDefault: '/file/folder-default.svg',
-        iconActive: '/file/folder-active.png',
-      })
-    }
-  }
-}
-
 const tableData = reactive<Array<any>>([])
 
 const paginationConfig = reactive<TablePaginationProps>({
@@ -125,10 +148,11 @@ const updateTableData = async () => {
   }
   const result = (await axiosInstance.post(url, params)) as ResponseInfo
   paginationConfig.total = result.data.count
+  const data = tableInfo[assetTypeName.value].data
   if (paginationConfig.total === 0) {
-    tableData.splice(0, tableData.length)
+    data.splice(0, tableData.length)
   } else {
-    tableData.splice(0, tableData.length, ...result.data.list)
+    data.splice(0, tableData.length, ...result.data.list)
   }
 }
 
@@ -143,7 +167,7 @@ const updateResolution = async () => {
     return
   }
   const resolutionList = result.data['resolution']
-  const filterInfo = isVideo.value ? videoFilterInfo : imgFilterInfo
+  const filterInfo = tableInfo[assetTypeName.value].filters
   const filterResolution = (filterInfo as any)['resolution']
   filterResolution['options'] = resolutionList.map((item: any) => {
     return {
@@ -153,6 +177,39 @@ const updateResolution = async () => {
   })
 }
 
+const viewDetails = (row: any) => {
+  drawerVisible.value = true
+  selectRowInfo.value = row
+}
+
+const saveTableName = '素材'
+
+/**
+ * @description: 保存的文件名
+ * @return {*}
+ */
+const fileName = computed(() => {
+  return `${saveTableName}-${assetTypeName.value}`
+})
+
+// 每个表格的自定义方案的IO控制器
+const tableControllers: {
+  [key: string]: TableCustomIndicatorController
+} = {}
+
+const { changeScheme, updateCustomIndicator, initData } = useMenuTable(
+  saveTableName,
+  fileName,
+  assetTypeName,
+  customIndicatorScheme,
+  tableControllers,
+  tableInfo,
+  {},
+  paginationConfig,
+  listRef,
+  [],
+)
+
 const updateFilterInfo = async () => {
   await updateResolution()
   await updateGameInfo()
@@ -166,7 +223,9 @@ const changeAssetType = async () => {
 
 onMounted(async () => {
   await updateFilterInfo()
+
   await updateTableData()
+  await initData(false)
 })
 </script>
 
@@ -185,15 +244,18 @@ onMounted(async () => {
     </div>
     <div class="flContent">
       <PromotionTable
-        :table-container="tableContainer"
-        :filters-info="isVideo ? videoFilterInfo : imgFilterInfo"
-        :table-data="tableData"
-        :table-fields="isVideo ? videoFields : imgFields"
         :pagination-config="paginationConfig"
+        :table-fields="tableInfo[assetTypeName].fields"
+        :filters-info="tableInfo[assetTypeName].filters"
+        :sorted-table-fields="tableInfo[assetTypeName].tableSortedFields"
+        :table-data="tableInfo[assetTypeName].data"
         :need-export="false"
-        :remote-pagination="true"
-        :fixed-fields="['action']"
+        :remote-pagination="tableInfo[assetTypeName].remote"
+        :fixed-fields="tableInfo[assetTypeName].fixedFields"
+        :scheme-list="customIndicatorScheme"
         @query-table="updateTableData"
+        @update-custom-indicator="updateCustomIndicator"
+        @change-scheme="changeScheme"
         ref="listRef"
         style="height: 100%"
       >
@@ -206,14 +268,35 @@ onMounted(async () => {
             >上传素材
           </el-button>
         </template>
-        <template #operations>
+        <template #operations="{ row }">
           <div>
-            <el-button text type="primary">预览</el-button>
+            <el-button text type="primary" @click="viewDetails(row)"
+              >详情</el-button
+            >
             <el-button text type="success">下载</el-button>
           </div>
         </template>
       </PromotionTable>
     </div>
+    <el-drawer
+      v-model="drawerVisible"
+      direction="rtl"
+      :size="1160"
+      :show-close="false"
+      :with-header="false"
+      :append-to-body="true"
+      :destroy-on-close="true"
+    >
+      <el-tabs v-model="activeName">
+        <el-tab-pane
+          v-for="item in drawerTagConfig"
+          :label="item.label"
+          :name="item.name"
+        >
+          <component :info="selectRowInfo" :is="item.component"></component>
+        </el-tab-pane>
+      </el-tabs>
+    </el-drawer>
   </div>
 </template>
 
@@ -226,14 +309,11 @@ onMounted(async () => {
   overflow: scroll;
 }
 
-.gameSelectContainer,
-.flQueryForm,
 .flContent {
   width: 100%;
   height: 100%;
 }
 
-.gameSelectContainer,
 .filmLibraryHeader,
 .flContent {
   padding: 10px 20px;

+ 9 - 3
src/views/Material/config/FimLibraryConfig.ts

@@ -223,7 +223,7 @@ const videoFields: Array<BaseFieldItem<BaseFieldInfo>> = [
         label: '素材名称',
         name: 'name',
         state: true,
-        fixed: false,
+        fixed: true,
       },
       {
         label: '游戏ID',
@@ -255,7 +255,7 @@ const videoFields: Array<BaseFieldItem<BaseFieldInfo>> = [
 
         sort: true,
         state: true,
-        fixed: false,
+        fixed: true,
       },
       {
         label: '更新时间',
@@ -268,7 +268,13 @@ const videoFields: Array<BaseFieldItem<BaseFieldInfo>> = [
         name: 'tag',
         type: TableFieldType.Tag,
         state: true,
-        fixed: false,
+        fixed: true,
+      },
+      {
+        label: '操作',
+        name: 'action',
+        state: true,
+        fixed: true,
       },
     ],
   },

+ 3 - 3
src/views/Promotion/accManage/accTencentAd.vue

@@ -187,7 +187,7 @@ const tableInfo = reactive<TableInfo>({
     ],
     tableSortedFields: [],
     filters: allFilters['advertiserTable'],
-    fixedFields: allFixedFileds['advertiserTable'],
+    fixedFields: [],
     remote: true,
   },
   businessManagerTable: {
@@ -202,7 +202,7 @@ const tableInfo = reactive<TableInfo>({
     ],
     tableSortedFields: [],
     filters: allFilters['businessManagerTable'],
-    fixedFields: allFixedFileds['businessManagerTable'],
+    fixedFields: [],
     remote: true,
   },
   agencyTable: {
@@ -217,7 +217,7 @@ const tableInfo = reactive<TableInfo>({
     ],
     tableSortedFields: [],
     filters: allFilters['agencyTable'],
-    fixedFields: allFixedFileds['agencyTable'],
+    fixedFields: [],
     remote: true,
   },
 })

+ 3 - 3
src/views/Promotion/accManage/accTtAd.vue

@@ -187,7 +187,7 @@ const tableInfo = reactive<TableInfo>({
     ],
     tableSortedFields: [],
     filters: allFilters['advertiserAccTable'],
-    fixedFields: allFixedFileds['advertiserAccTable'],
+    fixedFields: [],
     remote: true,
   },
   managerAccTable: {
@@ -202,7 +202,7 @@ const tableInfo = reactive<TableInfo>({
     ],
     tableSortedFields: [],
     filters: allFilters['managerAccTable'],
-    fixedFields: allFixedFileds['managerAccTable'],
+    fixedFields: [],
     remote: true,
   },
   agencyAccTable: {
@@ -217,7 +217,7 @@ const tableInfo = reactive<TableInfo>({
     ],
     tableSortedFields: [],
     filters: allFilters['agencyAccTable'],
-    fixedFields: allFixedFileds['agencyAccTable'],
+    fixedFields: [],
     remote: true,
   },
 })

+ 3 - 3
src/views/Promotion/adManage/tencentAd.vue

@@ -178,7 +178,7 @@ const tableInfo = reactive<TableInfo>({
     ],
     tableSortedFields: [],
     filters: allFilters['mediaTable'],
-    fixedFields: allFixedFileds['mediaTable'],
+    fixedFields: [],
     remote: true,
   },
   adTable: {
@@ -193,7 +193,7 @@ const tableInfo = reactive<TableInfo>({
     ],
     tableSortedFields: [],
     filters: allFilters['adTable'],
-    fixedFields: allFixedFileds['adTable'],
+    fixedFields: [],
     remote: true,
   },
   creativityTable: {
@@ -208,7 +208,7 @@ const tableInfo = reactive<TableInfo>({
     ],
     tableSortedFields: [],
     filters: allFilters['creativityTable'],
-    fixedFields: allFixedFileds['creativityTable'],
+    fixedFields: [],
     remote: true,
   },
 })

+ 3 - 3
src/views/Promotion/adManage/ttad.vue

@@ -543,7 +543,7 @@ const tableInfo = reactive<TableInfo>({
     ],
     tableSortedFields: [],
     filters: allFilters['account'],
-    fixedFields: allFixedFileds['account'],
+    fixedFields: [],
     remote: true,
   },
   project: {
@@ -558,7 +558,7 @@ const tableInfo = reactive<TableInfo>({
     ],
     tableSortedFields: [],
     filters: allFilters['project'],
-    fixedFields: allFixedFileds['project'],
+    fixedFields: [],
     remote: true,
   },
   advertise: {
@@ -573,7 +573,7 @@ const tableInfo = reactive<TableInfo>({
     ],
     tableSortedFields: [],
     filters: allFilters['advertise'],
-    fixedFields: allFixedFileds['advertise'],
+    fixedFields: [],
     remote: true,
   },
 })

+ 7 - 1
tsconfig.json

@@ -7,5 +7,11 @@
     {
       "path": "./tsconfig.app.json"
     }
-  ]
+  ],
+  "compilerOptions": {
+    "baseUrl": ".",
+    "paths": {
+      "@/*": ["src/*"]
+    }
+  }
 }

Některé soubory nejsou zobrazeny, neboť je v těchto rozdílových datech změněno mnoho souborů