update ui and fix some problem (#3)

* update code lint and update ui
This commit is contained in:
bingochaos
2025-08-15 17:19:29 +08:00
committed by GitHub
parent 3fddf021be
commit 519fcb64a2
18 changed files with 162219 additions and 2816 deletions

View File

@@ -1,12 +0,0 @@
root = true
[*]
charset = utf-8
end_of_line = lf
indent_size = 2
indent_style = space
insert_final_newline = true
max_line_length = 100
quote_type = single
trim_trailing_whitespace = true
semi = false

View File

@@ -1,11 +0,0 @@
build
coverage
dist
es
lib
node_modules
package-lock.json
pnpm-lock.yaml
yarn.lock
*.min.js
*.min.css

View File

@@ -1,10 +1,7 @@
{ {
"printWidth": 80,
"singleQuote": true,
"trailingComma": "all",
"proseWrap": "never",
"tabWidth": 2,
"semi": false, "semi": false,
"arrowParens": "always", "singleQuote": true,
"overrides": [{ "files": ".prettierrc", "options": { "parser": "json" } }] "trailingComma": "es5",
"printWidth": 100,
"htmlWhitespaceSensitivity": "ignore"
} }

View File

@@ -1,10 +0,0 @@
build
coverage
dist
es
lib
node_modules
package-lock.json
pnpm-lock.yaml
yarn.lock
*.min.css

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

70731
dist/assets/index.js vendored

File diff suppressed because one or more lines are too long

21
eslint.config.js Normal file
View File

@@ -0,0 +1,21 @@
import pluginVue from 'eslint-plugin-vue'
import globals from 'globals'
export default [
// add more generic rulesets here, such as:
// js.configs.recommended,
...pluginVue.configs['flat/recommended'],
// ...pluginVue.configs['flat/vue2-recommended'], // Use this if you are using Vue.js 2.x.
{
rules: {
// override/add rules settings here, such as:
// 'vue/no-unused-vars': 'error'
},
languageOptions: {
sourceType: 'module',
globals: {
...globals.browser,
},
},
},
]

View File

@@ -1,37 +0,0 @@
import { base as aliBase } from 'eslint-config-ali';
import prettier from 'eslint-plugin-prettier/recommended';
import { defineConfig, globalIgnores } from 'eslint/config';
import globals from 'globals';
// import tslintPlugin from 'typescript-eslint';
export default defineConfig([
// ...tslintPlugin.configs.recommended,
...aliBase,
prettier,
{
ignores: ['dist/**/*', 'node_modules/**/*'],
files: ['**/*.{ts,tsx}'],
languageOptions: {
ecmaVersion: 2020,
globals: globals.browser,
},
rules: {
'@typescript-eslint/no-unused-vars': 'warn',
'@typescript-eslint/no-explicit-any': 'warn',
'@typescript-eslint/consistent-type-definitions': ['error', 'interface'],
'@/semi': [1, 'never'],
'prettier/prettier': [
'error',
{
printWidth: 80,
singleQuote: true,
trailingComma: 'all',
proseWrap: 'never',
tabWidth: 2,
semi: false,
arrowParens: 'always',
},
],
},
},
globalIgnores(['**/dist/**', '**/node_modules/**']),
]);

View File

@@ -5,28 +5,14 @@
"type": "module", "type": "module",
"scripts": { "scripts": {
"build": "vue-tsc && vite build", "build": "vue-tsc && vite build",
"ci:eslint": "eslint -f json src -o ./.ci/eslint.json",
"ci:test": "vitest -c ./vitest.config.ts --coverage",
"dev": "vite", "dev": "vite",
"eslint": "eslint --fix --ext .js,.ts,.vue src", "lint": "eslint . --ext .js,.ts,.vue --fix",
"format": "prettier --write --cache --parser typescript \"**/*.[tj]s?(x)\"", "prepare": "husky install"
"lint": "eslint . && stylelint --allow-empty-input \"**/*.{css,less,scss}\"",
"lint-staged": "lint-staged",
"lint:fix": "prettier --write . && eslint --fix . && stylelint --allow-empty-input --fix \"**/*.{css,less,scss}\"",
"local": "sudo vite",
"prepare": "husky",
"preview": "vite preview",
"test": "vitest"
}, },
"lint-staged": { "lint-staged": {
"*.{cjs,cts,js,jsx,mjs,mts,ts,tsx,vue}": "eslint --fix", "*.{js,ts,vue}": [
"*.{cjs,css,cts,html,js,json,jsx,less,md,mjs,mts,scss,ts,tsx,vue,yaml,yml}": "prettier --write" "eslint --fix",
}, "prettier --write"
"prettier": "prettier-config-ali",
"stylelint": {
"extends": [
"stylelint-config-ali",
"stylelint-prettier/recommended"
] ]
}, },
"dependencies": { "dependencies": {
@@ -48,36 +34,24 @@
"vue-i18n": "^11.1.9" "vue-i18n": "^11.1.9"
}, },
"devDependencies": { "devDependencies": {
"@commitlint/config-conventional": "^19.8.1", "@eslint/eslintrc": "^3.3.1",
"@eslint/js": "^9.33.0",
"@types/node": "^20.17.6", "@types/node": "^20.17.6",
"@types/python-struct": "^1.0.4", "@types/python-struct": "^1.0.4",
"@typescript-eslint/parser": "^8.39.1",
"@vitejs/plugin-legacy": "^7.0.0", "@vitejs/plugin-legacy": "^7.0.0",
"@vitejs/plugin-vue": "^6.0.0", "@vitejs/plugin-vue": "^6.0.0",
"@vue/eslint-config-prettier": "^10.2.0", "eslint": "^9.33.0",
"eslint": "^9.31.0", "eslint-plugin-vue": "^10.4.0",
"eslint-config-ali": "^16.3.0",
"eslint-config-prettier": "^10.1.8",
"eslint-plugin-prettier": "^5.5.3",
"eslint-plugin-vue": "^10.3.0",
"globals": "^16.3.0", "globals": "^16.3.0",
"husky": "^9.1.7", "husky": "^9.1.7",
"less": "^4.2.0", "less": "^4.2.0",
"lint-staged": "^16.1.2", "lint-staged": "^16.1.5",
"prettier": "^3.6.2", "prettier": "^3.6.2",
"prettier-config-ali": "^1.3.4",
"simple-git-hooks": "^2.13.0", "simple-git-hooks": "^2.13.0",
"stylelint": "^16.22.0",
"stylelint-config-ali": "^2.1.2",
"stylelint-config-standard": "^38.0.0",
"stylelint-prettier": "^5.0.3",
"terser": "^5.36.0", "terser": "^5.36.0",
"typescript": "5.8.3",
"typescript-eslint": "^8.38.0",
"vite": "^7.0.1", "vite": "^7.0.1",
"vite-plugin-eslint2": "^5.0.4",
"vite-plugin-mkcert": "^1.17.6", "vite-plugin-mkcert": "^1.17.6",
"vite-plugin-stylelint": "^6.0.2",
"vue-eslint-parser": "^10.2.0",
"vue-tsc": "^3.0.1" "vue-tsc": "^3.0.1"
}, },
"packageManager": "pnpm@10.10.0+sha512.d615db246fe70f25dcfea6d8d73dee782ce23e2245e3c4f6f888249fb568149318637dca73c2c5c8ef2a4ca0d5657fb9567188bfab47f566d1ee6ce987815c39" "packageManager": "pnpm@10.10.0+sha512.d615db246fe70f25dcfea6d8d73dee782ce23e2245e3c4f6f888249fb568149318637dca73c2c5c8ef2a4ca0d5657fb9567188bfab47f566d1ee6ce987815c39"

2584
pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,11 +1,11 @@
<script setup lang="ts"> <script setup lang="ts">
import WebcamPermission from '@/components/WebcamPermission.vue'; import WebcamPermission from '@/components/WebcamPermission.vue'
import { antdLocale, locale } from '@/langs'; import { antdLocale, locale } from '@/langs'
import VideoChat from '@/views/VideoChat/index.vue'; import VideoChat from '@/views/VideoChat/index.vue'
import { ConfigProvider } from 'ant-design-vue'; import { ConfigProvider } from 'ant-design-vue'
import { useVideoChatStore } from './store'; import { useVideoChatStore } from './store'
const videoChatState = useVideoChatStore(); const videoChatState = useVideoChatStore()
videoChatState.init(); videoChatState.init()
// import dayjs from 'dayjs'; // import dayjs from 'dayjs';
// import 'dayjs/locale/zh-cn'; // import 'dayjs/locale/zh-cn';
// dayjs.locale('zh-cn'); // dayjs.locale('zh-cn');

View File

@@ -1,19 +1,19 @@
<template> <template>
<div class="action-group"> <div class="action-group">
<div v-if="hasCamera"> <div v-if="hasCamera">
<div class="action" @click="handleCameraOff" v-click-outside="() => (cameraListShow = false)"> <div v-click-outside="() => (cameraListShow = false)" class="action" @click="handleCameraOff">
<Iconfont :icon="cameraOff ? CameraOff : CameraOn" /> <Iconfont :icon="cameraOff ? CameraOff : CameraOn" />
<div <div
v-if="streamState === 'closed'" v-if="streamState === 'closed'"
class="corner" class="corner"
@click.stop.prevent="() => (cameraListShow = !cameraListShow)" @click.stop.prevent="() => (cameraListShow = !cameraListShow)"
> >
<div class="corner-inner"></div> <div class="corner-inner" />
</div> </div>
<div <div
v-show="cameraListShow && streamState === 'closed'"
class="selectors" class="selectors"
:class="{ left: isLandscape }" :class="{ left: isLandscape }"
v-show="cameraListShow && streamState === 'closed'"
> >
<div <div
v-for="device in availableVideoDevices" v-for="device in availableVideoDevices"
@@ -21,8 +21,8 @@
class="selector" class="selector"
@click.stop=" @click.stop="
() => { () => {
handleDeviceChange(device.deviceId); handleDeviceChange(device.deviceId)
cameraListShow = false; cameraListShow = false
} }
" "
> >
@@ -38,19 +38,19 @@
</div> </div>
</div> </div>
<div v-if="hasMic"> <div v-if="hasMic">
<div class="action" @click="handleMicMuted" v-click-outside="() => (micListShow = false)"> <div v-click-outside="() => (micListShow = false)" class="action" @click="handleMicMuted">
<Iconfont :icon="micMuted ? MicOff : MicOn" /> <Iconfont :icon="micMuted ? MicOff : MicOn" />
<div <div
v-if="streamState === 'closed'" v-if="streamState === 'closed'"
class="corner" class="corner"
@click.stop.prevent="() => (micListShow = !micListShow)" @click.stop.prevent="() => (micListShow = !micListShow)"
> >
<div class="corner-inner"></div> <div class="corner-inner" />
</div> </div>
<div <div
v-show="micListShow && streamState === 'closed'"
class="selectors" class="selectors"
:class="{ left: isLandscape }" :class="{ left: isLandscape }"
v-show="micListShow && streamState === 'closed'"
> >
<div <div
v-for="device in availableAudioDevices" v-for="device in availableAudioDevices"
@@ -58,8 +58,8 @@
class="selector" class="selector"
@click.stop=" @click.stop="
(e) => { (e) => {
handleDeviceChange(device.deviceId); handleDeviceChange(device.deviceId)
micListShow = false; micListShow = false
} }
" "
> >
@@ -86,10 +86,10 @@
</div> </div>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { useVideoChatStore } from '@/store'; import { useVideoChatStore } from '@/store'
import { useVisionStore } from '@/store/vision'; import { useVisionStore } from '@/store/vision'
import { storeToRefs } from 'pinia'; import { storeToRefs } from 'pinia'
import { ref } from 'vue'; import { ref } from 'vue'
import Iconfont, { import Iconfont, {
CameraOff, CameraOff,
CameraOn, CameraOn,
@@ -100,9 +100,9 @@ import Iconfont, {
SubtitleOn, SubtitleOn,
VolumeOff, VolumeOff,
VolumeOn, VolumeOn,
} from './Iconfont'; } from './Iconfont'
const videoChatStore = useVideoChatStore(); const videoChatStore = useVideoChatStore()
const visionStore = useVisionStore(); const visionStore = useVisionStore()
const { const {
hasCamera, hasCamera,
hasMic, hasMic,
@@ -116,18 +116,18 @@ const {
selectedVideoDevice, selectedVideoDevice,
availableAudioDevices, availableAudioDevices,
availableVideoDevices, availableVideoDevices,
} = storeToRefs(videoChatStore); } = storeToRefs(videoChatStore)
const { const {
handleCameraOff, handleCameraOff,
handleMicMuted, handleMicMuted,
handleVolumeMute, handleVolumeMute,
handleDeviceChange, handleDeviceChange,
handleSubtitleToggle, handleSubtitleToggle,
} = videoChatStore; } = videoChatStore
const { wrapperRect, isLandscape } = storeToRefs(visionStore); const { wrapperRect, isLandscape } = storeToRefs(visionStore)
const micListShow = ref(false); const micListShow = ref(false)
const cameraListShow = ref(false); const cameraListShow = ref(false)
</script> </script>
<style lang="less" scoped> <style lang="less" scoped>

View File

@@ -4,7 +4,7 @@
:class="[ :class="[
'chat-btn', 'chat-btn',
streamState === StreamState.closed && 'start-chat', streamState === StreamState.closed && 'start-chat',
streamState === StreamState.open && 'stop-chat' streamState === StreamState.open && 'stop-chat',
]" ]"
@click="onStartChat" @click="onStartChat"
> >
@@ -14,8 +14,7 @@
<template v-else-if="streamState === StreamState.waiting"> <template v-else-if="streamState === StreamState.waiting">
<div class="waiting-icon-text"> <div class="waiting-icon-text">
<div class="icon" title="spinner"> <div class="icon" title="spinner">
<!-- <Spin wrapperClassName="spin-icon"></Spin> --> <Spin wrapperClassName="spin-icon"></Spin>
<!-- TODO: spinner 替换 -->
</div> </div>
<span>等待中</span> <span>等待中</span>
</div> </div>
@@ -37,23 +36,23 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import {Spin} from 'ant-design-vue' import { Spin } from 'ant-design-vue';
import { StreamState } from '@/interface/voiceChat' import { StreamState } from '@/interface/voiceChat';
import AudioWave from '@/components/AudioWave.vue' import AudioWave from '@/components/AudioWave.vue';
const props = withDefaults( const props = withDefaults(
defineProps<{ defineProps<{
streamState: StreamState streamState: StreamState;
onStartChat: any onStartChat: any;
audioSourceCallback: () => MediaStream | null audioSourceCallback: () => MediaStream | null;
waveColor: string waveColor: string;
}>(), }>(),
{ {
streamState: StreamState.closed streamState: StreamState.closed,
} },
) );
const emit = defineEmits([]) const emit = defineEmits([]);
</script> </script>
<style scoped lang="less"></style> <style scoped lang="less"></style>
@@ -106,6 +105,12 @@ const emit = defineEmits([])
stroke: #ffffff; stroke: #ffffff;
color: #ffffff; color: #ffffff;
} }
.spin-icon {
color: #fff;
}
:global(.ant-spin-dot-item) {
background-color: #fff !important;
}
} }
.stop-chat { .stop-chat {

View File

@@ -110,9 +110,7 @@ export const useVideoChatStore = defineStore('videoChatStore', {
this.cameraOff = false this.cameraOff = false
this.volumeMuted = false this.volumeMuted = false
if (!navigator.mediaDevices) { if (!navigator.mediaDevices) {
message.error( message.error('无法获取媒体设备请确保用localhost访问或https协议访问')
'无法获取媒体设备请确保用localhost访问或https协议访问',
)
return return
} }
await navigator.mediaDevices await navigator.mediaDevices
@@ -136,16 +134,12 @@ export const useVideoChatStore = defineStore('videoChatStore', {
console.log('🚀 ~ access_webcam ~ devices:', devices) console.log('🚀 ~ access_webcam ~ devices:', devices)
const videoDeviceId = const videoDeviceId =
this.selectedVideoDevice && this.selectedVideoDevice &&
devices.some( devices.some((device) => device.deviceId === this.selectedVideoDevice?.deviceId)
(device) => device.deviceId === this.selectedVideoDevice?.deviceId,
)
? this.selectedVideoDevice.deviceId ? this.selectedVideoDevice.deviceId
: '' : ''
const audioDeviceId = const audioDeviceId =
this.selectedAudioDevice && this.selectedAudioDevice &&
devices.some( devices.some((device) => device.deviceId === this.selectedAudioDevice?.deviceId)
(device) => device.deviceId === this.selectedAudioDevice?.deviceId,
)
? this.selectedAudioDevice.deviceId ? this.selectedAudioDevice.deviceId
: '' : ''
console.log(videoDeviceId, audioDeviceId, ' access web device') console.log(videoDeviceId, audioDeviceId, ' access web device')
@@ -153,7 +147,7 @@ export const useVideoChatStore = defineStore('videoChatStore', {
this.webcamAccessed = true this.webcamAccessed = true
} catch (err: any) { } catch (err: any) {
console.log(err) console.log(err)
message.error(err.message) message.error(err)
} }
}, },
async init() { async init() {
@@ -163,6 +157,7 @@ export const useVideoChatStore = defineStore('videoChatStore', {
if (config.rtc_configuration) { if (config.rtc_configuration) {
this.rtcConfig = config.rtc_configuration this.rtcConfig = config.rtc_configuration
} }
console.log(config) console.log(config)
if (config.avatar_config) { if (config.avatar_config) {
this.avatarType = config.avatar_config.avatar_type this.avatarType = config.avatar_config.avatar_type
@@ -174,9 +169,7 @@ export const useVideoChatStore = defineStore('videoChatStore', {
} }
}) })
.catch(() => { .catch(() => {
message.error( message.error('服务端链接失败,请检查是否能正确访问到 OpenAvatarChat 服务端')
'服务端链接失败,请检查是否能正确访问到 OpenAvatarChat 服务端',
)
}) })
}, },
handleCameraOff() { handleCameraOff() {
@@ -204,29 +197,19 @@ export const useVideoChatStore = defineStore('videoChatStore', {
console.log('🚀 ~ handle_device_change ~ devices:', devices) console.log('🚀 ~ handle_device_change ~ devices:', devices)
let videoDeviceId = let videoDeviceId =
this.selectedVideoDevice && this.selectedVideoDevice &&
devices.some( devices.some((device) => device.deviceId === this.selectedVideoDevice?.deviceId)
(device) => device.deviceId === this.selectedVideoDevice?.deviceId,
)
? this.selectedVideoDevice.deviceId ? this.selectedVideoDevice.deviceId
: '' : ''
let audioDeviceId = let audioDeviceId =
this.selectedAudioDevice && this.selectedAudioDevice &&
devices.some( devices.some((device) => device.deviceId === this.selectedAudioDevice?.deviceId)
(device) => device.deviceId === this.selectedAudioDevice?.deviceId,
)
? this.selectedAudioDevice.deviceId ? this.selectedAudioDevice.deviceId
: '' : ''
if ( if (this.availableVideoDevices.find((video_device) => video_device.deviceId === device_id)) {
this.availableVideoDevices.find(
(video_device) => video_device.deviceId === device_id,
)
) {
videoDeviceId = device_id videoDeviceId = device_id
this.cameraOff = false this.cameraOff = false
} else if ( } else if (
this.availableAudioDevices.find( this.availableAudioDevices.find((audio_device) => audio_device.deviceId === device_id)
(audio_device) => audio_device.deviceId === device_id,
)
) { ) {
audioDeviceId = device_id audioDeviceId = device_id
this.micMuted = false this.micMuted = false
@@ -235,6 +218,14 @@ export const useVideoChatStore = defineStore('videoChatStore', {
}, },
handleSubtitleToggle() { handleSubtitleToggle() {
this.showChatRecords = !this.showChatRecords this.showChatRecords = !this.showChatRecords
const visionState = useVisionStore()
const { wrapperRef, wrapperRect } = visionState
console.log(wrapperRect, wrapperRef)
if (!wrapperRef || !wrapperRect) return
wrapperRef.getBoundingClientRect()
wrapperRect.width = wrapperRef!.clientWidth
wrapperRect.height = wrapperRef!.clientHeight
visionState.isLandscape = wrapperRect.width > wrapperRect.height
}, },
async updateAvailableDevices() { async updateAvailableDevices() {
const devices = await getDevices() const devices = await getDevices()
@@ -250,9 +241,8 @@ export const useVideoChatStore = defineStore('videoChatStore', {
return device.kind === 'audioinput' && device.deviceId return device.kind === 'audioinput' && device.deviceId
}) && this.hasMicPermission }) && this.hasMicPermission
this.hasCamera = this.hasCamera =
devices.some( devices.some((device) => device.kind === 'videoinput' && device.deviceId) &&
(device) => device.kind === 'videoinput' && device.deviceId, this.hasCameraPermission
) && this.hasCameraPermission
await getStream( await getStream(
audioDeviceId && audioDeviceId !== 'default' audioDeviceId && audioDeviceId !== 'default'
? { deviceId: { exact: audioDeviceId } } ? { deviceId: { exact: audioDeviceId } }
@@ -260,7 +250,7 @@ export const useVideoChatStore = defineStore('videoChatStore', {
videoDeviceId && videoDeviceId !== 'default' videoDeviceId && videoDeviceId !== 'default'
? { deviceId: { exact: videoDeviceId } } ? { deviceId: { exact: videoDeviceId } }
: this.hasCamera, : this.hasCamera,
this.trackConstraints, this.trackConstraints
) )
.then(async (local_stream) => { .then(async (local_stream) => {
console.log('local_stream', local_stream) console.log('local_stream', local_stream)
@@ -269,20 +259,17 @@ export const useVideoChatStore = defineStore('videoChatStore', {
}) })
.then(() => { .then(() => {
const used_devices = this.stream!.getTracks().map( const used_devices = this.stream!.getTracks().map(
(track) => track.getSettings()?.deviceId, (track) => track.getSettings()?.deviceId
) )
used_devices.forEach((device_id) => { used_devices.forEach((device_id) => {
const used_device = devices.find( const used_device = devices.find((device) => device.deviceId === device_id)
(device) => device.deviceId === device_id,
)
if (used_device && used_device?.kind.includes('video')) { if (used_device && used_device?.kind.includes('video')) {
this.selectedVideoDevice = used_device this.selectedVideoDevice = used_device
} else if (used_device && used_device?.kind.includes('audio')) { } else if (used_device && used_device?.kind.includes('audio')) {
this.selectedAudioDevice = used_device this.selectedAudioDevice = used_device
} }
}) })
!this.selectedVideoDevice && !this.selectedVideoDevice && (this.selectedVideoDevice = this.availableVideoDevices[0])
(this.selectedVideoDevice = this.availableVideoDevices[0])
}) })
.catch((e) => { .catch((e) => {
console.error('image.no_webcam_support', e) console.error('image.no_webcam_support', e)
@@ -315,29 +302,22 @@ export const useVideoChatStore = defineStore('videoChatStore', {
if (this.streamState === 'closed') { if (this.streamState === 'closed') {
this.chatRecords = [] this.chatRecords = []
this.peerConnection = new RTCPeerConnection() // TODO RTC_configuration this.peerConnection = new RTCPeerConnection() // TODO RTC_configuration
this.peerConnection.addEventListener( this.peerConnection.addEventListener('connectionstatechange', async (event) => {
'connectionstatechange', switch (this.peerConnection!.connectionState) {
async (event) => { case 'connected':
switch (this.peerConnection!.connectionState) { this.streamState = StreamState.open
case 'connected': break
this.streamState = StreamState.open case 'disconnected':
break this.streamState = StreamState.closed
case 'disconnected': stop(this.peerConnection!)
this.streamState = StreamState.closed // await access_webcam() //TODO 重置状态
stop(this.peerConnection!) break
// await access_webcam() //TODO 重置状态 default:
break break
default: }
break })
}
},
)
this.streamState = StreamState.waiting this.streamState = StreamState.waiting
await setupWebRTC( await setupWebRTC(this.stream!, this.peerConnection!, visionState.remoteVideoRef!)
this.stream!,
this.peerConnection!,
visionState.remoteVideoRef!,
)
.then(([dataChannel, webRTCId]) => { .then(([dataChannel, webRTCId]) => {
this.streamState = StreamState.open this.streamState = StreamState.open
this.webRTCId = webRTCId as string this.webRTCId = webRTCId as string
@@ -355,6 +335,7 @@ export const useVideoChatStore = defineStore('videoChatStore', {
console.info('catching', e) console.info('catching', e)
this.streamState = StreamState.closed this.streamState = StreamState.closed
message.error(e) message.error(e)
message.error('请检查是否超过数字人并发上限')
}) })
} else if (this.streamState === 'waiting') { } else if (this.streamState === 'waiting') {
// waiting 中不允许操作 // waiting 中不允许操作
@@ -373,7 +354,7 @@ export const useVideoChatStore = defineStore('videoChatStore', {
}, },
initWebsocket(ws_route: string, webRTCId: string) { initWebsocket(ws_route: string, webRTCId: string) {
const ws = new WS( const ws = new WS(
`${window.location.protocol.includes('https') ? 'wss' : 'ws'}://${window.location.host}${ws_route}/${webRTCId}`, `${window.location.protocol.includes('https') ? 'wss' : 'ws'}://${window.location.host}${ws_route}/${webRTCId}`
) )
ws.on(WsEventTypes.WS_OPEN, () => { ws.on(WsEventTypes.WS_OPEN, () => {
console.log('socket opened') console.log('socket opened')

View File

@@ -85,6 +85,7 @@
position: absolute; position: absolute;
bottom: 0; bottom: 0;
right: 0; right: 0;
width: 50%;
padding: 10px; padding: 10px;
} }
} }

View File

@@ -1,30 +0,0 @@
export default {
extends: ['stylelint-config-standard'],
// stylelint不识别:global, 添加selector-pseudo-class-no-unknown忽略:global
rules: {
'selector-pseudo-class-no-unknown': [
true,
{
ignorePseudoClasses: ['global'],
},
],
// 对:global处理有问题, 所以关掉该规则
'no-descending-specificity': null,
// 要求css的选择器名称是kebab-case, 历史代码很多是驼峰的, 所以关掉该规则
'selector-class-pattern': null,
// 该规则不允许供应商前缀值; 而最多显示几行时需要display: -webkit-box; 所以忽略'box'
'value-no-vendor-prefix': [true, { ignoreValues: ['box'] }],
'custom-property-pattern': '^([a-zA-Z0-9]|-|_)*$',
'rule-empty-line-before': null,
'declaration-empty-line-before': null,
'allow-empty-input': true,
// 采用系统默认字体
'font-family-no-missing-generic-family-keyword': null,
},
overrides: [
{
files: ['**/*.less'],
customSyntax: 'postcss-less',
},
],
};

View File

@@ -1,10 +1,11 @@
import legacyPlugin from '@vitejs/plugin-legacy' import legacyPlugin from '@vitejs/plugin-legacy'
import vue from '@vitejs/plugin-vue' import vue from '@vitejs/plugin-vue'
import { defineConfig } from 'vite' import { defineConfig } from 'vite'
// import mkcert from 'vite-plugin-mkcert' import mkcert from 'vite-plugin-mkcert'
import { join } from 'path' import { join } from 'path'
// server of your OpenAvatarChat // server of your OpenAvatarChat
// if you are not use localhost, you need to start https
const serverIP = '127.0.0.1' const serverIP = '127.0.0.1'
const serverPort = '8282' const serverPort = '8282'
@@ -13,10 +14,6 @@ export default defineConfig({
base: './', base: './',
build: { build: {
rollupOptions: { rollupOptions: {
// input: {
// index: resolve(__dirname, 'index.html'),
// cropImage: resolve(__dirname, 'cropImage.html')
// },
output: { output: {
entryFileNames: `assets/[name].js`, entryFileNames: `assets/[name].js`,
chunkFileNames: `assets/[name].js`, chunkFileNames: `assets/[name].js`,