Compare commits

..

No commits in common. "main" and "dev" have entirely different histories.
main ... dev

7 changed files with 142 additions and 231 deletions

View File

@ -5,7 +5,4 @@ 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 = 'https://erptest.fontree.cn:9020'
VITE_SERVER_BASEURL = 'http://114.218.158.24:9020'

View File

@ -52,7 +52,6 @@
"build:app-ios": "uni build -p app-ios",
"build:custom": "uni build -p",
"build:h5": "uni build",
"build:h5-dev": "uni build --mode dev",
"build": "uni build",
"build:h5:ssr": "uni build --ssr",
"build:mp-alipay": "uni build -p mp-alipay",

View File

@ -54,7 +54,7 @@ const httpInterceptor = {
const userStore = useUserStore()
const { token } = userStore.userInfo as unknown as IUserInfo
if (token) {
options.header.Authorization = `${token}`
options.header.Authorization = `Bearer ${token}`
}
},
}

View File

@ -160,7 +160,7 @@
v-for="(file, fileIdx) in msg.content"
:key="fileIdx"
style="flex: 0 0 6rem"
class="relative text-xs h-32 rounded-md overflow-hidden mr-1 c-black"
class="relative text-xs h-32 w-80 rounded-md overflow-hidden mr-1 c-black"
>
<!-- @click="previewVideo(msg.content)"-->
<video
@ -184,17 +184,11 @@
</view>
</view>
<view
v-if="
msg.role === 'assistant' && msg.type === 'text' && messages.length - 1 === idx
"
v-if="msg.role === 'assistant' && msg.type === 'text'"
class="absolute bottom--3.5 flex space-x-3 ml-1"
>
<image src="/static/aichat/copy.png" class="w-4 h-4" @click="copyText(msg)" />
<image
src="/static/aichat/resect.png"
class="w-4.3 h-4"
@click="refreshText(msg)"
/>
<image src="/static/aichat/resect.png" class="w-4.3 h-4" @click="refreshText()" />
</view>
</view>
<image
@ -338,7 +332,6 @@
@focus="onFocus"
@confirm="sendText"
placeholder="想对我说点什么~"
maxlength="5000"
class="flex-1 h-10 px-3 border border-gray-100 bg-[#f9f9f9] rounded-1 focus:outline-none"
/>
<!-- 将keyup替换为confirm -->
@ -356,6 +349,7 @@
v-if="sendTextLoading && inputText.length <= 0"
src="/static/aichat/enter-no.png"
class="w-7 h-7"
@click="sendText()"
:disabled="loading"
:class="[knowledgeOpen ? 'ml-2' : 'ml-0']"
/>
@ -483,7 +477,6 @@
import { ref, reactive, nextTick, watchEffect, watch } from 'vue'
import dayjs from 'dayjs'
import { useUserStore } from '@/store'
// import store from '@/store'
import { getEnvBaseUrl } from '@/utils'
import guid from '@/utils/guid.js'
import type { IGptRequestBody } from '@/service/index/foo'
@ -496,16 +489,15 @@ import {
officeFileTypeList as fileType,
videoFileType as videoType,
picFileType as picType,
isJsonObject,
} from './utils/index'
import 'dayjs/locale/zh-cn'
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 { log } from 'console'
dayjs.locale('zh-cn')
const store = useUserStore()
interface UploadFile {
id: string
@ -529,7 +521,7 @@ interface IMessage {
timestamp: Date
}
const MAX_FILE_SIZE = 10 * 1024 * 1024 // 5mb
const FILE_SLICE_SIZE = 5 * 1024 * 1024 //
const FILE_SLICE_SIZE = 10 * 1024 * 1024 //
const userAvatar = ref()
const chatMode = ref('qwen-vl-plus')
let isUserOk = false // 使 tongyi-app
@ -613,7 +605,7 @@ async function createChatSession() {
gptModel: chatMode.value,
},
header: {
// Authorization: token.value,
Authorization: token.value,
},
})
// listUuid
@ -635,9 +627,9 @@ const state = reactive({
})
const scrollTop = ref(0)
async function fetchHistoryList() {
if (state.page >= state.total / state.pageSize + 1 && state.total !== null) {
return
}
// if(state.page*state.pageSize>state.total && state.total!==null){
// return
// }
if (state.loading) {
return
}
@ -651,18 +643,12 @@ async function fetchHistoryList() {
pageSize: state.pageSize,
},
header: {
// Authorization: token.value,
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 {
rawList.value = rawList.value.concat(resp.data.data.data)
state.total = resp.data.data.count //Math.ceil(resp.data.count/state.page)
}
rawList.value = rawList.value.concat(resp.data.data.data)
state.total = resp.data.data.count //Math.ceil(resp.data.count/state.page)
// scrollTop.value+=60;
}
} catch (err) {
@ -676,10 +662,7 @@ const scrolltolowerLoadData = (e) => {
}
watch(
() => state.page,
async (newval) => {
if (newval <= 0) {
return
}
async () => {
await fetchHistoryList()
},
{ deep: true },
@ -687,12 +670,9 @@ watch(
async function openPopup() {
state.page++
showPopup.value = true
rawList.value = []
}
function closePopup() {
showPopup.value = false
state.page = 0
state.total = null
}
function toggleFullscreen() {
fullscreen.value = !fullscreen.value
@ -709,12 +689,12 @@ async function fetchHistoryDiets(value) {
gptModel: chatMode.value,
},
header: {
// Authorization: token.value,
Authorization: token.value,
},
})
if (resp && resp.data && resp.data.data) {
const rawList = resp?.data?.data?.detail //
listUuid.value = resp?.data?.data?.listUuid
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))
@ -991,30 +971,18 @@ onMounted(async () => {
try {
const init = async () => {
const wv = plus.webview.currentWebview() // Webview
token.value =
wv.token ||
uni.getStorageSync('token') ||
store.userInfo.token ||
import.meta.env.VITE_DEV_TOKEN
token.value = wv.token || uni.getStorageSync('token') || import.meta.env.VITE_DEV_TOKEN
userInfo.value = JSON.parse(wv.userInfo) || {}
refreshToken.value = wv.refreshToken || uni.getStorageSync('refreshToken')
statusBarHeight.value = wv.statusBarHeight || uni.getSystemInfoSync().statusBarHeight
userAvatar.value = userInfo.value.Avatar
mask.value = userInfo.value.ID
store.setUserInfo({
token: token.value,
avatar: userInfo.value.Avatar,
refreshToken: refreshToken.value,
statusBarHeight: statusBarHeight.value,
})
await createChatSession()
}
init()
} catch (e) {
console.error('onMounted e: ', e)
} finally {
token.value = store.userInfo.token
await createChatSession()
}
})
@ -1443,60 +1411,12 @@ 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'],
sourceType: ['album'],
maxDuration: 60,
compressed: true,
camera: 'back',
albumMode: 'custom',
// extension: uploadConfig.video.supportType,
success: (res: any) => {
console.log(res)
const tempFile = res.tempFile
tempFile.path = res.tempFilePath
//
addUploadQueue([tempFile], uploadFileTypeEm.video)
},
fail: (err) => {
uni.showToast({
title: '选取视频失败',
icon: 'none',
})
},
})
}
//
const onPickVideo2 = () => {
uni.chooseVideo({
sourceType: ['album', 'camera'],
maxDuration: 60,
compressed: true,
camera: 'back',
// extension: uploadConfig.video.supportType,
success: (res: any) => {
console.log(res)
@ -1641,6 +1561,7 @@ const stopMsg = () => {
stopStreamMsg = true
}
async function sendText() {
console.log('uploadList: ', uploadList)
if (uploadList.length > 0) {
const isUpLoading = uploadList.some((file) => {
// return file.status==="error" || file.status==="pending"
@ -1657,16 +1578,18 @@ async function sendText() {
}
}
const msg = inputText.value.trim()
if (!msg) {
if (!msg && !refreshSend.value) {
return showToastErr('不可以发送空消息!')
}
// if (uploadList.length > 0) {
// return showToastErr('!')
// }
if (!sendTextLoading.value) {
sendTextLoading.value = true
return showToastErr('正在接收消息请稍后')
}
//
sendTextLoading.value = false
//
// +
@ -1818,16 +1741,16 @@ async function sendText() {
}
}
} else {
// if (!refreshSend.value) {
//
addMessage({
role: 'user',
type: 'text',
content: msg,
timestamp: new Date(),
mask: 'new',
})
// }
if (!refreshSend.value) {
//
addMessage({
role: 'user',
type: 'text',
content: msg,
timestamp: new Date(),
mask: 'new',
})
}
//
chatMode.value = 'tongyi-app' //'tongyi-app'; qwen-long
@ -1859,6 +1782,7 @@ async function sendText() {
// +
//
console.log('message: ', messages)
uploadList.splice(0, uploadList.length) //
const list = formatData(messages)
@ -1866,39 +1790,9 @@ async function sendText() {
body.detail = JSON.stringify(messages)
aiMsg.content = ''
addMessage(aiMsg)
send(body)
// return
// return
//
}
const spliceMsg = (list, model) => {
let file = false
let image = false
let video = false
const length = list.length
console.log(list)
for (let i = length - 1; i >= 0; i--) {
const item = list[i]
if (model === 'tongyi-long' && item.type === 'image' && item.type === 'video') {
const index = length - i - 1
return list.splice(i - 1)
} else if (model !== 'tongyi-long' && item.type === 'file') {
const index = i
return list.splice(index + 1)
}
}
return list
}
const send = async (body) => {
// refreshSend.value = true; //
//
sendTextLoading.value = false //
const [aiMsg] = messages.slice(-1)
const recordList = messages.slice(0, messages.length - 1)
body.detail = JSON.stringify(recordList)
// console.log('body: ',body);
// body.messages = spliceMsg(body.messages, chatMode.value)
try {
// aiMsg.content = ''
//
@ -1907,14 +1801,10 @@ const send = async (body) => {
const signal = controller.signal
const resp = await fetch(baseUrl + '/chat/app/completion', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
Authorization: token.value,
},
headers: { 'Content-Type': 'application/json', Authorization: token.value },
body: JSON.stringify(body),
signal: signal,
})
// console.log(resp)
const reader = resp.body!.getReader()
const decoder = new TextDecoder()
@ -1942,23 +1832,20 @@ const send = async (body) => {
if (chunk === '[DONE]') {
done = true
console.log('sss')
break
}
try {
const json = JSON.parse(chunk)
const delta = json.choices?.[0]?.delta?.content
if (delta) {
msgLoading.value = false
aiMsg.content += delta
// msgLoading.value = false
//messages
messages[messages.length - 1] = { ...aiMsg }
scrollToBottom()
}
} catch (e) {
console.log(e)
} finally {
console.log('over')
}
} catch {}
}
//
@ -1984,13 +1871,6 @@ const send = async (body) => {
console.log('chunk------------------: ')
}
}
if (isJsonObject(buffer)) {
const response = JSON.parse(buffer)
if (response.code === 401) {
showToastErr('请重新登录')
}
}
scrollToBottom()
} catch (err) {
// aiMsg.content = ''
@ -2000,7 +1880,7 @@ const send = async (body) => {
} finally {
sendTextLoading.value = true
showActions.value = false
// refreshSend.value = false //
refreshSend.value = false //
msgLoading.value = false
}
}
@ -2012,22 +1892,14 @@ function copyText(msg: IMessage) {
uni.showToast({ title: '已复制', icon: 'success' })
},
fail(err) {
console.error('复制失败', err)
uni.showToast({ title: '复制失败', icon: 'error' })
},
})
}
}
const msgType = (msg) => {
return (
msg &&
msg.role === 'user' &&
(msg.type === 'text' || msg.type === 'image' || msg.type === 'video')
)
}
function refreshText(msg) {
console.log('refresh msg', msg)
function refreshText() {
if (!sendTextLoading.value) {
//
return
@ -2038,57 +1910,98 @@ function refreshText(msg) {
// 1.
const userMessages = messages.filter((msg) => msg.role === 'user')
// const lastTwoUserMsgs = userMessages.slice(-2)
// const [msg1, msg2, msg3] = deepClone(userMessages.slice(-3))
const newMsgArr = deepClone(userMessages.slice(-3))
const [msg1, msg2] = deepClone(userMessages.slice(-2))
// let text=lastTwoUserMsgs[0] // lastTwoUserMsgs.every((msg)=>msg.type==="text" || msg.type==="image" || msg.type==="video" || msg.type==="file")
// let file=lastTwoUserMsgs[1] // lastTwoUserMsgs.every((msg)=>msg.type==="text" || msg.type==="image" || msg.type==="video" || msg.type==="file")
// 2.
let text = null
let refreshText = null
const refreshFiles: UploadFile[] = []
for (let i = newMsgArr.length - 1; i >= 0; i--) {
const msg = newMsgArr[i]
if (msg.type === 'text') {
refreshFiles.unshift(msg)
break
} else {
refreshFiles.unshift(msg)
}
if (msg1 && msg1.type === 'text' && msg2 && msg2.type !== 'text') {
msg1.mask = 'new'
msg2.mask = 'new'
refreshFiles.push(msg1)
refreshFiles.push(msg2)
} else if (msg1.type === 'text' && msg1.role === 'user' && !msg2) {
msg1.mask = 'new'
refreshFiles.push(msg1)
} else if (msg2.type === 'text' && msg2.role === 'user' && !msg1) {
msg2.mask = 'new'
refreshFiles.push(msg2)
} else {
msg2.mask = 'new'
refreshFiles.push(msg2)
}
// lastTwoUserMsgs.forEach((msg,i) => {
// console.log('msg: ',msg);
// if (msg.type === 'text' && msg.role==="user") {
// refreshText = msg.content //
// refreshFiles.push({
// content:msg.content,
// type:"text",
// role:"user",
// timestamp:new Date(),
// mask:"new"
// })
// } else if(msg.type==="video"){
// msg.mask="new"
// refreshFiles.push(msg)
// // msg.content.forEach((file : any) => {
// // console.log('lastTwoUserMsgs file: ',file);
// // refreshFiles.push({
// // id: guid.getGuid(),
// // url: file.video_url.url,
// // status: 'success',
// // name: file.name || '',
// // size: file.size || 0,
// // uploadFileType: file.uploadFileType || detectFileType(file.video_url.url),
// // })
// // })
// }else if(msg.type==="image"){
// msg.mask="new"
// refreshFiles.push(msg)
// // msg.content.forEach((file : any) => {
// // console.log('lastTwoUserMsgs file: ',file);
// // refreshFiles.push({
// // id: guid.getGuid(),
// // url: file.image_url.url,
// // status: 'success',
// // name: file.name || '',
// // size: file.size || 0,
// // uploadFileType: file.uploadFileType || detectFileType(file.image_url.url),
// // })
// // })
// }else{
// msg.mask="new"
// refreshFiles.push(msg)
// // msg.content.forEach((file : any) => {
// // console.log('lastTwoUserMsgs file: ',file);
// // refreshFiles.push({
// // id: guid.getGuid(),
// // url: file.content,
// // status: 'success',
// // name: file.name || '',
// // size: file.size || 0,
// // uploadFileType: file.uploadFileType || detectFileType(file.content),
// // })
// // })
// }
// })
// 3.
// inputText.value = text
// inputText.value = refreshText
// uploadList.splice(0, uploadList.length, ...refreshFiles)
refreshFiles.forEach((ele) => {
messages.push(ele)
})
// return
// refreshSend.value = true
// inputText.value = text
refreshSend.value = true
// inputText.value = refreshText
// 4.
// setTimeout(() => {
// sendText()
// }, 100)
let list = formatData(messages)
const aiMsg = {
role: 'assistant',
type: 'text',
content: '',
timestamp: new Date(),
}
messages.push(aiMsg)
const body = {
model: chatMode.value, //
max_tokens: 1000,
top_p: 1,
presence_penalty: 0,
frequency_penalty: 0,
messages: list, // text ? [aiMsg] : historyUserMsgs,
stream: true,
listUuid: listUuid.value,
// listUuid:"eff18a10-1719-4528-ad63-ee5c01d0a412"
}
send(body)
setTimeout(() => {
sendText()
}, 100)
}
// URL

View File

@ -7,6 +7,7 @@ const baseUrl = getEnvBaseUrl()
// /artwork/get-chunk-list 获取文件分断数据
// /artwork/upload-chunk 分断上传画作图片
export const uploadFiles = (url, params) => {
let token = uni.getStorageSync('authorization')
return new Promise((resolve, reject) => {
uni.uploadFile({
url: baseUrl + url,
@ -14,6 +15,7 @@ export const uploadFiles = (url, params) => {
name: 'Chunk',
formData: params.formData,
header: {
authorization: token,
},
complete: (res) => {
// console.log('res: ',res);

View File

@ -202,6 +202,4 @@ async function sendText1(msgData = '') {
loading.value = false
showActions.value = false
}
}
export const TOKEN="79b5c732d96d2b27a48a99dfd4a5566c43aaa5796242e854ebe3ffc198d6876b9628e7b764d9af65ab5dbb2d517ced88170491b74b048c0ba827c0d3741462cb89dc59ed46653a449af837a8262941ca1430937103230a1e32a1715f569f3efdbe6f8cb8b7b8642bd679668081b9b08f693d1b5be6002d936ec51e1e3e0c4927de9e32ac99a109b326e5d2bda27ec87624bb416ec70d2a95a2e190feeba9f0d6bae8571b3dfe89c824712344759a8f2bff9d70747c52525cf6a5614f9c770bca461a9b9c247b6dca97bcf83bbaf99bb726752c4fe1e9a4aa7de5c4cf3e88a3e480801280d45cdc124f9d8221105d852945dc6ce10bc1647e4f09dff4d52ffdfcde73053dc1f269841c964c3b0779ceae38fcd1ac41220de5941cafd00664ae15bb706dfecc00972d1cf3c94b3ddec7758e514d8c0b32e2195e3bcb802d58861ca93e98cf322b9824623cfba4820be34e"
}

View File

@ -5,10 +5,6 @@ export const fileSuffix = (str) => {
let reg = /\.\w*$/
return str.match(reg)[0]
}
export const isJsonObject = (json) => {
const str = json.trim()
return str.startsWith('{') && str.endsWith('}')
}
export const officeFileTypeList = ['.docx', '.doc', '.xls', '.xlsx', '.pdf', '.txt']
export const videoFileType = ['.mp4', '.mov', '.wmv']
export const picFileType = ['.jpg', '.png', '.jpeg']
@ -39,16 +35,10 @@ export const formatParams = (uploadList) => {
}
videoList.push(media)
} else if (officeFileTypeList.includes(fileSuffix(item.ori_url))) {
const config = {
content: item.url,
filename: item.name,
title: item.name,
}
let file = {
role: 'system',
name: item.name,
// content: item.url,
content: {}, // item.url,
content: item.url,
size: item.size,
mask: 'new',
}
@ -122,7 +112,7 @@ export function formatData(list) {
result.push({
role: 'user',
content: content,
type: item.type,
type: 'image',
mask: item.mask,
})
} else if (item.type === 'file') {
@ -181,3 +171,15 @@ export async function readFile(file, chunkSize = 10 * 1024 * 1024) {
const buffer = await blob.blob()
return sliceFile(buffer, chunkSize)
}
function uploadChunkFile({ chunk, fileName }, index, total, fileId) {
const formData = new FormData()
formData.append('Chunk', chunk)
formData.append('ChunkFileName', `${fileName}_${index}`)
formData.append('total', total)
formData.append('UseType', 100)
formData.append('FileName', fileName)
formData.append('Source', 'aiChat')
formData.append('UseType', 100)
return
}