diff --git a/AIchat.rar b/AIchat.rar deleted file mode 100644 index 81667e2..0000000 Binary files a/AIchat.rar and /dev/null differ diff --git a/src/pages.json b/src/pages.json index c39000d..9c77a3d 100644 --- a/src/pages.json +++ b/src/pages.json @@ -40,22 +40,6 @@ "navigationBarTitleText": "关于" } }, - { - "path": "pages/index/index copy", - "type": "page", - "layout": "default", - "style": { - "navigationBarHidden": true - } - }, - { - "path": "pages/index/index1", - "type": "page", - "layout": "default", - "style": { - "navigationBarHidden": true - } - }, { "path": "pages/preview/index", "type": "page" diff --git a/src/pages/index/index copy.vue b/src/pages/index/index copy.vue deleted file mode 100644 index a09c66b..0000000 --- a/src/pages/index/index copy.vue +++ /dev/null @@ -1,1510 +0,0 @@ - -{ - layout: 'default', - style: { - navigationBarHidden: true, - }, -} - - - - - - - diff --git a/src/pages/index/index-来源于韩庆伟分支.vue b/src/pages/index/index-来源于韩庆伟分支.vue deleted file mode 100644 index 57da3a8..0000000 --- a/src/pages/index/index-来源于韩庆伟分支.vue +++ /dev/null @@ -1,1005 +0,0 @@ - -{ - layout: 'default', - style: { - navigationBarHidden: true, - }, -} - - - - - - - diff --git a/src/pages/index/index.vue b/src/pages/index/index.vue index 48fbf91..e704e7e 100644 --- a/src/pages/index/index.vue +++ b/src/pages/index/index.vue @@ -146,7 +146,7 @@ @click="previewFile(file.url)" > {{ file.name }} - {{ file.size }} + {{ calcFileSize(file.size) }} @@ -191,6 +191,7 @@ + @@ -225,13 +226,47 @@ class="relative w-16 h-16 rounded overflow-hidden flex-shrink-0" > - {{item.uploadFileType}}-{{ uploadFileTypeEm.file}}--> + + + + + + + + + + - {{ item.name }} @@ -265,7 +300,9 @@ - + @@ -295,6 +332,7 @@ > 知识库 + @@ -302,10 +340,11 @@ + @@ -396,13 +435,21 @@ class="fixed inset-0 bg-black bg-opacity-90 z-999 flex justify-center items-start pt-10" @click="closePreview" > - + + ([]) +const messages = reactive([]) //获取用户上下文 const historyUserMsgs = reactive([]) const inputText = ref('') @@ -464,7 +516,7 @@ const uploadQueue = reactive([]) // 上传中文件数量 const uploadingCount = ref(0) // 最大并行上传数 -const MAX_CONCURRENT_UPLOADS = 6 +const MAX_CONCURRENT_UPLOADS = 5 // 6 // ------------------ // 控制弹窗显隐 & 全屏/底部模式 @@ -472,6 +524,10 @@ const MAX_CONCURRENT_UPLOADS = 6 const showPopup = ref(false) const fullscreen = ref(false) +const officeFileTypeList = ref(['.docx', '.doc', '.excel', '.pdf']) +const otherFileType = ref(['.txt']) +const videoFileType = ref(['.mp4', '.mov', '.wmv']) +const picFileType = ref(['.jpg', '.png', '.jpeg']) async function openPopup() { await fetchHistoryList() showPopup.value = true @@ -553,7 +609,7 @@ async function fetchHistoryList() { method: 'POST', data: { page: 1, - pageSize: 9990, + pageSize: 10, }, header: { Authorization: token.value, @@ -715,9 +771,7 @@ function tryParseMapFormat(str: string): ParsedPart[] | null { return result.length > 0 ? result : null } -const token = ref( - '79b5c732d96d2b27a48a99dfd4a5566c43aaa5796242e854ebe3ffc198d6876b9628e7b764d9af65ab5dbb2d517ced88170491b74b048c0ba827c0d3741462cb89dc59ed46653a449af837a8262941ca1430937103230a1e32a1715f569f3efdbe6f8cb8b7b8642bd679668081b9b08f693d1b5be6002d936ec51e1e3e0c4927de9e32ac99a109b326e5d2bda27ec87624bb416ec70d2a95a2e190feeba9f0d6bae8571b3dfe89c824712344759a8f2bff9d70747c52525cf6a5614f9c770bca461a9b9c247b6dca97bcf83bbaf99bb726752c4fe1e9a4aa7de5c4cf3e88a3e480801280d45cdc124f9d8221105d852945dc6ce10bc1647e4f09dff4d52ffdfc54709466166877e6ec300eecfc80f0c545e4240ab11ec248a32ee67129097b0b7abb383a5e398056f06c98cd65f5944054e10bdad0f7659f6c036b2010f30f74ff2a3fb7bd70a7cd3640a6f393b36a17', -) +const token = ref(TOKEN) const userInfo = ref({}) const refreshToken = ref('') const statusBarHeight = ref(0) @@ -727,7 +781,7 @@ const mask = ref('') onMounted(() => { // 1. 定义一个 init 函数,拿 Extras 并依次调用接口 const init = async () => { - const wv = plus.webview.currentWebview() + const wv = plus.webview.currentWebview() // 获取当前页面所属的 Webview 对象。 // 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') @@ -777,7 +831,7 @@ const previewVideo = (files) => { }) } -function addMessage(msg: IMessage) { +function addMessage(msg) { messages.push(msg) scrollToBottom() } @@ -932,12 +986,23 @@ const uploadFile = (file: UploadFile) => { file.progress = 100 file.url = result.data.cover_url || result.data.ori_url || file.tempFilePath file.ori_url = result.data.ori_url || '' + uni.showToast({ + title: res.msg || '文件上传成功', + icon: 'none', + }) } else { file.status = 'error' } }, fail: (err) => { file.status = 'error' + if (err.errMsg === 'uploadFile:fail timeout') { + uni.showToast({ + title: '上传文件超时', + icon: 'none', + duration: 3000, + }) + } }, complete: () => { // 更新上传文件列表状态 @@ -980,10 +1045,11 @@ const uploadFile = (file: UploadFile) => { const onPickImage = () => { loading.value = true uni.chooseImage({ - count: 10, // 最多选择9张 + count: 9, // 最多选择9张 sizeType: ['original', 'compressed'], sourceType: ['album'], - extension: ['.jpeg', '.png', '.jpg'], + // extension: ['.rar', '.png', '.jpg'], + // extension: ['jpeg', 'png', 'jpg'], success: (res: any) => { console.log(res) @@ -1005,7 +1071,7 @@ const onPickVideo = () => { uni.chooseVideo({ sourceType: ['album', 'camera'], compressed: true, - extension: uploadConfig.video.supportType, + // extension: uploadConfig.video.supportType, success: (res: any) => { console.log(res) const tempFile = res.tempFile @@ -1022,22 +1088,23 @@ const onPickVideo = () => { }, }) } - +const fileInput = ref(null) +// extension: [ +// 'txt', // 文本 +// 'pdf', // PDF +// 'doc', +// 'docx', // Word +// 'xls', +// 'xlsx', // Excel +// 'ppt', +// 'pptx', // PowerPoint +// ], // 文件 const onPickFile = () => { uni.chooseFile({ - count: 10, + count: 9, type: 'all', - extension: [ - '.txt', // 文本 - '.pdf', // PDF - '.doc', - '.docx', // Word - '.xls', - '.xlsx', // Excel - '.ppt', - '.pptx', // PowerPoint - ], + success: (res: any) => { console.log(res) // 开始上传 @@ -1085,6 +1152,7 @@ const previewFile = (url: string) => { } } +// 下载并打开文件 const downloadAndOpenFile = (downloadUrl: string) => { uni.showLoading({ title: '加载中...', mask: true }) @@ -1119,130 +1187,116 @@ const downloadAndOpenFile = (downloadUrl: string) => { dtask.start() } const msgLoading = ref(true) -// 发送消息 -async function sendText(msgData = '') { - console.log(msgData) - - msgLoading.value = true - const text = inputText.value.trim() - const dataBlo = toRaw(msgData) - console.log(dataBlo) - if (!text && dataBlo == '') { - msgLoading.value = false - - uni.showToast({ title: '请输入信息', icon: 'error' }) - - return +interface EventTargetSendText { + detail: { value: string } +} +type EventTypeTarget = string | EventTargetSendText +async function sendText() { + const msg = inputText.value.trim() + if (!msg) { + return showToastErr('不可以发送空消息!') } - if (loading.value) return + // 开启加载状态 + loading.value = true + // 文本消息 - const tempUploadList = Object.assign([], uploadList) - let fileList: any[] = [] - if (tempUploadList.length > 0) { - fileList = tempUploadList.map((item: UploadFile) => { - if (item.uploadFileType === uploadFileTypeEm.image) { - // 图片格式 - return { - type: 'image_url', - image_url: { - url: item.url, - }, - } - } else if (item.uploadFileType === uploadFileTypeEm.video) { - console.log(item, '====item=====') - // 视频格式(改成和图片一样的结构) - return { - type: 'video_url', - video_url: { - url: item.ori_url, - }, - } - } else { - // 其他文件类型保持原样 - const fileType = `${item.uploadFileType}_url` - return { - type: fileType, - [fileType]: item.url, - } + // 先判断是否上传文件,若有文件在判断文件类型,视频+图片不能与文档类文件同时上传 + addMessage({ + role: 'user', + type: 'text', + content: msg, + timestamp: new Date(), + }) + if (uploadList.length > 0) { + console.log(': 文件上传', uploadQueue) + console.log(': 文件上传', uploadList) + let mediaList = [] // 媒体文件 参数中的content + let fileList = [] // 文档文件 + // 格式化请求参数 + const { media, file } = formatParams(uploadList) + if (media.length > 0 && file.length > 0) { + // 媒体文件与文档同时上传时 + return showToastErr('视频或图片不能与文件同时上传') + } else if (media.length > 0 && file.length <= 0) { + // 仅上传了媒体文件时 + chatMode.value = 'qwen-vl-max' + let aiMsg = { + text: msg, + type: 'text', } - }) - } - - // 添加用户文本消息 - addMessage( - msgData || { - role: 'user', - type: 'text', - content: text, - timestamp: new Date(), - }, - ) - - //图片、视频、文件分开发送 - if (tempUploadList.length > 0) { - Object.values(uploadFileTypeEm).forEach((item: any) => { - if (tempUploadList.find((v: UploadFile) => v.uploadFileType === item)) { - addMessage({ - role: 'user', - type: item, - content: tempUploadList.filter((v) => v.uploadFileType === item), - timestamp: new Date(), - }) + let content = [].concat(media) + content.push(aiMsg) + const lastMsg = { + role: 'user', + content: content, + mask: 'new', } - }) + historyUserMsgs.push(lastMsg) + let body: IGptRequestBody = { + model: chatMode.value, // 模型选择 + max_tokens: 1000, + top_p: 1, + presence_penalty: 0, + frequency_penalty: 0, + messages: historyUserMsgs, // text ? [aiMsg] : historyUserMsgs, + stream: true, + } + // 开始发请求 api + } else if (media.length <= 0 && file.length > 0) { + // 仅上传了文档类文件时 + chatMode.value = 'qwen-long' + let aiMsg = { + role: 'user', + content: msg, + mask: 'new', + } + let content = [aiMsg] + content.concat(file) + let body: IGptRequestBody = { + model: chatMode.value, // 模型选择 + max_tokens: 1000, + top_p: 1, + presence_penalty: 0, + frequency_penalty: 0, + messages: historyUserMsgs, // text ? [aiMsg] : historyUserMsgs, + stream: true, + } + } + } else { + // 纯文本时发送 + chatMode.value = 'tongyi-app' //更新上下文消息 historyUserMsgs.push({ role: 'user', - content: [{ type: 'text', text }, ...fileList], + content: msg, timestamp: new Date(), }) - - //显示更多图片遮罩 - const showMoreImgMask = - tempUploadList.filter((v: UploadFile) => v.uploadFileType === uploadFileTypeEm.image).length > - 4 - showImageMask.value = showMoreImgMask - } else { - //更新上下文消息 - !msgData && - historyUserMsgs.push({ - role: 'user', - content: text, - timestamp: new Date(), - }) + const aiMsg = { + role: 'assistant', + type: 'text', + content: inputText.value, + timestamp: new Date(), + } + addMessage(aiMsg) + let body: IGptRequestBody = { + model: chatMode.value, // 模型选择 + max_tokens: 1000, + top_p: 1, + presence_penalty: 0, + frequency_penalty: 0, + messages: historyUserMsgs, // text ? [aiMsg] : historyUserMsgs, + stream: true, + } } - - inputText.value = '' - loading.value = true - - // AI消息 - const aiMsg: IMessage = { - role: 'assistant', - type: 'text', - content: text, - timestamp: new Date(), - } - addMessage(aiMsg) - - //清除上传列表 + // 第一次发送纯文本消息,第二次发送图片+视频,第三次发送文档,此时因为历史消息都要一起发送给后端, + // 所以要想办法在遇到这种情况时,截断历史记录,主动为用户建立一个新的回话,但是不需要清空历史记录 uploadList.splice(0, uploadList.length) - - const body: IGptRequestBody = { - model: chatMode.value, - max_tokens: 1000, - temperature: 1, - listUuid: listUuid.value, - top_p: 1, - presence_penalty: 0, - frequency_penalty: 0, - messages: msgData ? [msgData] : historyUserMsgs, - stream: true, - } - + // 没有上传文件,仅文字消息 try { - aiMsg.content = '' - + // aiMsg.content = '' + // 发送问题到后端 + inputText.value = '' const resp = await fetch(baseUrl + '/chat/app/completion', { method: 'POST', headers: { 'Content-Type': 'application/json', Authorization: token.value }, @@ -1302,7 +1356,6 @@ async function sendText(msgData = '') { showActions.value = false } } - function copyText(msg: IMessage) { if (typeof msg.content === 'string') { uni.setClipboardData({ @@ -1350,7 +1403,7 @@ function refreshText() { // 4. 自动触发发送(模拟用户点击发送按钮) setTimeout(() => { - sendText('') + sendText() }, 100) } @@ -1387,15 +1440,39 @@ const onFocus = () => { } const showPreview = ref(false) -const previewUrl = ref('') +const previewUrl = ref('') // 预览图片 +const previewVideoUrl = ref('') // 预览视频 const previewTop = ref(30) // 距离顶部30px -const handleImageClick = (data) => { - previewUrl.value = data - showPreview.value = true +const handleImageClick = (src) => { + let fileList = officeFileTypeList.value.concat(otherFileType.value) + // officeFileTypeList=ref(['.docx','.doc','.excel','.pdf']) + // const otherFileType=ref(['.txt']) + // const otherFileType=ref(['.txt']) + if (picFileType.value.includes(isFileType(src))) { + previewUrl.value = src + showPreview.value = true + } else if (videoFileType.value.includes(isFileType(src))) { + previewVideoUrl.value = src + showPreview.value = true + } else if (fileList.includes(isFileType(src))) { + previewFile(src) + } } const closePreview = () => { showPreview.value = false + previewUrl.value = '' + previewVideoUrl.value = '' +} +const reload = () => { + const currentWebview = plus.webview.currentWebview() + currentWebview.reload(true) +} + +const isFileType = (name: string) => { + let reg = /\.[\w\d]+$/ + let match = name.match(reg) + return match ? match[0] : null } @@ -1404,14 +1481,17 @@ const closePreview = () => { .slide-up-leave-active { transition: transform 0.3s ease-out; } + .slide-up-enter-from, .slide-up-leave-to { transform: translateY(100%); } + .slide-up-enter-to, .slide-up-leave-from { transform: translateY(0%); } + .font-pf { font-family: PingFangSC-Medium, sans-serif; } @@ -1431,10 +1511,12 @@ const closePreview = () => { padding: 0 24rpx; background: #fff; } + .nav-title { font-size: 32rpx; color: #333; } + .nav-icon { width: 40rpx; height: 40rpx; @@ -1459,6 +1541,7 @@ const closePreview = () => { background: #fff; border-radius: 12rpx 12rpx 0 0; } + .popup.fullscreen { height: 90%; border-radius: 0; @@ -1472,10 +1555,12 @@ const closePreview = () => { padding: 0 24rpx; border-bottom: 1rpx solid #f0f0f0; } + .popup-header .icon { width: 32rpx; height: 32rpx; } + .popup-header .title { flex: 1; font-size: 32rpx; @@ -1487,16 +1572,19 @@ const closePreview = () => { flex: 1; padding: 24rpx 0; } + .date-label { padding: 0 32rpx; margin-top: 24rpx; font-size: 24rpx; color: #999; } + .history-item { padding: 24rpx 32rpx; border-bottom: 1rpx solid #f0f0f0; } + .history-text { font-size: 28rpx; color: #333; @@ -1505,6 +1593,7 @@ const closePreview = () => { .tops { padding-top: var(--status-bar-height); } + .flex-i { display: flex !important; } diff --git a/src/pages/index/index1.vue b/src/pages/index/index1.vue deleted file mode 100644 index 0658951..0000000 --- a/src/pages/index/index1.vue +++ /dev/null @@ -1,553 +0,0 @@ - -{ - layout: 'default', - style: { - navigationBarHidden: true, - }, -} - - - - - - - diff --git a/src/pages/index/utils/data.js b/src/pages/index/utils/data.js new file mode 100644 index 0000000..ce35b5c --- /dev/null +++ b/src/pages/index/utils/data.js @@ -0,0 +1,205 @@ +// 发送消息 +async function sendText1(msgData = '') { + // let msgData='' + // if(msg===''){ + // msgData=msg + // }else if(msg.detail && msg.detail.value){ + + // msgData=msg.detail.value + // } + // console.log('msgData',msg) + // uni.showToast({ title: inputText.value, icon: 'error' }) + + msgLoading.value = true + const text = inputText.value.trim() + const dataBlo = text //toRaw(msgData) + console.log('dataBlo', dataBlo) + if (!text) { + msgLoading.value = false + + uni.showToast({ + title: '请输入信息', + icon: 'error' + }) + + return + } + if (loading.value) return + + inputText.value = '' + loading.value = true + const tempUploadList = Object.assign([], uploadList) + let fileList: any[] = [] + if (tempUploadList.length > 0) { + fileList = tempUploadList.map((item: UploadFile) => { + if (item.uploadFileType === uploadFileTypeEm.image) { + // 图片格式 + return { + type: 'image_url', + image_url: { + url: item.url, + }, + } + } else if (item.uploadFileType === uploadFileTypeEm.video) { + console.log(item, '====item=====') + // 视频格式(改成和图片一样的结构) + return { + type: 'video_url', + video_url: { + url: item.ori_url, + }, + } + } else { + // 其他文件类型保持原样 + const fileType = `${item.uploadFileType}_url` + return { + type: fileType, + [fileType]: item.url, + } + } + }) + } + + // 添加用户文本消息 + addMessage({ + role: 'user', + type: 'text', + content: text, + timestamp: new Date(), + }) + + //图片、视频、文件分开发送 + if (tempUploadList.length > 0) { + Object.values(uploadFileTypeEm).forEach((item: any) => { + if (tempUploadList.find((v: UploadFile) => v.uploadFileType === item)) { + addMessage({ + role: 'user', + type: item, + content: tempUploadList.filter((v) => v.uploadFileType === item), + timestamp: new Date(), + }) + } + }) + + //更新上下文消息 + historyUserMsgs.push({ + role: 'user', + content: [{ + type: 'text', + text + }, ...fileList], + timestamp: new Date(), + }) + + //显示更多图片遮罩 + const showMoreImgMask = tempUploadList.filter((v: UploadFile) => v.uploadFileType === uploadFileTypeEm.image).length > 4 + showImageMask.value = showMoreImgMask + } else { + //更新上下文消息 + historyUserMsgs.push({ + role: 'user', + content: text, + timestamp: new Date(), + }) + } + + // AI消息 + // const aiMsg: IMessage = { + const aiMsg = { + role: 'assistant', + type: 'text', + content: inputText.value, + timestamp: new Date(), + } + addMessage(aiMsg) + + //清除上传列表 + uploadList.splice(0, uploadList.length) + // console.log('[msgData] : historyUserMsgs: ',msgData); + // console.log('[msgData] : historyUserMsgs: ', historyUserMsgs); + const body: IGptRequestBody = { + model: chatMode.value, + max_tokens: 1000, + temperature: 1, + listUuid: listUuid.value, + top_p: 1, + presence_penalty: 0, + frequency_penalty: 0, + messages: historyUserMsgs, // text ? [aiMsg] : historyUserMsgs, + stream: true, + } + + try { + // aiMsg.content = '' + // 发送问题到后端 + const resp = await fetch(baseUrl + '/chat/app/completion', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + Authorization: token.value + }, + body: JSON.stringify(body), + }) + + const reader = resp.body!.getReader() + const decoder = new TextDecoder() + let buffer = '' + let done = false + + while (!done) { + const { + value, + done: streamDone + } = await reader.read() + done = streamDone + if (value) { + buffer += decoder.decode(value, { + stream: true + }) + const lines = buffer.split(/\r?\n/) + buffer = lines.pop() ! + + for (const line of lines) { + // 只处理以 "data: " 开头的行 + if (!line.startsWith('data: ')) continue + const chunk = line.slice(6).trim() + + 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 + //每次更新messages消息,实现流式输出 + messages[messages.length - 1] = { + ...aiMsg + } + scrollToBottom() + console.log('2') + } + } catch {} + } + + //更新上下文消息 + done && historyUserMsgs.push(aiMsg) + } + } + scrollToBottom() + } catch (err) { + aiMsg.content = '请重新发送' + //更新messages消息 + messages[messages.length - 1] = { + ...aiMsg + } + console.error(err) + } finally { + loading.value = false + showActions.value = false + } +} \ No newline at end of file diff --git a/src/pages/index/utils/index.ts b/src/pages/index/utils/index.ts new file mode 100644 index 0000000..df319c7 --- /dev/null +++ b/src/pages/index/utils/index.ts @@ -0,0 +1,52 @@ +export const formatParams = (uploadList) => { + // 上传文件formData类型 + const uploadFileTypeEm = { + image: 'image', + video: 'video', + file: 'file', + text: 'text', + } + let mediaList = [] // 媒体文件 参数中的content + let fileList = [] // 文档文件 + uploadList.forEach((item) => { + if (item.uploadFileType === uploadFileTypeEm.image) { + // 图片 + let media = { + type: 'image_url', + image_url: { + url: item.ori_url, + }, + } + mediaList.push(media) + } else if (item.uploadFileType === uploadFileTypeEm.video) { + // 视频 + let media = { + type: 'video_url', + video_url: { + url: item.url, + }, + } + mediaList.push(media) + } else if (item.uploadFileType === uploadFileTypeEm.file) { + let file = { + role: 'system', + content: item.url, + mask: 'new', + } + fileList.push(file) + } + }) + return { media: mediaList, file: fileList } +} +export const calcFileSize = (size: number) => { + const type = ['B', 'KB', 'MB', 'GB', 'TB'] + // for(let i=0;i1024;i++){ + // size/=1024 + // } + let unit = 'B' + while (size > 1024) { + size /= 1024 + unit = type.shift() + } + return `${Math.ceil(size)}${unit}` +} diff --git a/src/pages/index/utils/test.js b/src/pages/index/utils/test.js new file mode 100644 index 0000000..efafc04 --- /dev/null +++ b/src/pages/index/utils/test.js @@ -0,0 +1,3 @@ +export const TOKEN="79b5c732d96d2b27a48a99dfd4a5566c43aaa5796242e854ebe3ffc198d6876b9628e7b764d9af65ab5dbb2d517ced88170491b74b048c0ba827c0d3741462cb89dc59ed46653a449af837a8262941ca1430937103230a1e32a1715f569f3efdbe6f8cb8b7b8642bd679668081b9b08f693d1b5be6002d936ec51e1e3e0c4927de9e32ac99a109b326e5d2bda27ec87624bb416ec70d2a95a2e190feeba9f0d6bae8571b3dfe89c824712344759a8f2bff9d70747c52525cf6a5614f9c770bca461a9b9c247b6dca97bcf83bbaf99bb726752c4fe1e9a4aa7de5c4cf3e88a3e480801280d45cdc124f9d8221105d852945dc6ce10bc1647e4f09dff4d52ffdfc7eec89db303f76bb398a9e990517855cc34a9b4b5f8ebb42741e3f2c66d25790e78ad4d101c615554bbe75fdc3c97ddfe1a175322a675f7f0f55870b0222814de6998a4e9f7b24aaf9e07396389c2ec7" + +export const AVATAR="https://ts1.tc.mm.bing.net/th/id/R-C.66d7b796377883a92aad65b283ef1f84?rik=sQ%2fKoYAcr%2bOwsw&riu=http%3a%2f%2fwww.quazero.com%2fuploads%2fallimg%2f140305%2f1-140305131415.jpg&ehk=Hxl%2fQ9pbEiuuybrGWTEPJOhvrFK9C3vyCcWicooXfNE%3d&risl=&pid=ImgRaw&r=0" diff --git a/src/static/aichat/ic_video.png b/src/static/aichat/ic_video.png new file mode 100644 index 0000000..d3afbf8 Binary files /dev/null and b/src/static/aichat/ic_video.png differ diff --git a/src/static/aichat/txt.png b/src/static/aichat/txt.png new file mode 100644 index 0000000..d874ac6 Binary files /dev/null and b/src/static/aichat/txt.png differ diff --git a/src/static/aichat/word.png b/src/static/aichat/word.png new file mode 100644 index 0000000..df0eb20 Binary files /dev/null and b/src/static/aichat/word.png differ diff --git a/src/types/uni-pages.d.ts b/src/types/uni-pages.d.ts index 5fe5f4a..08d071f 100644 --- a/src/types/uni-pages.d.ts +++ b/src/types/uni-pages.d.ts @@ -6,8 +6,6 @@ interface NavigateToOptions { url: "/pages/index/index" | "/pages/about/about" | - "/pages/index/index copy" | - "/pages/index/index1" | "/pages/preview/index" | "/pages/webview/index"; } diff --git a/src/utils/api.js b/src/utils/api.js new file mode 100644 index 0000000..6efb333 --- /dev/null +++ b/src/utils/api.js @@ -0,0 +1,8 @@ +import {httpPost,httpGet} from "./http" +import {getEnvBaseUrl} from "./index" +const baseUrl=getEnvBaseUrl(); + +// 发送文本消息 +const endMsg=async (params)=>{ + return await httpGet(baseUrl+url,data) +} \ No newline at end of file diff --git a/src/utils/tools.js b/src/utils/tools.js new file mode 100644 index 0000000..d816f3f --- /dev/null +++ b/src/utils/tools.js @@ -0,0 +1,435 @@ +import { getEnvBaseUrl } from "./index"; +export const baseUrl =getEnvBaseUrl(); +// 获取接口(application/json,带token) +export const api = (url = '', params = {}, method = 'post') => { + let token = wx.getStorageSync('token'); + return new Promise((resolve, reject) => { + wx.request({ + url: baseUrl+url, + data: params, + method, + header: { + 'Content-Type': "application/json", + 'token': token, + }, + complete: res => { + if(res.statusCode == 200) { + resolve(res.data) + } else { + reject(res) + } + } + }) + }) +} +// 获取接口(application/x-www-form-urlencoded,带token) +export const api_form = (url = '', params = {}, method = 'post') => { + let token = wx.getStorageSync('token'); + return new Promise((resolve, reject) => { + wx.request({ + url: baseUrl+url, + data: params, + method, + header: { + 'Content-Type':"application/x-www-form-urlencoded", + 'token': token, + }, + complete: res => { + if(res.statusCode == 200) { + resolve(res.data) + } else { + reject(res) + } + } + }) + }) +} +// 获取接口(application/x-www-form-urlencoded,不带token) +export const apis = (url = '', params = {}, method = 'post') => { + return new Promise((resolve, reject) => { + wx.request({ + url: baseUrl+url, + data: params, + method, + header: { + 'Content-Type':"application/x-www-form-urlencoded", + }, + complete: res => { + if(res.statusCode == 200) { + resolve(res.data) + } else { + reject(res) + } + } + }) + }) +} +// 时间戳转日期(年月日) + export const time_format = (time) =>{ + // 判断时间戳是否为13位数,如果不是则*1000,时间戳只有13位数(带毫秒)和10(不带毫秒)位数的 + if(time.toString().length == 13){ + var tme = new Date(time); + }else{ + var tme = new Date(time * 1000); + } + var Y = tme.getFullYear(); + var M = (tme.getMonth() + 1 < 10 ? '0' + (tme.getMonth() + 1) : tme.getMonth() + 1); + var D = tme.getDate(); + var h = tme.getHours(); + var m = tme.getMinutes(); + var s = tme.getSeconds(); + var tem1 = Y + '-' + M + '-' + D + // + h + '时' + m + '分' + // + s +'秒' + return tem1; + } + export const time_format3 = (time) =>{ + // 判断时间戳是否为13位数,如果不是则*1000,时间戳只有13位数(带毫秒)和10(不带毫秒)位数的 + if(time.toString().length == 13){ + var tme = new Date(time); + }else{ + var tme = new Date(time * 1000); + } + var Y = tme.getFullYear(); + var M = (tme.getMonth() + 1 < 10 ? '0' + (tme.getMonth() + 1) : tme.getMonth() + 1); + var D = tme.getDate(); + var h = tme.getHours(); + if(h<10){ + h='0'+h; + } + var m = tme.getMinutes(); + if(m<10){ + m='0'+m; + } + var s = tme.getSeconds(); + if(s<10){ + s='0'+s; + } + var tem1 = Y + '-' + M + '-' + D +' '+h+':'+m+':'+s + // + h + '时' + m + '分' + // + s +'秒' + return tem1; + } +// 时间戳转日期(时分) + export const time_format1 = (time) =>{ + if(time.toString().length == 13){ + var tme = new Date(time); + }else{ + var tme = new Date(time * 1000); + } + var Y = tme.getFullYear(); + var M = (tme.getMonth() + 1 < 10 ? '0' + (tme.getMonth() + 1) : tme.getMonth() + 1); + var D = tme.getDate(); + var h = tme.getHours(); + var m = tme.getMinutes(); + var s = tme.getSeconds(); + var tem2 = + h + '时' + m + '分' + // + s +'秒' + return tem2; + } +// 时间戳转日期(时分 00:00格式) + export const toHHmmss= (data)=> { + var time; + var hours = parseInt((data % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60)); + var minutes = parseInt((data % (1000 * 60 * 60)) / (1000 * 60)); + // var seconds = (data % (1000 * 60)) / 1000; + time = (hours < 10 ? ('0' + hours) : hours) + ':' + (minutes < 10 ? ('0' + minutes) : minutes) ; + return time; +} +// 错误toast提示 +export const showToastErr = (title,mask=false) =>{ + wx.showToast({ + title: title, + icon: 'none', + duration: 1500, + mask:mask + }); +} +export function showToastErrMask(title){ + + wx.showToast({ + title:title, + icon:"none", + duration:1500, + mask:true + }) +} +// export function showToastErrMask(title){ +// wx.showToast({ +// title: title, +// icon:"none", +// duration:1500, +// mask:false +// }) +// } +// 成功toast提示 +export const showToastOk = (title,mask=false) =>{ + wx.showToast({ + title: title, + icon: 'success', + duration: 1500, + mask:mask + }); +} +export function showToastOkMask(title){ + // 用于不需要控制用户点击频率时 + wx.showToast({ + title:title, + icon:"success", + duration:1500, + mask:true + }) +} +// 上传图片 +export const uploadFile = (url,file)=>{ + let token = wx.getStorageSync('token'); + return new Promise((resolve, reject) => { + wx.uploadFile({ + url: baseUrl+ url, + filePath: file, + name: "file", + header: { + "Content-Type": "application/x-www-form-urlencoded", + 'token': token, + }, + complete: (res) => { + if(res.statusCode == 200) { + resolve(res) + } else { + reject(res) + } + } + }) + }) +} +// 上传图片(选择图片) +export const selectPic = ()=>{ + return new Promise((resolve,reject) => { + wx.chooseImage({ + count: 4, //默认9 + sizeType: ["original", "compressed"], //可以指定是原图还是压缩图,默认二者都有 + sourceType: ["album", "camera"], //从相册选择 + success: function (res) { + resolve(res) + }, + fail:function(){ + reject("选择文件失败") + } + }) + }) +} +// 日期字符串添加年月日 +export const times=(strTime, type)=> { + // 字符串转数组 + var strTimes = strTime.split(type) + strTimes[0] = strTimes[0] + strTimes[1] = strTimes[1] + strTimes[2] = strTimes[2] + // 数组转字符串 + strTimes = strTimes.join(type) + return strTimes + } + export const times1=(strTime, type)=> { + // 字符串转数组 + var strTimes = strTime.split(type) + strTimes[0] = strTimes[0] + '年' + strTimes[1] = strTimes[1] + '月' + strTimes[2] = strTimes[2] + '日' + strTimes[2] = strTimes[3] + '时' + strTimes[2] = strTimes[4] + '分' + strTimes[2] = strTimes[5] + '秒' + // 数组转字符串 + strTimes = strTimes.join(type) + return strTimes + } +// 登录 + export const login = () => { + return new Promise(function (resolve, reject) { + wx.login({ + success: function (res) { + if (res.code) { + resolve(res); + } else { + reject(res); + } + }, + fail: function (err) { + reject(err); + }, + }); + }); +}; +// 模态框 +export const Modal=(title,content)=> { + return new Promise((resolve,reject)=>{ + wx.showModal({ + title: title, + content: content, + success: function(res) { + if(res.confirm) { + resolve(res.confirm) + } else if(res.cancel) { + reject(res.cancel) + } + }, + fail: function(rej){ + reject(rej) + } + }) + }) +} +// 获取个人信息 + export const getUserInfo=()=> { + return new Promise((resolve, reject) => { + wx.getUserInfo({ + desc: '用于完善会员资料', + success: function (res) { + if (res) { + resolve(res); + } else { + reject(res); + } + }, + fail: function (err) { + reject(err); + }, + }) + }) +}; +export function navigateTo(url) { + wx.navigateTo({ + url: `/pages/${url}/${url}` + }) + } + export function reLaunch(url) { + wx.reLaunch({ + url: `/pages/${url}/${url}` + }) + } + + // 日期转时间戳 + export const date_stamp=(time)=> new Date(time).getTime()/1000 + + export function travelTree(tree,arr) { + for (let item of tree) { + arr.push(item.label); + if (item.children&& item.children.length) travelTree(item.children,arr); + } + return arr; +} +export function getToday(){ + let date=new Date(); + let year=date.getFullYear(); + let month=date.getMonth(); + let day=date.getDate(); + return `${year}-${month}-${day}`; +} + +// 重定向到某个页面 +export function redirectTo(nextUrl){ + wx.redirectTo({ + url: nextUrl, + }) +} +export function showloading(title=""){ + wx.showLoading({ + title:title, + mask:true + }) +} +export function hideloading(){ + wx.hideLoading() +} + +// 获取用户授权权限 +export function getLimit(){ + return new Promise((resolve,reject)=>{ + wx.getSetting({ + withSubscriptions:true, + success:function(res){ + if(res){ + resolve(res) + }else{ + reject(res) + } + }, + fail:(rej)=>{ + reject(rej) + } + }) + }) +} + +// 开启订阅 +export function subscribe(id){ + return new Promise((resolve,reject)=>{ + wx.requestSubscribeMessage({ + tmplIds: id, + success:function(res){ + if(res){ + resolve(res) + }else{ + reject(res) + } + }, + fail:function(rej){ + reject(rej) + } + }) + }) +} + +export const chooseMsgFile=()=>{ + return new Promise((resolve,reject)=>{ + wx.chooseMessageFile({ + count: 100, + type:"all", + success(res){ + if(res){ + resolve(res) + }else{ + reject(res) + } + }, + fail(rej){ + reject(rej) + }, + complete(res){ + if(res){ + resolve(res) + }else{ + reject(res) + } + } + }) + }) +} + +// 拍摄或者从相册上传 +export const chooseMedia=(count=9)=>{ + return new Promise((resolve,reject)=>{ + wx.chooseMedia({ + count:count, + mediaType:["image"], + sourceType:['album', 'camera'], + camera:"back", + success(res){ + if(res){ + resolve(res) + }else{ + reject(res) + } + }, + fail(rej){ + reject(rej) + }, + complete(res){ + if(res){ + resolve(res) + }else{ + reject(res) + } + } + }) + }) +} \ No newline at end of file diff --git a/src/utils/uploadFile.ts b/src/utils/uploadFile.ts new file mode 100644 index 0000000..41439c7 --- /dev/null +++ b/src/utils/uploadFile.ts @@ -0,0 +1,3 @@ +export const uploadFile = (url: string, options) => { + console.log('options: ', options) +}