diff --git a/App.vue b/App.vue index f5d59f6..ffd4211 100644 --- a/App.vue +++ b/App.vue @@ -6,6 +6,7 @@ import useUserStore from './stores/useUserStore'; import usePageAnimation from './hook/usePageAnimation'; import useDictStore from './stores/useDictStore'; import { GlobalInactivityManager } from '@/utils/GlobalInactivityManager'; +import { playTextDirectly } from '@/hook/useTTSPlayer-all-in-one'; const { $api, navTo, @@ -98,6 +99,7 @@ function handleInactivity() { if (useUserStore().hasLogin) { // 1. 正常弹出确认框 + playTextDirectly('长时间无操作,是否继续使用?'); $confirm({ title: '会话即将过期', content: '长时间无操作,是否继续使用?', diff --git a/common/all-in-one-listen.js b/common/all-in-one-listen.js index 1ff93d4..52ef429 100644 --- a/common/all-in-one-listen.js +++ b/common/all-in-one-listen.js @@ -4,6 +4,9 @@ import { } from "./globalFunction"; import baseDB from '@/utils/db.js'; import useUserStore from '@/stores/useUserStore'; +import { + playTextDirectly +} from '@/hook/useTTSPlayer-all-in-one' export class IncreaseRevie { constructor(arg) { @@ -52,6 +55,7 @@ export class IncreaseRevie { useUserStore() .loginSetToken(resData.token) .then((resume) => { + playTextDirectly('登录成功') if (resume.data.jobTitleId) { useUserStore().initSeesionId(); safeReLaunch('/pages/index/index'); @@ -63,6 +67,7 @@ export class IncreaseRevie { } } else { $api.msg('识别失败') + playTextDirectly('识别失败') } } } \ No newline at end of file diff --git a/hook/useTTSPlayer-all-in-one.js b/hook/useTTSPlayer-all-in-one.js index cca5e8f..5fe2a69 100644 --- a/hook/useTTSPlayer-all-in-one.js +++ b/hook/useTTSPlayer-all-in-one.js @@ -6,6 +6,69 @@ import { onHide, onUnload } from '@dcloudio/uni-app' +import { + isY9MachineType +} from '../common/globalFunction'; + +/** + * 封装 hh.call 通用调用 + */ +const callBridge = (params) => { + return new Promise((resolve) => { + if (typeof window !== 'undefined' && window.hh && window.hh.call) { + // 打印日志方便调试 + console.log('[TTS Bridge Send]:', params) + window.hh.call("ampeHHCommunication", params, (res) => { + console.log('[TTS Bridge Res]:', res) + resolve(res) + }) + } else { + console.warn('当前环境不支持 hh.call,模拟成功') + resolve({ + success: true + }) + } + }) +} + +/** + * 生成随机 TaskId + */ +const generateTaskId = () => { + return 'task_' + Date.now() + '_' + Math.floor(Math.random() * 1000) +} + +/** + * 直接播放文本 (静态方法,无需实例化 Hook) + * @param {string} text - 需要朗读的文本 + */ +export async function playTextDirectly(text) { + if (!text) return + + if (!isY9MachineType()) return + + const processedText = extractSpeechText(text) + if (!processedText) return + + try { + // 构造播放参数 + const params = { + "action": "speech", + "event": "open", + "taskId": generateTaskId(), + "params": { + "text": processedText, + "pitch": 1.0, + "rate": 1.0, + "speechQueue": 1 // 1表示打断当前播放,立即播放新的 + } + } + // 直接调用 + await callBridge(params) + } catch (e) { + console.error('Direct Play Error:', e) + } +} /** * 一体机 TTS 播放器 Hook (修复版) @@ -19,34 +82,6 @@ export function useTTSPlayer() { // 记录最后一次播放的文本 const lastText = ref('') - /** - * 封装 hh.call 通用调用 - */ - const callBridge = (params) => { - return new Promise((resolve) => { - if (typeof window !== 'undefined' && window.hh && window.hh.call) { - // 打印日志方便调试 - console.log('[TTS Bridge Send]:', params) - window.hh.call("ampeHHCommunication", params, (res) => { - console.log('[TTS Bridge Res]:', res) - resolve(res) - }) - } else { - console.warn('当前环境不支持 hh.call,模拟成功') - resolve({ - success: true - }) - } - }) - } - - /** - * 生成随机 TaskId - */ - const generateTaskId = () => { - return 'task_' + Date.now() + '_' + Math.floor(Math.random() * 1000) - } - /** * 停止 (中断) - 内部使用 */ @@ -221,4 +256,19 @@ function extractSpeechText(markdown) { finalTextParts.push(...jobTexts); if (endingText) finalTextParts.push(endingText); return finalTextParts.join('\n'); -} \ No newline at end of file +} + + +// 使用方法 1 +// import { useTTSPlayer } from '@/hook/useTTSPlayer-all-in-one' + +// const { speak, stop, isSpeaking } = useTTSPlayer() + +// // 调用 +// speak('你好,这是一段测试文本') + +// 使用方法 2 +// import { playTextDirectly } from '@/hook/useTTSPlayer-all-in-one' + +// // 直接调用即可,无需实例化 +// playTextDirectly('直接朗读这段话,不需要处理暂停和UI状态') \ No newline at end of file diff --git a/packageA/pages/post/post.vue b/packageA/pages/post/post.vue index 10f5f48..4166edc 100644 --- a/packageA/pages/post/post.vue +++ b/packageA/pages/post/post.vue @@ -185,6 +185,7 @@ import dictLabel from '@/components/dict-Label/dict-Label.vue'; import RadarMap from './component/radarMap.vue'; import { storeToRefs } from 'pinia'; import useUserStore from '@/stores/useUserStore'; +import { playTextDirectly } from '@/hook/useTTSPlayer-all-in-one'; const { isMiniProgram, hasLogin } = storeToRefs(useUserStore()); const { $api, navTo, getLenPx, parseQueryParams, navBack, isEmptyObject } = inject('globalFunction'); @@ -331,10 +332,12 @@ function jobApply() { }; if (jobInfo.value.isApply) { $api.msg('已经投递过该岗位了~'); + playTextDirectly('已经投递过该岗位了'); return; } else { $api.createRequest(`/app/internal/sendResume`, params, 'POST').then((resData) => { $api.msg('投递成功'); + playTextDirectly('投递成功'); getDetail(jobIdRef.value); }); } @@ -348,6 +351,7 @@ function jobApply() { $api.createRequest(`/app/job/apply/${jobId}`, {}, 'GET').then((resData) => { getDetail(jobId); $api.msg('申请成功'); + playTextDirectly('申请成功'); const jobUrl = jobInfo.value.jobUrl; return window.open(jobUrl); }); @@ -364,11 +368,13 @@ function jobCollection() { $api.createRequest(`/app/job/collection/${id}/2`, {}, 'DELETE').then((resData) => { getDetail(jobIdRef.value); $api.msg('取消收藏成功'); + playTextDirectly('取消收藏成功'); }); } else { $api.createRequest(`/app/job/collection/${id}/2`, {}, 'POST').then((resData) => { getDetail(jobIdRef.value); $api.msg('收藏成功'); + playTextDirectly('收藏成功'); }); } } else { @@ -378,11 +384,13 @@ function jobCollection() { $api.createRequest(`/app/job/collection/${jobId}/1`, {}, 'DELETE').then((resData) => { getDetail(jobId); $api.msg('取消收藏成功'); + playTextDirectly('取消收藏成功'); }); } else { $api.createRequest(`/app/job/collection/${jobId}/1`, {}, 'POST').then((resData) => { getDetail(jobId); $api.msg('收藏成功'); + playTextDirectly('收藏成功'); }); } } diff --git a/pages/login/login.vue b/pages/login/login.vue index 7eb0670..6ed175f 100644 --- a/pages/login/login.vue +++ b/pages/login/login.vue @@ -196,11 +196,13 @@ import { reactive, inject, watch, ref, onMounted, onUnmounted } from 'vue'; import { onLoad, onShow } from '@dcloudio/uni-app'; import useUserStore from '@/stores/useUserStore'; import useDictStore from '@/stores/useDictStore'; +import { playTextDirectly } from '@/hook/useTTSPlayer-all-in-one'; const { $api, navTo } = inject('globalFunction'); const { loginSetToken, getUserResume } = useUserStore(); const { isMachineEnv } = storeToRefs(useUserStore()); const { getDictSelectOption, oneDictData } = useDictStore(); const openSelectPopup = inject('openSelectPopup'); + // status const selectJobsModel = ref(); const tabCurrent = ref(1); @@ -242,6 +244,7 @@ onMounted(() => { if (isMachineEnv) { startCountdown(); startScanAnimation(); + playTextDirectly('请进行用户登录'); } }); onUnmounted(() => {