3 Коміти f3b4a3aed8 ... 9b46c37b02

Автор SHA1 Опис Дата
  davy66666 9b46c37b02 merge main 1 місяць тому
  davy66666 f9a79d2add add domain 1 місяць тому
  davy66666 11b4dff5a1 init 1 місяць тому

+ 1 - 1
.gitignore

@@ -3,7 +3,7 @@ node_modules/
 npm-debug.log*
 yarn-debug.log*
 yarn-error.log*
-
+dist/*
 build/
 !build/icons
 

+ 1 - 2
config/dev.env.ts

@@ -1,5 +1,4 @@
-const domian = 'openimhailiao.com'
-
+const domian = 'openimchat.ops777777.cc'
 export default {
   NODE_ENV: 'development',
   CHAT_URL: `https://${domian}/chat`,

+ 11 - 10
config/prod.env.ts

@@ -1,15 +1,16 @@
-const domian = 'openimhailiao.com'
+
+const domian = 'openimchat.ops777777.cc'
 
 export default {
-  NODE_ENV: 'development',
-  CHAT_URL: `https://${domian}/chat`,
+	NODE_ENV: 'development',
+	CHAT_URL: `https://${domian}/chat`,
   API_URL: `https://${domian}/api`,
   WS_URL: `wss://${domian}/msg_gateway`,
-  //CHAT_URL: "http://120.77.93.35:10008",
-  //API_URL: "http://120.77.93.35:10002",
-  //WS_URL: "ws://120.77.93.35:10001",
-  OBJECT_STORAGE: 'minio',
-  AMAP_KEY: '36e6a7bb847411f06258d03b066ecc67', //jsapi
-  AMAP_SNAP_KEY: '39b41b2a48453d7e66007c6f45d26a12',
-  VERSION: 'IM-HCER 3.5.1 SDK v3.5.1',
+	//CHAT_URL: "http://120.77.93.35:10008",
+	//API_URL: "http://120.77.93.35:10002",
+	//WS_URL: "ws://120.77.93.35:10001",
+	OBJECT_STORAGE: 'minio',
+	AMAP_KEY: '36e6a7bb847411f06258d03b066ecc67',//jsapi
+	AMAP_SNAP_KEY: '39b41b2a48453d7e66007c6f45d26a12',
+	VERSION: 'IM-HCER 3.5.1 SDK v3.5.1',
 }

+ 48 - 0
package-lock.json

@@ -32,6 +32,7 @@
         "vite-plugin-vue-setup-extend": "^0.4.0",
         "vue": "^3.2.37",
         "vue-clipboard3": "^2.0.0",
+        "vue-dompurify-html": "^5.2.0",
         "vue-request": "^2.0.4",
         "vue-router": "^4.1.5",
         "vue3-qr-reader": "^1.0.0",
@@ -1231,6 +1232,12 @@
       "integrity": "sha512-QB5D2sqfSjCmTuWcBWyJ+/44bcjO7VbjSbOE0ucoVbAsSNQc4Lt6QkgkVXkTDwkL4z/beecZNDvVX15D4P8Jbw==",
       "devOptional": true
     },
+    "node_modules/@types/trusted-types": {
+      "version": "2.0.7",
+      "resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.7.tgz",
+      "integrity": "sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==",
+      "optional": true
+    },
     "node_modules/@types/uuid": {
       "version": "9.0.0",
       "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-9.0.0.tgz",
@@ -2341,6 +2348,14 @@
       "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==",
       "dev": true
     },
+    "node_modules/dompurify": {
+      "version": "3.2.5",
+      "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.2.5.tgz",
+      "integrity": "sha512-mLPd29uoRe9HpvwP2TxClGQBzGXeEC/we/q+bFlmPPmj2p2Ugl3r6ATu/UU1v77DXNcehiBg9zsr1dREyA/dJQ==",
+      "optionalDependencies": {
+        "@types/trusted-types": "^2.0.7"
+      }
+    },
     "node_modules/downloadjs": {
       "version": "1.4.7",
       "resolved": "https://registry.npmjs.org/downloadjs/-/downloadjs-1.4.7.tgz",
@@ -4715,6 +4730,17 @@
         "clipboard": "^2.0.6"
       }
     },
+    "node_modules/vue-dompurify-html": {
+      "version": "5.2.0",
+      "resolved": "https://registry.npmjs.org/vue-dompurify-html/-/vue-dompurify-html-5.2.0.tgz",
+      "integrity": "sha512-GX+BStkKEJ8wu/+hU1EK2nu/gzXWhb4XzBu6aowpsuU/3nkvXvZ2jx4nZ9M3jtS/Vu7J7MtFXjc7x3cWQ+zbVQ==",
+      "dependencies": {
+        "dompurify": "^3.2.1"
+      },
+      "peerDependencies": {
+        "vue": "^3.0.0"
+      }
+    },
     "node_modules/vue-i18n": {
       "version": "9.1.10",
       "resolved": "https://registry.npmjs.org/vue-i18n/-/vue-i18n-9.1.10.tgz",
@@ -5786,6 +5812,12 @@
       "integrity": "sha512-QB5D2sqfSjCmTuWcBWyJ+/44bcjO7VbjSbOE0ucoVbAsSNQc4Lt6QkgkVXkTDwkL4z/beecZNDvVX15D4P8Jbw==",
       "devOptional": true
     },
+    "@types/trusted-types": {
+      "version": "2.0.7",
+      "resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.7.tgz",
+      "integrity": "sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==",
+      "optional": true
+    },
     "@types/uuid": {
       "version": "9.0.0",
       "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-9.0.0.tgz",
@@ -6609,6 +6641,14 @@
       "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==",
       "dev": true
     },
+    "dompurify": {
+      "version": "3.2.5",
+      "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.2.5.tgz",
+      "integrity": "sha512-mLPd29uoRe9HpvwP2TxClGQBzGXeEC/we/q+bFlmPPmj2p2Ugl3r6ATu/UU1v77DXNcehiBg9zsr1dREyA/dJQ==",
+      "requires": {
+        "@types/trusted-types": "^2.0.7"
+      }
+    },
     "downloadjs": {
       "version": "1.4.7",
       "resolved": "https://registry.npmjs.org/downloadjs/-/downloadjs-1.4.7.tgz",
@@ -8248,6 +8288,14 @@
         "clipboard": "^2.0.6"
       }
     },
+    "vue-dompurify-html": {
+      "version": "5.2.0",
+      "resolved": "https://registry.npmjs.org/vue-dompurify-html/-/vue-dompurify-html-5.2.0.tgz",
+      "integrity": "sha512-GX+BStkKEJ8wu/+hU1EK2nu/gzXWhb4XzBu6aowpsuU/3nkvXvZ2jx4nZ9M3jtS/Vu7J7MtFXjc7x3cWQ+zbVQ==",
+      "requires": {
+        "dompurify": "^3.2.1"
+      }
+    },
     "vue-i18n": {
       "version": "9.1.10",
       "resolved": "https://registry.npmjs.org/vue-i18n/-/vue-i18n-9.1.10.tgz",

+ 1 - 0
package.json

@@ -34,6 +34,7 @@
     "vite-plugin-vue-setup-extend": "^0.4.0",
     "vue": "^3.2.37",
     "vue-clipboard3": "^2.0.0",
+    "vue-dompurify-html": "^5.2.0",
     "vue-request": "^2.0.4",
     "vue-router": "^4.1.5",
     "vue3-qr-reader": "^1.0.0",

+ 2 - 0
src/main.ts

@@ -1,4 +1,5 @@
 import { createApp } from 'vue'
+import VueDOMPurifyHTML from 'vue-dompurify-html';
 import './style.scss'
 import App from './App.vue'
 import router from './router'
@@ -28,6 +29,7 @@ const app = createApp(App)
 app.use(router)
 app.use(store)
 app.use(i18n)
+app.use(VueDOMPurifyHTML);
 errorHandler(app)
 
 app.mount('#app')

+ 53 - 3
src/pages/contact/createGroup/index.vue

@@ -33,8 +33,23 @@
 			</div>
 		</div>
 
-		<van-uploader v-show="false" ref="uploaderRef" accept="image/*" capture="camcorder" :preview-image="false"
-			:multiple="false" :after-read="afterReadFile" reupload max-count="1" />
+		<van-uploader
+			v-show="false"
+			ref="uploaderRef"
+			:accept="uploadChooseOptions.accept"
+			:capture="uploadChooseOptions.capture"
+			:preview-image="false"
+			:multiple="false"
+			:after-read="afterReadFile"
+			reupload max-count="1"
+		/>
+
+		<van-action-sheet
+			v-model:show="isShowActionSheet"
+			teleport="body"
+			:actions="actionList"
+			@select="onActionSelect"
+		/>
 	</div>
 </template>
 
@@ -54,6 +69,12 @@
 	type CreateGroupProps = {
 		groupType : GroupType
 	}
+
+	enum ChooseGroupAvatarActionType {
+		Album,
+  	Shoot,
+	}
+
 	const props = defineProps<CreateGroupProps>()
 
 	const { toSpecifiedConversation } = useConversationToggle()
@@ -65,6 +86,25 @@
 		groupName: '',
 		groupFaceUrl: '',
 	})
+
+	const uploadChooseOptions = reactive({
+		accept: '*',
+		capture: undefined as any,
+	})
+
+	const isShowActionSheet = ref(false)
+
+	const actionList = [
+		{
+			name: t('picture'),
+			type: ChooseGroupAvatarActionType.Album,
+		},
+		{
+			name: t('photograph'),
+			type: ChooseGroupAvatarActionType.Shoot,
+		},
+	]
+
 	const checkedUserList = ref<PublicUserItem[]>([])
 	const createLoading = ref(false)
 	const uploaderRef = ref<UploaderInstance>()
@@ -131,7 +171,17 @@
 	}
 
 	const chooseAvatar = () => {
-		uploaderRef.value?.chooseFile()
+		isShowActionSheet.value = true
+	}
+
+	const onActionSelect = ({ type } : any, idx : number) => {
+		if (type === ChooseGroupAvatarActionType.Shoot) {
+			uploadChooseOptions.capture = 'camera'
+		} else {
+			uploadChooseOptions.accept = 'image/*'
+		}
+		nextTick(() => uploaderRef.value?.chooseFile())
+		isShowActionSheet.value = false
 	}
 
 	onBeforeMount(() => {

+ 7 - 7
src/pages/conversation/chat/components/ChatContent.vue

@@ -32,12 +32,12 @@
 
 			<template v-if="showMoreMember">
 				<div class="mt-3 flex w-full flex-row justify-start px-1">
-					<div class="flex w-1/6 justify-center" v-for="item in callingData!.participant!.slice(0, 5)"
+					<div class="flex w-1/6 justify-center" v-for="item in callingData?.participant?.slice(0, 5)"
 						:key="item.userInfo.userID">
-						<Avatar :size="44" :src="item!.groupMemberInfo!.faceURL"
-							:desc="item!.groupMemberInfo!.nickname" />
+						<Avatar :size="44" :src="item?.groupMemberInfo?.faceURL"
+							:desc="item?.groupMemberInfo?.nickname" />
 					</div>
-					<div class="flex w-1/6 justify-center" v-if="callingData!.participant!.length > 5">
+					<div class="flex w-1/6 justify-center" v-if="callingData?.participant?.length > 5">
 						<img :src="more" class="h-11 w-11" alt="more" />
 					</div>
 				</div>
@@ -49,7 +49,7 @@
 		<virtual-list :class="{ '!flex-col': overflow }" ref="vsl" class="my_scrollbar h-full overflow-y-auto"
 			:data-key="'clientMsgID'" :data-sources="messageStore.storeHistoryMessageList" :topThreshold="120"
 			:keeps="50" :data-component="
-        (message: MessageItem) =>
+        (message) =>
           checkIsNotification(message) ? SystemNotificationItem : MessageItemVue
       " :extra-props="{
         showCheck: multipleCheckVisible,
@@ -173,8 +173,8 @@
 
 	const joinRtc = () => {
 		emitter.emit('OPEN_RTC_MODAL', {
-			invitation: callingData!.value!.invitation,
-			participant: callingData!.value!.participant?.[0],
+			invitation: callingData?.value?.invitation,
+			participant: callingData?.value?.participant?.[0],
 			isJoin: true,
 		})
 	}

+ 12 - 3
src/pages/conversation/chat/components/ChatFooter/ChatFooter.vue

@@ -19,8 +19,8 @@
 				</div>
 			</div>
 			<img @click="clickEmojiBtn" class="ml-3 h-[26px] min-w-[26px]" :src="emoji" alt="" />
-			<img v-show="!messageContent" @click="clickAddBtn" class="ml-3 h-[26px] min-w-[26px]" :src="add" alt="" />
-			<div class="send ml-2" v-show="messageContent" @click="switchTextMessage">
+			<img v-show="!isInputMessageTyped" @click="clickAddBtn" class="ml-3 h-[26px] min-w-[26px]" :src="add" alt="" />
+			<div class="send ml-2" v-show="isInputMessageTyped" @click="switchTextMessage">
 				发送
 			</div>
 		</div>
@@ -79,7 +79,13 @@
 			? `${t('messageMenu.replay')}:${formatMessageByType(conversationStore.storeQuoteMessage)}`
 			: null,
 	)
-
+	const isInputMessageTyped = computed(() => {
+		// 清空输入框的时候 组件只会返回空的<br>而不是空字符串.
+		if (!messageContent.value) {
+			return false
+		}
+		return messageContent.value !== '<br>'
+	})
 	const clearQuoteMessage = () => {
 		conversationStore.updateQuoteMessage()
 	}
@@ -316,6 +322,9 @@
 	})
 
 	onActivated(() => {
+		if (!conversationStore.currentConversation?.draftText) {
+			return
+		}
 		inputRef.value.clear()
 		inputRef.value.inputRef.focus()
 		if (!conversationStore.currentConversation.conversationID) return

+ 5 - 5
src/pages/conversation/chat/components/ChatFooter/ChatFooterAction.vue

@@ -80,11 +80,11 @@
 			icon: card,
 			type: ChatFooterActionType.IDCard,
 		},
-		{
-			text: t('footerAction.location'),
-			icon: location,
-			type: ChatFooterActionType.Location,
-		},
+		// {
+		// 	text: t('footerAction.location'),
+		// 	icon: location,
+		// 	type: ChatFooterActionType.Location,
+		// },
 	]
 
 	const albumActions = [

+ 1 - 1
src/pages/conversation/index/components/ConversationListItem.vue

@@ -14,7 +14,7 @@
 					<span v-show="messagePrefix" class="mr-1" :class="{ 'text-[#02C25F]': activePrefix }">
 						{{ messagePrefix }}
 					</span>
-					<span>{{ formattedMessage }}</span>
+					<span v-dompurify-html="formattedMessage"></span>
 				</div>
 			</div>
 			<div class="flex h-12 flex-col items-end text-xs text-[#999]"