xiebaomin 1 jaar geleden
bovenliggende
commit
ac157b8d8f

+ 1 - 0
components.d.ts

@@ -9,6 +9,7 @@ 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']
+    ElButton: typeof import('element-plus/es')['ElButton']
     ElForm: typeof import('element-plus/es')['ElForm']
     ElFormItem: typeof import('element-plus/es')['ElFormItem']
     ElInput: typeof import('element-plus/es')['ElInput']

+ 1 - 1
index.html

@@ -7,7 +7,7 @@
     <link rel="icon" type="image/svg+xml" href="/favicon.ico" />
     <meta name="viewport" content="width=device-width, initial-scale=1.0" />
     <meta name="viewport" content="user-scalable=no, width=device-width, initial-scale=1, maximum-scale=1" />
-    <title>内容库</title>
+    <title></title>
     <style>
       #app {
         width: 100vw;

+ 67 - 0
package-lock.json

@@ -11,6 +11,7 @@
         "@emotion/css": "^11.11.2",
         "@emotion/react": "^11.11.1",
         "axios": "^1.6.2",
+        "clipboard": "^2.0.11",
         "dommatrix": "^1.0.3",
         "element-plus": "^2.4.3",
         "nprogress": "^0.2.0",
@@ -2023,6 +2024,16 @@
         "fsevents": "~2.3.2"
       }
     },
+    "node_modules/clipboard": {
+      "version": "2.0.11",
+      "resolved": "https://registry.npmmirror.com/clipboard/-/clipboard-2.0.11.tgz",
+      "integrity": "sha512-C+0bbOqkezLIsmWSvlsXS0Q0bmkugu7jcfMIACB+RDEntIzQIkdr148we28AfSloQLRdZlYL/QYyrq05j/3Faw==",
+      "dependencies": {
+        "good-listener": "^1.2.2",
+        "select": "^1.1.2",
+        "tiny-emitter": "^2.0.0"
+      }
+    },
     "node_modules/color-convert": {
       "version": "1.9.3",
       "resolved": "https://registry.npmmirror.com/color-convert/-/color-convert-1.9.3.tgz",
@@ -2157,6 +2168,11 @@
         "node": ">=0.4.0"
       }
     },
+    "node_modules/delegate": {
+      "version": "3.2.0",
+      "resolved": "https://registry.npmmirror.com/delegate/-/delegate-3.2.0.tgz",
+      "integrity": "sha512-IofjkYBZaZivn0V8nnsMJGBr4jVLxHDheKSW88PyxS5QC4Vo9ZbZVvhzlSxY87fVq3STR6r+4cGepyHkcWOQSw=="
+    },
     "node_modules/dom-walk": {
       "version": "0.1.2",
       "resolved": "https://registry.npmmirror.com/dom-walk/-/dom-walk-0.1.2.tgz",
@@ -2520,6 +2536,14 @@
         "node": ">=4"
       }
     },
+    "node_modules/good-listener": {
+      "version": "1.2.2",
+      "resolved": "https://registry.npmmirror.com/good-listener/-/good-listener-1.2.2.tgz",
+      "integrity": "sha512-goW1b+d9q/HIwbVYZzZ6SsTr4IgE+WA44A0GmPIQstuOrgsFcT7VEJ48nmr9GaRtNu0XTKacFLGnBPAM6Afouw==",
+      "dependencies": {
+        "delegate": "^3.1.2"
+      }
+    },
     "node_modules/graceful-fs": {
       "version": "4.2.11",
       "resolved": "https://registry.npmmirror.com/graceful-fs/-/graceful-fs-4.2.11.tgz",
@@ -3449,6 +3473,11 @@
       "integrity": "sha512-vRUjqhyM/YWYzT+jsMk6tnl3NkY4A4soJ8uyh3O6Um+JXEQL9ozUCe7pqrxn3CSKokw0hw3nFStfskzpgYwR0g==",
       "dev": true
     },
+    "node_modules/select": {
+      "version": "1.1.2",
+      "resolved": "https://registry.npmmirror.com/select/-/select-1.1.2.tgz",
+      "integrity": "sha512-OwpTSOfy6xSs1+pwcNrv0RBMOzI39Lp3qQKUTPVVPRjCdNa5JH/oPRiqsesIskK8TVgmRiHwO4KXlV2Li9dANA=="
+    },
     "node_modules/semver": {
       "version": "7.5.4",
       "resolved": "https://registry.npmmirror.com/semver/-/semver-7.5.4.tgz",
@@ -3594,6 +3623,11 @@
       "resolved": "https://registry.npmmirror.com/through/-/through-2.3.8.tgz",
       "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg=="
     },
+    "node_modules/tiny-emitter": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmmirror.com/tiny-emitter/-/tiny-emitter-2.1.0.tgz",
+      "integrity": "sha512-NB6Dk1A9xgQPMoGqC5CVXn123gWyte215ONT5Pp5a0yt4nlEoO1ZWeCwpncaekPHXO60i47ihFnZPiRPjRMq4Q=="
+    },
     "node_modules/to-fast-properties": {
       "version": "2.0.0",
       "resolved": "https://registry.npmmirror.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz",
@@ -5529,6 +5563,16 @@
         "readdirp": "~3.6.0"
       }
     },
+    "clipboard": {
+      "version": "2.0.11",
+      "resolved": "https://registry.npmmirror.com/clipboard/-/clipboard-2.0.11.tgz",
+      "integrity": "sha512-C+0bbOqkezLIsmWSvlsXS0Q0bmkugu7jcfMIACB+RDEntIzQIkdr148we28AfSloQLRdZlYL/QYyrq05j/3Faw==",
+      "requires": {
+        "good-listener": "^1.2.2",
+        "select": "^1.1.2",
+        "tiny-emitter": "^2.0.0"
+      }
+    },
     "color-convert": {
       "version": "1.9.3",
       "resolved": "https://registry.npmmirror.com/color-convert/-/color-convert-1.9.3.tgz",
@@ -5645,6 +5689,11 @@
       "resolved": "https://registry.npmmirror.com/delayed-stream/-/delayed-stream-1.0.0.tgz",
       "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ=="
     },
+    "delegate": {
+      "version": "3.2.0",
+      "resolved": "https://registry.npmmirror.com/delegate/-/delegate-3.2.0.tgz",
+      "integrity": "sha512-IofjkYBZaZivn0V8nnsMJGBr4jVLxHDheKSW88PyxS5QC4Vo9ZbZVvhzlSxY87fVq3STR6r+4cGepyHkcWOQSw=="
+    },
     "dom-walk": {
       "version": "0.1.2",
       "resolved": "https://registry.npmmirror.com/dom-walk/-/dom-walk-0.1.2.tgz",
@@ -5950,6 +5999,14 @@
       "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==",
       "dev": true
     },
+    "good-listener": {
+      "version": "1.2.2",
+      "resolved": "https://registry.npmmirror.com/good-listener/-/good-listener-1.2.2.tgz",
+      "integrity": "sha512-goW1b+d9q/HIwbVYZzZ6SsTr4IgE+WA44A0GmPIQstuOrgsFcT7VEJ48nmr9GaRtNu0XTKacFLGnBPAM6Afouw==",
+      "requires": {
+        "delegate": "^3.1.2"
+      }
+    },
     "graceful-fs": {
       "version": "4.2.11",
       "resolved": "https://registry.npmmirror.com/graceful-fs/-/graceful-fs-4.2.11.tgz",
@@ -6707,6 +6764,11 @@
       "integrity": "sha512-vRUjqhyM/YWYzT+jsMk6tnl3NkY4A4soJ8uyh3O6Um+JXEQL9ozUCe7pqrxn3CSKokw0hw3nFStfskzpgYwR0g==",
       "dev": true
     },
+    "select": {
+      "version": "1.1.2",
+      "resolved": "https://registry.npmmirror.com/select/-/select-1.1.2.tgz",
+      "integrity": "sha512-OwpTSOfy6xSs1+pwcNrv0RBMOzI39Lp3qQKUTPVVPRjCdNa5JH/oPRiqsesIskK8TVgmRiHwO4KXlV2Li9dANA=="
+    },
     "semver": {
       "version": "7.5.4",
       "resolved": "https://registry.npmmirror.com/semver/-/semver-7.5.4.tgz",
@@ -6826,6 +6888,11 @@
       "resolved": "https://registry.npmmirror.com/through/-/through-2.3.8.tgz",
       "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg=="
     },
+    "tiny-emitter": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmmirror.com/tiny-emitter/-/tiny-emitter-2.1.0.tgz",
+      "integrity": "sha512-NB6Dk1A9xgQPMoGqC5CVXn123gWyte215ONT5Pp5a0yt4nlEoO1ZWeCwpncaekPHXO60i47ihFnZPiRPjRMq4Q=="
+    },
     "to-fast-properties": {
       "version": "2.0.0",
       "resolved": "https://registry.npmmirror.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz",

+ 1 - 0
package.json

@@ -13,6 +13,7 @@
     "@emotion/css": "^11.11.2",
     "@emotion/react": "^11.11.1",
     "axios": "^1.6.2",
+    "clipboard": "^2.0.11",
     "dommatrix": "^1.0.3",
     "element-plus": "^2.4.3",
     "nprogress": "^0.2.0",

+ 4 - 3
src/App.vue

@@ -4,11 +4,12 @@ import { useRoute } from 'vue-router';
 
 const route = useRoute()
 watch(() => route.query, () => {
-  console.log(123)
-  if (!localStorage.getItem('isDetailRefresh')) {
-		localStorage.setItem('isDetailRefresh', '1')
+  if (!sessionStorage.getItem('isDetailRefresh') && route.fullPath !== '/login') {
+		sessionStorage.setItem('isDetailRefresh', '1')
     window.location.reload()
 	}
+}, {
+  immediate: true,
 })
 </script>
 

+ 15 - 6
src/Hooks/useCopyText.ts

@@ -2,12 +2,21 @@ import { showNotify } from 'vant';
 import { statisticAddContext } from '@/api/context/context';
 
 const useCopyText = async (text: string, authorId: string) => {
-    if (navigator.clipboard && window.isSecureContext) { // 判断浏览器支持Clipboard API并且页面运行在安全上下文中
-        await statisticAddContext({ type: 1, authorId })
-        navigator.clipboard.writeText(text); // 将文本内容复制到剪贴板
-        showNotify('已成功复制!'); // 提示复制成功信息
-    } else {
-        console.log('不支持复制'); 
+    await statisticAddContext({ type: 1, authorId })
+    if (navigator.clipboard && navigator.clipboard.writeText) {
+        navigator.clipboard.writeText(text)
+            .then(() => {
+                showNotify('已成功复制!'); // 提示复制成功信息
+            })
+            .catch(() => {
+                const oInput = document.createElement('input');
+                oInput.value = text;
+                document.body.appendChild(oInput);
+                oInput.select(); // 选择对象
+                document.execCommand("Copy"); // 执行浏览器复制命令
+                document.body.removeChild(oInput);
+                showNotify('已成功复制!'); // 提示复制成功信息
+            }); 
     }
 }
 

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

@@ -55,8 +55,8 @@ const MyComponent = (prop: IPermiObj | Boolean): ComponentOptions =>
 					route.query.t +
 					'&isDataBase=' +
 					1 +
-					'&spId=' +
-					route.query.spId +
+					'&suid=' +
+					route.query.suid +
 					'&id=' +
 					route.query.id
 			}
@@ -97,7 +97,7 @@ const MyComponent = (prop: IPermiObj | Boolean): ComponentOptions =>
 						</div>
 					</div>
 				)
-			) 
+			)
 		},
 	})
 

+ 12 - 19
src/Hooks/useStatisticalTime.ts

@@ -26,13 +26,16 @@ const useStatisticalTime = (callback: (timing: number) => void) => {
 		}
 	}
 
-	const isAndroid = () => /Android/i.test(navigator.userAgent) //android终端
+	//const isAndroid = () => /Android/i.test(navigator.userAgent) //android终端
 	const isIOS = () => /iPhone|iPad|iPod/i.test(navigator.userAgent) //ios终端
 
 	onMounted(() => {
 		startTiming()
 		console.log('页面进入初始化')
-		if (isAndroid()) {
+		if (isIOS()) {
+			//window.addEventListener('pagehide', () => {
+			//	endTiming()
+			//}, false)
 			window.addEventListener("visibilitychange", () => {
 				let p = document.visibilityState
 				console.log('visibilityState', p)
@@ -44,17 +47,6 @@ const useStatisticalTime = (callback: (timing: number) => void) => {
 				}
 				console.log('页面关闭')
 			})
-			window.addEventListener("beforeunload", () => {
-				//let e = Number(window.localStorage.getItem('onbeforeLoad'));
-				//e += 1
-				//localStorage.setItem('onbeforeLoad', e.toString())
-				console.log('页面关闭')
-				endTiming()
-			})
-		} else if (isIOS()) {
-			window.addEventListener('pagehide', () => {
-				endTiming()
-			}, false)
 		} else {
 			window.addEventListener("visibilitychange", () => {
 				let p = document.visibilityState
@@ -67,17 +59,18 @@ const useStatisticalTime = (callback: (timing: number) => void) => {
 				}
 				console.log('页面关闭')
 			})
+			window.addEventListener("beforeunload", () => {
+				//let e = Number(window.localStorage.getItem('onbeforeLoad'));
+				//e += 1
+				//localStorage.setItem('onbeforeLoad', e.toString())
+				console.log('页面关闭')
+				endTiming()
+			})
 		}
 	})
 
 
 	return () => {
-		//window.removeEventListener('pagehide', () => {
-		//	console.log('页面关闭')
-		//	endTiming()
-		//})
-		//window
-		//localStorage.removeItem('timing')
 	}
 }
 

+ 2 - 3
src/Hooks/useWeChatShare.ts

@@ -67,8 +67,8 @@ const useWeChatShare = async (params: shareParams) => {
 		(Number(params.type) === 7 ? '/encyclopedia/detail-' : '/info/detail-') +
 		params.id +
 		'.html'
-	if (localStorage.getItem('isDetailRefresh')) {
-		localStorage.removeItem('isDetailRefresh')
+	if (sessionStorage.getItem('isDetailRefresh')) {
+		sessionStorage.removeItem('isDetailRefresh')
 	}
 	if (!isWeChat()) return params.isShowToast && showToast('请在微信浏览器中分享')
 	const { data } = await getShareConfig({
@@ -101,7 +101,6 @@ const useWeChatShare = async (params: shareParams) => {
 		},
 		fail: () => {
 			window.location.reload()
-			console.log('失败', obj, location.href)
 		},
 		cancel: () => {
 			console.log('取消了')

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


+ 21 - 7
src/components/image-preview/image-preview.vue

@@ -1,9 +1,9 @@
 <template>
   <div class="imagePreview">
     <van-swipe :autoplay="3000" lazy-render>
-      <van-swipe-item v-for="(image, index) in urls" :key="index">
+      <van-swipe-item v-for="(image, index) in urls" :key="index" @click="handlePreview(index)">
         <div class="stop_save" />
-        <img :src="image" style="width: 100%" />
+        <img :src="image" style="width: 100%;height: 100%;" />
       </van-swipe-item>
     </van-swipe>
   </div>
@@ -11,10 +11,19 @@
 
 <script setup lang="ts">
 import { IImagePreviewList } from "./index.type";
-defineProps<IImagePreviewList>()
+import { showImagePreview } from "vant";
+const props = defineProps<IImagePreviewList>()
+
+const handlePreview = (index: number) => {
+  console.log(index)
+  showImagePreview({
+    images: props.urls,
+    startPosition: index,
+  });
+}
 </script>
 
-<style scoped lang="scss">
+<style lang="scss">
 .imagePreview {
   padding: 80px 20px;
   width: 100%;
@@ -22,10 +31,13 @@ defineProps<IImagePreviewList>()
   height: 100vh;
 }
 :deep() {
-  .van-swipe,
+  .van-swipe {
+    height: 30vh;
+  }
   .van-swipe-item,
   .van-swipe__track {
     width: 100%;
+    height: 30vh;
     position: relative;
   }
   .stop_save {
@@ -38,12 +50,14 @@ defineProps<IImagePreviewList>()
     opacity: 0;
     -webkit-touch-callout: none;
   }
-  .van-image {
+  .van-image,
+  .van-image-preview__image, 
+  .van-image-preview__image-wrap {
     pointer-events: none !important;
     -webkit-user-select: none !important;
     -moz-user-select: none !important;
     user-select: none !important;
-    -webkit-touch-callout: none;
+    -webkit-touch-callout: none !important;
   }
 }
 img {

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


+ 12 - 2
src/components/pdf-preview/pdf-preview.vue

@@ -1,6 +1,7 @@
 <template>
   <div class="pdf">
     <div id="pdfView"></div>
+    <div class="loading"></div>
   </div>
 </template>
 
@@ -30,8 +31,8 @@ onMounted(() => {
 });
 </script>
 
-<style scoped lang="scss">
-img {
+<style lang="scss">
+.pdfjs .pdfViewer .pageContainer img {
   pointer-events: none !important;
   -webkit-user-select: none !important;
   -moz-user-select: none !important;
@@ -48,11 +49,20 @@ img {
 #pdfView {
   width: 100vw;
   height: 100%;
+  position: relative;
 }
 .pdf {
   width: 100vw;
   height: 100vh;
 }
+.loading {
+  position: absolute;
+  left: 0;
+  top: 0;
+  width: 100%;
+  height: 100%;
+  z-index: -1;
+}
 :deep() {
   .pdfjs .backTop, .pageNum {
     display: none !important;

+ 1 - 0
src/components/video-preview/video-preview.vue

@@ -38,6 +38,7 @@ const handleTimeUpdate = () => {
 }
 
 onMounted(async () => {
+  console.log('视频链接', props.url)
   await useBlobFile(myVideoRef.value!, props.url);
 });
 </script>

+ 1 - 1
src/router/route.ts

@@ -102,7 +102,7 @@ export const staticRouter: Array<RouteRecordRaw> = [
 		name: 'preview',
 		component: () => import('@/views/Preview/index.vue'),
 		meta: {
-			title: '内容库'
+			title: '采美商城'
 		}
 	},
 ]

+ 5 - 2
src/types/views/database.type.ts

@@ -1,5 +1,8 @@
 import { reactive } from "vue";
 import { DArchiveResultData, IArchiveRequest } from "../api/context.type";
+import { useTabStore } from "@/store/tab/tab";
+
+const { productId, stageStatus } = useTabStore();
 
 export type DMenu = {
 	text: string;
@@ -82,13 +85,13 @@ export const menuTypeOptions = reactive<Array<DMenuList<DMenu>>>([
   {
     type: "Singular",
     title: "商品",
-    changeValue: 0,
+    changeValue: productId ? Number(productId) : 0,
     options: [],
   },
   {
     type: "Singular",
     title: "用户阶段",
-    changeValue: 0,
+    changeValue: stageStatus ? Number(stageStatus) : 0,
     options: [
       {
         text: "用户阶段(全部)",

+ 2 - 6
src/util/http.ts

@@ -5,12 +5,12 @@ import axios, {
 	AxiosResponse,
 	InternalAxiosRequestConfig
 } from "axios";
-import { showLoadingToast, showFailToast } from 'vant'
+import { showFailToast } from 'vant'
 import type { IResultData } from '@/types/api/index'
 import { getStorage } from './authStorage'
 
 enum RequestEnums {
-	TIME_OUT = 10000,
+	TIME_OUT = 20000,
 	SUCCESS = 200,
 	CODE = 0
 }
@@ -32,10 +32,6 @@ class RequestHttp implements IRequestClass {
 		this.service = axios.create(config)
 
 		this.service.interceptors.request.use((config: InternalAxiosRequestConfig) => {
-			showLoadingToast({
-				message: '加载中...',
-				forbidClick: true
-			})
 			if (!!config.headers!.isToken && getStorage()) {
 				config.headers!['X-token'] = getStorage()
 			}

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

@@ -28,7 +28,8 @@ import { DTabStore } from "@/store/tab/tab.type";
 import { useRoute } from "vue-router";
 const route = useRoute();
 const props = defineProps<{
-  type: ChangeTabEmit;
+  type: ChangeTabEmit
+  index: number
 }>();
 const form = ref<Pick<DTabStore, 'type'> & Pick<DTabStore, 'allStatus'>>({
   type: route.query.t as ChangeTabEmit,
@@ -47,7 +48,7 @@ watch(
 watch(
   () => form.value.allStatus,
   () => {
-    emit("handle-all-status", { type: props.type, allStatus: form.value.allStatus });
+    emit("handle-all-status", { type: props.type, allStatus: form.value.allStatus, index: props.index });
   }
 );
 

+ 25 - 5
src/views/Database/components/context-share.vue

@@ -1,6 +1,7 @@
 <template>
   <div class="share" v-if="type === '5'">
-    <div class="show" @click.stop="useCopyText(props.content!, props.id!)">复制话术内容</div>
+    <!--<div class="show" @click.stop="useCopyText(props.content!, props.id!)">复制话术内容</div>-->
+    <el-button class="show copy" type="text" @click="handleCopy(props.content!, props.id!)">复制话术内容</el-button>
     <div class="showNum" v-if="allStatus === 1">已使用:{{ props.pv || 0 }}次</div>
   </div>
   <div class="share" v-else>
@@ -12,6 +13,7 @@
         spId: serviceProviderId as number,
         imageUrl: imageLink,
         isShowToast: true,
+        suid: userId as number,
       })
       ">
       分享
@@ -20,22 +22,25 @@
 </template>
 
 <script setup lang="ts">
+import Clipboard from 'clipboard'
 import { DArchiveResultData } from "@/types/api/context.type";
 import { DFindParams, DScrollTab, tabList } from "@/types/views/database.type";
 import { computed } from "vue";
 import { useRouter } from "vue-router";
-import useCopyText from "@/Hooks/useCopyText";
+//import useCopyText from "@/Hooks/useCopyText";
 import useWeChatShare from "@/Hooks/useWeChatShare";
 import { useUserInfoState } from "@/store/user/user";
 import getFileImg from "@/Hooks/useFileImage";
+import { statisticAddContext } from "@/api/context/context";
+import { showNotify } from 'vant';
 
 const props = defineProps<DArchiveResultData>();
-const { serviceProviderId } = useUserInfoState();
+const { serviceProviderId, userId } = useUserInfoState();
 const router = useRouter();
 
 const imageLink = computed<string>(() => {
   if (props.type !== "3") return props.image as string;
-  else return getFileImg(props.waters![0].split('?')[0]).img as string;
+  else return getFileImg(props.waters![0] && props.waters![0].split('?')[0]).img as string;
 });
 console.log(imageLink.value)
 const controlText = computed<DFindParams<DScrollTab, "text">>(
@@ -46,11 +51,26 @@ const handleDetail = ($event: DArchiveResultData) => {
     import.meta.env.VITE_HTTP_URL +
     (Number($event.type) === 7 ? "/encyclopedia/detail-" : "/info/detail-") +
     $event.id +
-    ".html";
+    (Number($event.type) === 6 ? "-1.html" : ".html");
+  console.log('链接', link)
   if (Number($event.type) > 5) return window.open(link);
   router.push("/database/detail?id=" + $event.id + "&t=" + $event.type);
   console.log($event.type);
 };
+
+const handleCopy = async (content: string, authorId: string) => {
+  await statisticAddContext({ type: 1, authorId })
+  const clipboard = new Clipboard('.copy', {
+        text: function () {
+          return content
+        }
+      })
+      clipboard.on('success', () => {
+        showNotify('已成功复制!'); // 提示复制成功信息
+        // 释放内存
+        clipboard.destroy()
+      })
+}
 </script>
 
 <style scoped lang="scss">

+ 30 - 7
src/views/Database/components/search-head.vue

@@ -9,7 +9,7 @@
         <van-icon name="https://static.caimei365.com/app/mini-database/search.png" />
       </template>
     </van-search>
-    <van-dropdown-menu active-color="#FF5B00">
+    <van-dropdown-menu active-color="#FF5B00" ref="dropMenuRef" :close-on-click-overlay="false">
       <van-dropdown-item
         active-color="#FF5B00"
         :title="i.title"
@@ -55,6 +55,9 @@
               </van-cell>
             </van-cell-group>
           </van-checkbox-group>
+          <div class="changeBtn">
+            <data-button label="确定" @handleEmit="dropMenuRef?.close()" width="200px" />
+          </div>
         </template>
         <template v-if="i.type === 'Singular'">
           <van-radio-group v-model="i.changeValue">
@@ -63,7 +66,7 @@
                 v-for="(item, index) in i.options"
                 clickable
                 :key="index"
-                @click="i.changeValue = item.value"
+                @click="i.changeValue = item.value, dropMenuRef?.close()"
                 :class="i.changeValue === item.value ? 'd-checked' : ''"
               >
                 <template #title>
@@ -86,10 +89,10 @@ import { ref, onBeforeUpdate, onMounted, VNodeRef } from "vue";
 import type { DMenu, DEmit } from "@/types/views/database.type";
 import { menuTypeOptions } from "@/types/views/database.type";
 import { getLabelKeyList, getStoreList } from "@/api/context/context";
-import { CheckboxInstance } from "vant";
+import { CheckboxInstance, showToast, DropdownMenuInstance } from "vant";
 import { ILabelKeyRequest, IStoreRequest } from "@/types/api/context.type";
 import { useTabStore } from "@/store/tab/tab";
-const {searchValue, labelIds } = useTabStore();
+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";
@@ -105,8 +108,11 @@ const labelKeyParams = ref<ILabelKeyRequest>({
   v: "",
 }); // 搜索条件
 const value = ref<string>(searchValue || ""); // 标题搜索
-const checked = ref<Array<number | null>>(labelIds?.split(',').map(e => Number(e)) || []); // 默认选中 多选
+const checked = ref<Array<number | null>>(
+  labelIds?.split(",").map((e) => Number(e)) || []
+); // 默认选中 多选
 const checkboxRefs = ref<Array<CheckboxInstance | VNodeRef>>([]); // 多选默认
+const dropMenuRef = ref<DropdownMenuInstance>()
 
 const checkHistoryList = ref<Array<DMenu>>([]);
 const toggle = (index: DMenu) => {
@@ -131,6 +137,7 @@ const toggle = (index: DMenu) => {
 };
 const emit = defineEmits<DEmit>();
 const handleDropdownClose = (): void => {
+  if (checked.value.length === 0 && menuTypeOptions[1].changeValue === 0 && menuTypeOptions[2].changeValue === 0) return
   emit("handle-change-emit", {
     labelIds: checked.value.join(),
     productId: menuTypeOptions[1].changeValue!,
@@ -139,6 +146,12 @@ const handleDropdownClose = (): void => {
 };
 const reqLabelKeyList = async () => {
   const { data } = await getLabelKeyList(labelKeyParams.value);
+  if (data!.list!.length === 0 && labelKeyParams.value.v.length > 0) {
+    showToast({
+      message: "未找到该标签",
+      position: "top",
+    });
+  }
   menuTypeOptions[0]!.options = [
     ...checkHistoryList.value,
     ...data!
@@ -151,17 +164,23 @@ const reqLabelKeyList = async () => {
         }
       })
       .filter((o) => o),
-  ].filter((_,i) => i < 10);
+  ].filter((_, i) => i < 10);
 };
 const reqStoreList = async () => {
   const { data } = await getStoreList(storeParams.value);
+  if (data!.list!.length === 0 && storeParams.value.productName.length > 0) {
+    showToast({
+      message: "未找到该商品",
+      position: "top",
+    });
+  }
   menuTypeOptions[1]!.options = [
     { text: "商品(全部)", value: 0 },
     ...data!.list!.map((e) => ({
       text: e.productName,
       value: e.productId,
     })),
-  ].filter((_,i) => i < 10);
+  ].filter((_, i) => i < 10);
 };
 onMounted(() => {
   reqLabelKeyList();
@@ -308,4 +327,8 @@ onBeforeUpdate(() => {
 .activeMenu {
   color: $basicColor;
 }
+.changeBtn {
+  width: 100%;
+  @include display-flex-center;
+}
 </style>

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

@@ -33,7 +33,7 @@ const props = defineProps<DArchiveResultData>();
 
 const fileUrl = computed<string>(() => {
   if (props.type === "2" && props.waters!.length > 0) {
-    return props.waters![0].split("?")[0];
+    return props.waters![0];
   } else {
     return "";
   }

+ 31 - 5
src/views/Database/data-all/index.vue

@@ -9,7 +9,7 @@
       @handle-see-more="handleSeeMore"
     >
       <template #head="{ data }">
-        <context-head :type="data.type" @handle-all-status="handleAllStatus" />
+        <context-head :type="data.type" :index="i" @handle-all-status="handleAllStatus" />
       </template>
       <template #share="{ data }">
         <context-share
@@ -35,7 +35,7 @@
 </template>
 
 <script setup lang="ts">
-import { computed, ref, watch } from "vue";
+import { computed, ref, watch, onMounted } from "vue";
 import contextContain from "../components/context-contain.vue";
 import { DDataBaseListAll, DetailParams, tabList } from "@/types/views/database.type";
 import contextHead from "../components/context-head.vue";
@@ -45,6 +45,7 @@ import { getArchiveList } from "@/api/context/context";
 import { IArchiveRequest } from "@/types/api/context.type";
 import { useUserInfoState } from "@/store/user/user";
 import { myDecrypt } from "@/util/authStorage";
+import useWeChatShare from "@/Hooks/useWeChatShare";
 
 const { userId } = useUserInfoState();
 const router = useRouter();
@@ -58,7 +59,7 @@ const reqParams = computed<IArchiveRequest>(
       type: routeQuery(route.query.t),
       title: route.query.sv,
       productId: routeQuery(route.query.pId),
-      labelIds: route.query.lId,
+      labelIds: routeQuery(route.query.lId),
       stageStatus: routeQuery(route.query.ss),
       spId: "",
       userId: userId,
@@ -105,17 +106,31 @@ const reqArchiveList = async (res?: DetailParams) => {
     dataList.value![res.index!]!.showMore = res.pageNum! > 1 && data?.length! < 5;
   }
 };
+const isSearch = () => {
+  if (route.query.t !== '0') {
+    return true
+  }
+  if (
+    (route.query.lId !== "0" && route.query.lId !== "") ||
+    route.query.sv !== "" ||
+    (route.query.pId !== "0" && route.query.pId !== "") ||
+    (route.query.ss !== "0" && route.query.ss !== "")
+  ) {
+    return true;
+  }
+};
 watch(
   () => route.query,
   () => {
     console.log("路由变化", route);
-    if (route.path === '/database/index') {
+    if (route.path === "/database/index" && isSearch()) {
       formParams.value.allStatus = "1";
       reqArchiveList();
+    } else {
+      dataList.value = []
     }
   },
   {
-    deep: true,
     immediate: true,
   }
 );
@@ -130,6 +145,16 @@ const handleAllStatus = ($event: DetailParams) => {
   reqArchiveList($event);
   isAddStatus.value = $event.allStatus === "2";
 };
+onMounted(() => {
+  useWeChatShare({
+    type: '3',
+    id: '1',
+    imageUrl: '',
+    spId: 0,
+    isShowToast: false,
+    suid: 0,
+  });
+})
 </script>
 
 <style lang="scss" scoped>
@@ -143,6 +168,7 @@ const handleAllStatus = ($event: DetailParams) => {
   box-sizing: border-box;
   width: 100%;
 }
+
 .empty {
   width: 100%;
   height: 135px;

+ 21 - 4
src/views/Database/detail.vue

@@ -18,12 +18,12 @@
         :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?.stageStatus ? menuTypeOptions[2].options.filter(e => e.value === form?.stageStatus)[0].subtitle : '' }}</p>
     <p class="foot-mark">{{ form?.shopName }}</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"
+      <data-button @handle-emit="handleCopy(form!.content!, form!.id!)" backgroundColor="#FFF" color="#FF5B00"
         label="复制文本" v-if="type === '5'" />
       <data-button @handle-emit="
         useWeChatShare({
@@ -32,6 +32,7 @@
           imageUrl: imageLink,
           spId: serviceProviderId as number,
           isShowToast: true,
+          suid: userId as number,
         })
         " backgroundColor="#FFF" color="#FF5B00" label="分享" v-if="type !== '5'" />
     </div>
@@ -39,17 +40,20 @@
 </template>
 
 <script setup lang="ts">
-import useCopyText from '@/Hooks/useCopyText'
+//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 { ChangeTabEmit, menuTypeOptions } 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'
+import Clipboard from 'clipboard'
+import { statisticAddContext } from "@/api/context/context";
+import { showNotify } from 'vant';
 
 const route = useRoute()
 const router = useRouter()
@@ -80,6 +84,19 @@ const getArchiveForm = async () => {
 const move = () => {
   document.body.style.position = 'static'
 }
+const handleCopy = async (content: string, authorId: string) => {
+  await statisticAddContext({ type: 1, authorId })
+  const clipboard = new Clipboard('.copy', {
+        text: function () {
+          return content
+        }
+      })
+      clipboard.on('success', () => {
+        showNotify('已成功复制!'); // 提示复制成功信息
+        // 释放内存
+        clipboard.destroy()
+      })
+}
 onActivated(() => {
   getArchiveForm()
   move()

+ 35 - 23
src/views/Login/index.vue

@@ -21,20 +21,25 @@
         />
       </van-cell-group>
       <div style="margin: 52px 30px">
-        <data-button label="登录" type="primary" :disabled="disabled" @handle-emit="onSubmit" />
+        <data-button
+          label="登录"
+          type="primary"
+          :disabled="disabled"
+          @handle-emit="onSubmit"
+        />
       </div>
     </van-form>
   </div>
 </template>
 
 <script setup lang="ts">
-import { ref, computed } from "vue";
+import { ref, computed, onMounted } from "vue";
 import { useUserInfoState } from "@/store/user/user";
-import { useRouter } from "vue-router";
+//import { useRouter } from "vue-router";
 import { ILogin } from "@/types/api/user.type";
-import { showLoadingToast } from 'vant';
+import { showLoadingToast } from "vant";
 
-const router = useRouter();
+//const router = useRouter();
 
 const { login } = useUserInfoState();
 
@@ -45,21 +50,28 @@ const form = ref<ILogin>({
   //unionId: 'ox_1SwSaz62JsEppFjhlecqhENdQ'
 });
 
-const disabled = computed<boolean>(() => (!form.value.mobileOrEmail || !form.value.password))
+const disabled = computed<boolean>(
+  () => !form.value.mobileOrEmail || !form.value.password
+);
 
 const onSubmit = async () => {
   if (!disabled.value) {
     const { data, code, msg } = await login(form.value);
     console.log(data);
     if (code === 0) {
-      showLoadingToast(msg!)
-      window.location.reload()
-      router.replace('/database/index?t=0&lId=&sv=&pId=&ss=')
+      showLoadingToast(msg!);
+      window.location.href = '/database/index?t=0&lId=&sv=&pId=&ss='
     } else {
-      showLoadingToast(msg!)
+      showLoadingToast(msg!);
     }
   }
 };
+onMounted(() => {
+  if (!sessionStorage.getItem("isRefresh")) {
+    sessionStorage.setItem("isRefresh", "1");
+    window.location.reload();
+  }
+});
 </script>
 
 <style scoped lang="scss">
@@ -84,18 +96,18 @@ const onSubmit = async () => {
   margin: 0 auto;
 }
 :deep() {
-	.van-form {
-		.van-field__left-icon {
-			margin-right: 14px;
-			.van-icon {
-				width: 16px;
-				height: 20px;
-			}
-		}
-		width: 400px;
-	}
-	.van-field__control {
-		font-size: 13px;
-	}
+  .van-form {
+    .van-field__left-icon {
+      margin-right: 14px;
+      .van-icon {
+        width: 16px;
+        height: 20px;
+      }
+    }
+    width: 400px;
+  }
+  .van-field__control {
+    font-size: 13px;
+  }
 }
 </style>

+ 62 - 25
src/views/Preview/index.vue

@@ -1,16 +1,23 @@
 <template>
-  <video-preview
-    v-if="params.type === '2' && fileUrl"
+  <video-preview v-if="params.type === '2' && fileUrl" :url="fileUrl" />
+  <pdf-preview
+    v-if="params.type === '3' && fileUrl && fileUrl.indexOf('.pdf') !== -1"
     :url="fileUrl"
   />
-  <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"
+  <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" />
+  <text-preview
+    v-if="params.type === '4' && form.content"
+    :content="form.content"
+    :max-height="'100vh'"
   />
-  <text-preview v-if="params.type === '4' && form.content" :content="form.content" :max-height="'100vh'"/>
   <permiNode v-if="!route.query.isSp && permiNode" />
 </template>
 
@@ -18,7 +25,15 @@
 import { usePermission } from "@/Hooks/usePermission/usePermission";
 import { previewData } from "@/api/context/context";
 import useStatisticalTime from "@/Hooks/useStatisticalTime";
-import { computed, onUnmounted, ref, watch, onActivated, ComponentOptions, shallowRef } 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 { shareOptions, shareParams } from "@/Hooks/useWeChatShare";
@@ -27,6 +42,8 @@ import { myDecrypt } from "@/util/authStorage";
 import useStopWindowContext from "@/Hooks/useStopWindowContext";
 import createWebShareCard from "@/Hooks/useCreateWebShareCard";
 import { showLoadingToast } from "vant";
+import useWeChatShare from "@/Hooks/useWeChatShare";
+import { onMounted } from 'vue';
 const route = useRoute();
 useStopWindowContext();
 const form = ref<IPreviewForm>({
@@ -35,10 +52,10 @@ const form = ref<IPreviewForm>({
   productId: "0",
   fileArchiveList: [],
   image: "",
-  content: '',
-  id: ''
+  content: "",
+  id: "",
 });
-const permiNode = shallowRef<ComponentOptions | null>()
+const permiNode = shallowRef<ComponentOptions | null>();
 const fileUrl = ref<string>();
 const params = computed<shareParams & { url: string }>(
   () =>
@@ -49,6 +66,7 @@ const params = computed<shareParams & { url: string }>(
       spId: route.query?.spId as string,
       imageUrl: form.value?.image,
       url: route.query?.url as string,
+      suid: route.query?.suid as string,
     } as unknown) as shareParams & { url: string })
 );
 watch(
@@ -56,9 +74,9 @@ watch(
   (val) => {
     if (val) {
       setTimeout(() => {
-        console.log('传递的url 链接为:', [route.query?.url])
-        fileUrl.value = val as string
-      }, 1000)
+        console.log("传递的url 链接为:", [route.query?.url]);
+        fileUrl.value = val as string;
+      }, 1000);
     }
   },
   {
@@ -77,8 +95,10 @@ const getPreviewData = async () => {
   } as IPreviewForm;
   form.value = DcreptoList;
   fileUrl.value = form.value.waters[0]?.split("?")[0];
-  const { PermiMode } = usePermission(route.query.isSp ? 0 : form.value?.permission! as number)
-  permiNode.value = PermiMode! as ComponentOptions
+  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);
@@ -86,9 +106,13 @@ const statistical = useStatisticalTime((time) => {
   localStorage.setItem("spentTime", t.toString());
   const f = {
     productArchiveId: params.value.id,
-    headUserId: params.value.spId,
+    headUserId: params.value.suid,
     accessClient: "0",
-    pagePath: location.href,
+    pagePath: encodeURIComponent(
+      `${import.meta.env.VITE_BASE_HTTP}/preview?t=${params.value.type}&id=${
+        params.value.id
+      }&isSp=1`
+    ),
     accessDuration: t * 1000,
     pageType: params.value.type === "1" ? "70" : params.value.type === "2" ? "71" : "69",
     pageLabel: "内容库预览",
@@ -105,7 +129,9 @@ const statistical = useStatisticalTime((time) => {
       f.accessDuration
     }&pageLabel=${f.pageLabel}&behaviorType=${f.behaviorType}&shopId=${
       f.shopId
-    }&pageType=${f.pageType}
+    }&pageType=${f.pageType}&productArchiveId=${f.productArchiveId}&headUserId=${
+      f.headUserId
+    }
     `,
     {
       method: "GET",
@@ -122,10 +148,11 @@ const statistical = useStatisticalTime((time) => {
 });
 const initData = () => {
   fileUrl.value = "";
-  !route.query.isSp && showLoadingToast({
-    message: "加载中...",
-    forbidClick: true,
-  });
+  !route.query.isSp &&
+    showLoadingToast({
+      message: "加载中...",
+      forbidClick: true,
+    });
   const obj = shareOptions.filter((e) => e.type === params.value.type)[0];
   if (!params.value.url) {
     getPreviewData();
@@ -143,6 +170,16 @@ onUnmounted(() => {
 onActivated(() => {
   initData();
 });
+onMounted(() => {
+  useWeChatShare({
+    type: params.value.type,
+    id: params.value.id!,
+    imageUrl: '',
+    spId: params.value.spId,
+    isShowToast: false,
+    suid: params.value.suid,
+  });
+})
 </script>
 
 <style scoped lang="scss">