Browse Source

ios 语音问题

master
kami 2 years ago
parent
commit
5bc9ce0118
  1. 5
      src/main.js
  2. 2
      src/store/wx.js
  3. 27
      src/views/Home.vue
  4. 75
      src/views/mail/components/Write.vue
  5. 13
      vite.config.js

5
src/main.js

@ -2,6 +2,7 @@ import { createApp } from 'vue'
import router from './router/index' import router from './router/index'
import { createPinia } from 'pinia' import { createPinia } from 'pinia'
import App from './App.vue' import App from './App.vue'
import { Button, Tab, Tabs, Form, Field, CellGroup, Cell, RadioGroup, Radio, Uploader, Icon, Popup, Loading, Overlay, Empty, List, Picker } from 'vant'; import { Button, Tab, Tabs, Form, Field, CellGroup, Cell, RadioGroup, Radio, Uploader, Icon, Popup, Loading, Overlay, Empty, List, Picker } from 'vant';
import IconComponent from '@/components/Icon.vue' import IconComponent from '@/components/Icon.vue'
@ -13,6 +14,10 @@ import 'vant/lib/index.css';
import './assets/style/style.scss' import './assets/style/style.scss'
import './assets/style/vant.scss' import './assets/style/vant.scss'
// import VConsole from 'vconsole';
//
// const vConsole = new VConsole();
const app = createApp(App) const app = createApp(App)
.use(router) .use(router)
.use(createPinia()) .use(createPinia())

2
src/store/wx.js

@ -11,7 +11,7 @@ const WxStore = defineStore(
initSign() { initSign() {
const _this = this; const _this = this;
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
const url = window.location.href.split("?")[0]; const url = window.location.href;
wxSign(url).then((data) => { wxSign(url).then((data) => {
wx.config({ wx.config({
// debug: true, // 开启调试模式 // debug: true, // 开启调试模式

27
src/views/Home.vue

@ -1,7 +1,7 @@
<template> <template>
<div class="wrapper"> <div class="wrapper">
<header> <header>
<img src="/imgs/bg1.png" alt="" /> <img src="/imgs/bg1.png" alt=""/>
</header> </header>
<main> <main>
<div class="flex gap-10 center mt-20"> <div class="flex gap-10 center mt-20">
@ -10,7 +10,7 @@
@click="router.push('/realName/auth')" @click="router.push('/realName/auth')"
> >
<div style="width: 48px"> <div style="width: 48px">
<img src="/imgs/write.png" alt="" /> <img src="/imgs/write.png" alt=""/>
</div> </div>
<span>我要写信</span> <span>我要写信</span>
</a> </a>
@ -19,7 +19,7 @@
@click="router.push('/mail?active=my')" @click="router.push('/mail?active=my')"
> >
<div style="width: 48px"> <div style="width: 48px">
<img src="/imgs/search.png" alt="" /> <img src="/imgs/search.png" alt=""/>
</div> </div>
<span>回复查询</span> <span>回复查询</span>
</a> </a>
@ -32,15 +32,16 @@
</main> </main>
</div> </div>
<Loading :loading="loading" /> <Loading :loading="loading"/>
</template> </template>
<script setup> <script setup>
import { useRoute, useRouter } from "vue-router"; import {useRoute, useRouter} from "vue-router";
import { auth, authOpenid } from "@/api/auth"; import {auth, authOpenid} from "@/api/auth";
import UserStore from "@/store/user"; import UserStore from "@/store/user";
import { setToken, getToken } from "@/util/cookie"; import {setToken, getToken} from "@/util/cookie";
import WxStore from "@/store/wx"; import WxStore from "@/store/wx";
const wxStore = WxStore(); const wxStore = WxStore();
const router = useRouter(); const router = useRouter();
@ -57,8 +58,8 @@ if (!getToken()) {
setToken(data.token); setToken(data.token);
userStore.user = data.user; userStore.user = data.user;
loading.value = false loading.value = false
window.location.href = "https://mailbox.biutag.com/"
wxStore.initSign() // wxStore.initSign()
}); });
} else if (route.query.openid) { } else if (route.query.openid) {
// //
@ -66,8 +67,8 @@ if (!getToken()) {
setToken(data.token); setToken(data.token);
userStore.user = data.user; userStore.user = data.user;
loading.value = false loading.value = false
window.location.href = "https://mailbox.biutag.com/"
wxStore.initSign() // wxStore.initSign()
}); });
} else { } else {
const appid = "wx795f76e4bc3b0062"; const appid = "wx795f76e4bc3b0062";
@ -80,7 +81,6 @@ if (!getToken()) {
} }
} else { } else {
loading.value = false loading.value = false
wxStore.initSign() wxStore.initSign()
} }
</script> </script>
@ -88,11 +88,13 @@ if (!getToken()) {
.wrapper { .wrapper {
background-color: #fff; background-color: #fff;
} }
header { header {
img { img {
width: 100%; width: 100%;
} }
} }
a { a {
width: 45.2%; width: 45.2%;
height: 84px; height: 84px;
@ -101,6 +103,7 @@ a {
color: var(--primary-color); color: var(--primary-color);
font-weight: bold; font-weight: bold;
font-size: 18px; font-size: 18px;
&:hover { &:hover {
cursor: pointer; cursor: pointer;
} }

75
src/views/mail/components/Write.vue

@ -63,7 +63,8 @@
sendBtnDisabled sendBtnDisabled
? `${time}秒后重发` ? `${time}秒后重发`
: "发送验证码" : "发送验证码"
}}</van-button }}
</van-button
> >
</div> </div>
</template> </template>
@ -130,7 +131,7 @@
> >
语音录入 语音录入
<template #icon> <template #icon>
<Icon name="voice" :size="16" /> <Icon name="voice" :size="16"/>
</template> </template>
</van-button> </van-button>
</van-cell-group> </van-cell-group>
@ -161,7 +162,7 @@
class="upload-btn flex v-center center column" class="upload-btn flex v-center center column"
@click="chooseImage" @click="chooseImage"
> >
<van-icon name="plus" size="26" /> <van-icon name="plus" size="26"/>
<div>上传附件</div> <div>上传附件</div>
</a> </a>
</div> </div>
@ -175,7 +176,8 @@
> >
<van-button block @click="handleSaveDraft">存稿</van-button> <van-button block @click="handleSaveDraft">存稿</van-button>
<van-button block type="primary" @click="handleSave" <van-button block type="primary" @click="handleSave"
>提交</van-button >提交
</van-button
> >
</div> </div>
</van-form> </van-form>
@ -184,7 +186,7 @@
<div class="recording-container"> <div class="recording-container">
<div class="text"> <div class="text">
<textarea v-model="speechText" ref="speechTextRef" @input="onInput"></textarea> <textarea v-model="speechText" ref="speechTextRef" @input="onInput"></textarea>
<img src="/imgs/recording.gif" alt="" /> <img src="/imgs/recording.gif" alt=""/>
<span class="countdown" v-if="showCountdown">{{ <span class="countdown" v-if="showCountdown">{{
recordTime > 0 recordTime > 0
? `将在 ${recordTime} 秒后停止录音` ? `将在 ${recordTime} 秒后停止录音`
@ -197,11 +199,11 @@
ref="cancleBtnRef" ref="cancleBtnRef"
class="cancel flex center v-center column" class="cancel flex center v-center column"
> >
<Icon name="cancel" size="30" /> <Icon name="cancel" size="30"/>
<div class="mt-8">取消</div> <div class="mt-8">取消</div>
</button> </button>
<button @touchstart="handleSuccenssTalk" ref="successBtnRef"> <button @touchstart="handleSuccenssTalk" ref="successBtnRef">
<van-icon name="success" size="40" /> <van-icon name="success" size="40"/>
</button> </button>
</div> </div>
</div> </div>
@ -213,24 +215,24 @@
:icon="loading.icon" :icon="loading.icon"
/> />
<ImgPreview v-model:filepath="imgFilepath" v-model:show="showImgPreview" /> <ImgPreview v-model:filepath="imgFilepath" v-model:show="showImgPreview"/>
</template> </template>
<script setup> <script setup>
import { showToast, showSuccessToast, showFailToast } from "vant"; import {showToast, showSuccessToast, showFailToast} from "vant";
import ImgPreview from "@/components/ImgPreview.vue"; import ImgPreview from "@/components/ImgPreview.vue";
import { validatorIdCard, validatorPhone } from "@/util/validator"; import {validatorIdCard, validatorPhone} from "@/util/validator";
import { send } from "@/api/sms"; import {send} from "@/api/sms";
import { addMail } from "@/api/mail"; import {addMail} from "@/api/mail";
import { saveDraft, getDraft } from "@/api/mailDraft"; import {saveDraft, getDraft} from "@/api/mailDraft";
import UserStore from "@/store/user"; import UserStore from "@/store/user";
import PageStore from "@/store/page"; import PageStore from "@/store/page";
import WxStore from "@/store/wx"; import WxStore from "@/store/wx";
import { depts } from "@/store/dept"; import {depts} from "@/store/dept";
import { upload } from "@/util/request"; import {upload} from "@/util/request";
import { startRecorder } from "@/util/audio"; import {startRecorder} from "@/util/audio";
import { getSex } from "@/util/utils"; import {getSex} from "@/util/utils";
const userStore = UserStore(); const userStore = UserStore();
@ -262,6 +264,7 @@ if (!wxStore.signInitFlag) {
const mail = ref({}); const mail = ref({});
initMail(); initMail();
function initMail() { function initMail() {
mail.value = { mail.value = {
contactName: userStore.user.realName, contactName: userStore.user.realName,
@ -379,17 +382,22 @@ let timer;
let recorder; let recorder;
const recordTime = ref(59); const recordTime = ref(59);
const showCountdown = ref(false); const showCountdown = ref(false);
function handleVoiceShow() { function handleVoiceShow() {
navigator.mediaDevices navigator.mediaDevices
.getUserMedia({ audio: true }) .getUserMedia({audio: true})
.then(function () { .then(function () {
showCountdown.value = false; showCountdown.value = false;
voiceShow.value = true; voiceShow.value = true;
// //
if ('vibrate' in navigator) {
navigator.vibrate([100]); navigator.vibrate([100]);
}
speechText.value = ""; speechText.value = "";
// //
recorder = startRecorder(() => {}, speechText); recorder = startRecorder(() => {
}, speechText);
recordTime.value = 59; recordTime.value = 59;
timer = setInterval(() => { timer = setInterval(() => {
recordTime.value -= 1; recordTime.value -= 1;
@ -403,12 +411,14 @@ function handleVoiceShow() {
}, 1000); }, 1000);
}) })
.catch(function (err) { .catch(function (err) {
console.log(err)
showToast("未启用麦克风权限,请刷新重试"); showToast("未启用麦克风权限,请刷新重试");
}); });
} }
const cancleBtnRef = ref(); const cancleBtnRef = ref();
const successBtnRef = ref(); const successBtnRef = ref();
function handleCanleTalk() { function handleCanleTalk() {
cancleBtnRef.value.style.backgroundColor = "#d15454"; cancleBtnRef.value.style.backgroundColor = "#d15454";
recorder?.stop(); recorder?.stop();
@ -429,6 +439,7 @@ function handleSuccenssTalk() {
const sendBtnDisabled = ref(false); const sendBtnDisabled = ref(false);
let time = ref(30); let time = ref(30);
function smsSendCode() { function smsSendCode() {
formRef.value.validate("contactPhone").then(() => { formRef.value.validate("contactPhone").then(() => {
sendBtnDisabled.value = true; sendBtnDisabled.value = true;
@ -449,6 +460,7 @@ function smsSendCode() {
const showImgPreview = ref(false); const showImgPreview = ref(false);
const imgFilepath = ref(""); const imgFilepath = ref("");
function handleShowImgPreview(filepath) { function handleShowImgPreview(filepath) {
imgFilepath.value = filepath; imgFilepath.value = filepath;
showImgPreview.value = true; showImgPreview.value = true;
@ -473,7 +485,7 @@ function onInput() {
const showPicker = ref(false) const showPicker = ref(false)
function onSelectDept({ selectedOptions }) { function onSelectDept({selectedOptions}) {
showPicker.value = false; showPicker.value = false;
mail.value.involvedDeptId = selectedOptions[0].value; mail.value.involvedDeptId = selectedOptions[0].value;
mail.value.involvedDeptName = selectedOptions[0].text; mail.value.involvedDeptName = selectedOptions[0].text;
@ -495,6 +507,7 @@ function validatorContent() {
top: 3px; top: 3px;
right: var(--van-cell-horizontal-padding); right: var(--van-cell-horizontal-padding);
} }
.upload-btn { .upload-btn {
width: 108px; width: 108px;
height: 108px; height: 108px;
@ -502,18 +515,22 @@ function validatorContent() {
border: 1px solid var(--primary-color); border: 1px solid var(--primary-color);
color: var(--primary-color); color: var(--primary-color);
} }
.attachments { .attachments {
margin-top: 10px; margin-top: 10px;
display: grid; display: grid;
grid-template-columns: 1fr 1fr 1fr; grid-template-columns: 1fr 1fr 1fr;
grid-gap: 10px; grid-gap: 10px;
img { img {
width: 100%; width: 100%;
height: 108px; height: 108px;
} }
.file { .file {
background-color: #f3faff; background-color: #f3faff;
height: 108px; height: 108px;
.name { .name {
width: 100%; width: 100%;
max-width: 108px; max-width: 108px;
@ -524,8 +541,10 @@ function validatorContent() {
} }
} }
} }
.van-popup { .van-popup {
user-select: none; user-select: none;
header { header {
font-size: 16px; font-size: 16px;
font-family: PingFangSC-Medium; font-family: PingFangSC-Medium;
@ -533,16 +552,19 @@ function validatorContent() {
margin: 20px; margin: 20px;
} }
} }
.send-btn { .send-btn {
position: absolute; position: absolute;
top: -4px; top: -4px;
right: 0; right: 0;
} }
.record-btn { .record-btn {
&[active="true"] { &[active="true"] {
animation: scaleIn 1.2s ease-out infinite; animation: scaleIn 1.2s ease-out infinite;
} }
} }
@keyframes scaleIn { @keyframes scaleIn {
0% { 0% {
transform: scale(1, 1); transform: scale(1, 1);
@ -563,12 +585,14 @@ function validatorContent() {
bottom: 0; bottom: 0;
z-index: 2; z-index: 2;
background-color: var(--van-overlay-background); background-color: var(--van-overlay-background);
.recording-container { .recording-container {
position: fixed; position: fixed;
left: 0; left: 0;
right: 0; right: 0;
bottom: 0; bottom: 0;
} }
.text { .text {
min-height: 60px; min-height: 60px;
background-color: var(--primary-color); background-color: var(--primary-color);
@ -578,6 +602,7 @@ function validatorContent() {
padding: var(--van-padding-md); padding: var(--van-padding-md);
margin-bottom: 60px; margin-bottom: 60px;
position: relative; position: relative;
textarea { textarea {
border: none; border: none;
background-color: inherit; background-color: inherit;
@ -587,12 +612,14 @@ function validatorContent() {
max-height: calc(90vh - 280px); max-height: calc(90vh - 280px);
font-size: 16px; font-size: 16px;
} }
img { img {
position: absolute; position: absolute;
bottom: -13px; bottom: -13px;
right: 6px; right: 6px;
width: 50px; width: 50px;
} }
.countdown { .countdown {
position: absolute; position: absolute;
bottom: 4px; bottom: 4px;
@ -600,9 +627,11 @@ function validatorContent() {
color: #bbb; color: #bbb;
} }
} }
.tools { .tools {
padding: 30px; padding: 30px;
margin-bottom: 10vh; margin-bottom: 10vh;
button { button {
background-color: #3a3a3a; background-color: #3a3a3a;
height: 100px; height: 100px;
@ -610,25 +639,30 @@ function validatorContent() {
border-radius: 50%; border-radius: 50%;
border: none; border: none;
color: #ccc; color: #ccc;
&:hover { &:hover {
background-color: #ddd; background-color: #ddd;
color: #777; color: #777;
} }
&.cancel { &.cancel {
background-color: transparent; background-color: transparent;
color: #fff; color: #fff;
&:hover { &:hover {
background-color: #d15454; background-color: #d15454;
} }
} }
} }
} }
.recording { .recording {
height: 16vh; height: 16vh;
margin-top: 60px; margin-top: 60px;
background: linear-gradient(#a4a4a4, #fff); background: linear-gradient(#a4a4a4, #fff);
color: #ccc; color: #ccc;
position: relative; position: relative;
&::before { &::before {
display: block; display: block;
content: ""; content: "";
@ -645,6 +679,7 @@ function validatorContent() {
} }
} }
} }
.file-item { .file-item {
a { a {
position: absolute; position: absolute;

13
vite.config.js

@ -38,5 +38,18 @@ export default defineConfig({
rewrite: (p) => p.replace(/^\/api/, '') rewrite: (p) => p.replace(/^\/api/, '')
} }
} }
},
build: {
rollupOptions: {
output: {
entryFileNames: `assets/[name].${new Date().getTime()}.js`,
chunkFileNames: `assets/[name].${new Date().getTime()}.js`,
assetFileNames: `assets/[name].${new Date().getTime()}.[ext]`,
compact: true,
manualChunks: {
vue: ['vue']
},
}
}
} }
}) })

Loading…
Cancel
Save