From 09510a24003ef922b2de526492aa9d5c06e3689f Mon Sep 17 00:00:00 2001 From: changDongFang <2628162102@qq.com> Date: Thu, 19 Jun 2025 17:06:34 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20ai=E8=81=8A=E5=A4=A9=E5=AE=8C=E6=88=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- env/.env.development | 13 ++- env/.env.production | 11 +- package.json | 1 + pnpm-lock.yaml | 21 ++++ src/pages/index/index.vue | 186 +++++++++++++++++---------------- src/pages/index/utils/api.js | 8 +- src/pages/index/utils/data.js | 19 +++- src/pages/index/utils/index.ts | 6 +- 8 files changed, 166 insertions(+), 99 deletions(-) diff --git a/env/.env.development b/env/.env.development index 64ddf7c..c004352 100644 --- a/env/.env.development +++ b/env/.env.development @@ -5,7 +5,18 @@ VITE_DELETE_CONSOLE = false # 是否开启sourcemap VITE_SHOW_SOURCEMAP = true +# 开发环境 # VITE_SERVER_BASEURL = 'http://114.218.158.24:9020' -VITE_SERVER_BASEURL = 'https://erpapi.fontree.cn' +# VITE_SERVER_BASEURL = 'http://192.168.88.80:9040/api' +# 正式环境 作为测试使用 +# VITE_SERVER_BASEURL = 'https://warehouse.szjixun.cn/oa_backend' + +#体制外 +# VITE_SERVER_BASEURL = 'https://oa-a.szjixun.cn/api' + +# 体制内 +VITE_SERVER_BASEURL = 'https://oa-b.szjixun.cn/api' +# VITE_SERVER_BASEURL = 'https://oa-b.szjixun.cn/api' +# VITE_SERVER_BASEURL = 'https://erpapi.fontree.cn' # VITE_SERVER_BASEURL = 'https://erptest.fontree.cn:9020' \ No newline at end of file diff --git a/env/.env.production b/env/.env.production index fe4a86a..d7b0f56 100644 --- a/env/.env.production +++ b/env/.env.production @@ -5,6 +5,15 @@ VITE_DELETE_CONSOLE = true # 是否开启sourcemap VITE_SHOW_SOURCEMAP = false -VITE_SERVER_BASEURL = 'https://erpapi.fontree.cn' # 体制外 OA +# VITE_SERVER_BASEURL = 'https://erpapi.fontree.cn' # 体制外 OA +# 正式环境 作为测试使用 +# VITE_SERVER_BASEURL = 'https://warehouse.szjixun.cn/oa_backend' +# VITE_SERVER_BASEURL = 'https://oa-a.szjixun.cn/api' +#体制外 +# VITE_SERVER_BASEURL = 'https://oa-a.szjixun.cn/api' + +# 体制内 +VITE_SERVER_BASEURL = 'https://oa-b.szjixun.cn/api' + diff --git a/package.json b/package.json index 95f057d..ee9507c 100644 --- a/package.json +++ b/package.json @@ -107,6 +107,7 @@ "pinia": "2.0.36", "pinia-plugin-persistedstate": "3.2.1", "qs": "6.5.3", + "vconsole": "^3.15.1", "vue": "3.4.21", "wot-design-uni": "^1.4.0", "z-paging": "^2.8.4" diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 63c1e99..a436fcf 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -70,6 +70,9 @@ dependencies: qs: specifier: 6.5.3 version: 6.5.3 + vconsole: + specifier: ^3.15.1 + version: 3.15.1 vue: specifier: 3.4.21 version: 3.4.21(typescript@5.8.3) @@ -5555,6 +5558,11 @@ packages: engines: {node: '>= 0.6'} dev: true + /copy-text-to-clipboard@3.2.0: + resolution: {integrity: sha512-RnJFp1XR/LOBDckxTib5Qjr/PMfkatD0MUCQgdpqS8MdKiNUzBjAQBEN6oUy+jW7LI93BBG3DtMB2KOOKpGs2Q==} + engines: {node: '>=12'} + dev: false + /core-js-compat@3.42.0: resolution: {integrity: sha512-bQasjMfyDGyaeWKBIu33lHh9qlSR0MFE/Nmc6nMjf/iU9b3rSMdAYz1Baxrv4lPdGUsTqZudHA4jIGSJy0SWZQ==} dependencies: @@ -8325,6 +8333,10 @@ packages: resolution: {integrity: sha512-ckmWDJjphvd/FvZawgygcUeQCxzvohjFO5RxTjj4eq8kw359gFF3E1brjfI+viLMxss5JrHTDRHZvu2/tuy0Qg==} dev: true + /mutation-observer@1.0.3: + resolution: {integrity: sha512-M/O/4rF2h776hV7qGMZUH3utZLO/jK7p8rnNgGkjKUw8zCGjRQPxB8z6+5l8+VjRUQ3dNYu4vjqXYLr+U8ZVNA==} + dev: false + /nanoid@3.3.11: resolution: {integrity: sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==} engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} @@ -10495,6 +10507,15 @@ packages: engines: {node: '>= 0.8'} dev: true + /vconsole@3.15.1: + resolution: {integrity: sha512-KH8XLdrq9T5YHJO/ixrjivHfmF2PC2CdVoK6RWZB4yftMykYIaXY1mxZYAic70vADM54kpMQF+dYmvl5NRNy1g==} + dependencies: + '@babel/runtime': 7.27.1 + copy-text-to-clipboard: 3.2.0 + core-js: 3.42.0 + mutation-observer: 1.0.3 + dev: false + /vite-plugin-restart@0.4.2(vite@5.2.8): resolution: {integrity: sha512-9aWN2ScJ8hbT7aC8SDeZnsbWapnslz1vhNq6Vgf2GU9WdN4NExlrWhtnu7pmtOUG3Guj8y6lPcUZ+ls7SVP33w==} peerDependencies: diff --git a/src/pages/index/index.vue b/src/pages/index/index.vue index 6167733..100a256 100644 --- a/src/pages/index/index.vue +++ b/src/pages/index/index.vue @@ -11,7 +11,7 @@
小墨
@@ -164,11 +164,23 @@ > + +
@@ -309,10 +321,11 @@
@@ -503,6 +516,7 @@ import { showToastErr, showToastOk, time_format3 } from '@/utils/tools' import { uploadFileChunk } from './utils/api.js' // import { TOKEN, AVATAR } from './utils/test' import { deepClone } from 'wot-design-uni/components/common/util' +import VConsole from 'vconsole' dayjs.locale('zh-cn') const store = useUserStore() @@ -528,8 +542,8 @@ interface IMessage { content: string | any[] timestamp: Date } -const MAX_FILE_SIZE = 10 * 1024 * 1024 // 5mb属于大文件 -const FILE_SLICE_SIZE = 5 * 1024 * 1024 // 分片大小 +const MAX_FILE_SIZE = 5 * 1024 * 1024 // 5mb属于大文件 +const FILE_SLICE_SIZE = 2 * 1024 * 1024 // 分片大小 const userAvatar = ref() const chatMode = ref('qwen-vl-plus') let isUserOk = false // 用户确认使用 tongyi-app @@ -606,18 +620,23 @@ const listUuid = ref('') async function createChatSession() { try { - const createResp: any = await uni.request({ + const res: any = await uni.request({ url: `${baseUrl}/chat/app/create`, method: 'POST', data: { gptModel: chatMode.value, }, header: { - // Authorization: token.value, + Authorization: token.value, }, }) // 如果后台返回新的会话信息,可以在这里处理,比如拿到 listUuid 等 - listUuid.value = createResp.data.data.listUuid + + if (res.data.code === 0 && res?.data?.data?.listUuid) { + listUuid.value = res?.data?.data?.listUuid + } else { + showToastErr(res.data.msg) + } } catch (err) { console.log(err) } @@ -654,16 +673,20 @@ async function fetchHistoryList() { // Authorization: token.value, }, }) - if (resp.data && resp.data.data) { - if (state.total === null) { - rawList.value = resp.data.data.data - state.total = resp.data.data.count - } else { + if (resp.data.code == 0 && resp.data.data) { + if (rawList.value.length > 0) { rawList.value = rawList.value.concat(resp.data.data.data) state.total = resp.data.data.count //Math.ceil(resp.data.count/state.page) + } else { + if (resp?.data?.data?.data) { + rawList.value = resp.data.data.data + } + state.total = resp.data.data.count } // scrollTop.value+=60; + } else { + showToastErr(resp.data.msg || '') } } catch (err) { console.log('err: ', err) @@ -685,14 +708,14 @@ watch( { deep: true }, ) async function openPopup() { - state.page++ showPopup.value = true - rawList.value = [] + state.page++ } function closePopup() { showPopup.value = false state.page = 0 state.total = null + rawList.value = [] } function toggleFullscreen() { fullscreen.value = !fullscreen.value @@ -712,12 +735,14 @@ async function fetchHistoryDiets(value) { // Authorization: token.value, }, }) - if (resp && resp.data && resp.data.data) { + if (resp.data.status === 0 && resp.data && resp.data.data) { const rawList = resp?.data?.data?.detail // 假设后端直接返回消息数组 listUuid.value = resp?.data?.data?.listUuid // const newMessages = parseBackendMessages(JSON.parse(rawList)) // 用解析后的消息替换当前消息列表 messages.splice(0, messages.length, ...JSON.parse(rawList)) + } else { + showToastErr(resp.msg || '') } } catch (err) { console.log('err: ', err) @@ -1007,15 +1032,21 @@ onMounted(async () => { refreshToken: refreshToken.value, statusBarHeight: statusBarHeight.value, }) + if (userInfo.value.TelNum === '18639432358') { + new VConsole() + } await createChatSession() } init() } catch (e) { console.error('onMounted e: ', e) } finally { - token.value = store.userInfo.token - await createChatSession() + // store.userInfo.token = '' + // token.value = store.userInfo.token } + // if (JSON.parse(uni.getStorageSync('userInfo'))?.NickName === '常东方') { + // new VConsole() + // } }) function scrollToBottom() { @@ -1056,7 +1087,6 @@ const previewVideo = (files) => { } function addMessage(msg) { - console.log('msg: ', msg) messages.push(msg) scrollToBottom() } @@ -1191,9 +1221,8 @@ const startUploads = () => { if (file.size > MAX_FILE_SIZE) { bigFileUpload(file) .then((res) => { - console.log('全部成功 res: ', res) // const length=res.length; - url = res.FullFileUrl + // file.url = res.FullFileUrl file.status = 'success' uploadingCount.value-- }) @@ -1203,7 +1232,23 @@ const startUploads = () => { // uploadingCount.value-- }) } else { - uploadFile(file) + bigFileUpload(file) + .then((res) => { + console.log('全部成功 res: ', res) + // const length=res.length; + file.url = res.FullFileUrl + file.status = 'success' + uploadingCount.value-- + console.log(file) + }) + .catch((rej) => { + console.log('失败rej: ', rej) + file.status = 'error' + // uploadingCount.value-- + }) + .finally(() => { + console.log('filesToUpload', filesToUpload) + }) } }) } @@ -1287,7 +1332,6 @@ function bigFileUpload(file) { file.status = 'uploading' uploadingCount.value++ - console.log('file: ', file) //progress return new Promise(async (resolve, reject) => { const md5 = file.id const fileName = file.name @@ -1296,7 +1340,7 @@ function bigFileUpload(file) { const chunksList = await readFile(file, maxSize) const chunksLength = chunksList.length const requestList = [] - const maxConcurrency = 3 // 一次最多3个 + const maxConcurrency = 1 // 一次最多3个 let currentRunning = 0 let index = 0 let success = null @@ -1361,10 +1405,17 @@ function bigFileUpload(file) { currentRunning-- if (chunkIndex === chunksLength - 1) { if (errors.length === 0) { - file.status = 'success' - resolve(success) + if (success.FullFileUrl || success.CoverUrl) { + file.status = 'success' + file.FullFileUrl = success.FullFileUrl || success.CoverUrl + + resolve(success) + } else { + file.status = 'error' + } } else { file.status = 'error' + reject(errors) } } else if (index < chunksLength) { @@ -1374,48 +1425,6 @@ function bigFileUpload(file) { } } next() - // const request = (chunks, i) => { - // const chunk = chunks.shift() - // const params = { - // FileMd5: md5, - // Chunk: chunk, - // ChunkFileName: `${fileName}_${i}`, - // Total: chunksLength, - // UseType: 100, - // FileName: fileName, - // Source: 'aiChat', - // } - - // uploadFileChunk({ formData: params, tempFilePath: tempFilePath }) - // .then((res) => { - // // requestList.push(Promise.resolve(res)) - // if (res.status === 0) { - // file.progress = Math.ceil(((i + 1) / chunksLength) * 100) - // Promise.resolve(JSON.parse(res.data)) - // } else { - // Promise.reject(res) - // } - // }) - // .catch((rej) => { - // // requestList.push(Promise.resolve(rej)) - // Promise.reject(rej) - // }) - // .finally(() => { - // if (chunks.length > 0) { - // request(chunks, ++i) - // } - // }) - // } - // console.log('success,next: ', success, errors); - // const promiseList=chunksList.map(request); - // request(chunksList, 0) - // return Promise.all(chunksList) - // .then((res) => { - // console.log('all res: ', res) - // }) - // .catch((rej) => { - // console.log('all rej: ', rej) - // }) }) } @@ -1445,25 +1454,6 @@ const onPickImage = () => { } // 调用原生 Android API 拍摄视频 -const onPickVideo3 = () => { - var cmr = plus.camera.getCamera() - - try { - cmr.startVideoCapture( - () => { - alert('ok') - }, - () => { - alert('err') - }, - {}, - ) - } catch (e) { - } finally { - cmr.stopVideoCapture() - } -} - const onPickVideo = () => { uni.chooseVideo({ // sourceType: ['album', 'camera'], @@ -1533,7 +1523,6 @@ const onPickFile = () => { type: 'all', success: (res: any) => { - console.log(res) // 开始上传 addUploadQueue(res.tempFiles, uploadFileTypeEm.file) }, @@ -1866,6 +1855,8 @@ async function sendText() { body.detail = JSON.stringify(messages) aiMsg.content = '' addMessage(aiMsg) + console.log('api body', body) + send(body) // return // return @@ -1897,6 +1888,14 @@ const send = async (body) => { const [aiMsg] = messages.slice(-1) const recordList = messages.slice(0, messages.length - 1) body.detail = JSON.stringify(recordList) + // body.model = chatMode.value // 模型选择 + // body.max_tokens = 1000 + // body.top_p = 1 + // body.presence_penalty = 0 + // body.frequency_penalty = 0 + // messages: deepClone(historyUserMsgs), // text ? [aiMsg] : historyUserMsgs, + // body.stream = true + // body.listUuid = listUuid.value // console.log('body: ',body); // body.messages = spliceMsg(body.messages, chatMode.value) try { @@ -1987,7 +1986,9 @@ const send = async (body) => { if (isJsonObject(buffer)) { const response = JSON.parse(buffer) if (response.code === 401) { - showToastErr('请重新登录') + showToastErr(response.msg) + } else { + showToastErr(response.msg) } } @@ -2162,6 +2163,9 @@ const isFileType = (name: string) => { let match = name.match(reg) return match ? match[0] : null } +const isVideo = (video) => { + return videoFileType.value.includes(isFileType(video)) +}