Browse Source

Merge remote-tracking branch 'origin/wanzi'

liyanbo 3 months ago
parent
commit
81e6995d7a

+ 7 - 0
package-lock.json

@@ -15,6 +15,7 @@
         "@vue-office/excel": "^1.7.14",
         "@vue-office/pptx": "^1.0.1",
         "axios": "^1.10.0",
+        "crypto-js": "^4.2.0",
         "element-plus": "^2.10.2",
         "highlight.js": "^11.11.1",
         "hls.js": "^1.6.7",
@@ -3730,6 +3731,12 @@
         "node": ">= 8"
       }
     },
+    "node_modules/crypto-js": {
+      "version": "4.2.0",
+      "resolved": "https://registry.npmjs.org/crypto-js/-/crypto-js-4.2.0.tgz",
+      "integrity": "sha512-KALDyEYgpY+Rlob/iriUtjV6d5Eq+Y191A5g4UqLAi8CyGP9N1+FdVbkc1SxKc2r4YAYqG8JzO2KGL+AizD70Q==",
+      "license": "MIT"
+    },
     "node_modules/cssesc": {
       "version": "3.0.0",
       "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz",

+ 1 - 0
package.json

@@ -16,6 +16,7 @@
     "@vue-office/excel": "^1.7.14",
     "@vue-office/pptx": "^1.0.1",
     "axios": "^1.10.0",
+    "crypto-js": "^4.2.0",
     "element-plus": "^2.10.2",
     "highlight.js": "^11.11.1",
     "hls.js": "^1.6.7",

+ 3 - 1
src/components/ai/text/TextToText.vue

@@ -635,8 +635,10 @@ onUnmounted(() => {
 // 暴露方法给父组件
 defineExpose({
   stopStream,
-  clearMessageList
+  clearMessageList,
+  stopPlayback
 });
+
 </script>
 
 <style scoped lang="scss">

+ 25 - 4
src/utils/loginUtils.js

@@ -2,6 +2,25 @@ import { ref, computed } from 'vue'
 import { getTenantIdByName, login, smsLogin, smsCode } from '@/api/login/login.js'
 import { ElLoading, ElMessage } from 'element-plus'
 import { updateAllDictData } from './dictUtils.js';
+// CryptoJS 库(用于密码加密)
+import CryptoJS from 'crypto-js';
+
+// 加密密钥 (从环境变量获取)
+const SECRET_KEY = import.meta.env.VITE_SECRET_KEY;
+
+// 密码加密函数(使用AES加密)
+const encryptPassword = (password) => {
+  // 将加密结果转换为字符串并返回 (encrypt加密)
+  return CryptoJS.AES.encrypt(password, SECRET_KEY).toString();
+};
+
+// 密码解密函数 (接收加密后的密码字符串作为参数)
+const decryptPassword = (encryptedPassword) => {
+  // (decrypt解密)
+  const bytes = CryptoJS.AES.decrypt(encryptedPassword, SECRET_KEY);
+  // 将解密结果转换为 UTF-8 编码的字符串并返回
+  return bytes.toString(CryptoJS.enc.Utf8);
+};
 
 // 登录数据结构
 const createLoginData = () => {
@@ -119,6 +138,7 @@ const loginLogic = async (loginForm, tenantId, isAuthorized, router, redirectPat
       )
     } else {
       // 授权状态,使用账号密码登录
+      // 传输时使用明文密码,确保后端能正确处理
       res = await login(
         { 'Tenant-Id': tenantId },
         loginForm
@@ -144,8 +164,8 @@ const loginLogic = async (loginForm, tenantId, isAuthorized, router, redirectPat
       localStorage.setItem('rememberMe', loginForm.rememberMe)
       
       if (loginForm.rememberMe) {
-        // 保存密码
-        localStorage.setItem('password', loginForm.password)
+        // 保存加密后的密码
+        localStorage.setItem('password', encryptPassword(loginForm.password))
       } else {
         // 如果没有勾选记住我,清除密码
         localStorage.removeItem('password')
@@ -209,7 +229,8 @@ const loadLoginData = (loginData) => {
     loginData.value.loginForm.username = storedUserName
   }
   if (storedPassword) {
-    loginData.value.loginForm.password = storedPassword
+    // 解密密码并显示明文
+    loginData.value.loginForm.password = decryptPassword(storedPassword)
     loginData.value.loginForm.rememberMe = true
   }
 }
@@ -278,7 +299,7 @@ const autoLogin = async (tenantName, username, password, router, redirectPath) =
       localStorage.setItem('token', res.data.accessToken)
       localStorage.setItem('userName', username)
       localStorage.setItem('tenantName', tenantName)
-      localStorage.setItem('password', password)
+      localStorage.setItem('password', encryptPassword(password))
       localStorage.setItem('rememberMe', 'true')
 
       ElMessage.success('信息校验成功')

+ 5 - 14
src/views/laboratory/ExperimentalInterface.vue

@@ -140,8 +140,6 @@ import ImageToVideo from "@/components/ai/video/ImageToVideo.vue";
 import MapGame from "@/components/blockly/MapGame.vue";
 // 根据ID获取课程列表
 import { getBlocklyByTypeId } from '@/api/programming/index.js'
-// 导入音频播放器
-import { useAudioPlayer } from '@/api/tts/useAudioPlayer';
 
 // 定义常量
 const CONSTANTS = {
@@ -156,8 +154,6 @@ const router = useRouter() // 获取当前路由对象
 const boxIconTitle = ref('')
 // AI组件refs
 const aiTextToText = ref(null)
-// 音频播放器实例
-const { stopPlayback } = useAudioPlayer();
 // 定义组件的props
 const props = defineProps({
   courseData: {
@@ -221,12 +217,11 @@ const playPreviousVideo = () => {
   if (props.courseList && props.courseList.length > 0) {
     const currentIndex = currentCourseIndex.value
     if (currentIndex > 0) {
-      // 停止音频播放并清理资源
-      stopPlayback();
-      // 终止AI问答流并清空消息列表
+      // 终止AI问答流并清空消息列表,同时清理语音资源
       if (aiTextToText.value) {
         aiTextToText.value.stopStream();
         aiTextToText.value.clearMessageList();
+        aiTextToText.value.stopPlayback();
       }
       const previousCourse = props.courseList[currentIndex - 1]
       // 更新当前课程数据
@@ -243,12 +238,11 @@ const playNextVideo = () => {
   if (props.courseList && props.courseList.length > 0) {
     const currentIndex = currentCourseIndex.value
     if (currentIndex !== -1 && currentIndex < props.courseList.length - 1) {
-      // 停止音频播放并清理资源
-      stopPlayback();
-      // 终止AI问答流并清空消息列表
+      // 终止AI问答流并清空消息列表,同时清理语音资源
       if (aiTextToText.value) {
         aiTextToText.value.stopStream();
         aiTextToText.value.clearMessageList();
+        aiTextToText.value.stopPlayback();
       }
       const nextCourse = props.courseList[currentIndex + 1]
       // 更新当前课程数据
@@ -427,10 +421,7 @@ onMounted(async () => {
 })
 
 // 清理函数
-onUnmounted(() => {
-  // 组件卸载时清理音频资源
-  stopPlayback();
-})
+onUnmounted(() => {})
 
 // 保存视频/bockly进度接口
 const handleSaveProgress = async (type, progress) => {