增加语音播放暂停功能

main
xushilin 3 months ago
parent 9fba96e374
commit 2e88029c58

@ -1,11 +1,38 @@
import request from '@/request';
// 获取回复
export const getAIResponse = (data) => request({
method : 'POST',
method: 'POST',
url: '/api/chat',
data
});
export const getTextToAudio = (tex) => {
return new Promise(resolve => {
uni.request({
url: `https://tsn.baidu.com/text2audio`,
method: 'POST',
data : {
tex,
tok : '24.1c8cc30b5f7be445723b6d4b19a36152.2592000.1765094496.282335-120706844',
cuid : '17619124287472660978',
ctp : '1',
lan : 'zh',
spd : 5,
pit : 5,
vol : 5,
per : 0,
aue : 3
},
'headers': {
'Content-Type': 'application/json',
'Accept': 'application/json'
}
}).then(res => {
console.log('res getBaiduToken ',res);
})
})
}

@ -1,25 +1,28 @@
import App from './App'
// #ifndef VUE3
import Vue from 'vue'
import './uni.promisify.adaptor'
import store from './store'
Vue.config.productionTip = false
Vue.prototype.$store = store
Vue.prototype.$store = store;
App.mpType = 'app'
const app = new Vue({
...App
...App
})
app.$mount()
// #endif
// #ifdef VUE3
import { createSSRApp } from 'vue'
import {
createSSRApp
} from 'vue'
export function createApp() {
const app = createSSRApp(App)
return {
app
}
const app = createSSRApp(App)
return {
app
}
}
// #endif

@ -1,116 +1,116 @@
{
"name" : "萃星智能AI",
"appid" : "__UNI__5BDEDB4",
"description" : "",
"versionName" : "1.0.1",
"versionCode" : 100,
"transformPx" : false,
/* 5+App */
"app-plus" : {
"usingComponents" : true,
"nvueStyleCompiler" : "uni-app",
"compilerVersion" : 3,
"splashscreen" : {
"alwaysShowBeforeRender" : true,
"waiting" : true,
"autoclose" : true,
"delay" : 0
},
"compatible": {
"ignoreVersion": true
},
/* */
"modules" : {
"Record" : {}
},
/* */
"distribute" : {
/* android */
"android" : {
"permissions" : [
"<uses-permission android:name=\"android.permission.CHANGE_NETWORK_STATE\"/>",
"<uses-permission android:name=\"android.permission.MOUNT_UNMOUNT_FILESYSTEMS\"/>",
"<uses-permission android:name=\"android.permission.VIBRATE\"/>",
"<uses-permission android:name=\"android.permission.READ_LOGS\"/>",
"<uses-permission android:name=\"android.permission.ACCESS_WIFI_STATE\"/>",
"<uses-feature android:name=\"android.hardware.camera.autofocus\"/>",
"<uses-permission android:name=\"android.permission.ACCESS_NETWORK_STATE\"/>",
"<uses-permission android:name=\"android.permission.CAMERA\"/>",
"<uses-permission android:name=\"android.permission.GET_ACCOUNTS\"/>",
"<uses-permission android:name=\"android.permission.READ_PHONE_STATE\"/>",
"<uses-permission android:name=\"android.permission.CHANGE_WIFI_STATE\"/>",
"<uses-permission android:name=\"android.permission.WAKE_LOCK\"/>",
"<uses-permission android:name=\"android.permission.FLASHLIGHT\"/>",
"<uses-feature android:name=\"android.hardware.camera\"/>",
"<uses-permission android:name=\"android.permission.WRITE_SETTINGS\"/>"
],
"abiFilters" : [ "armeabi-v7a", "arm64-v8a", "x86" ]
},
/* ios */
"ios" : {
"dSYMs" : false
},
/* SDK */
"sdkConfigs" : {
"ad" : {}
},
"icons" : {
"android" : {
"hdpi" : "unpackage/res/icons/72x72.png",
"xhdpi" : "unpackage/res/icons/96x96.png",
"xxhdpi" : "unpackage/res/icons/144x144.png",
"xxxhdpi" : "unpackage/res/icons/192x192.png"
},
"ios" : {
"appstore" : "unpackage/res/icons/1024x1024.png",
"ipad" : {
"app" : "unpackage/res/icons/76x76.png",
"app@2x" : "unpackage/res/icons/152x152.png",
"notification" : "unpackage/res/icons/20x20.png",
"notification@2x" : "unpackage/res/icons/40x40.png",
"proapp@2x" : "unpackage/res/icons/167x167.png",
"settings" : "unpackage/res/icons/29x29.png",
"settings@2x" : "unpackage/res/icons/58x58.png",
"spotlight" : "unpackage/res/icons/40x40.png",
"spotlight@2x" : "unpackage/res/icons/80x80.png"
},
"iphone" : {
"app@2x" : "unpackage/res/icons/120x120.png",
"app@3x" : "unpackage/res/icons/180x180.png",
"notification@2x" : "unpackage/res/icons/40x40.png",
"notification@3x" : "unpackage/res/icons/60x60.png",
"settings@2x" : "unpackage/res/icons/58x58.png",
"settings@3x" : "unpackage/res/icons/87x87.png",
"spotlight@2x" : "unpackage/res/icons/80x80.png",
"spotlight@3x" : "unpackage/res/icons/120x120.png"
}
}
}
}
},
/* */
"quickapp" : {},
/* */
"mp-weixin" : {
"appid" : "wxb86917d1487922b9",
"setting" : {
"urlCheck" : false,
"postcss" : true,
"minified" : true
},
"usingComponents" : true
},
"mp-alipay" : {
"usingComponents" : true
},
"mp-baidu" : {
"usingComponents" : true
},
"mp-toutiao" : {
"usingComponents" : true
},
"uniStatistics" : {
"enable" : false
},
"vueVersion" : "2"
"name": "萃星智能AI",
"appid": "__UNI__5BDEDB4",
"description": "",
"versionName": "1.0.1",
"versionCode": 100,
"transformPx": false,
/* 5+App */
"app-plus": {
"usingComponents": true,
"nvueStyleCompiler": "uni-app",
"compilerVersion": 3,
"splashscreen": {
"alwaysShowBeforeRender": true,
"waiting": true,
"autoclose": true,
"delay": 0
},
"compatible": {
"ignoreVersion": true
},
/* */
"modules": {
"Record": {}
},
/* */
"distribute": {
/* android */
"android": {
"permissions": [
"<uses-permission android:name=\"android.permission.CHANGE_NETWORK_STATE\"/>",
"<uses-permission android:name=\"android.permission.MOUNT_UNMOUNT_FILESYSTEMS\"/>",
"<uses-permission android:name=\"android.permission.VIBRATE\"/>",
"<uses-permission android:name=\"android.permission.READ_LOGS\"/>",
"<uses-permission android:name=\"android.permission.ACCESS_WIFI_STATE\"/>",
"<uses-feature android:name=\"android.hardware.camera.autofocus\"/>",
"<uses-permission android:name=\"android.permission.ACCESS_NETWORK_STATE\"/>",
"<uses-permission android:name=\"android.permission.CAMERA\"/>",
"<uses-permission android:name=\"android.permission.GET_ACCOUNTS\"/>",
"<uses-permission android:name=\"android.permission.READ_PHONE_STATE\"/>",
"<uses-permission android:name=\"android.permission.CHANGE_WIFI_STATE\"/>",
"<uses-permission android:name=\"android.permission.WAKE_LOCK\"/>",
"<uses-permission android:name=\"android.permission.FLASHLIGHT\"/>",
"<uses-feature android:name=\"android.hardware.camera\"/>",
"<uses-permission android:name=\"android.permission.WRITE_SETTINGS\"/>"
],
"abiFilters": ["armeabi-v7a", "arm64-v8a", "x86"]
},
/* ios */
"ios": {
"dSYMs": false
},
/* SDK */
"sdkConfigs": {
"ad": {}
},
"icons": {
"android": {
"hdpi": "unpackage/res/icons/72x72.png",
"xhdpi": "unpackage/res/icons/96x96.png",
"xxhdpi": "unpackage/res/icons/144x144.png",
"xxxhdpi": "unpackage/res/icons/192x192.png"
},
"ios": {
"appstore": "unpackage/res/icons/1024x1024.png",
"ipad": {
"app": "unpackage/res/icons/76x76.png",
"app@2x": "unpackage/res/icons/152x152.png",
"notification": "unpackage/res/icons/20x20.png",
"notification@2x": "unpackage/res/icons/40x40.png",
"proapp@2x": "unpackage/res/icons/167x167.png",
"settings": "unpackage/res/icons/29x29.png",
"settings@2x": "unpackage/res/icons/58x58.png",
"spotlight": "unpackage/res/icons/40x40.png",
"spotlight@2x": "unpackage/res/icons/80x80.png"
},
"iphone": {
"app@2x": "unpackage/res/icons/120x120.png",
"app@3x": "unpackage/res/icons/180x180.png",
"notification@2x": "unpackage/res/icons/40x40.png",
"notification@3x": "unpackage/res/icons/60x60.png",
"settings@2x": "unpackage/res/icons/58x58.png",
"settings@3x": "unpackage/res/icons/87x87.png",
"spotlight@2x": "unpackage/res/icons/80x80.png",
"spotlight@3x": "unpackage/res/icons/120x120.png"
}
}
}
}
},
/* */
"quickapp": {},
/* */
"mp-weixin": {
"appid": "wxb86917d1487922b9",
"setting": {
"urlCheck": false,
"postcss": true,
"minified": true
},
"usingComponents": true
},
"mp-alipay": {
"usingComponents": true
},
"mp-baidu": {
"usingComponents": true
},
"mp-toutiao": {
"usingComponents": true
},
"uniStatistics": {
"enable": false
},
"vueVersion": "2"
}

6
node_modules/.package-lock.json generated vendored

@ -0,0 +1,6 @@
{
"name": "AI-app",
"lockfileVersion": 3,
"requires": true,
"packages": {}
}

6
package-lock.json generated

@ -0,0 +1,6 @@
{
"name": "AI-app",
"lockfileVersion": 3,
"requires": true,
"packages": {}
}

@ -2,13 +2,27 @@
<view class="chat">
<view v-for="(m,index) in messages" :key="m.id" :id="'msg-' + m.id" :class="['msg', m.role]">
<view v-if="m.role === 'user'" class="bubble user-bubble">
<text v-if="m.inputType === 'text'" @longpress.prevent="loadTool($event,m)" >{{ m.content }}</text>
<text v-if="m.inputType === 'text'" @longpress.prevent="loadTool($event,m)">{{ m.content }}</text>
<view class="text-voice" v-if="m.inputType === 'voice'" @tap="playVoice(m)">
<text>{{ m.duration }}</text>
<image class="voice-play" src="@/static/voice-play.png" mode="widthFix"></image>
</view>
</view>
<view v-else class="bubble ai-bubble">
<view v-if="m.role !== 'user' && m.type !== 'card' && !m.loading " class="ai-voice" style="width: 100%;">
<view class="ai-voice-play" @tap="clickAiVocie(m.src)">
<image class="voice-play" :src="leftVoiceImgList[current].image" mode="widthFix"
v-if="playSrc === m.src">
</image>
<image class="voice-play" :src="leftVoiceImgList[2].image" mode="widthFix"
v-else>
</image>
<text
style="margin-left: 5px;font-size: 14px;">{{ m.duration ? Math.ceil( m.duration) : 0 }}"</text>
</view>
</view>
<view v-if="m.role !== 'user'" class="bubble ai-bubble">
<view v-if="m.type === 'card'" class="ai-card">
<view class="ai-card-title">{{ m.title }}</view>
<view class="ai-card-body">{{ m.content }}</view>
@ -90,7 +104,9 @@
</template>
<script>
import {copyText} from '@/utils/utils.js'
import {
copyText
} from '@/utils/utils.js'
export default {
props: {
messages: {
@ -102,21 +118,36 @@
isReplying: {
type: Boolean,
default: false,
textTool: []
}
},
isPalyingVoice: {
type: Boolean,
default: false,
},
playSrc : {
type: String,
default: '',
},
},
data() {
return {
upvoteImage: require('@/static/upvote.png'),
upvoteHighLightImage: require('@/static/upvote-highlight.png'),
textToolList : [{
id : 1,
text : '复制',
imageUrl : require('@/static/copy.png')
},{
id : 2,
text : '修改',
imageUrl : require('@/static/edit.png')
leftVoiceImgList: [{
image: require('@/static/voice-play-left1.png')
}, {
image: require('@/static/voice-play-left2.png')
}, {
image: require('@/static/voice-play-left3.png')
}],
current: 2,
textToolList: [{
id: 1,
text: '复制',
imageUrl: require('@/static/copy.png')
}, {
id: 2,
text: '修改',
imageUrl: require('@/static/edit.png')
}],
isHighLight: false,
upvoteIndex: null,
@ -134,47 +165,69 @@
}
],
askActive: null,
textToolStyle : {},
isOpenTextTool : false,
textToolStyle: {},
isOpenTextTool: false,
showTool: false,
screenWidth : 0,
selectText : ''
screenWidth: 0,
selectText: '',
voiceTimer: null,
}
},
mounted () {
mounted() {
this.screenWidth = uni.getSystemInfoSync().screenWidth;
},
watch: {
isPalyingVoice(val) {
if (val) {
this.voiceTimer = setInterval(() => {
if (this.current === 2) {
this.current = -1;
}
this.current += 1;
}, 500)
}else{
if (this.voiceTimer) {
clearInterval(this.voiceTimer)
};
this.current = 2;
}
},
},
methods: {
selectTextTool(id){
switch(id){
clickAiVocie(src) {
this.$emit('handleVoice', src)
},
selectTextTool(id) {
switch (id) {
case 1:
copyText(this.selectText)
break;
copyText(this.selectText)
break;
case 2:
this.$emit('changeInputText',this.selectText)
this.$emit('changeInputText', this.selectText)
default:
break;
break;
}
this.closeTool();
},
closeTool(){
closeTool() {
this.showTool = false;
this.isOpenTextTool = false;
this.$emit('changeShow', false)
},
loadTool($event, m) {
loadTool($event, m) {
this.selectText = m.content;
uni.createSelectorQuery().select(`#msg-${m.id}`).boundingClientRect((rect) => {
uni.createSelectorQuery().select(`#msg-${m.id}`).boundingClientRect((rect) => {
let height = rect.height || 0;
if($event.touches[0].pageX > (this.screenWidth / 2)){
if ($event.touches[0].pageX > (this.screenWidth / 2)) {
this.textToolStyle = {
top : $event.target.offsetTop + height - 10 + 'px',
right : this.screenWidth - Math.ceil($event.touches[0].pageX) + 'px'
top: $event.target.offsetTop + height - 10 + 'px',
right: this.screenWidth - Math.ceil($event.touches[0].pageX) + 'px'
}
}else{
} else {
this.textToolStyle = {
top : $event.target.offsetTop + height - 10 + 'px',
left : Math.ceil($event.touches[0].pageX) + 'px'
top: $event.target.offsetTop + height - 10 + 'px',
left: Math.ceil($event.touches[0].pageX) + 'px'
}
}
this.isOpenTextTool = true;
@ -422,7 +475,7 @@
transform: translateY(0) scale(1);
}
.tool-item{
.tool-item {
display: flex;
width: 160px;
padding: 10px;
@ -435,11 +488,11 @@
animation: slideInItem 0.3s ease forwards;
}
.tool-item:last-child{
.tool-item:last-child {
border-bottom: 0px;
}
.img{
.img {
width: 16px;
margin-right: 10px;
}
@ -450,6 +503,7 @@
opacity: 0;
transform: translateX(-10px);
}
to {
opacity: 1;
transform: translateX(0);
@ -523,7 +577,7 @@
}
}
.mark-layer{
.mark-layer {
position: fixed;
width: 100vw;
height: 100vh;
@ -534,4 +588,14 @@
z-index: 9999;
opacity: 0;
}
.ai-voice-play {
width: 60px;
background-color: #fff;
margin-bottom: 10px;
padding: 10px 12px;
border-radius: 14px;
display: flex;
align-items: center;
}
</style>

@ -5,23 +5,30 @@
<scroll-view class="content" :scroll-y="true" show-scrollbar="false" scroll-with-animation ref="scrollView">
<front @onSuggestionTap="onQuickAsk" />
<chat :messages="messages" @continueCreate="continueCreate" :isReplying="isReplying" @refresh="refresh"
@changeShow="changeShow" @changeInputText="changeInputText"/>
@changeShow="changeShow" @changeInputText="changeInputText" @handleVoice="handleVoice" :isPalyingVoice="isPalyingVoice" :playSrc="playSrc"/>
</scroll-view>
<view :style="{height: marginBottom + 'px',backgroundColor : '#fff'}" />
<view :style="{ height: marginBottom + 'px', backgroundColor: '#fff' }" />
<leftDrawer :historyGroups="historyGroups" ref="popup" @changeShow="changeShow"
@onHistoryItemTap="onHistoryItemTap" @removeFromHistory="removeFromHistory"
@clearAllHistory="clearAllHistory" />
<search ref="searchRef" :inputText="inputText" @onSend="onSend" @onQuickAsk="onQuickAsk"
@changeInputText="changeInputText" :isReplying="isReplying" @handleBreak="handleBreak" />
@changeInputText="changeInputText" :isReplying="isReplying" @handleBreak="handleBreak"
@changeShow="changeShow" />
</view>
</template>
<script>
const HISTORY_KEY = "chat_history_groups";
import {
getAIResponse
getAIResponse,
} from "@/api/index.js";
import {
textToSpeech,
base64ToFile,
removeFile
} from '@/utils/utils.js'
import top from "./top/index.vue";
import front from "./front/index.vue";
import chat from "./chat/index.vue";
@ -44,16 +51,17 @@
typewriterTimers: {},
show: false,
marginBottom: 0,
isReplying: false,
breakReplying: false,
replyData: {},
isRefresh: false
isReplying: false, //
breakReplying: false, //
replyData: {}, //
isRefresh: false, //
audioContext: null,
isPalyingVoice : false, //
playSrc : ''
};
},
async mounted() {
this.loadChatHistory();
// this.scrollToBottom();
let self = this;
uni.onKeyboardHeightChange((res) => {
uni.pageScrollTo({
scrollTop: this.height + res.height,
@ -66,7 +74,8 @@
this.marginBottom = this.$refs.searchRef.getHeight() || 103;
});
// #endif
this.marginBottom = 103
this.marginBottom = 103;
this.initAudio();
},
beforeDestroy() {
//
@ -76,6 +85,82 @@
this.typewriterTimers = {};
},
methods: {
handleVoice(src){
if(this.isReplying){
console.log('正在回复中');
return;
}
if(this.audioContext.src === src && this.isPalyingVoice){
this.isPalyingVoice = false;
this.audioContext.stop();
return;
};
if(this.audioContext.src === src && !this.isPalyingVoice){
this.isPalyingVoice = true;
this.audioContext.play();
return;
};
if(this.isPalyingVoice){
this.audioContext.stop();
};
this.isPalyingVoice = true;
this.audioContext.src = src;
this.playSrc = src;
this.audioContext.play();
},
initAudio() {
this.audioContext = uni.createInnerAudioContext()
this.audioContext.onCanplay((e) => {
console.log('src onCanplay',this.audioContext.src);
let items = this.messages.find(item => item.src && item.src === this.audioContext.src);
items.duration = this.audioContext.duration;
this.isPalyingVoice = true;
this.audioContext.play();
});
this.audioContext.onEnded(res => {
this.isPalyingVoice = false
// const platform = uni.getSystemInfoSync().uniPlatform;
// if(platform === 'web') return;
// removeFile(this.audioContext.src)
})
},
getSpeech(speechStr) {
let self = this;
return new Promise((resolve, reject) => {
textToSpeech(speechStr).then(audioData => {
const platform = uni.getSystemInfoSync().uniPlatform;
// H5
if (platform === 'web') {
const blob = new Blob([audioData], {
type: 'audio/mp3'
});
const url = URL.createObjectURL(blob);
this.playSrc = url;
console.log('赋值 h5');
this.audioContext.src = url;
resolve(true)
}
// App
else {
const base64Audio = uni.arrayBufferToBase64(audioData);
const base64WithPrefix = `data:audio/mp3;base64,${base64Audio}`;
const fileName = `_doc/${Date.now()}_numberPerson.mp3`;
base64ToFile(base64WithPrefix, fileName, (path) => {
console.log('赋值 plus');
this.playSrc = path;
self.audioContext.src = path;
resolve(true)
});
}
}).catch(err => {
resolve(true)
})
})
},
deleteSpeech() {
removeFile(this.audioContext.src)
},
//
refresh() {
this.messages.splice(this.messages.length - 1, 1);
@ -252,10 +337,15 @@
this.isRefresh = false;
this.scrollToBottom();
this.addToHistory(text);
if(this.isPalyingVoice){
this.audioContext.stop();
this.isPalyingVoice = false;
}
// 3. AI
const reply = await getAIResponse({
message: text,
});
await this.getSpeech(reply);
this.replyData = reply;
this.isLoading = false;
if (this.breakReplying) {
@ -276,6 +366,7 @@
if (loadingIdx > -1) this.messages.splice(loadingIdx, 1);
// 5. +
const replyId = this.baseId + 1;
console.log('添加');
if (!isCreate) {
this.messages.push({
id: replyId,
@ -283,9 +374,10 @@
type: "text",
content,
displayText: "",
src : JSON.parse(JSON.stringify(this.audioContext.src)),
duration : null
});
}
this.$nextTick(() => this.scrollToBottom());
this.typewriter(replyId, content);
},
@ -310,6 +402,8 @@
this.isReplying = false;
this.breakReplying = false
this.isLoading = false;
this.isPalyingVoice =false;
this.audioContext.stop();
}
if (index < fullText.length) {
msg.displayText = fullText.substring(0, index + 1);
@ -324,7 +418,7 @@
this.breakReplying = false;
this.$nextTick(() => {
this.scrollToBottom();
})
});
}
}, speed);
this.typewriterTimers[messageId] = timer;

@ -40,7 +40,7 @@
<uni-popup ref="inputDialog" type="dialog" style="z-index: 10003;" >
<uni-popup-dialog ref="inputClose" mode="input" title="添加快捷提问" v-model="dialogText" placeholder="请输入内容"
@confirm="dialogInputConfirm" :maxlength="15" ></uni-popup-dialog>
@confirm="dialogInputConfirm" :maxlength="15" @close='dialogInputClose'></uni-popup-dialog>
</uni-popup>
<view v-if="isRecording" class="mask-layer"> </view>
@ -118,11 +118,16 @@
}
})
},
dialogInputClose(){
this.$emit('changeShow',false)
},
inputDialogToggle() {
this.dialogText = '';
this.$refs.inputDialog.open()
this.$refs.inputDialog.open();
this.$emit('changeShow',true)
},
dialogInputConfirm() {
this.$emit('changeShow',false)
if(!this.dialogText && !this.dialogText.trim()){
uni.showToast({
title: '内容不能为空',
@ -175,6 +180,7 @@
if (this.recorder) {
this.recorder.onStart();
this.recorder.onStop(async (res) => {
this.$emit('changeShow',false)
const duration = Date.now() - this.recordStartTs;
if (this.willCancel || duration < 700) {
uni.showToast({
@ -230,6 +236,7 @@
})
return
}
this.$emit('changeShow',true)
this.ensureRecorder();
this.isRecording = true;
this.willCancel = false;
@ -421,6 +428,7 @@
top: 0;
bottom: 0;
background-color: rgba(0, 0, 0, 0.1);
z-index: 100004;
}
.cancel {

@ -1,217 +1,324 @@
<template>
<view class="setting-page">
<uni-nav-bar left-icon="left" @clickLeft="$pageJumb.backJump()" title="设置" >
<view class="setting-page">
<uni-nav-bar left-icon="left" @clickLeft="$pageJumb.backJump()" title="设置">
<template v-slot:left>
<view ></view>
<view></view>
</template>
<template v-slot:right>
<view class="close" @tap="onClose"></view>
<view class="close" @tap="onClose"></view>
</template>
</uni-nav-bar>
<view class="group" >
<view class="group-title">账户</view>
<view class="card">
<view class="item" @tap="onItem('账号管理')">
<view class="left">
<view class="icon-wrap"><uni-icons type="person" size="20" color="#3b3f45" /></view>
<text class="text">账号管理</text>
</view>
<text class="arrow"></text>
</view>
<view class="divider" />
<view class="item" @tap="onItem('数据管理')">
<view class="left">
<view class="icon-wrap">
<image src="../../static/data-management.png" mode="widthFix" style="width: 20px;"></image>
<view class="group">
<view class="group-title">账户</view>
<view class="card">
<view class="item" @tap="onItem('账号管理')">
<view class="left">
<view class="icon-wrap"><uni-icons type="person" size="20" color="#3b3f45" /></view>
<text class="text">账号管理</text>
</view>
<text class="arrow"></text>
</view>
<view class="divider" />
<view class="item" @tap="onItem('数据管理')">
<view class="left">
<view class="icon-wrap">
<image src="../../static/data-management.png" mode="widthFix" style="width: 18px;"></image>
</view>
<text class="text">数据管理</text>
</view>
<text class="arrow"></text>
</view>
</view>
</view>
<view class="group">
<view class="group-title">关于</view>
<view class="card">
<view class="item" @tap="onItem('检查更新')">
<view class="left">
<view class="icon-wrap"><uni-icons type="refreshempty" size="20" color="#3b3f45" /></view>
<text class="text">检查更新</text>
</view>
<text class="arrow"></text>
</view>
<view class="divider" />
<view class="item" @tap="onItem('服务协议')">
<view class="left">
<view class="icon-wrap"><uni-icons type="help" size="20" color="#3b3f45" /></view>
<text class="text">服务协议</text>
</view>
<text class="arrow"></text>
</view>
</view>
</view>
<view class="card single" style="margin-top: 30px;">
<view class="item" @tap="onItem('联系我们')">
<view class="left">
<view class="icon-wrap"><uni-icons type="phone" size="20" color="#3b3f45" /></view>
<text class="text">联系我们</text>
</view>
<text class="arrow"></text>
</view>
</view>
<view class="card single">
<view class="item danger" @tap="onLogout">
<view class="left">
<view class="icon-wrap"><image src="../../static/quit.png" mode="widthFix" style="width: 20px;"></image></view>
<text class="text danger">退出登录</text>
</view>
</view>
</view>
<view class="brand">
<text class="text">数据管理</text>
</view>
<text class="arrow"></text>
</view>
</view>
</view>
<view class="group">
<view class="group-title">应用</view>
<view class="card">
<view class="item" @tap="chatPattern">
<view class="left">
<view class="icon-wrap"><uni-icons type="chat" size="20" color="#3b3f45" /></view>
<text class="text">回复模式</text>
</view>
<text class="arrow"></text>
</view>
<view class="divider" />
<view class="item" @tap="onItem('字体大小')">
<view class="left">
<view class="icon-wrap"><uni-icons type="help" size="20" color="#3b3f45" /></view>
<text class="text">字体大小</text>
</view>
<text class="arrow"></text>
</view>
</view>
</view>
<view class="group">
<view class="group-title">关于</view>
<view class="card">
<view class="item" @tap="onItem('检查更新')">
<view class="left">
<view class="icon-wrap"><uni-icons type="refreshempty" size="20" color="#3b3f45" /></view>
<text class="text">检查更新</text>
</view>
<text class="arrow"></text>
</view>
<view class="divider" />
<view class="item" @tap="onItem('服务协议')">
<view class="left">
<view class="icon-wrap"><uni-icons type="help" size="20" color="#3b3f45" /></view>
<text class="text">服务协议</text>
</view>
<text class="arrow"></text>
</view>
</view>
</view>
<view class="card single" style="margin-top: 30px;">
<view class="item" @tap="onItem('联系我们')">
<view class="left">
<view class="icon-wrap"><uni-icons type="phone" size="20" color="#3b3f45" /></view>
<text class="text">联系我们</text>
</view>
<text class="arrow"></text>
</view>
</view>
<view class="card single">
<view class="item danger" @tap="onLogout">
<view class="left">
<view class="icon-wrap">
<image src="../../static/quit.png" mode="widthFix" style="width: 16px;"></image>
</view>
<text class="text danger">退出登录</text>
</view>
</view>
</view>
<view class="brand">
<image src="../../static/cxlogo.png" mode="heightFix" style="height: 40px;"></image>
</view>
</view>
</view>
<uni-popup ref="popup" class="popup" type="center" border-radius="10px 10px 0 0" :is-mask-click="false">
<view class="chat-box">
<view class="chat-title"> AI回复模式 </view>
<radio-group @change="radioChange">
<label v-for="(item, index) in items" :key="item.value" style="display: flex;margin-bottom: 10px;">
<view>
<radio :value="item.value" :checked="item.value === current" />
</view>
<view style="margin-left: 10px;">{{item.label}}</view>
</label>
</radio-group>
<view class="confirm" @tap="confirmPattern"></view>
</view>
</uni-popup>
</view>
</template>
<script>
export default {
methods: {
onClose() {
uni.navigateBack();
},
onItem(name) {
uni.showToast({ title: name, icon: 'none' })
},
onLogout() {
uni.showModal({
title: '提示',
content: '确认退出登录?',
success: (res) => {
if (res.confirm) {
uni.showToast({ title: '已退出', icon: 'none' })
}
}
})
}
}
}
export default {
data() {
return {
current : '0',
items : [{
label : '文字回复',
value : '0'
},{
label : '语音回复',
value : '1'
},{
label : '文字 + 语音回复',
value : '2'
}]
}
},
mounted () {
this.current = this.$store.state.set.replyPattern;
},
methods: {
onClose() {
uni.navigateBack();
},
onItem(name) {
uni.showToast({
title: name,
icon: 'none'
})
},
onLogout() {
uni.showModal({
title: '提示',
content: '确认退出登录?',
success: (res) => {
if (res.confirm) {
uni.showToast({
title: '已退出',
icon: 'none'
})
}
}
})
},
chatPattern() {
this.$refs.popup.open()
},
radioChange(e){
this.current = e.detail.value;
},
confirmPattern(){
this.$refs.popup.close();
this.$store.commit('set/SET_REPLY_PATTERN', this.current)
},
}
}
</script>
<style scoped >
.setting-page {
min-height: 100vh;
display: flex;
flex-direction: column;
background: #eef1f4;
}
.header {
height: 52px;
display: flex;
align-items: center;
justify-content: center;
position: relative;
background: #eef1f4;
}
.title {
font-size: 16px;
font-weight: 600;
color: #333;
}
.close {
width: 28px;
height: 28px;
line-height: 28px;
text-align: center;
border-radius: 14px;
background: #ffffff;
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.06);
color: #666;
}
.content {
flex: 1;
padding: 8px 14px 20px;
}
.group {
width: 80vw;
margin: 8px auto;
}
.group-title {
font-size: 12px;
color: #9aa3b2;
margin: 10px 6px;
}
.card {
width: 80vw;
margin: 0 auto;
background: #fff;
border-radius: 12px;
padding: 0 12px;
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.04);
box-sizing: border-box;
}
.card.single {
margin-top: 12px;
}
.item {
height: 48px;
display: flex;
align-items: center;
justify-content: space-between;
}
.left {
display: flex;
align-items: center;
gap: 10px;
}
.icon-wrap {
width: 28px;
height: 28px;
border-radius: 14px;
background: #f1f3f6;
display: flex;
align-items: center;
justify-content: center;
}
.icon-wrap.danger {
background: #fdecea;
}
.text {
font-size: 14px;
color: #333;
}
.arrow {
color: #b3bac5;
font-size: 18px;
}
.divider {
height: 1px;
background: #eef0f3;
}
.brand {
position: absolute;
bottom: 20px;
left : 50%;
transform: translateX(-50%);
}
<style scoped lang="scss">
.setting-page {
min-height: 100vh;
display: flex;
flex-direction: column;
background: #eef1f4;
}
.header {
height: 52px;
display: flex;
align-items: center;
justify-content: center;
position: relative;
background: #eef1f4;
}
.title {
font-size: 16px;
font-weight: 600;
color: #333;
}
.close {
width: 28px;
height: 28px;
line-height: 28px;
text-align: center;
border-radius: 14px;
background: #ffffff;
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.06);
color: #666;
}
.content {
flex: 1;
padding: 8px 14px 20px;
}
.group {
width: 80vw;
margin: 8px auto;
}
.group-title {
font-size: 12px;
color: #9aa3b2;
margin: 10px 6px;
}
.card {
width: 80vw;
margin: 0 auto;
background: #fff;
border-radius: 12px;
padding: 0 12px;
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.04);
box-sizing: border-box;
}
.card.single {
margin-top: 12px;
}
.item {
height: 38px;
display: flex;
align-items: center;
justify-content: space-between;
}
.left {
display: flex;
align-items: center;
gap: 10px;
}
.icon-wrap {
width: 18px;
height: 18px;
border-radius: 14px;
background: #f1f3f6;
display: flex;
align-items: center;
justify-content: center;
}
.icon-wrap.danger {
background: #fdecea;
}
.text {
font-size: 14px;
color: #333;
}
.arrow {
color: #b3bac5;
font-size: 18px;
}
.divider {
height: 1px;
background: #eef0f3;
}
.brand {
position: absolute;
bottom: 20px;
left: 50%;
transform: translateX(-50%);
}
.popup {
z-index: 99999;
}
.chat-box {
background-color: #fff;
width: 70vw;
border-radius: 10px;
padding: 0 20px;
box-sizing: border-box;
::v-deep uni-radio .uni-radio-input{
width: 16px !important;
height: 16px !important;
}
.chat-title {
text-align: center;
padding: 10px;
border-bottom: 1px solid #ddd;
margin-bottom: 10px;
}
.confirm {
color: #048bff;
text-align: center;
padding: 8px;
border-top: 1px solid #ddd;
}
}
</style>

Binary file not shown.

After

Width:  |  Height:  |  Size: 439 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 886 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

@ -1,10 +1,12 @@
import Vue from 'vue';
import Vuex from 'vuex'
import permission from './module/permission'
import set from './module/set'
Vue.use(Vuex)
export default new Vuex.Store({
modules : {
permission
permission,
set
}
})

@ -1,8 +1,12 @@
export default {
namespaced : true,
state : {
// microphoneAuthorized : uni.getAppAuthorizeSetting().microphoneAuthorized
},
mutations : {
},
actions : {
}
}

@ -0,0 +1,15 @@
export default {
namespaced : true,
state : {
replyPattern : uni.getStorageSync('replyPattern') || '0'
},
mutations : {
SET_REPLY_PATTERN(state,value){
state.replyPattern = value;
uni.setStorageSync('replyPattern',value)
}
},
actions : {
}
}

@ -1,8 +1,8 @@
var isReady=false;var onReadyCallbacks=[];
var isServiceReady=false;var onServiceReadyCallbacks=[];
var __uniConfig = {"pages":["pages/index/index"],"window":{"navigationBarTextStyle":"black","navigationBarTitleText":"uni-app","navigationBarBackgroundColor":"#F8F8F8","backgroundColor":"#F8F8F8"},"darkmode":false,"nvueCompiler":"uni-app","nvueStyleCompiler":"uni-app","renderer":"auto","splashscreen":{"alwaysShowBeforeRender":true,"autoclose":false},"appname":"漆包车间看板","compilerVersion":"4.29","entryPagePath":"pages/index/index","networkTimeout":{"request":60000,"connectSocket":60000,"uploadFile":60000,"downloadFile":60000}};
var __uniRoutes = [{"path":"/pages/index/index","meta":{"isQuit":true},"window":{"navigationStyle":"custom"}}];
var __uniConfig = {"pages":["pages/index/index","pages/setting/index"],"window":{"navigationBarTextStyle":"black","navigationBarTitleText":"uni-app","navigationBarBackgroundColor":"#F8F8F8","backgroundColor":"#F8F8F8"},"darkmode":false,"nvueCompiler":"uni-app","nvueStyleCompiler":"uni-app","renderer":"auto","splashscreen":{"alwaysShowBeforeRender":true,"autoclose":false},"appname":"萃星智能AI","compilerVersion":"4.29","entryPagePath":"pages/index/index","networkTimeout":{"request":60000,"connectSocket":60000,"uploadFile":60000,"downloadFile":60000}};
var __uniRoutes = [{"path":"/pages/index/index","meta":{"isQuit":true},"window":{"navigationStyle":"custom","titleNView":false,"softinputMode":"adjustResize"}},{"path":"/pages/setting/index","meta":{},"window":{"navigationStyle":"custom"}}];
__uniConfig.onReady=function(callback){if(__uniConfig.ready){callback()}else{onReadyCallbacks.push(callback)}};Object.defineProperty(__uniConfig,"ready",{get:function(){return isReady},set:function(val){isReady=val;if(!isReady){return}const callbacks=onReadyCallbacks.slice(0);onReadyCallbacks.length=0;callbacks.forEach(function(callback){callback()})}});
__uniConfig.onServiceReady=function(callback){if(__uniConfig.serviceReady){callback()}else{onServiceReadyCallbacks.push(callback)}};Object.defineProperty(__uniConfig,"serviceReady",{get:function(){return isServiceReady},set:function(val){isServiceReady=val;if(!isServiceReady){return}const callbacks=onServiceReadyCallbacks.slice(0);onServiceReadyCallbacks.length=0;callbacks.forEach(function(callback){callback()})}});
service.register("uni-app-config",{create(a,b,c){if(!__uniConfig.viewport){var d=b.weex.config.env.scale,e=b.weex.config.env.deviceWidth,f=Math.ceil(e/d);Object.assign(__uniConfig,{viewport:f,defaultFontSize:Math.round(f/20)})}return{instance:{__uniConfig:__uniConfig,__uniRoutes:__uniRoutes,global:void 0,window:void 0,document:void 0,frames:void 0,self:void 0,location:void 0,navigator:void 0,localStorage:void 0,history:void 0,Caches:void 0,screen:void 0,alert:void 0,confirm:void 0,prompt:void 0,fetch:void 0,XMLHttpRequest:void 0,WebSocket:void 0,webkit:void 0,print:void 0}}}});

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

@ -1 +1 @@
{"@platforms":["android","iPhone","iPad"],"id":"__UNI__5BDEDB4","name":"漆包车间看板","version":{"name":"1.0.17","code":102},"description":"","launch_path":"__uniappview.html","developer":{"name":"","email":"","url":""},"permissions":{"UniNView":{"description":"UniNView原生渲染"}},"plus":{"useragent":{"value":"uni-app","concatenate":true},"splashscreen":{"autoclose":true,"delay":0,"target":"id:1","waiting":true},"popGesture":"close","launchwebview":{"render":"always","id":"1","kernel":"WKWebview"},"statusbar":{"immersed":"supportedDevice","style":"dark","background":"#F8F8F8"},"usingComponents":true,"nvueStyleCompiler":"uni-app","compilerVersion":3,"distribute":{"icons":{"android":{"hdpi":"icon-android-hdpi.png","xhdpi":"icon-android-xhdpi.png","xxhdpi":"icon-android-xxhdpi.png","xxxhdpi":"icon-android-xxxhdpi.png"},"ios":{"appstore":"unpackage/res/icons/1024x1024.png","ipad":{"app":"unpackage/res/icons/76x76.png","app@2x":"unpackage/res/icons/152x152.png","notification":"unpackage/res/icons/20x20.png","notification@2x":"unpackage/res/icons/40x40.png","proapp@2x":"unpackage/res/icons/167x167.png","settings":"unpackage/res/icons/29x29.png","settings@2x":"unpackage/res/icons/58x58.png","spotlight":"unpackage/res/icons/40x40.png","spotlight@2x":"unpackage/res/icons/80x80.png"},"iphone":{"app@2x":"unpackage/res/icons/120x120.png","app@3x":"unpackage/res/icons/180x180.png","notification@2x":"unpackage/res/icons/40x40.png","notification@3x":"unpackage/res/icons/60x60.png","settings@2x":"unpackage/res/icons/58x58.png","settings@3x":"unpackage/res/icons/87x87.png","spotlight@2x":"unpackage/res/icons/80x80.png","spotlight@3x":"unpackage/res/icons/120x120.png"},"prerendered":"false"}},"google":{"abiFilters":["armeabi-v7a","arm64-v8a","x86"],"permissions":["<uses-permission android:name=\"android.permission.CHANGE_NETWORK_STATE\"/>","<uses-permission android:name=\"android.permission.MOUNT_UNMOUNT_FILESYSTEMS\"/>","<uses-permission android:name=\"android.permission.VIBRATE\"/>","<uses-permission android:name=\"android.permission.READ_LOGS\"/>","<uses-permission android:name=\"android.permission.ACCESS_WIFI_STATE\"/>","<uses-feature android:name=\"android.hardware.camera.autofocus\"/>","<uses-permission android:name=\"android.permission.ACCESS_NETWORK_STATE\"/>","<uses-permission android:name=\"android.permission.CAMERA\"/>","<uses-permission android:name=\"android.permission.GET_ACCOUNTS\"/>","<uses-permission android:name=\"android.permission.READ_PHONE_STATE\"/>","<uses-permission android:name=\"android.permission.CHANGE_WIFI_STATE\"/>","<uses-permission android:name=\"android.permission.WAKE_LOCK\"/>","<uses-permission android:name=\"android.permission.FLASHLIGHT\"/>","<uses-feature android:name=\"android.hardware.camera\"/>","<uses-permission android:name=\"android.permission.WRITE_SETTINGS\"/>"],"packagename":"uni.UNI5BDEDB4","aliasname":"","password":"","keystore":"html5plus://test","custompermissions":true},"apple":{"dSYMs":false,"devices":"universal"},"plugins":{"ad":{},"audio":{"mp3":{"description":"Android平台录音支持MP3格式文件"}}},"orientation":"portrait-primary"},"uniStatistics":{"enable":false},"allowsInlineMediaPlayback":true,"uni-app":{"compilerVersion":"4.29","control":"uni-v3","nvueCompiler":"uni-app","renderer":"auto","nvue":{"flex-direction":"column"},"nvueLaunchMode":"normal"},"launch_path":"__uniappview.html","adid":"124076130506"}}
{"@platforms":["android","iPhone","iPad"],"id":"__UNI__5BDEDB4","name":"萃星智能AI","version":{"name":"1.0.1","code":100},"description":"","launch_path":"__uniappview.html","developer":{"name":"","email":"","url":""},"permissions":{"Record":{},"UniNView":{"description":"UniNView原生渲染"}},"plus":{"useragent":{"value":"uni-app","concatenate":true},"splashscreen":{"autoclose":true,"delay":0,"target":"id:1","waiting":true},"popGesture":"close","launchwebview":{"render":"always","id":"1","kernel":"WKWebview"},"statusbar":{"immersed":"supportedDevice","style":"dark","background":"#F8F8F8"},"usingComponents":true,"nvueStyleCompiler":"uni-app","compilerVersion":3,"compatible":{"ignoreVersion":true},"distribute":{"icons":{"android":{"hdpi":"icon-android-hdpi.png","xhdpi":"icon-android-xhdpi.png","xxhdpi":"icon-android-xxhdpi.png","xxxhdpi":"icon-android-xxxhdpi.png"},"ios":{"appstore":"unpackage/res/icons/1024x1024.png","ipad":{"app":"unpackage/res/icons/76x76.png","app@2x":"unpackage/res/icons/152x152.png","notification":"unpackage/res/icons/20x20.png","notification@2x":"unpackage/res/icons/40x40.png","proapp@2x":"unpackage/res/icons/167x167.png","settings":"unpackage/res/icons/29x29.png","settings@2x":"unpackage/res/icons/58x58.png","spotlight":"unpackage/res/icons/40x40.png","spotlight@2x":"unpackage/res/icons/80x80.png"},"iphone":{"app@2x":"unpackage/res/icons/120x120.png","app@3x":"unpackage/res/icons/180x180.png","notification@2x":"unpackage/res/icons/40x40.png","notification@3x":"unpackage/res/icons/60x60.png","settings@2x":"unpackage/res/icons/58x58.png","settings@3x":"unpackage/res/icons/87x87.png","spotlight@2x":"unpackage/res/icons/80x80.png","spotlight@3x":"unpackage/res/icons/120x120.png"},"prerendered":"false"}},"google":{"abiFilters":["armeabi-v7a","arm64-v8a","x86"],"permissions":["<uses-permission android:name=\"android.permission.CHANGE_NETWORK_STATE\"/>","<uses-permission android:name=\"android.permission.MOUNT_UNMOUNT_FILESYSTEMS\"/>","<uses-permission android:name=\"android.permission.VIBRATE\"/>","<uses-permission android:name=\"android.permission.READ_LOGS\"/>","<uses-permission android:name=\"android.permission.ACCESS_WIFI_STATE\"/>","<uses-feature android:name=\"android.hardware.camera.autofocus\"/>","<uses-permission android:name=\"android.permission.ACCESS_NETWORK_STATE\"/>","<uses-permission android:name=\"android.permission.CAMERA\"/>","<uses-permission android:name=\"android.permission.GET_ACCOUNTS\"/>","<uses-permission android:name=\"android.permission.READ_PHONE_STATE\"/>","<uses-permission android:name=\"android.permission.CHANGE_WIFI_STATE\"/>","<uses-permission android:name=\"android.permission.WAKE_LOCK\"/>","<uses-permission android:name=\"android.permission.FLASHLIGHT\"/>","<uses-feature android:name=\"android.hardware.camera\"/>","<uses-permission android:name=\"android.permission.WRITE_SETTINGS\"/>"],"packagename":"uni.UNI5BDEDB4","custompermissions":true},"apple":{"dSYMs":false,"plistcmds":["Add :UIFileSharingEnabled bool true"],"devices":"universal"},"plugins":{"ad":{},"audio":{"mp3":{"description":"Android平台录音支持MP3格式文件"}}},"debug":true,"syncDebug":true,"orientation":"portrait-primary"},"uniStatistics":{"enable":false},"allowsInlineMediaPlayback":true,"uni-app":{"compilerVersion":"4.29","control":"uni-v3","nvueCompiler":"uni-app","renderer":"auto","nvue":{"flex-direction":"column"},"nvueLaunchMode":"normal"},"launch_path":"__uniappview.html","adid":"124076130506"}}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 612 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 399 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 409 B

@ -1,8 +1,8 @@
var isReady=false;var onReadyCallbacks=[];
var isServiceReady=false;var onServiceReadyCallbacks=[];
var __uniConfig = {"pages":["pages/index/index"],"window":{"navigationBarTextStyle":"black","navigationBarTitleText":"uni-app","navigationBarBackgroundColor":"#F8F8F8","backgroundColor":"#F8F8F8"},"darkmode":false,"nvueCompiler":"uni-app","nvueStyleCompiler":"uni-app","renderer":"auto","splashscreen":{"alwaysShowBeforeRender":true,"autoclose":false},"appname":"漆包车间看板","compilerVersion":"4.29","entryPagePath":"pages/index/index","networkTimeout":{"request":60000,"connectSocket":60000,"uploadFile":60000,"downloadFile":60000}};
var __uniRoutes = [{"path":"/pages/index/index","meta":{"isQuit":true},"window":{"navigationStyle":"custom"}}];
var __uniConfig = {"pages":["pages/index/index","pages/setting/index"],"window":{"navigationBarTextStyle":"black","navigationBarTitleText":"uni-app","navigationBarBackgroundColor":"#F8F8F8","backgroundColor":"#F8F8F8"},"darkmode":false,"nvueCompiler":"uni-app","nvueStyleCompiler":"uni-app","renderer":"auto","splashscreen":{"alwaysShowBeforeRender":true,"autoclose":false},"appname":"萃星智能AI","compilerVersion":"4.29","entryPagePath":"pages/index/index","networkTimeout":{"request":60000,"connectSocket":60000,"uploadFile":60000,"downloadFile":60000}};
var __uniRoutes = [{"path":"/pages/index/index","meta":{"isQuit":true},"window":{"navigationStyle":"custom","titleNView":false,"softinputMode":"adjustResize"}},{"path":"/pages/setting/index","meta":{},"window":{"navigationStyle":"custom"}}];
__uniConfig.onReady=function(callback){if(__uniConfig.ready){callback()}else{onReadyCallbacks.push(callback)}};Object.defineProperty(__uniConfig,"ready",{get:function(){return isReady},set:function(val){isReady=val;if(!isReady){return}const callbacks=onReadyCallbacks.slice(0);onReadyCallbacks.length=0;callbacks.forEach(function(callback){callback()})}});
__uniConfig.onServiceReady=function(callback){if(__uniConfig.serviceReady){callback()}else{onServiceReadyCallbacks.push(callback)}};Object.defineProperty(__uniConfig,"serviceReady",{get:function(){return isServiceReady},set:function(val){isServiceReady=val;if(!isServiceReady){return}const callbacks=onServiceReadyCallbacks.slice(0);onServiceReadyCallbacks.length=0;callbacks.forEach(function(callback){callback()})}});
service.register("uni-app-config",{create(a,b,c){if(!__uniConfig.viewport){var d=b.weex.config.env.scale,e=b.weex.config.env.deviceWidth,f=Math.ceil(e/d);Object.assign(__uniConfig,{viewport:f,defaultFontSize:Math.round(f/20)})}return{instance:{__uniConfig:__uniConfig,__uniRoutes:__uniRoutes,global:void 0,window:void 0,document:void 0,frames:void 0,self:void 0,location:void 0,navigator:void 0,localStorage:void 0,history:void 0,Caches:void 0,screen:void 0,alert:void 0,confirm:void 0,prompt:void 0,fetch:void 0,XMLHttpRequest:void 0,WebSocket:void 0,webkit:void 0,print:void 0}}}});

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

@ -1 +1 @@
{"@platforms":["android","iPhone","iPad"],"id":"__UNI__5BDEDB4","name":"漆包车间看板","version":{"name":"1.0.17","code":102},"description":"","launch_path":"__uniappview.html","developer":{"name":"","email":"","url":""},"permissions":{"UniNView":{"description":"UniNView原生渲染"}},"plus":{"useragent":{"value":"uni-app","concatenate":true},"splashscreen":{"target":"id:1","autoclose":true,"waiting":true,"delay":0},"popGesture":"close","launchwebview":{"render":"always","id":"1","kernel":"WKWebview"},"statusbar":{"immersed":"supportedDevice","style":"dark","background":"#F8F8F8"},"usingComponents":true,"nvueStyleCompiler":"uni-app","compilerVersion":3,"distribute":{"icons":{"android":{"hdpi":"unpackage/res/icons/72x72.png","xhdpi":"unpackage/res/icons/96x96.png","xxhdpi":"unpackage/res/icons/144x144.png","xxxhdpi":"unpackage/res/icons/192x192.png"},"ios":{"appstore":"unpackage/res/icons/1024x1024.png","ipad":{"app":"unpackage/res/icons/76x76.png","app@2x":"unpackage/res/icons/152x152.png","notification":"unpackage/res/icons/20x20.png","notification@2x":"unpackage/res/icons/40x40.png","proapp@2x":"unpackage/res/icons/167x167.png","settings":"unpackage/res/icons/29x29.png","settings@2x":"unpackage/res/icons/58x58.png","spotlight":"unpackage/res/icons/40x40.png","spotlight@2x":"unpackage/res/icons/80x80.png"},"iphone":{"app@2x":"unpackage/res/icons/120x120.png","app@3x":"unpackage/res/icons/180x180.png","notification@2x":"unpackage/res/icons/40x40.png","notification@3x":"unpackage/res/icons/60x60.png","settings@2x":"unpackage/res/icons/58x58.png","settings@3x":"unpackage/res/icons/87x87.png","spotlight@2x":"unpackage/res/icons/80x80.png","spotlight@3x":"unpackage/res/icons/120x120.png"}}},"google":{"permissions":["<uses-permission android:name=\"android.permission.CHANGE_NETWORK_STATE\"/>","<uses-permission android:name=\"android.permission.MOUNT_UNMOUNT_FILESYSTEMS\"/>","<uses-permission android:name=\"android.permission.VIBRATE\"/>","<uses-permission android:name=\"android.permission.READ_LOGS\"/>","<uses-permission android:name=\"android.permission.ACCESS_WIFI_STATE\"/>","<uses-feature android:name=\"android.hardware.camera.autofocus\"/>","<uses-permission android:name=\"android.permission.ACCESS_NETWORK_STATE\"/>","<uses-permission android:name=\"android.permission.CAMERA\"/>","<uses-permission android:name=\"android.permission.GET_ACCOUNTS\"/>","<uses-permission android:name=\"android.permission.READ_PHONE_STATE\"/>","<uses-permission android:name=\"android.permission.CHANGE_WIFI_STATE\"/>","<uses-permission android:name=\"android.permission.WAKE_LOCK\"/>","<uses-permission android:name=\"android.permission.FLASHLIGHT\"/>","<uses-feature android:name=\"android.hardware.camera\"/>","<uses-permission android:name=\"android.permission.WRITE_SETTINGS\"/>"],"abiFilters":["armeabi-v7a","arm64-v8a","x86"]},"apple":{"dSYMs":false},"plugins":{"ad":{},"audio":{"mp3":{"description":"Android平台录音支持MP3格式文件"}}}},"uniStatistics":{"enable":false},"allowsInlineMediaPlayback":true,"uni-app":{"compilerVersion":"4.29","control":"uni-v3","nvueCompiler":"uni-app","renderer":"auto","nvue":{"flex-direction":"column"},"nvueLaunchMode":"normal"},"launch_path":"__uniappview.html"}}
{"@platforms":["android","iPhone","iPad"],"id":"__UNI__5BDEDB4","name":"萃星智能AI","version":{"name":"1.0.1","code":100},"description":"","launch_path":"__uniappview.html","developer":{"name":"","email":"","url":""},"permissions":{"Record":{},"UniNView":{"description":"UniNView原生渲染"}},"plus":{"useragent":{"value":"uni-app","concatenate":true},"splashscreen":{"target":"id:1","autoclose":true,"waiting":true,"delay":0},"popGesture":"close","launchwebview":{"render":"always","id":"1","kernel":"WKWebview"},"statusbar":{"immersed":"supportedDevice","style":"dark","background":"#F8F8F8"},"usingComponents":true,"nvueStyleCompiler":"uni-app","compilerVersion":3,"compatible":{"ignoreVersion":true},"distribute":{"icons":{"android":{"hdpi":"unpackage/res/icons/72x72.png","xhdpi":"unpackage/res/icons/96x96.png","xxhdpi":"unpackage/res/icons/144x144.png","xxxhdpi":"unpackage/res/icons/192x192.png"},"ios":{"appstore":"unpackage/res/icons/1024x1024.png","ipad":{"app":"unpackage/res/icons/76x76.png","app@2x":"unpackage/res/icons/152x152.png","notification":"unpackage/res/icons/20x20.png","notification@2x":"unpackage/res/icons/40x40.png","proapp@2x":"unpackage/res/icons/167x167.png","settings":"unpackage/res/icons/29x29.png","settings@2x":"unpackage/res/icons/58x58.png","spotlight":"unpackage/res/icons/40x40.png","spotlight@2x":"unpackage/res/icons/80x80.png"},"iphone":{"app@2x":"unpackage/res/icons/120x120.png","app@3x":"unpackage/res/icons/180x180.png","notification@2x":"unpackage/res/icons/40x40.png","notification@3x":"unpackage/res/icons/60x60.png","settings@2x":"unpackage/res/icons/58x58.png","settings@3x":"unpackage/res/icons/87x87.png","spotlight@2x":"unpackage/res/icons/80x80.png","spotlight@3x":"unpackage/res/icons/120x120.png"}}},"google":{"permissions":["<uses-permission android:name=\"android.permission.CHANGE_NETWORK_STATE\"/>","<uses-permission android:name=\"android.permission.MOUNT_UNMOUNT_FILESYSTEMS\"/>","<uses-permission android:name=\"android.permission.VIBRATE\"/>","<uses-permission android:name=\"android.permission.READ_LOGS\"/>","<uses-permission android:name=\"android.permission.ACCESS_WIFI_STATE\"/>","<uses-feature android:name=\"android.hardware.camera.autofocus\"/>","<uses-permission android:name=\"android.permission.ACCESS_NETWORK_STATE\"/>","<uses-permission android:name=\"android.permission.CAMERA\"/>","<uses-permission android:name=\"android.permission.GET_ACCOUNTS\"/>","<uses-permission android:name=\"android.permission.READ_PHONE_STATE\"/>","<uses-permission android:name=\"android.permission.CHANGE_WIFI_STATE\"/>","<uses-permission android:name=\"android.permission.WAKE_LOCK\"/>","<uses-permission android:name=\"android.permission.FLASHLIGHT\"/>","<uses-feature android:name=\"android.hardware.camera\"/>","<uses-permission android:name=\"android.permission.WRITE_SETTINGS\"/>"],"abiFilters":["armeabi-v7a","arm64-v8a","x86"]},"apple":{"dSYMs":false},"plugins":{"ad":{},"audio":{"mp3":{"description":"Android平台录音支持MP3格式文件"}}}},"uniStatistics":{"enable":false},"allowsInlineMediaPlayback":true,"uni-app":{"compilerVersion":"4.29","control":"uni-v3","nvueCompiler":"uni-app","renderer":"auto","nvue":{"flex-direction":"column"},"nvueLaunchMode":"normal"},"launch_path":"__uniappview.html"}}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 612 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 399 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 409 B

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

@ -0,0 +1,134 @@
// base64.ts
export const Base64 = {
keyStr: 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=',
encode(input) {
let output = '';
let chr1;
let chr2;
let chr3;
let enc1;
let enc2;
let enc3;
let enc4;
let i = 0;
const utf8Input = this.utf8Encode(input);
while (i < utf8Input.length) {
chr1 = utf8Input.charCodeAt(i);
chr2 = utf8Input.charCodeAt(i + 1);
chr3 = utf8Input.charCodeAt(i + 2);
enc1 = chr1 >> 2;
enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
enc4 = chr3 & 63;
if (isNaN(chr2)) {
enc3 = enc4 = 64;
} else if (isNaN(chr3)) {
enc4 = 64;
}
output =
output +
this.keyStr.charAt(enc1) +
this.keyStr.charAt(enc2) +
this.keyStr.charAt(enc3) +
this.keyStr.charAt(enc4);
i += 3;
}
return output;
},
decode(input) {
let output = '';
let chr1;
let chr2;
let chr3;
let enc1;
let enc2;
let enc3;
let enc4;
let i = 0;
const base64Input = input.replace(/[^A-Za-z0-9+/=]/g, '');
while (i < base64Input.length) {
enc1 = this.keyStr.indexOf(base64Input.charAt(i));
enc2 = this.keyStr.indexOf(base64Input.charAt(i + 1));
enc3 = this.keyStr.indexOf(base64Input.charAt(i + 2));
enc4 = this.keyStr.indexOf(base64Input.charAt(i + 3));
chr1 = (enc1 << 2) | (enc2 >> 4);
chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
chr3 = ((enc3 & 3) << 6) | enc4;
output += String.fromCharCode(chr1);
if (enc3 !== 64) {
output += String.fromCharCode(chr2);
}
if (enc4 !== 64) {
output += String.fromCharCode(chr3);
}
i += 4;
}
return this.utf8Decode(output);
},
utf8Encode(string) {
let utftext = '';
let c;
for (let n = 0; n < string.length; n += 1) {
c = string.charCodeAt(n);
if (c < 128) {
utftext += String.fromCharCode(c);
} else if (c < 2048) {
utftext += String.fromCharCode((c >> 6) | 192);
utftext += String.fromCharCode((c & 63) | 128);
} else {
utftext += String.fromCharCode((c >> 12) | 224);
utftext += String.fromCharCode(((c >> 6) & 63) | 128);
utftext += String.fromCharCode((c & 63) | 128);
}
}
return utftext;
},
utf8Decode(utftext) {
let string = '';
let i = 0;
let c = 0;
let c1 = 0;
let c2 = 0;
// const c3 = 0;
while (i < utftext.length) {
c = utftext.charCodeAt(i);
if (c < 128) {
string += String.fromCharCode(c);
i += 1;
} else if (c < 224) {
c1 = utftext.charCodeAt(i + 1);
string += String.fromCharCode(((c & 31) << 6) | (c1 & 63));
i += 2;
} else {
c1 = utftext.charCodeAt(i + 1);
c2 = utftext.charCodeAt(i + 2);
string += String.fromCharCode(((c & 15) << 12) | ((c1 & 63) << 6) | (c2 & 63));
i += 3;
}
}
return string;
}
};

@ -36,4 +36,131 @@ export function copyText(text) {
});
}
});
};
export const removeFile = (filePath) => {
plus.io.resolveLocalFileSystemURL(
filePath,
(entry) => {
entry.remove(
() => console.log("删除成功"), // 成功回调
(error) => console.log(`删除失败:${error.message}`) // 失败回调
);
},
(error) => console.log(`文件不存在:${error.message}`)
);
}
export const base64ToFile = (base64Strs, fileName, callback) => {
let index = base64Strs.indexOf(',');
let base64Str = base64Strs.slice(index + 1, base64Strs.length);
plus.io.requestFileSystem(plus.io.PRIVATE_DOC, function(fs) {
fs.root.getFile(fileName, {
create: true
}, function(entry) {
let fullPath = entry.fullPath;
let platform = uni.getSystemInfoSync().platform;
if (platform == 'android') {
let Base64 = plus.android.importClass("android.util.Base64");
let FileOutputStream = plus.android.importClass("java.io.FileOutputStream");
try {
let out = new FileOutputStream(fullPath);
let bytes = Base64.decode(base64Str, Base64.DEFAULT);
out.write(bytes);
out.close();
callback && callback(entry.toLocalURL());
} catch (e) {
console.log(e.message);
}
} else if (platform == 'ios') {
let NSData = plus.ios.importClass('NSData');
let nsData = new NSData();
nsData = nsData.initWithBase64EncodedStringoptions(base64Str, 0);
if (nsData) {
nsData.plusCallMethod({
writeToFile: fullPath,
atomically: true
});
plus.ios.deleteObject(nsData);
}
callback && callback(entry.toLocalURL());
}
});
});
};
export function textToSpeech(text, options = {}) {
return new Promise((resolve, reject) => {
const {
token = '24.1c8cc30b5f7be445723b6d4b19a36152.2592000.1765094496.282335-120706844',
tex = text,
cuid = 'uni-app-demo',
ctp = 1,
lan = 'zh',
spd = 5,
pit = 5,
vol = 5,
per = 0
} = options
const url = 'https://tsn.baidu.com/text2audio'
const params = {
tex: encodeURIComponent(tex),
cuid,
ctp,
lan,
spd,
pit,
vol,
per,
tok: token
}
// 构建查询字符串
const queryString = Object.keys(params).map(key => {
return `${key}=${params[key]}`
}).join('&')
uni.request({
url: `${url}?${queryString}`,
method: 'GET',
responseType: 'arraybuffer',
success: (res) => {
// 检查响应状态
if (res.statusCode === 200) {
// 检查是否是音频数据MP3格式通常以特定字节开头
if (res.data && res.data.byteLength > 0) {
// 检查是否是JSON错误响应百度API错误时返回JSON
try {
const textDecoder = new TextDecoder('utf-8')
const text = textDecoder.decode(new Uint8Array(res.data.slice(0, 100)))
if (text.startsWith('{') || text.startsWith('[')) {
// 是JSON响应说明是错误
const errorData = JSON.parse(text)
console.error('TTS API Error:', errorData)
reject(new Error(errorData.err_msg || 'TTS请求失败'))
return
}
} catch (e) {
// 不是JSON应该是音频数据
}
resolve(res.data)
} else {
reject(new Error('返回数据为空'))
}
} else {
reject(new Error(`请求失败,状态码: ${res.statusCode}`))
}
},
fail: (err) => {
console.error('TTS Request Error:', err)
reject(new Error(err.errMsg || '网络请求失败'))
}
})
})
}
Loading…
Cancel
Save