xiebaomin 1 rok pred
rodič
commit
d2371bca38
39 zmenil súbory, kde vykonal 682 pridanie a 652 odobranie
  1. 4 0
      components.d.ts
  2. 111 255
      package-lock.json
  3. 6 2
      package.json
  4. 10 0
      src/App.vue
  5. 2 2
      src/Hooks/useFileImage.ts
  6. 1 1
      src/Hooks/usePermission/permiMode.tsx
  7. 2 1
      src/Hooks/usePermission/usePermission.ts
  8. 16 16
      src/Hooks/useStopWindowContext.ts
  9. 5 1
      src/Hooks/useWeChatShare.ts
  10. BIN
      src/assets/logo_m.png
  11. 43 0
      src/components/docx-preview/docx-preview.vue
  12. 7 0
      src/components/docx-preview/index.d.ts
  13. 4 0
      src/components/docx-preview/index.type.ts
  14. 0 3
      src/components/pdf-preview/index.ts
  15. 32 27
      src/components/pdf-preview/pdf-preview.vue
  16. 56 0
      src/components/ppt-preview/ppt-preview.vue
  17. 16 0
      src/components/text-preview/text-preview.vue
  18. 2 2
      src/components/video-preview/index.type.ts
  19. 7 3
      src/components/video-preview/video-preview.vue
  20. 12 12
      src/router/route.ts
  21. 3 2
      src/types/api/context.type.ts
  22. 18 16
      src/types/views/database.type.ts
  23. 1 0
      src/util/toArrayBuffer.ts
  24. 6 2
      src/views/Database/components/context-contain.vue
  25. 10 10
      src/views/Database/components/context-head.vue
  26. 3 2
      src/views/Database/components/context-share.vue
  27. 7 4
      src/views/Database/components/file-content.vue
  28. 15 10
      src/views/Database/components/high-light-text.vue
  29. 43 0
      src/views/Database/components/image-content.vue
  30. 25 17
      src/views/Database/components/search-head.vue
  31. 14 6
      src/views/Database/components/text-file-content.vue
  32. 36 69
      src/views/Database/components/video-img-content.vue
  33. 24 29
      src/views/Database/data-all/index.vue
  34. 71 105
      src/views/Database/detail.vue
  35. 1 1
      src/views/Database/index.vue
  36. 6 3
      src/views/Login/index.vue
  37. 52 49
      src/views/Preview/index.vue
  38. 10 1
      src/vite-env.d.ts
  39. 1 1
      tsconfig.json

+ 4 - 0
components.d.ts

@@ -8,13 +8,16 @@ export {}
 declare module 'vue' {
   export interface GlobalComponents {
     DataButton: typeof import('./src/components/data-button/data-button.vue')['default']
+    DocxPreview: typeof import('./src/components/docx-preview/docx-preview.vue')['default']
     ElForm: typeof import('element-plus/es')['ElForm']
     ElFormItem: typeof import('element-plus/es')['ElFormItem']
     ElInput: typeof import('element-plus/es')['ElInput']
     ImagePreview: typeof import('./src/components/image-preview/image-preview.vue')['default']
     PdfPreview: typeof import('./src/components/pdf-preview/pdf-preview.vue')['default']
+    PptPreview: typeof import('./src/components/ppt-preview/ppt-preview.vue')['default']
     RouterLink: typeof import('vue-router')['RouterLink']
     RouterView: typeof import('vue-router')['RouterView']
+    TextPreview: typeof import('./src/components/text-preview/text-preview.vue')['default']
     VanButton: typeof import('vant/es')['Button']
     VanCell: typeof import('vant/es')['Cell']
     VanCellGroup: typeof import('vant/es')['CellGroup']
@@ -34,6 +37,7 @@ declare module 'vue' {
     VanSwipeItem: typeof import('vant/es')['SwipeItem']
     VanTab: typeof import('vant/es')['Tab']
     VanTabs: typeof import('vant/es')['Tabs']
+    VanWatermark: typeof import('vant/es')['Watermark']
     VideoPreview: typeof import('./src/components/video-preview/video-preview.vue')['default']
   }
 }

+ 111 - 255
package-lock.json

@@ -11,6 +11,7 @@
         "@emotion/css": "^11.11.2",
         "@emotion/react": "^11.11.1",
         "axios": "^1.6.2",
+        "dommatrix": "^1.0.3",
         "element-plus": "^2.4.3",
         "nprogress": "^0.2.0",
         "pinia": "^2.1.7",
@@ -19,19 +20,22 @@
         "vant": "^4.8.0",
         "vite-plugin-style-import": "^2.0.0",
         "vue": "^3.3.8",
-        "vue-pdf-embed": "^1.2.1",
         "vue-router": "^4.2.5",
         "vue-styled-components": "^1.6.0",
-        "vue3-pdfjs": "^0.1.6"
+        "web-streams-polyfill": "^3.3.2"
       },
       "devDependencies": {
         "@types/crypto-js": "^4.2.1",
         "@types/node": "^20.10.0",
+        "@types/path-browserify": "^1.0.2",
         "@types/video.js": "^7.3.56",
         "@vitejs/plugin-vue": "^4.5.0",
         "@vitejs/plugin-vue-jsx": "^3.1.0",
+        "@vue-office/docx": "^1.6.0",
         "@vueuse/core": "^10.7.1",
         "crypto-js": "^4.2.0",
+        "path-browserify": "^1.0.1",
+        "pdfh5": "^1.4.7",
         "postcss-px-to-viewport": "^1.1.1",
         "sass": "^1.69.5",
         "typescript": "^5.2.2",
@@ -1347,6 +1351,12 @@
       "resolved": "https://registry.npmmirror.com/@types/parse-json/-/parse-json-4.0.2.tgz",
       "integrity": "sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw=="
     },
+    "node_modules/@types/path-browserify": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmmirror.com/@types/path-browserify/-/path-browserify-1.0.2.tgz",
+      "integrity": "sha512-ZkC5IUqqIFPXx3ASTTybTzmQdwHwe2C0u3eL75ldQ6T9E9IWFJodn6hIfbZGab73DfyiHN4Xw15gNxUq2FbvBA==",
+      "dev": true
+    },
     "node_modules/@types/video.js": {
       "version": "7.3.56",
       "resolved": "https://registry.npmmirror.com/@types/video.js/-/video.js-7.3.56.tgz",
@@ -1523,6 +1533,23 @@
         "path-browserify": "^1.0.1"
       }
     },
+    "node_modules/@vue-office/docx": {
+      "version": "1.6.0",
+      "resolved": "https://registry.npmmirror.com/@vue-office/docx/-/docx-1.6.0.tgz",
+      "integrity": "sha512-OKEapOPq223uszA8mRSOWPhdfBchJa6sIqP46eMrMMe5RSUrG9m3QE/o0JBIaMgxDrtNd7aI9CvF2kDvb7G2hw==",
+      "dev": true,
+      "hasInstallScript": true,
+      "peerDependencies": {
+        "@vue/composition-api": "^1.7.1",
+        "vue": "^2.0.0 || >=3.0.0",
+        "vue-demi": "^0.14.6"
+      },
+      "peerDependenciesMeta": {
+        "@vue/composition-api": {
+          "optional": true
+        }
+      }
+    },
     "node_modules/@vue/babel-helper-vue-transform-on": {
       "version": "1.1.5",
       "resolved": "https://registry.npmmirror.com/@vue/babel-helper-vue-transform-on/-/babel-helper-vue-transform-on-1.1.5.tgz",
@@ -1695,29 +1722,6 @@
         "url": "https://github.com/sponsors/antfu"
       }
     },
-    "node_modules/@vueuse/core/node_modules/vue-demi": {
-      "version": "0.14.6",
-      "resolved": "https://registry.npmmirror.com/vue-demi/-/vue-demi-0.14.6.tgz",
-      "integrity": "sha512-8QA7wrYSHKaYgUxDA5ZC24w+eHm3sYCbp0EzcDwKqN3p6HqtTCGR/GVsPyZW92unff4UlcSh++lmqDWN3ZIq4w==",
-      "dev": true,
-      "hasInstallScript": true,
-      "bin": {
-        "vue-demi-fix": "bin/vue-demi-fix.js",
-        "vue-demi-switch": "bin/vue-demi-switch.js"
-      },
-      "engines": {
-        "node": ">=12"
-      },
-      "peerDependencies": {
-        "@vue/composition-api": "^1.0.0-rc.1",
-        "vue": "^3.0.0-0 || ^2.6.0"
-      },
-      "peerDependenciesMeta": {
-        "@vue/composition-api": {
-          "optional": true
-        }
-      }
-    },
     "node_modules/@vueuse/metadata": {
       "version": "10.7.1",
       "resolved": "https://registry.npmjs.org/@vueuse/metadata/-/metadata-10.7.1.tgz",
@@ -1739,32 +1743,6 @@
         "url": "https://github.com/sponsors/antfu"
       }
     },
-    "node_modules/@vueuse/shared/node_modules/vue-demi": {
-      "version": "0.14.6",
-      "resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.14.6.tgz",
-      "integrity": "sha512-8QA7wrYSHKaYgUxDA5ZC24w+eHm3sYCbp0EzcDwKqN3p6HqtTCGR/GVsPyZW92unff4UlcSh++lmqDWN3ZIq4w==",
-      "dev": true,
-      "hasInstallScript": true,
-      "bin": {
-        "vue-demi-fix": "bin/vue-demi-fix.js",
-        "vue-demi-switch": "bin/vue-demi-switch.js"
-      },
-      "engines": {
-        "node": ">=12"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/antfu"
-      },
-      "peerDependencies": {
-        "@vue/composition-api": "^1.0.0-rc.1",
-        "vue": "^3.0.0-0 || ^2.6.0"
-      },
-      "peerDependenciesMeta": {
-        "@vue/composition-api": {
-          "optional": true
-        }
-      }
-    },
     "node_modules/@xmldom/xmldom": {
       "version": "0.8.10",
       "resolved": "https://registry.npmmirror.com/@xmldom/xmldom/-/xmldom-0.8.10.tgz",
@@ -1918,14 +1896,14 @@
       }
     },
     "node_modules/browserslist": {
-      "version": "4.22.1",
-      "resolved": "https://registry.npmmirror.com/browserslist/-/browserslist-4.22.1.tgz",
-      "integrity": "sha512-FEVc202+2iuClEhZhrWy6ZiAcRLvNMyYcxZ8raemul1DYVOVdFsbqckWLdsixQZCpJlwe77Z3UTalE7jsjnKfQ==",
+      "version": "4.22.2",
+      "resolved": "https://registry.npmmirror.com/browserslist/-/browserslist-4.22.2.tgz",
+      "integrity": "sha512-0UgcrvQmBDvZHFGdYUehrCNIazki7/lUP3kkoi/r3YB2amZbFM9J43ZRkJTXBUZK4gmx56+Sqk9+Vs9mwZx9+A==",
       "dev": true,
       "dependencies": {
-        "caniuse-lite": "^1.0.30001541",
-        "electron-to-chromium": "^1.4.535",
-        "node-releases": "^2.0.13",
+        "caniuse-lite": "^1.0.30001565",
+        "electron-to-chromium": "^1.4.601",
+        "node-releases": "^2.0.14",
         "update-browserslist-db": "^1.0.13"
       },
       "bin": {
@@ -2201,9 +2179,9 @@
       }
     },
     "node_modules/electron-to-chromium": {
-      "version": "1.4.597",
-      "resolved": "https://registry.npmmirror.com/electron-to-chromium/-/electron-to-chromium-1.4.597.tgz",
-      "integrity": "sha512-0XOQNqHhg2YgRVRUrS4M4vWjFCFIP2ETXcXe/0KIQBjXE9Cpy+tgzzYfuq6HGai3hWq0YywtG+5XK8fyG08EjA==",
+      "version": "1.4.637",
+      "resolved": "https://registry.npmmirror.com/electron-to-chromium/-/electron-to-chromium-1.4.637.tgz",
+      "integrity": "sha512-G7j3UCOukFtxVO1vWrPQUoDk3kL70mtvjc/DC/k2o7lE0wAdq+Vwp1ipagOow+BH0uVztFysLWbkM/RTIrbK3w==",
       "dev": true
     },
     "node_modules/element-plus": {
@@ -2250,31 +2228,6 @@
         "url": "https://github.com/sponsors/antfu"
       }
     },
-    "node_modules/element-plus/node_modules/@vueuse/core/node_modules/vue-demi": {
-      "version": "0.14.6",
-      "resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.14.6.tgz",
-      "integrity": "sha512-8QA7wrYSHKaYgUxDA5ZC24w+eHm3sYCbp0EzcDwKqN3p6HqtTCGR/GVsPyZW92unff4UlcSh++lmqDWN3ZIq4w==",
-      "hasInstallScript": true,
-      "bin": {
-        "vue-demi-fix": "bin/vue-demi-fix.js",
-        "vue-demi-switch": "bin/vue-demi-switch.js"
-      },
-      "engines": {
-        "node": ">=12"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/antfu"
-      },
-      "peerDependencies": {
-        "@vue/composition-api": "^1.0.0-rc.1",
-        "vue": "^3.0.0-0 || ^2.6.0"
-      },
-      "peerDependenciesMeta": {
-        "@vue/composition-api": {
-          "optional": true
-        }
-      }
-    },
     "node_modules/element-plus/node_modules/@vueuse/metadata": {
       "version": "9.13.0",
       "resolved": "https://registry.npmjs.org/@vueuse/metadata/-/metadata-9.13.0.tgz",
@@ -2294,31 +2247,6 @@
         "url": "https://github.com/sponsors/antfu"
       }
     },
-    "node_modules/element-plus/node_modules/@vueuse/shared/node_modules/vue-demi": {
-      "version": "0.14.6",
-      "resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.14.6.tgz",
-      "integrity": "sha512-8QA7wrYSHKaYgUxDA5ZC24w+eHm3sYCbp0EzcDwKqN3p6HqtTCGR/GVsPyZW92unff4UlcSh++lmqDWN3ZIq4w==",
-      "hasInstallScript": true,
-      "bin": {
-        "vue-demi-fix": "bin/vue-demi-fix.js",
-        "vue-demi-switch": "bin/vue-demi-switch.js"
-      },
-      "engines": {
-        "node": ">=12"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/antfu"
-      },
-      "peerDependencies": {
-        "@vue/composition-api": "^1.0.0-rc.1",
-        "vue": "^3.0.0-0 || ^2.6.0"
-      },
-      "peerDependenciesMeta": {
-        "@vue/composition-api": {
-          "optional": true
-        }
-      }
-    },
     "node_modules/encoding": {
       "version": "0.1.13",
       "resolved": "https://registry.npmmirror.com/encoding/-/encoding-0.1.13.tgz",
@@ -3127,9 +3055,9 @@
       }
     },
     "node_modules/node-releases": {
-      "version": "2.0.13",
-      "resolved": "https://registry.npmmirror.com/node-releases/-/node-releases-2.0.13.tgz",
-      "integrity": "sha512-uYr7J37ae/ORWdZeQ1xxMJe3NtdmqMC/JZK+geofDrkLUApKRHPd18/TxtBOJ4A0/+uUIliorNrfYV6s1b02eQ==",
+      "version": "2.0.14",
+      "resolved": "https://registry.npmmirror.com/node-releases/-/node-releases-2.0.14.tgz",
+      "integrity": "sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==",
       "dev": true
     },
     "node_modules/normalize-path": {
@@ -3236,22 +3164,11 @@
       "integrity": "sha512-d+RQGp0MAYTIaDBIMmOfMwz3E+LOZnxx1HZd5R18mmCZY0QBlK0LDZfPc8FW8Ed2DlvsuE6PRjroDY+wg4+j/Q==",
       "dev": true
     },
-    "node_modules/pdfjs-dist": {
-      "version": "2.16.105",
-      "resolved": "https://registry.npmmirror.com/pdfjs-dist/-/pdfjs-dist-2.16.105.tgz",
-      "integrity": "sha512-J4dn41spsAwUxCpEoVf6GVoz908IAA3mYiLmNxg8J9kfRXc2jxpbUepcP0ocp0alVNLFthTAM8DZ1RaHh8sU0A==",
-      "dependencies": {
-        "dommatrix": "^1.0.3",
-        "web-streams-polyfill": "^3.2.1"
-      },
-      "peerDependencies": {
-        "worker-loader": "^3.0.8"
-      },
-      "peerDependenciesMeta": {
-        "worker-loader": {
-          "optional": true
-        }
-      }
+    "node_modules/pdfh5": {
+      "version": "1.4.7",
+      "resolved": "https://registry.npmmirror.com/pdfh5/-/pdfh5-1.4.7.tgz",
+      "integrity": "sha512-bVfxQl5G7jCRCn1ogiW7ozuSSeoLsQ7zJ1OPvp5mKH8aTRvHP4a2Us/Wj7srhSf1i42OyvDCjVDETCoIiW3huQ==",
+      "dev": true
     },
     "node_modules/picocolors": {
       "version": "1.0.0",
@@ -3296,28 +3213,6 @@
         "pinia": "^2.0.0"
       }
     },
-    "node_modules/pinia/node_modules/vue-demi": {
-      "version": "0.14.6",
-      "resolved": "https://registry.npmmirror.com/vue-demi/-/vue-demi-0.14.6.tgz",
-      "integrity": "sha512-8QA7wrYSHKaYgUxDA5ZC24w+eHm3sYCbp0EzcDwKqN3p6HqtTCGR/GVsPyZW92unff4UlcSh++lmqDWN3ZIq4w==",
-      "hasInstallScript": true,
-      "bin": {
-        "vue-demi-fix": "bin/vue-demi-fix.js",
-        "vue-demi-switch": "bin/vue-demi-switch.js"
-      },
-      "engines": {
-        "node": ">=12"
-      },
-      "peerDependencies": {
-        "@vue/composition-api": "^1.0.0-rc.1",
-        "vue": "^3.0.0-0 || ^2.6.0"
-      },
-      "peerDependenciesMeta": {
-        "@vue/composition-api": {
-          "optional": true
-        }
-      }
-    },
     "node_modules/pkcs7": {
       "version": "1.0.4",
       "resolved": "https://registry.npmmirror.com/pkcs7/-/pkcs7-1.0.4.tgz",
@@ -3676,9 +3571,9 @@
       "dev": true
     },
     "node_modules/terser": {
-      "version": "5.24.0",
-      "resolved": "https://registry.npmmirror.com/terser/-/terser-5.24.0.tgz",
-      "integrity": "sha512-ZpGR4Hy3+wBEzVEnHvstMvqpD/nABNelQn/z2r0fjVWGQsN3bpOLzQlqDxmb4CDZnXq5lpjnQ+mHQLAOpfM5iw==",
+      "version": "5.27.0",
+      "resolved": "https://registry.npmmirror.com/terser/-/terser-5.27.0.tgz",
+      "integrity": "sha512-bi1HRwVRskAjheeYl291n3JC4GgO/Ty4z1nVs5AAsmonJulGxpSektecnNedrwK9C7vpvVtcX3cw00VSLt7U2A==",
       "optional": true,
       "peer": true,
       "dependencies": {
@@ -4087,12 +3982,26 @@
         }
       }
     },
-    "node_modules/vue-pdf-embed": {
-      "version": "1.2.1",
-      "resolved": "https://registry.npmmirror.com/vue-pdf-embed/-/vue-pdf-embed-1.2.1.tgz",
-      "integrity": "sha512-4uUm4wxaEGT9cS1cyuagAmMJjBxfQXWG1MvdGPesD3CiXhhSp4i0VMUCYwhFXtZ5+QqWv4mXbfLJ29Wpt+Qcuw==",
+    "node_modules/vue-demi": {
+      "version": "0.14.6",
+      "resolved": "https://registry.npmmirror.com/vue-demi/-/vue-demi-0.14.6.tgz",
+      "integrity": "sha512-8QA7wrYSHKaYgUxDA5ZC24w+eHm3sYCbp0EzcDwKqN3p6HqtTCGR/GVsPyZW92unff4UlcSh++lmqDWN3ZIq4w==",
+      "hasInstallScript": true,
+      "bin": {
+        "vue-demi-fix": "bin/vue-demi-fix.js",
+        "vue-demi-switch": "bin/vue-demi-switch.js"
+      },
+      "engines": {
+        "node": ">=12"
+      },
       "peerDependencies": {
-        "vue": "^2.x || ^3.x"
+        "@vue/composition-api": "^1.0.0-rc.1",
+        "vue": "^3.0.0-0 || ^2.6.0"
+      },
+      "peerDependenciesMeta": {
+        "@vue/composition-api": {
+          "optional": true
+        }
       }
     },
     "node_modules/vue-router": {
@@ -4145,22 +4054,10 @@
         "typescript": "*"
       }
     },
-    "node_modules/vue3-pdfjs": {
-      "version": "0.1.6",
-      "resolved": "https://registry.npmmirror.com/vue3-pdfjs/-/vue3-pdfjs-0.1.6.tgz",
-      "integrity": "sha512-7UaWbsp8wNqB0y/rRlyo5yRb0S+XOkkSpmdUuS267Dhi07Pt4RFEetQ8inrpf/aTFJwGnW0Uc/UE4p376s+Zmw==",
-      "dependencies": {
-        "pdfjs-dist": "^2.10.377",
-        "vue": "^3.2.19"
-      },
-      "engines": {
-        "node": ">=10.0.0"
-      }
-    },
     "node_modules/web-streams-polyfill": {
-      "version": "3.2.1",
-      "resolved": "https://registry.npmmirror.com/web-streams-polyfill/-/web-streams-polyfill-3.2.1.tgz",
-      "integrity": "sha512-e0MO3wdXWKrLbL0DgGnUV7WHVuw9OUvL4hjgnPkIeEvESk74gAITi5G606JtZPp39cd8HA9VQzCIvA49LpPN5Q==",
+      "version": "3.3.2",
+      "resolved": "https://registry.npmmirror.com/web-streams-polyfill/-/web-streams-polyfill-3.3.2.tgz",
+      "integrity": "sha512-3pRGuxRF5gpuZc0W+EpwQRmCD7gRqcDOMt688KmdlDAgAyaB1XlN0zq2njfDNm44XVdIouE7pZ6GzbdyH47uIQ==",
       "engines": {
         "node": ">= 8"
       }
@@ -5074,6 +4971,12 @@
       "resolved": "https://registry.npmmirror.com/@types/parse-json/-/parse-json-4.0.2.tgz",
       "integrity": "sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw=="
     },
+    "@types/path-browserify": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmmirror.com/@types/path-browserify/-/path-browserify-1.0.2.tgz",
+      "integrity": "sha512-ZkC5IUqqIFPXx3ASTTybTzmQdwHwe2C0u3eL75ldQ6T9E9IWFJodn6hIfbZGab73DfyiHN4Xw15gNxUq2FbvBA==",
+      "dev": true
+    },
     "@types/video.js": {
       "version": "7.3.56",
       "resolved": "https://registry.npmmirror.com/@types/video.js/-/video.js-7.3.56.tgz",
@@ -5217,6 +5120,13 @@
         "path-browserify": "^1.0.1"
       }
     },
+    "@vue-office/docx": {
+      "version": "1.6.0",
+      "resolved": "https://registry.npmmirror.com/@vue-office/docx/-/docx-1.6.0.tgz",
+      "integrity": "sha512-OKEapOPq223uszA8mRSOWPhdfBchJa6sIqP46eMrMMe5RSUrG9m3QE/o0JBIaMgxDrtNd7aI9CvF2kDvb7G2hw==",
+      "dev": true,
+      "requires": {}
+    },
     "@vue/babel-helper-vue-transform-on": {
       "version": "1.1.5",
       "resolved": "https://registry.npmmirror.com/@vue/babel-helper-vue-transform-on/-/babel-helper-vue-transform-on-1.1.5.tgz",
@@ -5370,15 +5280,6 @@
         "@vueuse/metadata": "10.7.1",
         "@vueuse/shared": "10.7.1",
         "vue-demi": ">=0.14.6"
-      },
-      "dependencies": {
-        "vue-demi": {
-          "version": "0.14.6",
-          "resolved": "https://registry.npmmirror.com/vue-demi/-/vue-demi-0.14.6.tgz",
-          "integrity": "sha512-8QA7wrYSHKaYgUxDA5ZC24w+eHm3sYCbp0EzcDwKqN3p6HqtTCGR/GVsPyZW92unff4UlcSh++lmqDWN3ZIq4w==",
-          "dev": true,
-          "requires": {}
-        }
       }
     },
     "@vueuse/metadata": {
@@ -5394,15 +5295,6 @@
       "dev": true,
       "requires": {
         "vue-demi": ">=0.14.6"
-      },
-      "dependencies": {
-        "vue-demi": {
-          "version": "0.14.6",
-          "resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.14.6.tgz",
-          "integrity": "sha512-8QA7wrYSHKaYgUxDA5ZC24w+eHm3sYCbp0EzcDwKqN3p6HqtTCGR/GVsPyZW92unff4UlcSh++lmqDWN3ZIq4w==",
-          "dev": true,
-          "requires": {}
-        }
       }
     },
     "@xmldom/xmldom": {
@@ -5531,14 +5423,14 @@
       }
     },
     "browserslist": {
-      "version": "4.22.1",
-      "resolved": "https://registry.npmmirror.com/browserslist/-/browserslist-4.22.1.tgz",
-      "integrity": "sha512-FEVc202+2iuClEhZhrWy6ZiAcRLvNMyYcxZ8raemul1DYVOVdFsbqckWLdsixQZCpJlwe77Z3UTalE7jsjnKfQ==",
+      "version": "4.22.2",
+      "resolved": "https://registry.npmmirror.com/browserslist/-/browserslist-4.22.2.tgz",
+      "integrity": "sha512-0UgcrvQmBDvZHFGdYUehrCNIazki7/lUP3kkoi/r3YB2amZbFM9J43ZRkJTXBUZK4gmx56+Sqk9+Vs9mwZx9+A==",
       "dev": true,
       "requires": {
-        "caniuse-lite": "^1.0.30001541",
-        "electron-to-chromium": "^1.4.535",
-        "node-releases": "^2.0.13",
+        "caniuse-lite": "^1.0.30001565",
+        "electron-to-chromium": "^1.4.601",
+        "node-releases": "^2.0.14",
         "update-browserslist-db": "^1.0.13"
       }
     },
@@ -5774,9 +5666,9 @@
       }
     },
     "electron-to-chromium": {
-      "version": "1.4.597",
-      "resolved": "https://registry.npmmirror.com/electron-to-chromium/-/electron-to-chromium-1.4.597.tgz",
-      "integrity": "sha512-0XOQNqHhg2YgRVRUrS4M4vWjFCFIP2ETXcXe/0KIQBjXE9Cpy+tgzzYfuq6HGai3hWq0YywtG+5XK8fyG08EjA==",
+      "version": "1.4.637",
+      "resolved": "https://registry.npmmirror.com/electron-to-chromium/-/electron-to-chromium-1.4.637.tgz",
+      "integrity": "sha512-G7j3UCOukFtxVO1vWrPQUoDk3kL70mtvjc/DC/k2o7lE0wAdq+Vwp1ipagOow+BH0uVztFysLWbkM/RTIrbK3w==",
       "dev": true
     },
     "element-plus": {
@@ -5815,14 +5707,6 @@
             "@vueuse/metadata": "9.13.0",
             "@vueuse/shared": "9.13.0",
             "vue-demi": "*"
-          },
-          "dependencies": {
-            "vue-demi": {
-              "version": "0.14.6",
-              "resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.14.6.tgz",
-              "integrity": "sha512-8QA7wrYSHKaYgUxDA5ZC24w+eHm3sYCbp0EzcDwKqN3p6HqtTCGR/GVsPyZW92unff4UlcSh++lmqDWN3ZIq4w==",
-              "requires": {}
-            }
           }
         },
         "@vueuse/metadata": {
@@ -5836,14 +5720,6 @@
           "integrity": "sha512-UrnhU+Cnufu4S6JLCPZnkWh0WwZGUp72ktOF2DFptMlOs3TOdVv8xJN53zhHGARmVOsz5KqOls09+J1NR6sBKw==",
           "requires": {
             "vue-demi": "*"
-          },
-          "dependencies": {
-            "vue-demi": {
-              "version": "0.14.6",
-              "resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.14.6.tgz",
-              "integrity": "sha512-8QA7wrYSHKaYgUxDA5ZC24w+eHm3sYCbp0EzcDwKqN3p6HqtTCGR/GVsPyZW92unff4UlcSh++lmqDWN3ZIq4w==",
-              "requires": {}
-            }
           }
         }
       }
@@ -6508,9 +6384,9 @@
       }
     },
     "node-releases": {
-      "version": "2.0.13",
-      "resolved": "https://registry.npmmirror.com/node-releases/-/node-releases-2.0.13.tgz",
-      "integrity": "sha512-uYr7J37ae/ORWdZeQ1xxMJe3NtdmqMC/JZK+geofDrkLUApKRHPd18/TxtBOJ4A0/+uUIliorNrfYV6s1b02eQ==",
+      "version": "2.0.14",
+      "resolved": "https://registry.npmmirror.com/node-releases/-/node-releases-2.0.14.tgz",
+      "integrity": "sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==",
       "dev": true
     },
     "normalize-path": {
@@ -6602,14 +6478,11 @@
       "integrity": "sha512-d+RQGp0MAYTIaDBIMmOfMwz3E+LOZnxx1HZd5R18mmCZY0QBlK0LDZfPc8FW8Ed2DlvsuE6PRjroDY+wg4+j/Q==",
       "dev": true
     },
-    "pdfjs-dist": {
-      "version": "2.16.105",
-      "resolved": "https://registry.npmmirror.com/pdfjs-dist/-/pdfjs-dist-2.16.105.tgz",
-      "integrity": "sha512-J4dn41spsAwUxCpEoVf6GVoz908IAA3mYiLmNxg8J9kfRXc2jxpbUepcP0ocp0alVNLFthTAM8DZ1RaHh8sU0A==",
-      "requires": {
-        "dommatrix": "^1.0.3",
-        "web-streams-polyfill": "^3.2.1"
-      }
+    "pdfh5": {
+      "version": "1.4.7",
+      "resolved": "https://registry.npmmirror.com/pdfh5/-/pdfh5-1.4.7.tgz",
+      "integrity": "sha512-bVfxQl5G7jCRCn1ogiW7ozuSSeoLsQ7zJ1OPvp5mKH8aTRvHP4a2Us/Wj7srhSf1i42OyvDCjVDETCoIiW3huQ==",
+      "dev": true
     },
     "picocolors": {
       "version": "1.0.0",
@@ -6628,14 +6501,6 @@
       "requires": {
         "@vue/devtools-api": "^6.5.0",
         "vue-demi": ">=0.14.5"
-      },
-      "dependencies": {
-        "vue-demi": {
-          "version": "0.14.6",
-          "resolved": "https://registry.npmmirror.com/vue-demi/-/vue-demi-0.14.6.tgz",
-          "integrity": "sha512-8QA7wrYSHKaYgUxDA5ZC24w+eHm3sYCbp0EzcDwKqN3p6HqtTCGR/GVsPyZW92unff4UlcSh++lmqDWN3ZIq4w==",
-          "requires": {}
-        }
       }
     },
     "pinia-plugin-persistedstate": {
@@ -6944,9 +6809,9 @@
       "dev": true
     },
     "terser": {
-      "version": "5.24.0",
-      "resolved": "https://registry.npmmirror.com/terser/-/terser-5.24.0.tgz",
-      "integrity": "sha512-ZpGR4Hy3+wBEzVEnHvstMvqpD/nABNelQn/z2r0fjVWGQsN3bpOLzQlqDxmb4CDZnXq5lpjnQ+mHQLAOpfM5iw==",
+      "version": "5.27.0",
+      "resolved": "https://registry.npmmirror.com/terser/-/terser-5.27.0.tgz",
+      "integrity": "sha512-bi1HRwVRskAjheeYl291n3JC4GgO/Ty4z1nVs5AAsmonJulGxpSektecnNedrwK9C7vpvVtcX3cw00VSLt7U2A==",
       "optional": true,
       "peer": true,
       "requires": {
@@ -7230,10 +7095,10 @@
         "@vue/shared": "3.3.9"
       }
     },
-    "vue-pdf-embed": {
-      "version": "1.2.1",
-      "resolved": "https://registry.npmmirror.com/vue-pdf-embed/-/vue-pdf-embed-1.2.1.tgz",
-      "integrity": "sha512-4uUm4wxaEGT9cS1cyuagAmMJjBxfQXWG1MvdGPesD3CiXhhSp4i0VMUCYwhFXtZ5+QqWv4mXbfLJ29Wpt+Qcuw==",
+    "vue-demi": {
+      "version": "0.14.6",
+      "resolved": "https://registry.npmmirror.com/vue-demi/-/vue-demi-0.14.6.tgz",
+      "integrity": "sha512-8QA7wrYSHKaYgUxDA5ZC24w+eHm3sYCbp0EzcDwKqN3p6HqtTCGR/GVsPyZW92unff4UlcSh++lmqDWN3ZIq4w==",
       "requires": {}
     },
     "vue-router": {
@@ -7277,19 +7142,10 @@
         "semver": "^7.5.4"
       }
     },
-    "vue3-pdfjs": {
-      "version": "0.1.6",
-      "resolved": "https://registry.npmmirror.com/vue3-pdfjs/-/vue3-pdfjs-0.1.6.tgz",
-      "integrity": "sha512-7UaWbsp8wNqB0y/rRlyo5yRb0S+XOkkSpmdUuS267Dhi07Pt4RFEetQ8inrpf/aTFJwGnW0Uc/UE4p376s+Zmw==",
-      "requires": {
-        "pdfjs-dist": "^2.10.377",
-        "vue": "^3.2.19"
-      }
-    },
     "web-streams-polyfill": {
-      "version": "3.2.1",
-      "resolved": "https://registry.npmmirror.com/web-streams-polyfill/-/web-streams-polyfill-3.2.1.tgz",
-      "integrity": "sha512-e0MO3wdXWKrLbL0DgGnUV7WHVuw9OUvL4hjgnPkIeEvESk74gAITi5G606JtZPp39cd8HA9VQzCIvA49LpPN5Q=="
+      "version": "3.3.2",
+      "resolved": "https://registry.npmmirror.com/web-streams-polyfill/-/web-streams-polyfill-3.3.2.tgz",
+      "integrity": "sha512-3pRGuxRF5gpuZc0W+EpwQRmCD7gRqcDOMt688KmdlDAgAyaB1XlN0zq2njfDNm44XVdIouE7pZ6GzbdyH47uIQ=="
     },
     "webpack-sources": {
       "version": "3.2.3",

+ 6 - 2
package.json

@@ -13,6 +13,7 @@
     "@emotion/css": "^11.11.2",
     "@emotion/react": "^11.11.1",
     "axios": "^1.6.2",
+    "dommatrix": "^1.0.3",
     "element-plus": "^2.4.3",
     "nprogress": "^0.2.0",
     "pinia": "^2.1.7",
@@ -21,19 +22,22 @@
     "vant": "^4.8.0",
     "vite-plugin-style-import": "^2.0.0",
     "vue": "^3.3.8",
-    "vue-pdf-embed": "^1.2.1",
     "vue-router": "^4.2.5",
     "vue-styled-components": "^1.6.0",
-    "vue3-pdfjs": "^0.1.6"
+    "web-streams-polyfill": "^3.3.2"
   },
   "devDependencies": {
     "@types/crypto-js": "^4.2.1",
     "@types/node": "^20.10.0",
+    "@types/path-browserify": "^1.0.2",
     "@types/video.js": "^7.3.56",
     "@vitejs/plugin-vue": "^4.5.0",
     "@vitejs/plugin-vue-jsx": "^3.1.0",
+    "@vue-office/docx": "^1.6.0",
     "@vueuse/core": "^10.7.1",
     "crypto-js": "^4.2.0",
+    "path-browserify": "^1.0.1",
+    "pdfh5": "^1.4.7",
     "postcss-px-to-viewport": "^1.1.1",
     "sass": "^1.69.5",
     "typescript": "^5.2.2",

+ 10 - 0
src/App.vue

@@ -1,5 +1,15 @@
 <script setup lang="ts">
+import { watch } from 'vue';
+import { useRoute } from 'vue-router';
 
+const route = useRoute()
+watch(() => route.query, () => {
+  console.log(123)
+  if (!localStorage.getItem('isDetailRefresh')) {
+		localStorage.setItem('isDetailRefresh', '1')
+    window.location.reload()
+	}
+})
 </script>
 
 <template>

+ 2 - 2
src/Hooks/useFileImage.ts

@@ -1,7 +1,7 @@
 const getFileImg = (str: string): { img: string } => {
-	const img = str?.indexOf(".pdf")
+	const img = str?.indexOf(".pdf") !== -1
 	? "https://static.caimei365.com/app/mini-database/H5-pdf.png"
-	: str?.indexOf(".docx")
+	: str?.indexOf(".docx") !== -1
 	? "https://static.caimei365.com/app/mini-database/H5-doc.png"
 	: "https://static.caimei365.com/app/mini-database/H5-ppt.png"
 	return {

+ 1 - 1
src/Hooks/usePermission/permiMode.tsx

@@ -97,7 +97,7 @@ const MyComponent = (prop: IPermiObj | Boolean): ComponentOptions =>
 						</div>
 					</div>
 				)
-			)
+			) 
 		},
 	})
 

+ 2 - 1
src/Hooks/usePermission/usePermission.ts

@@ -12,7 +12,8 @@ const permissionText: IPermi = [
 ]
 
 export const usePermission = (ps?: number): UsePermission => {
-	const permi = (): number => ps ? Number(ps) : 5
+	const permi = (): number => Number(ps)
+	console.log(ps, 'ps', permi())
 	const isPermi = (): Boolean | IPermiObj => permissionText[permi()]
 	const cE = MyComponent(isPermi())
 	return {

+ 16 - 16
src/Hooks/useStopWindowContext.ts

@@ -1,23 +1,23 @@
-const useStopWindowContext = (uid: number) => {
+const useStopWindowContext = () => {
+	const isDev = import.meta.env.VITE_ENV === 'production'
 	
 	// 监听键盘事件
-	window.addEventListener('keydown', function(event) {
+	isDev && window.addEventListener('keydown', function(event) {
 		if (event.ctrlKey && event.shiftKey && (event.key === 'I' || event.key === 'J')) {
 			event.preventDefault(); // 阻止默认行为
 		}
 	});
 
-	window.addEventListener("keydown", ev => ev.key === "F12" && ev.preventDefault())
-	console.log(uid)
-
-	uid && document.body.addEventListener(
-		"touchstart",
-		(e) => {
-			e.preventDefault();
-		},
-		{ passive: false }
-	);
-	window.addEventListener('beforeprint', function() {
+	isDev && window.addEventListener("keydown", ev => ev.key === "F12" && ev.preventDefault())
+	
+	//permission === 0 && document.body.addEventListener(
+	//	"touchstart",
+	//	(e) => {
+	//		e.preventDefault();
+	//	},
+	//	{ passive: false }
+	//);
+	isDev && window.addEventListener('beforeprint', function() {
 		// 在打印或生成 PDF 前的操作
 		const noPrintElements = document.querySelectorAll('.no-print');
 		for (var i = 0; i < noPrintElements.length; i++) {
@@ -25,7 +25,7 @@ const useStopWindowContext = (uid: number) => {
 		}
 	});
 	
-	window.addEventListener('afterprint', function() {
+	isDev && window.addEventListener('afterprint', function() {
 		// 在打印或生成 PDF 后的操作
 		const noPrintElements = document.querySelectorAll('.no-print');
 		for (var i = 0; i < noPrintElements.length; i++) {
@@ -33,11 +33,11 @@ const useStopWindowContext = (uid: number) => {
 		}
 	});
 
-	document.addEventListener('selectstart', (event) => {
+	isDev && document.addEventListener('selectstart', (event) => {
 		event.preventDefault();
 	});
 	// 监听鼠标右键事件
-	window.addEventListener('contextmenu', function(event) {
+	isDev && window.addEventListener('contextmenu', function(event) {
 		event.preventDefault(); // 阻止默认行为
 	});
 	

+ 5 - 1
src/Hooks/useWeChatShare.ts

@@ -44,7 +44,7 @@ export const shareOptions: shareOptions[] = [
 		text: '您的好友给你分享了文件链接',
 	},
 	{
-		type: '5',
+		type: '4',
 		imageUrl: '',
 		text: '您的好友给你分享了文本链接',
 	},
@@ -67,6 +67,9 @@ const useWeChatShare = async (params: shareParams) => {
 		(Number(params.type) === 7 ? '/encyclopedia/detail-' : '/info/detail-') +
 		params.id +
 		'.html'
+	if (localStorage.getItem('isDetailRefresh')) {
+		localStorage.removeItem('isDetailRefresh')
+	}
 	if (!isWeChat()) return params.isShowToast && showToast('请在微信浏览器中分享')
 	const { data } = await getShareConfig({
 		appId: 'wx91c4152b60ca91a3',
@@ -97,6 +100,7 @@ const useWeChatShare = async (params: shareParams) => {
 			console.log(obj, '成功')
 		},
 		fail: () => {
+			window.location.reload()
 			console.log('失败', obj, location.href)
 		},
 		cancel: () => {

BIN
src/assets/logo_m.png


+ 43 - 0
src/components/docx-preview/docx-preview.vue

@@ -0,0 +1,43 @@
+<template>
+  <div class="docx-preview">
+    <vue-office-docx :src="url" @rendered="rendered" @error="errorHandler" />
+    <van-watermark
+      :image="waterImage"
+      opacity="0.2"
+    />
+  </div>
+</template>
+
+<script setup lang="ts">
+import { IProps } from "./index.type";
+import VueOfficeDocx from "@vue-office/docx";
+import "@vue-office/docx/lib/index.css";
+import { onMounted } from "vue";
+import waterImage from '@/assets/logo_m.png'
+
+const props = defineProps<IProps>();
+
+const rendered = (res: any) => {
+  console.log("渲染完成", res);
+};
+const errorHandler = (res: any) => {
+  console.log("渲染失败", res);
+};
+
+onMounted(() => {
+  console.log(props);
+});
+</script>
+
+<style scoped lang="scss">
+.docx-preview {
+  height: 100%;
+  background: $basicColor-content;
+	position: relative;
+}
+:deep() {
+  .van-watermark--full {
+    position: absolute;
+  }
+}
+</style>

+ 7 - 0
src/components/docx-preview/index.d.ts

@@ -0,0 +1,7 @@
+declare module '*.svg'
+declare module '@/assets/logo_m.png'
+declare module '*.jpg'
+declare module '*.jpeg'
+declare module '*.gif'
+declare module '*.bmp'
+declare module '*.tiff'

+ 4 - 0
src/components/docx-preview/index.type.ts

@@ -0,0 +1,4 @@
+export type IProps = {
+	url: string;
+	isPermi: boolean;
+}

+ 0 - 3
src/components/pdf-preview/index.ts

@@ -1,3 +0,0 @@
-// start:ng42.barrel
-// end:ng42.barrel
-

+ 32 - 27
src/components/pdf-preview/pdf-preview.vue

@@ -1,41 +1,33 @@
 <template>
-  <pdf-view
-    :source="state.source!"
-    :page="i"
-    v-for="i,index in state.numPages"
-    :key="index"
-  />
+  <div class="pdf">
+    <div id="pdfView"></div>
+  </div>
 </template>
 
 <script setup lang="ts">
-import PdfView from "vue-pdf-embed";
-import { createLoadingTask } from "vue3-pdfjs";
-import { reactive, onMounted } from 'vue';
-import type { IProps, IPDFPreview } from "./index.type";
+import Pdfh5 from "pdfh5/js/pdfh5.js";
+import "pdfh5/css/pdfh5.css";
+import { onMounted, nextTick } from "vue";
+import type { IProps } from "./index.type";
 
 const props = defineProps<IProps>();
 
 console.log(props);
+console.log(props.url)
+const initPDF = async () => {
+  await nextTick(() => {
+    const pdfh5 = new Pdfh5("#pdfView", {
+      pdfurl: props.url,
+    });
 
-const state = reactive<IPDFPreview>({
-  source: props.url,
-  scale: 1,
-  pageNum: 1,
-  numPages: 0, // 总页数
-});
-
-const initPDF = () => {
-  console.log("PDF链接", state.source);
-  const loadingTask = createLoadingTask(state.source!);
-  loadingTask.promise
-      .then((pdf: Pick<IPDFPreview, "numPages">) => {
-        console.log("pdf", pdf);
-        state.numPages = pdf.numPages;
-      })
+    pdfh5.on("complete", (status: string, msg: string, time: number) => {
+      console.log(status, msg, time);
+    });
+  });
 };
 onMounted(() => {
-	initPDF()
-})
+  initPDF();
+});
 </script>
 
 <style scoped lang="scss">
@@ -53,4 +45,17 @@ img {
   -ms-user-select: none;
   user-select: none;
 }
+#pdfView {
+  width: 100vw;
+  height: 100%;
+}
+.pdf {
+  width: 100vw;
+  height: 100vh;
+}
+:deep() {
+  .pdfjs .backTop, .pageNum {
+    display: none !important;
+  }
+}
 </style>

+ 56 - 0
src/components/ppt-preview/ppt-preview.vue

@@ -0,0 +1,56 @@
+<template>
+  <div class="preview">
+		<iframe :src="`https://view.officeapps.live.com/op/view.aspx?src=${encodeURIComponent(url)}`" frameborder="0"></iframe>
+	</div>
+</template>
+
+<script setup lang="ts">
+import { IProps } from "../pdf-preview/index.type";
+import { onMounted } from 'vue';
+
+const props = defineProps<IProps>();
+
+const toBlob = (url: string) => {
+  return new Promise((resolve, reject) => {
+    fetch(url)
+      .then((response) => response.blob())
+      .then((blob) => {
+        resolve(blob);
+      })
+      .catch((err) => reject(err));
+  });
+};
+
+const toArrayBuffer = (blob: Blob): Promise<ArrayBuffer> => {
+	return new Promise((resolve) => {
+		const reader = new FileReader()
+		reader.onload = () => resolve(reader.result as ArrayBuffer);
+		reader.readAsArrayBuffer(blob)
+	})
+}
+
+const initData = async () => {
+  const b = await toBlob(props.url);
+	const ab = await toArrayBuffer(b as Blob);
+	console.log(props.url, ab);
+};
+
+onMounted(() => {
+	initData()
+})
+</script>
+
+<style scoped lang="scss">
+.preview {
+  position: fixed;
+  top: 0;
+  left: 0;
+  width: 100vw;
+  max-height: 100vh;
+  overflow: auto;
+	iframe {
+		width: 100%;
+		height: 100vh;
+	}
+}
+</style>

+ 16 - 0
src/components/text-preview/text-preview.vue

@@ -0,0 +1,16 @@
+<template>
+	<div class="text-preview" v-html="content"></div>
+</template>
+
+<script setup lang="ts">
+const props = defineProps<{ content: string, maxHeight: string }>()
+console.log(props.content)
+</script>
+
+<style scoped lang="scss">
+.text-preview {
+	width: 100%;
+  max-height: v-bind(maxHeight);
+  line-height: 21px;
+}
+</style>

+ 2 - 2
src/components/video-preview/index.type.ts

@@ -5,6 +5,6 @@ export type IProps = {
 export type IVideoOptions = {
 	currentTime: number;
 	allTime: number;
-	width: string
-	height: string
+	width?: string
+	height?: string
 }

+ 7 - 3
src/components/video-preview/video-preview.vue

@@ -28,8 +28,8 @@ const myVideoRef = ref<HTMLVideoElement | null>(null);
 const resultVideo = reactive<IVideoOptions>({
   currentTime: 0,
   allTime: 0,
-  width: "100vw",
-  height: "100vh",
+  width: "100%",
+  height: "210px",
 });
 
 const handleTimeUpdate = () => {
@@ -42,7 +42,11 @@ onMounted(async () => {
 });
 </script>
 
-<style lang="scss">
+<style lang="scss" scoped>
+.video-content {
+  width: 100%;
+  max-height: 210px;
+}
 video::-internal-media-controls-download-button {
   display: none;
 }

+ 12 - 12
src/router/route.ts

@@ -57,14 +57,6 @@ export const staticRouter: Array<RouteRecordRaw> = [
 			title: '登录'
 		}
 	},
-	{
-		path: '/preview',
-		name: 'preview',
-		component: () => import('@/views/Preview/index.vue'),
-		meta: {
-			title: '文件预览'
-		}
-	}, 
 	{
 		path: '/database',
 		name: 'database',
@@ -75,7 +67,7 @@ export const staticRouter: Array<RouteRecordRaw> = [
 				name: 'All',
 				component: () => import('@/views/Database/data-all/index.vue'),
 				meta: {
-					title: '文件资料',
+					title: '内容库',
 				}
 			},
 			//{
@@ -94,7 +86,7 @@ export const staticRouter: Array<RouteRecordRaw> = [
 		name: 'Detail',
 		component: () => import('@/views/Database/detail.vue'),
 		meta: {
-			title: '文件详情',
+			title: '内容库',
 		}
 	},
 	{
@@ -102,7 +94,15 @@ export const staticRouter: Array<RouteRecordRaw> = [
 		name: 'Add',
 		component: () => import('@/views/Database/add.vue'),
 		meta: {
-			title: '新增个人话术'
+			title: '内容库'
 		}
-	}
+	},
+	{
+		path: '/preview',
+		name: 'preview',
+		component: () => import('@/views/Preview/index.vue'),
+		meta: {
+			title: '内容库'
+		}
+	},
 ]

+ 3 - 2
src/types/api/context.type.ts

@@ -34,7 +34,7 @@ export interface DArchiveResultData extends IArchiveRequest { // 列表返回
 	productArchiveId?: number
 	productClassify?: number
 	keywords?: string
-	pv?: string
+	pv?: string | number
 	link?: string
 }
 
@@ -66,6 +66,7 @@ export type IPreviewForm = {
 	productId: string
 	id?: string
 	image: string
+	content: string
 }
 export type DPreviewResultData = IResultData<IPreviewForm>
 export interface ILabelKeyRequest extends IGlobalListRequest { // 参数
@@ -80,7 +81,7 @@ export interface IArchiveRequest { // 参数
 	userId?: string
 	type?: ChangeTabEmit | string
 	productId?: number | string
-	stageStatus?: string | null
+	stageStatus?: string | number | null
 	allStatus?: string | number | null
 	labelId?: string
 	labelIds?: string

+ 18 - 16
src/types/views/database.type.ts

@@ -30,6 +30,7 @@ export type DetailParams = {
   type: ChangeTabEmit
   pageNum?: number
   content?: string
+  index?: number
   allStatus?: DFindParams<IAllStatus, "allStatus">
 }
 
@@ -43,25 +44,17 @@ export const tabList: Array<DScrollTab> = [
     type: '0',
     text: "全部",
   },
-  {
-    type: '1',
-    text: "图片",
-  },
-  {
-    type: '2',
-    text: "视频",
-  },
   {
     type: '3',
     text: "文件",
   },
   {
-    type: '4',
-    text: "文本",
+    type: '2',
+    text: "视频",
   },
   {
-    type: '5',
-    text: "话术",
+    type: '1',
+    text: "图片",
   },
   {
     type: '6',
@@ -71,6 +64,14 @@ export const tabList: Array<DScrollTab> = [
     type: '7',
     text: "百科",
   },
+  {
+    type: '4',
+    text: "文本",
+  },
+  {
+    type: '5',
+    text: "话术",
+  },
 ]
 export const menuTypeOptions = reactive<Array<DMenuList<DMenu>>>([
   {
@@ -95,22 +96,22 @@ export const menuTypeOptions = reactive<Array<DMenuList<DMenu>>>([
       },
       {
         text: "认知阶段<span>(仅浏览过或咨询过一次该商品的用户)</span>",
-        subtitle: "",
+        subtitle: "认知阶段",
         value: 1,
       },
       {
         text: "兴趣阶段<span>(已咨询过该商品,且有过多次浏览搜索该商品的用户)</span>",
-        subtitle: "",
+        subtitle: "兴趣阶段",
         value: 2,
       },
       {
         text: "决策阶段<span>(多次询问商品且与同类商品比价,想要体验该商品的用户)</span>",
-        subtitle: "",
+        subtitle: "决策阶段",
         value: 3,
       },
       {
         text: "购买阶段<span>(正在走采购流程或已经将商品加入购物车的用户)</span>",
-        subtitle: "",
+        subtitle: "购买阶段",
         value: 4,
       },
     ],
@@ -136,6 +137,7 @@ export interface DEmit {
 export interface DDataBaseListAll {
   type: ChangeTabEmit
   showMore: boolean
+  index?: number
   dataList: DArchiveResultData[]
 }
 

+ 1 - 0
src/util/toArrayBuffer.ts

@@ -0,0 +1 @@
+const toArrayBuffer = () => {}

+ 6 - 2
src/views/Database/components/context-contain.vue

@@ -1,5 +1,5 @@
 <template>
-  <div class="box">
+  <div class="box" :style="{paddingBottom: route.query.t === '5' ? '100px' : ''}">
     <slot name="head" :data="props" />
     <div v-for="(d, i) in dataList" :key="i">
       <div class="shareFile">
@@ -14,6 +14,8 @@
         :waters="d.waters"
         :content="d.content"
         :image="d.image"
+        :keywords="d.keywords"
+        :stage-status="d.stageStatus"
         @click="d.type === '5' && router.push('/database/detail?id=' + d.id + '&t=' + d.type)"
       />
     </div>
@@ -34,8 +36,9 @@
 import { DDataBaseListAll, DEmit } from "@/types/views/database.type";
 import FileContent from "./file-content.vue";
 import { ref, computed } from 'vue';
-import { useRouter } from 'vue-router'
+import { useRouter, useRoute } from 'vue-router'
 const router = useRouter()
+const route = useRoute()
 const pageNum = ref<number>(1);
 const emit = defineEmits<DEmit>();
 
@@ -55,6 +58,7 @@ const handleSeeMore = () => {
   emit("handle-see-more", {
     type: props.type,
     pageNum: pageNum.value,
+    index: props.index
   });
   console.log(`点击了${btnLabel.value}`);
 };

+ 10 - 10
src/views/Database/components/context-head.vue

@@ -23,7 +23,7 @@ import {
   tabList,
   allStatusList,
 } from "@/types/views/database.type";
-import { ref, computed, watch } from "vue";
+import { ref, computed, watch } from 'vue';
 import { DTabStore } from "@/store/tab/tab.type";
 import { useRoute } from "vue-router";
 const route = useRoute();
@@ -35,15 +35,15 @@ const form = ref<Pick<DTabStore, 'type'> & Pick<DTabStore, 'allStatus'>>({
   allStatus: "1",
 });
 const emit = defineEmits<DEmit>();
-//watch(
-//  () => route.query,
-//  () => {
-//    form.value.allStatus = '1'
-//  },
-//  {
-//    immediate: true,
-//  }
-//);
+watch(
+  () => route.query,
+  () => {
+    form.value.allStatus = '1'
+  },
+  {
+    deep: true,
+  }
+);
 watch(
   () => form.value.allStatus,
   () => {

+ 3 - 2
src/views/Database/components/context-share.vue

@@ -34,9 +34,10 @@ const { serviceProviderId } = useUserInfoState();
 const router = useRouter();
 
 const imageLink = computed<string>(() => {
-  if (props.type !== "1") return props.image as string;
-  else return getFileImg(props.waters![0]).img as string;
+  if (props.type !== "3") return props.image as string;
+  else return getFileImg(props.waters![0].split('?')[0]).img as string;
 });
+console.log(imageLink.value)
 const controlText = computed<DFindParams<DScrollTab, "text">>(
   () => tabList.filter((e) => e.type === props.type)[0].text
 );

+ 7 - 4
src/views/Database/components/file-content.vue

@@ -20,10 +20,10 @@
 				:image="image"
       />
     </div>
-    <div class="foot">
-      <div class="mark">随便看看</div>
-      <div class="mark">{{ shopName }}</div>
-      <div class="mark">{{ keywords }}</div>
+    <div class="foot" v-if="type !== '6' && type !== '7'">
+      <div class="mark">{{ stageStatus ? menuTypeOptions[2].options.filter(e => e.value === stageStatus)[0].subtitle : '' }}</div>
+      <div class="mark">{{ filtContext(shopName!) }}</div>
+      <div class="mark">{{ filtContext(keywords!) }}</div>
     </div>
   </div>
 </template>
@@ -32,11 +32,14 @@
 import VideoImgContent from "./video-img-content.vue";
 import TextFileContent from "./text-file-content.vue";
 import { DArchiveResultData } from "@/types/api/context.type";
+import { menuTypeOptions } from '@/types/views/database.type';
 
 const props = defineProps<DArchiveResultData>();
 
 const showVideoImgContent = (): boolean =>
   ["1", "2", "4"].indexOf(props.type as string) !== -1;
+
+const filtContext = (str: string): string => str ? str.split(',').join('、').slice(0, 8) + '...' : ''
 </script>
 
 <style lang="scss" scoped>

+ 15 - 10
src/views/Database/components/high-light-text.vue

@@ -1,24 +1,29 @@
 <template>
-  <van-highlight
-    :keywords="keywords"
-    :source-string="text"
-    v-if="keywords"
-    highlight-class="custom-class"
-  />
-  <div v-else>{{ text }}</div>
+  <div v-if="keywords" :class="isTitle && 'text'">
+    <van-highlight
+      :keywords="keywords"
+      :source-string="text"
+      highlight-class="custom-class"
+    />
+  </div>
+  <div v-else :class="isTitle && 'text'">{{ text }}</div>
 </template>
 
 <script setup lang="ts">
 defineProps<{
   keywords: string;
   text: string;
+  isTitle: boolean;
 }>();
 </script>
 
 <style scoped lang="scss">
 :deep() {
-	.custom-class {
-		color: $basicColor;
-	}
+  .custom-class {
+    color: $basicColor;
+  }
+}
+.text {
+  @include webkit-line-clamp(2);
 }
 </style>

+ 43 - 0
src/views/Database/components/image-content.vue

@@ -0,0 +1,43 @@
+<template>
+	<div class="img-content" v-if="type === '1'">
+		<div class="item" v-for="(img, i) in props.waters" :key="i">
+			<van-image
+				fit="contain"
+				width="100%"
+				height="100%"
+				:src="img"
+				@click.native="shopImagePreviews(i)"
+			/>
+		</div>
+	</div>
+</template>
+
+<script setup lang="ts">
+import { ChangeTabEmit } from '@/types/views/database.type';
+import { showImagePreview } from "vant";
+const props = defineProps<{
+	waters: string[]
+	type: ChangeTabEmit
+}>()
+
+const shopImagePreviews = (index: number) => {
+  console.log(index);
+  showImagePreview({
+    images: props.waters,
+    startPosition: index,
+  });
+};
+</script>
+
+<style scoped lang="scss">
+.img-content {
+	display: grid;
+	grid-template-columns: repeat(3, 1fr);
+	grid-gap: 12px;
+	.item {
+		border: 1px solid #e1e1e1;
+		width: 106px;
+		height: 106px;
+	}
+}
+</style>

+ 25 - 17
src/views/Database/components/search-head.vue

@@ -2,8 +2,9 @@
   <div class="search-head">
     <van-search
       v-model="value"
-      placeholder="请输入搜索关键词"
-      @search="emit('handle-search-emit', value)">
+      placeholder="搜索"
+      @search="emit('handle-search-emit', value)"
+    >
       <template #right-icon>
         <van-icon name="https://static.caimei365.com/app/mini-database/search.png" />
       </template>
@@ -22,14 +23,15 @@
         <template v-if="o === 0">
           <van-search
             v-model="labelKeyParams.v"
-            placeholder="请输入搜索关键词"
-            @search="reqLabelKeyList">
+            placeholder="搜索标签"
+            @search="reqLabelKeyList"
+          >
           </van-search>
         </template>
         <template v-if="o === 1">
           <van-search
             v-model="storeParams.productName"
-            placeholder="请输入搜索关键词"
+            placeholder="搜索商品"
             @search="reqStoreList"
           />
         </template>
@@ -68,9 +70,7 @@
                   <span v-html="item.text" class="custom-title"></span>
                 </template>
                 <template #right-icon>
-                  <van-radio
-                    :name="item!.value"
-                  />
+                  <van-radio :name="item!.value" />
                 </template>
               </van-cell>
             </van-cell-group>
@@ -88,6 +88,8 @@ import { menuTypeOptions } from "@/types/views/database.type";
 import { getLabelKeyList, getStoreList } from "@/api/context/context";
 import { CheckboxInstance } from "vant";
 import { ILabelKeyRequest, IStoreRequest } from "@/types/api/context.type";
+import { useTabStore } from "@/store/tab/tab";
+const {searchValue, labelIds } = useTabStore();
 const activePadding = ref<string>("20vw 1vw 1vw 1vw"); // vue 样式
 const handleOpen = (val: number) => {
   activePadding.value = val < 2 ? "20vw 1vw 1vw 1vw" : "5vw 1vw 1vw 1vw";
@@ -102,8 +104,8 @@ const labelKeyParams = ref<ILabelKeyRequest>({
   pageSize: 10,
   v: "",
 }); // 搜索条件
-const value = ref<string>(""); // 标题搜索
-const checked = ref<Array<number | null>>([]); // 默认选中 多选
+const value = ref<string>(searchValue || ""); // 标题搜索
+const checked = ref<Array<number | null>>(labelIds?.split(',').map(e => Number(e)) || []); // 默认选中 多选
 const checkboxRefs = ref<Array<CheckboxInstance | VNodeRef>>([]); // 多选默认
 
 const checkHistoryList = ref<Array<DMenu>>([]);
@@ -139,11 +141,17 @@ const reqLabelKeyList = async () => {
   const { data } = await getLabelKeyList(labelKeyParams.value);
   menuTypeOptions[0]!.options = [
     ...checkHistoryList.value,
-    ...data!.list!.map((e) => ({
-      text: e.v,
-      value: Number(e.k),
-    })),
-  ];
+    ...data!
+      .list!.map((o) => {
+        if (!checkHistoryList.value!.some((e) => e.value === Number(o.k))) {
+          return {
+            text: o.v,
+            value: Number(o.k),
+          };
+        }
+      })
+      .filter((o) => o),
+  ].filter((_,i) => i < 10);
 };
 const reqStoreList = async () => {
   const { data } = await getStoreList(storeParams.value);
@@ -153,7 +161,7 @@ const reqStoreList = async () => {
       text: e.productName,
       value: e.productId,
     })),
-  ];
+  ].filter((_,i) => i < 10);
 };
 onMounted(() => {
   reqLabelKeyList();
@@ -247,7 +255,7 @@ onBeforeUpdate(() => {
   }
   .van-dropdown-menu__title:after {
     border: 4px solid;
-    border-color: transparent transparent #B1B1B1 #B1B1B1;
+    border-color: transparent transparent #b1b1b1 #b1b1b1;
     transform: translateY(-16%) rotate(-45deg);
   }
   .van-dropdown-menu__title--active::before {

+ 14 - 6
src/views/Database/components/text-file-content.vue

@@ -1,13 +1,13 @@
 <template>
   <div class="file">
-    <div class="image" v-if="type !== '5'">
+    <div class="image" v-if="type !== '5' && (image || props?.waters![0])">
       <van-image fit="contain" :src="image" v-if="type === '6' || type === '7'" />
-      <van-image fit="contain" :src="getFileImg(props?.waters as string).img" v-else />
+      <van-image fit="contain" :src="getFileImg(props?.waters![0].split('?')[0] as string).img" v-else />
     </div>
     <div class="title">
-      <div class="t1"><high-light-text :keywords="searchValue" :text="title!" /></div>
+      <div class="t1"><high-light-text v-if="title" :keywords="searchValue" :text="title!" :is-title="true"/></div>
       <div class="t2" v-if="!showFileContent()">
-        <high-light-text :keywords="searchValue" :text="title!" />
+        <high-light-text v-if="content" :keywords="searchValue" :text="content!" :is-title="false"/>
       </div>
     </div>
   </div>
@@ -17,13 +17,20 @@
 import highLightText from "./high-light-text.vue";
 import { DArchiveResultData } from "@/types/api/context.type";
 import { useTabStore } from "@/store/tab/tab";
-import { toRefs } from "vue";
+import { toRefs, computed } from 'vue';
 import getFileImg from "@/Hooks/useFileImage";
 
 const { searchValue } = toRefs(useTabStore());
 const props = defineProps<DArchiveResultData>();
 
 const showFileContent = (): boolean => ["3", "6"].indexOf(props.type as string) !== -1;
+const widthStyle = computed<string>(() => {
+  if (props.type === '5') {
+    return '100%';
+  } else {
+    return 'calc(100% - 75px)'
+  }
+})
 </script>
 
 <style lang="scss" scoped>
@@ -37,12 +44,13 @@ const showFileContent = (): boolean => ["3", "6"].indexOf(props.type as string)
     margin-right: 12px;
   }
   .title {
+    width: v-bind(widthStyle);
     font-size: $basicFS;
-    width: calc(100% - 75px);
     display: flex;
     justify-content: space-around;
     flex-direction: column;
     height: 63px;
+    line-height: 21px;
     .t1 {
       color: $basicColor-content;
       @include webkit-line-clamp(1);

+ 36 - 69
src/views/Database/components/video-img-content.vue

@@ -1,34 +1,23 @@
 <template>
   <div>
     <div class="text-title">
-      <high-light-text :keywords="searchValue" :text="props.title!" />
-    </div>
-    <div class="img-content" v-if="type === '1'">
-      <div class="item" v-for="(img, i) in waters" :key="i">
-        <van-image
-          fit="contain"
-          :src="img"
-          @click.native="shopImagePreviews(i)"
-        />
-      </div>
-    </div>
-    <div class="video-tontent" v-if="type === '2'">
-      <video
-        id="myVideoRef"
-        ref="myVideoRef"
-        class="video-js vjs-default-skin"
-        controls
-        autoplay
-        x5-video-player-fullscreen="true"
-        x5-video-player-type="h5"
-        controlslist="nodownload"
-      >
-        <source :src="waters![0]" />
-      </video>
-    </div>
-    <div class="text-content" v-if="type === '4'">
-      <div v-html="content" />
+      <high-light-text
+        v-if="props.title"
+        :keywords="searchValue"
+        :text="props.title!"
+        :is-title="true"
+      />
     </div>
+    <image-content
+      v-if="type === '1' && waters"
+      :waters="(waters as string[])"
+      :type="type"
+    />
+    <video-preview
+      v-if="type === '2' && fileUrl"
+      :url="fileUrl"
+    />
+    <text-preview v-if="type === '4' && content" :content="content" :max-height="'50vh'" />
   </div>
 </template>
 
@@ -36,21 +25,20 @@
 import { useTabStore } from "@/store/tab/tab";
 import highLightText from "./high-light-text.vue";
 import { DArchiveResultData } from "@/types/api/context.type";
-import { showImagePreview } from "vant";
-import { toRefs } from 'vue';
-const { searchValue } = toRefs(useTabStore())
-
-const props = defineProps<DArchiveResultData>()
+import { toRefs, computed } from "vue";
+import ImageContent from "./image-content.vue";
+const { searchValue } = toRefs(useTabStore());
 
-console.log('图片文件', props.waters)
+const props = defineProps<DArchiveResultData>();
 
-const shopImagePreviews = (index: number) => {
-  console.log(index);
-  showImagePreview({
-    images: props.waters as string[],
-    startPosition: index,
-  });
-};
+const fileUrl = computed<string>(() => {
+  if (props.type === "2" && props.waters!.length > 0) {
+    return props.waters![0].split("?")[0];
+  } else {
+    return "";
+  }
+});
+console.log("图片文件", props.waters);
 </script>
 
 <style scoped lang="scss">
@@ -71,40 +59,19 @@ const shopImagePreviews = (index: number) => {
     height: 106px;
   }
 }
-.video-tontent {
-  width: 100%;
-  height: 210px;
-  video {
-    height: 100%;
-    width: 100%;
-  }
-}
-.text-content {
-  width: 100%;
-  height: 221px;
-}
-video::-internal-media-controls-download-button {
-  display: none;
-}
-video::-webkit-media-controls-enclosure {
-  overflow: hidden;
-}
-video::-webkit-media-controls-panel {
-  width: calc(100% + 30px);
-}
 :deep() {
   .van-image {
     width: 100%;
     height: 100%;
   }
   .van-popup--center {
-		.van-swipe__track,
-		.van-swipe-item {
-			width: 100% !important;
-		}
-		.van-image-preview__index {
-			display: none;
-		}
-	}
+    .van-swipe__track,
+    .van-swipe-item {
+      width: 100% !important;
+    }
+    .van-image-preview__index {
+      display: none;
+    }
+  }
 }
 </style>

+ 24 - 29
src/views/Database/data-all/index.vue

@@ -4,7 +4,8 @@
       :type="data.type"
       :data-list="data.dataList"
       :show-more="data.showMore"
-      v-if="data.dataList.length > 0 && data.type !== '0' && data.type !== '5'"
+      v-if="data.type !== '0' && isShowType(data)"
+      :index="i"
       @handle-see-more="handleSeeMore"
     >
       <template #head="{ data }">
@@ -18,25 +19,11 @@
           :all-status="data.allStatus"
           :image="data.image"
           :waters="data.waters"
+          :pv="data.pv"
         />
       </template>
     </context-contain>
-    <!--<context-contain
-      :type="data.type"
-      :data-list="data.dataList"
-      :show-more="showSeeMore"
-      v-if="isShowType && data.type === '5'"
-      @handle-see-more="handleSeeMore"
-    >
-      <template #head="{ data }">
-        <context-head :type="data.type" @handle-all-status="handleAllStatus" />
-      </template>
-      <template #share="{ data }">
-        <context-share v-if="isShowType && data.type === '5'" :type="data.type!" :id="data.id" :content="data.content" :all-status="data.allStatus" />
-      </template>
-    </context-contain>-->
   </div>
-  <div v-if="isEmpty && route.query.t !== '5'" class="empty">暂无任何文件~</div>
   <div class="bottom-btn" v-if="reqParams.type === '5' && isAddStatus">
     <data-button
       @handle-emit="router.push('/database/add')"
@@ -79,7 +66,13 @@ const reqParams = computed<IArchiveRequest>(
 );
 const isAddStatus = ref<boolean>(false);
 const isEmpty = ref<boolean>(false);
-const isShowType = ref<boolean>(false);
+const isShowType = (data: DDataBaseListAll): boolean => {
+  if (routeQuery(route.query.t) !== "") {
+    return routeQuery(route.query.t) === data.type;
+  } else {
+    return true;
+  }
+};
 const formParams = ref({ allStatus: "1" });
 const reqArchiveList = async (res?: DetailParams) => {
   if (!res) {
@@ -101,32 +94,34 @@ const reqArchiveList = async (res?: DetailParams) => {
       waters: myDecrypt(e.waters! as string[]),
     }));
     if (res.allStatus || res.pageNum === 1) {
-      dataList.value![res.type]!.dataList = [];
+      dataList.value![res.index!]!.dataList = [];
     }
-    dataList.value![res.type]!.dataList = [
-      ...dataList.value![res.type]!.dataList,
+    dataList.value![res.index!]!.dataList = [
+      ...dataList.value![res.index!]!.dataList,
       ...DcreptoList!,
     ];
     isEmpty.value =
-      dataList.value![res.type]!.dataList.length === 0 && reqParams.value.type !== "";
-    dataList.value![res.type]!.showMore = res.pageNum! > 1 && data?.length! < 5;
+      dataList.value![res.index!]!.dataList.length === 0 && reqParams.value.type !== "";
+    dataList.value![res.index!]!.showMore = res.pageNum! > 1 && data?.length! < 5;
   }
 };
 watch(
   () => route.query,
-  (val) => {
-    console.log("路由变化", val);
-    isShowType.value = route.query.t === "0" || route.query.t === "5";
-    formParams.value.allStatus = "1";
-    reqArchiveList();
+  () => {
+    console.log("路由变化", route);
+    if (route.path === '/database/index') {
+      formParams.value.allStatus = "1";
+      reqArchiveList();
+    }
   },
   {
+    deep: true,
     immediate: true,
   }
 );
 
 const handleSeeMore = ($event: DetailParams) => {
-  console.log("查看更多");
+  console.log("查看更多", $event.index);
   reqArchiveList($event);
 };
 const handleAllStatus = ($event: DetailParams) => {
@@ -139,7 +134,7 @@ const handleAllStatus = ($event: DetailParams) => {
 
 <style lang="scss" scoped>
 .bottom-btn {
-  position: absolute;
+  position: fixed;
   bottom: 0;
   left: 0;
   padding: 24px 28px;

+ 71 - 105
src/views/Database/detail.vue

@@ -1,7 +1,8 @@
 <template>
   <div class="detail">
     <div class="other" v-if="type === '5'">
-      {{ form?.allStatus === 2 ? '个人话术' : '企业话术' }}<span v-if="form?.allStatus === 1">已使用:{{ form?.pv || 0 }}次</span>
+      {{ form?.allStatus === 2 ? '个人话术' : '企业话术'
+      }}<span v-if="form?.allStatus === 1">已使用:{{ form?.pv || 0 }}次</span>
     </div>
     <div class="time">{{ form?.addTime }}</div>
     <div class="title">{{ form?.title }}</div>
@@ -9,115 +10,86 @@
       {{ form?.content }}
     </div>
     <div class="content" v-if="type !== '5'">
-      <div v-html="form?.content" v-if="type === '4'" />
+      <text-preview v-if="type === '4' && form?.content" :content="form?.content" :max-height="'50vh'" />
       <div class="file-content" v-if="type === '3'">
-        <van-image :src="getFileImg(form?.waters as string).img" />
-      </div>
-      <div class="img-content" v-if="type === '1'">
-        <div class="item" v-for="(img, i) in form?.waters" :key="i">
-          <van-image
-            fit="contain"
-            width="100%"
-            height="100%"
-            :src="img"
-            @click.native="shopImagePreviews(i)"
-          />
-        </div>
-      </div>
-      <div class="video-tontent" v-if="type === '2'">
-        <video
-          id="myVideoRef"
-          ref="myVideoRef"
-          class="video-js vjs-default-skin"
-          controls
-          autoplay
-          x5-video-player-fullscreen="true"
-          x5-video-player-type="h5"
-          controlslist="nodownload"
-        >
-          <source :src="(form?.waters as string)" />
-        </video>
+        <van-image v-if="form?.waters![0]" :src="getFileImg(form?.waters[0].split('?')[0]).img" />
       </div>
+      <image-content v-if="type === '1' && form?.waters" :waters="(form?.waters! as string[])"
+        :type="(form?.type! as ChangeTabEmit)" />
+      <video-preview v-if="type === '2' && form?.waters![0].split('?')[0]" :url="form?.waters![0].split('?')[0]" />
     </div>
     <p class="foot-mark">随便看看</p>
     <p class="foot-mark">{{ form?.shopName }}</p>
-    <p class="foot-mark">{{ form?.keywords }}</p>
+    <p class="foot-mark">{{ form?.keywords?.split(',').join('、') }}</p>
     <div class="data-btn">
-      <data-button
-        @handle-emit="handleClick"
-        backgroundColor="#FFF"
-        color="#FF5B00"
-        label="查看文件"
-        v-if="type === '3'"
-      />
-      <data-button
-        @handle-emit="useCopyText(form?.content!, form?.id as string)"
-        backgroundColor="#FFF"
-        color="#FF5B00"
-        label="复制文本"
-        v-if="type === '5'"
-      />
-      <data-button
-        @handle-emit="useWeChatShare({ type: form?.type!, id: form?.id!, imageUrl: imageLink, spId: serviceProviderId as number, isShowToast: true })"
-        backgroundColor="#FFF"
-        color="#FF5B00"
-        label="分享"
-        v-if="type !== '5'"
-      />
+      <data-button @handle-emit="handleClick" backgroundColor="#FFF" color="#FF5B00" label="查看文件" v-if="type === '3'" />
+      <data-button @handle-emit="useCopyText(form?.content!, form?.id as string)" backgroundColor="#FFF" color="#FF5B00"
+        label="复制文本" v-if="type === '5'" />
+      <data-button @handle-emit="
+        useWeChatShare({
+          type: form?.type!,
+          id: form?.id!,
+          imageUrl: imageLink,
+          spId: serviceProviderId as number,
+          isShowToast: true,
+        })
+        " backgroundColor="#FFF" color="#FF5B00" label="分享" v-if="type !== '5'" />
     </div>
   </div>
 </template>
 
 <script setup lang="ts">
-import useCopyText from "@/Hooks/useCopyText";
-import useWeChatShare from "@/Hooks/useWeChatShare";
-import { getArchiveFormDetails } from "@/api/context/context";
-import { DArchiveResultData } from "@/types/api/context.type";
-import { ChangeTabEmit } from "@/types/views/database.type";
-import { showImagePreview } from "vant";
-import { computed, onMounted, ref } from "vue";
-import { useRoute, useRouter } from "vue-router";
-import getFileImg from "@/Hooks/useFileImage";
-import { useUserInfoState } from "@/store/user/user";
-import { myDecrypt } from "@/util/authStorage";
-const route = useRoute();
-const router = useRouter();
-const { userId, serviceProviderId } = useUserInfoState();
-const form = ref<DArchiveResultData>();
-const id = computed<string>(() => String(route.query.id));
-const type = computed<ChangeTabEmit>(() => route.query.t as ChangeTabEmit);
+import useCopyText from '@/Hooks/useCopyText'
+import useWeChatShare from '@/Hooks/useWeChatShare'
+import ImageContent from './components/image-content.vue'
+import { getArchiveFormDetails } from '@/api/context/context'
+import { DArchiveResultData } from '@/types/api/context.type'
+import { ChangeTabEmit } from '@/types/views/database.type'
+import { computed, ref, onActivated } from 'vue'
+import { useRoute, useRouter } from 'vue-router'
+import getFileImg from '@/Hooks/useFileImage'
+import { useUserInfoState } from '@/store/user/user'
+import { myDecrypt } from '@/util/authStorage'
+
+const route = useRoute()
+const router = useRouter()
+const { userId, serviceProviderId } = useUserInfoState()
+const form = ref<DArchiveResultData>()
+const id = computed<string>(() => String(route.query.id))
+const type = computed<ChangeTabEmit>(() => route.query.t as ChangeTabEmit)
+
 const handleClick = () => {
-  router.push("/preview?t=" + type.value + "&id=" + id.value + "&isSp=" + 1);
-};
+  router.push('/preview?t=' + type.value + '&id=' + id.value + '&isSp=' + 1)
+}
 const imageLink = computed<string>(() => {
-  if (form.value!.type !== '1') return form.value!.image as string
-  else return getFileImg(form.value!.waters![0]).img as string
+  if (form.value!.type !== '3') return form.value!.image as string
+  else return getFileImg(form.value!.waters![0].split('?')[0]).img as string
 })
 const getArchiveForm = async () => {
   const { data } = await getArchiveFormDetails({
     id: id.value,
     userId: userId as string,
-  });
-  const DcreptoList = { ...data, ...{ waters: myDecrypt(data!.waters! as string[]) } };
-  form.value = DcreptoList;
-  console.log(data);
-};
-const shopImagePreviews = (index: number) => {
-  console.log(index);
-  showImagePreview({
-    images: form.value?.waters! as string[],
-    startPosition: index,
-  });
-};
-
-onMounted(() => {
-  getArchiveForm();
-});
+  })
+  const DcreptoList = {
+    ...data,
+    ...{ waters: myDecrypt((data!.waters! || []) as string[]) },
+  }
+  form.value = DcreptoList
+  console.log(form.value.waters)
+}
+const move = () => {
+  document.body.style.position = 'static'
+}
+onActivated(() => {
+  getArchiveForm()
+  move()
+})
 </script>
 
 <style scoped lang="scss">
 .detail {
   padding: 24px 15px;
+
   .other {
     font-size: 15px;
     color: $basicColor-content;
@@ -125,6 +97,7 @@ onMounted(() => {
     font-weight: bold;
     display: flex;
     align-items: center;
+
     span {
       background: #f5f5f5;
       color: #666;
@@ -134,47 +107,37 @@ onMounted(() => {
       border-radius: 2px;
     }
   }
+
   .time {
     font-size: $basicFS;
     color: $basicColor-content;
     margin-bottom: 12px;
     font-weight: bold;
   }
+
   .title {
     font-size: $basicFS;
     color: $basicColor-content;
     margin-bottom: 8px;
+    line-height: 21px;
   }
+
   .text {
     font-size: $basicFS;
     color: $basicColor-foot;
     line-height: 21px;
     margin-bottom: 24px;
   }
+
   .content {
     margin-bottom: 18px;
-    .img-content {
-      display: grid;
-      grid-template-columns: repeat(3, 1fr);
-      grid-gap: 12px;
-      .item {
-        border: 1px solid #e1e1e1;
-        width: 106px;
-        height: 106px;
-      }
-    }
-    .video-tontent {
-      width: 100%;
-      height: 210px;
-      video {
-        height: 100%;
-        width: 100%;
-      }
-    }
+    line-height: 21px;
+
     .file-content {
       height: 128px;
       width: 100%;
       @include display-flex-center;
+
       :deep() {
         .van-image {
           width: 86px;
@@ -183,16 +146,19 @@ onMounted(() => {
       }
     }
   }
+
   .foot-mark {
     color: $basicColor-foot;
     font-size: $basicFS-foot;
     margin-bottom: 9px;
   }
+
   .data-btn {
     margin-top: 35px;
     padding: 0 13px;
   }
 }
+
 :deep() {
   .van-button {
     border: 1px solid $basicColor;

+ 1 - 1
src/views/Database/index.vue

@@ -17,7 +17,7 @@ import type {
   ChangeEmitParams,
   DScrollTab,
 } from "@/types/views/database.type";
-import { ref, toRefs } from "vue";
+import { ref, toRefs } from 'vue';
 import { useRouter } from "vue-router";
 import { DTabStore } from "@/store/tab/tab.type";
 const { type } = toRefs(useTabStore());

+ 6 - 3
src/views/Login/index.vue

@@ -6,15 +6,17 @@
           v-model="form.mobileOrEmail"
           name="mobileOrEmail"
           left-icon="https://static.caimei365.com/app/mini-database/phone.png"
-          placeholder="用户名"
+          placeholder="请输入手机号"
           autocomplete="off"
+          maxlength="11"
+          type="number"
         />
         <van-field
           v-model="form.password"
           type="password"
           name="password"
           left-icon="https://static.caimei365.com/app/mini-database/password.png"
-          placeholder="密码"
+          placeholder="请输入密码"
           autocomplete="off"
         />
       </van-cell-group>
@@ -51,7 +53,8 @@ const onSubmit = async () => {
     console.log(data);
     if (code === 0) {
       showLoadingToast(msg!)
-      router.replace('/database/index?t=0')
+      window.location.reload()
+      router.replace('/database/index?t=0&lId=&sv=&pId=&ss=')
     } else {
       showLoadingToast(msg!)
     }

+ 52 - 49
src/views/Preview/index.vue

@@ -2,78 +2,74 @@
   <video-preview
     v-if="params.type === '2' && fileUrl"
     :url="fileUrl"
-    :is-permi="isPermi"
   />
-  <pdf-preview v-if="params.type === '3' && fileUrl" :url="fileUrl" :is-permi="isPermi" />
+  <pdf-preview v-if="params.type === '3' && fileUrl && fileUrl.indexOf('.pdf')!==-1" :url="fileUrl" />
+  <docx-preview v-if="params.type === '3' && fileUrl && fileUrl.indexOf('.docx')!==-1" :url="fileUrl" />
+  <ppt-preview v-if="params.type === '3' && fileUrl && fileUrl.indexOf('.pptx')!==-1" :url="fileUrl" />
   <image-preview
     v-if="params.type === '1' && form?.waters"
     :urls="form?.waters"
-    :is-permi="isPermi"
   />
-  <permi-mode v-if="!query.isSp" />
-  <!--<iframe frameborder="0" src="http://localhost:8009/login.html" />-->
-  <!--<div class="hidden">
-    <div>pageHide: {{ pageHide }}</div>
-    <div>visibility: {{ visibility }}</div>
-    <div>onbeforeLoad: {{ onbeforeLoad }}</div>
-  </div>-->
+  <text-preview v-if="params.type === '4' && form.content" :content="form.content" :max-height="'100vh'"/>
+  <permiNode v-if="!route.query.isSp && permiNode" />
 </template>
 
 <script lang="ts" setup>
 import { usePermission } from "@/Hooks/usePermission/usePermission";
 import { previewData } from "@/api/context/context";
 import useStatisticalTime from "@/Hooks/useStatisticalTime";
-import { onMounted, computed, onUnmounted, ref, watch } from 'vue';
+import { computed, onUnmounted, ref, watch, onActivated, ComponentOptions, shallowRef } from "vue";
 import { useRoute } from "vue-router";
 import { ChangeTabEmit } from "@/types/views/database.type";
-import useWeChatShare, { shareOptions, shareParams } from "@/Hooks/useWeChatShare";
+import { shareOptions, shareParams } from "@/Hooks/useWeChatShare";
 import { IPreviewForm } from "@/types/api/context.type";
 import { myDecrypt } from "@/util/authStorage";
 import useStopWindowContext from "@/Hooks/useStopWindowContext";
 import createWebShareCard from "@/Hooks/useCreateWebShareCard";
-const { query } = useRoute();
-
+import { showLoadingToast } from "vant";
+const route = useRoute();
+useStopWindowContext();
 const form = ref<IPreviewForm>({
   waters: [],
-  permission: 0,
+  permission: 1,
   productId: "0",
   fileArchiveList: [],
   image: "",
+  content: '',
+  id: ''
 });
-
-//if (!window.localStorage.getItem("pageHide")) {
-//  window.localStorage.setItem("pageHide", "2");
-//}
-//if (!window.localStorage.getItem("visibility")) {
-//  window.localStorage.setItem("visibility", "2");
-//}
-//if (!window.localStorage.getItem("onbeforeLoad")) {
-//  window.localStorage.setItem("onbeforeLoad", "2");
-//}
-//const pageHide = window.localStorage.getItem("pageHide");
-//const visibility = window.localStorage.getItem("visibility");
-//const onbeforeLoad = window.localStorage.getItem("onbeforeLoad");
+const permiNode = shallowRef<ComponentOptions | null>()
 const fileUrl = ref<string>();
-const { isPermi, PermiMode } = usePermission(form.value?.permission! as number); // 权限hook
 const params = computed<shareParams & { url: string }>(
   () =>
     (({
-      type: query?.t as ChangeTabEmit,
-      userId: query?.uid as string,
-      id: query?.id as string,
-      spId: query?.spId as string,
+      type: route.query?.t as ChangeTabEmit,
+      userId: route.query?.uid as string,
+      id: route.query?.id as string,
+      spId: route.query?.spId as string,
       imageUrl: form.value?.image,
-      url: query?.url as string,
+      url: route.query?.url as string,
     } as unknown) as shareParams & { url: string })
 );
-watch(() => params.value.url, () => {
-  fileUrl.value = params.value.url
-})
+watch(
+  () => route.query?.url,
+  (val) => {
+    if (val) {
+      setTimeout(() => {
+        console.log('传递的url 链接为:', [route.query?.url])
+        fileUrl.value = val as string
+      }, 1000)
+    }
+  },
+  {
+    immediate: true,
+  }
+);
 const getPreviewData = async () => {
   const { data } = await previewData({
-    userId: (query.uid as string) || "0",
-    id: query.id as string,
-    type: query.t as ChangeTabEmit,
+    userId: (route.query.uid as string) || "0",
+    id: route.query.id as string,
+    type: route.query.t as ChangeTabEmit,
   });
   const DcreptoList = {
     ...data,
@@ -81,7 +77,8 @@ const getPreviewData = async () => {
   } as IPreviewForm;
   form.value = DcreptoList;
   fileUrl.value = form.value.waters[0]?.split("?")[0];
-  console.log(form.value.waters);
+  const { PermiMode } = usePermission(route.query.isSp ? 0 : form.value?.permission! as number)
+  permiNode.value = PermiMode! as ComponentOptions
 };
 const statistical = useStatisticalTime((time) => {
   const t = Math.floor(time / 1000);
@@ -123,22 +120,28 @@ const statistical = useStatisticalTime((time) => {
       console.log("时间推送记录成功");
     });
 });
-useStopWindowContext(params.value.userId!);
-onUnmounted(() => {
-  statistical();
-});
-
-onMounted(() => {
-  const obj = shareOptions.filter(e => e.type === params.value.type)[0]
+const initData = () => {
+  fileUrl.value = "";
+  !route.query.isSp && showLoadingToast({
+    message: "加载中...",
+    forbidClick: true,
+  });
+  const obj = shareOptions.filter((e) => e.type === params.value.type)[0];
   if (!params.value.url) {
     getPreviewData();
   }
-  useWeChatShare(params.value);
+  //useWeChatShare(params.value);
   createWebShareCard({
     title: obj.text,
     description: obj.text,
     image: params.value.imageUrl!,
   });
+};
+onUnmounted(() => {
+  statistical();
+});
+onActivated(() => {
+  initData();
 });
 </script>
 

+ 10 - 1
src/vite-env.d.ts

@@ -16,4 +16,13 @@ declare module 'vue-pdf';
 
 declare module 'vue-video-player';
 
-declare module 'vue3-video-play'
+declare module 'pdfh5/js/pdfh5.js'
+
+declare module 'vue3-video-play'
+declare module '*.svg'
+declare module '@/assets/logo_m.png'
+declare module '*.jpg'
+declare module '*.jpeg'
+declare module '*.gif'
+declare module '*.bmp'
+declare module '*.tiff'

+ 1 - 1
tsconfig.json

@@ -26,6 +26,6 @@
 
     "types": ["element-plus/global"],
   },
-  "include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.tsx", "src/**/*.vue"],
+  "include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.tsx", "src/**/*.vue", "images.d.ts"],
   "references": [{ "path": "./tsconfig.node.json" }]
 }