gemercheung 9 месяцев назад
Родитель
Сommit
6992ee2a3b
12 измененных файлов с 1517 добавлено и 1299 удалено
  1. 1 0
      .gitignore
  2. 2 0
      package.json
  3. 1259 1201
      pnpm-lock.yaml
  4. 61 13
      src/App.vue
  5. 37 0
      src/api/alova.ts
  6. 2 0
      src/api/index.ts
  7. 9 0
      src/api/module/tts.ts
  8. 10 0
      src/api/url.ts
  9. 31 17
      src/store/main.ts
  10. 30 18
      src/views/basicSettings/index.vue
  11. 62 50
      src/views/textToaudio/index.vue
  12. 13 0
      src/views/textToaudio/tts.d.ts

+ 1 - 0
.gitignore

@@ -1,6 +1,7 @@
 node_modules
 .DS_Store
 dist
+.idea
 dist-ssr
 *.local
 coverage

+ 2 - 0
package.json

@@ -21,6 +21,8 @@
     "@heroicons/vue": "^2.1.3",
     "@popperjs/core": "^2.11.8",
     "@vicons/ionicons5": "^0.12.0",
+    "@vueuse/core": "^11.2.0",
+    "alova": "^3.2.0",
     "body-scroll-lock": "^4.0.0-beta.0",
     "pinia": "^2.1.7",
     "vue": "^3.4.23",

Разница между файлами не показана из-за своего большого размера
+ 1259 - 1201
pnpm-lock.yaml


+ 61 - 13
src/App.vue

@@ -4,6 +4,8 @@
     :theme="theme"
     :theme-overrides="themeOverrides"
     :class="{ dark: mode }"
+    :locale="zhCN"
+    :date-locale="dateZhCN"
   >
     <n-layout position="absolute" style="height: 100vh">
       <n-layout-header style="padding: 24px" bordered>
@@ -12,7 +14,7 @@
             <n-icon size="24" :component="ChevronBackOutline" />
             <span style="position: relative; top: -6px">返回我的场景</span>
           </div>
-          <n-button type="primary"> 保存 </n-button>
+          <n-button type="primary"> 保存</n-button>
         </div>
       </n-layout-header>
       <n-layout
@@ -31,7 +33,19 @@
           :native-scrollbar="false"
           bordered
         >
-          <n-menu class="menu-class" style="--n-item-color-hover: rgb(243, 243, 245, .5);--n-item-text-color: white; --n-font-size: 14px;--n-item-icon-color: #fff;    --n-item-icon-color-active: #316c72;" v-model:value="activeKey" :options="menuOptions" @update:value="handleUpdateValue" />
+          <n-menu
+            class="menu-class"
+            style="
+              --n-item-color-hover: rgb(243, 243, 245, 0.5);
+              --n-item-text-color: white;
+              --n-font-size: 14px;
+              --n-item-icon-color: #fff;
+              --n-item-icon-color-active: #316c72;
+            "
+            v-model:value="activeKey"
+            :options="menuOptions"
+            @update:value="handleUpdateValue"
+          />
         </n-layout-sider>
         <n-layout-content
           content-class="layoutContent"
@@ -41,12 +55,25 @@
             <div
               class="app-scene"
               ref="sceneRef"
-              :style="{ width: sceneRefWidth, opacity: showScene ? 0 : 1 }"
+              :style="{
+                width: sceneRefWidth,
+                display: showScene ? 'none' : 'block'
+              }"
             >
-            <iframe v-if="sceneURL" :src="sceneURL" frameborder="0" :style="sceneMobileMode && {width:'375px',height:'677px'}" @load="setupSDK($event.target)"></iframe>
+              <iframe
+                v-if="sceneURL"
+                :src="sceneURL"
+                frameborder="0"
+                :style="sceneMobileMode && { width: '375px', height: '677px' }"
+                @load="setupSDK($event.target)"
+              ></iframe>
+            </div>
           </div>
-          </div>
-          <div class="app-view pointer-events-none" id="drawer-target">
+          <div
+            :class="{ isTran: showScene }"
+            class="app-view"
+            id="drawer-target"
+          >
             <n-message-provider>
               <n-dialog-provider>
                 <router-view />
@@ -65,9 +92,11 @@ import {
   darkTheme,
   lightTheme,
   NDialogProvider,
-  NMessageProvider
+  NMessageProvider,
+  zhCN,
+  dateZhCN
 } from 'naive-ui'
-import { computed, ref, toRaw , watchEffect, h, onMounted, watch } from 'vue'
+import { computed, ref, toRaw, watchEffect, h, onMounted, watch } from 'vue'
 import type { Component } from 'vue'
 import { useMainStore } from '@/store'
 import themeOverrides from '@/styles/theme.js'
@@ -81,9 +110,14 @@ import {
   PeopleOutline,
   ChatboxEllipses
 } from '@vicons/ionicons5'
+
 const darkStore = localStorage.getItem('dark')
 import { RouterLink } from 'vue-router'
 import { NIcon, useMessage } from 'naive-ui'
+import { useUrlSearchParams } from '@vueuse/core'
+
+const params = useUrlSearchParams('hash')
+
 const route = useRoute()
 const activeKey = ref(route.name)
 
@@ -107,6 +141,7 @@ const prefersDark: boolean = darkStore
 
 const mode = ref<boolean>(prefersDark)
 const theme = computed(() => (mode.value ? darkTheme : lightTheme))
+
 const sceneRefWidth = computed(() => {
   console.log('route', route, route.name === 'basicSettings')
   if (route.name === 'basicSettings' || route.name === 'topicNavigation')
@@ -115,18 +150,21 @@ const sceneRefWidth = computed(() => {
   return `calc(100% - ${mode.sceneRefWidth}px)`
 })
 
-const sceneURL = computed(()=>main.sceneURL)
-const sceneMobileMode = computed(()=>main.sceneMode == 'mobile')
+const sceneURL = computed(() => main.sceneURL)
+const sceneMobileMode = computed(() => main.sceneMode == 'mobile')
 
 const sceneRef = ref()
 const main = useMainStore()
-const { setSceneLink,setSceneRef } = main
+const { setSceneLink, setSceneRef } = main
+
 watchEffect(() => {
   localStorage.setItem('dark', `${mode.value}`)
 })
+
 function renderIcon(icon: Component) {
   return () => h(NIcon, null, { default: () => h(icon) })
 }
+
 const collapsed = ref(false)
 const menuOptions = [
   {
@@ -219,7 +257,9 @@ const handleUpdateValue = (value: string) => {
   console.log(value)
 }
 onMounted(() => {
-  setSceneLink('/page/spg.html?m=KJ-t-3Y6dxgyehDk')
+  const sceneCode = params.m ? String(params.m) : 'KJ-t-3Y6dxgyehDk'
+  main.setSceneCode(sceneCode)
+  setSceneLink(`/page/spg.html?m=${main.sceneCode}`)
   setSceneRef(sceneRef.value)
 })
 </script>
@@ -229,22 +269,28 @@ onMounted(() => {
   font-family: Inter, Avenir, Helvetica, Arial, sans-serif
   -webkit-font-smoothing: antialiased
   -moz-osx-font-smoothing: grayscale
+
 .layoutContent
   position: relative
   padding: 0px
   height: calc(100vh - 83px)
   overflow: hidden
-.app-wrap,.app-view
+
+.app-wrap, .app-view
   position: absolute
   left: 0
   top: 0
   width: 100%
   height: 100%
   z-index: 10
+
 .app-view
   z-index: 100
   pointer-events: none
 
+  &.isTran
+    pointer-events: all
+
 .app-scene
   width: 100%
   height: 100%
@@ -255,9 +301,11 @@ onMounted(() => {
 .app-scene iframe
   width: 100%
   height: 100%
+
 .required
   padding-left: 10px
   position: relative
+
   &:after
     content: " *"
     color: red

+ 37 - 0
src/api/alova.ts

@@ -0,0 +1,37 @@
+import { createAlova } from 'alova'
+import VueHook from 'alova/vue'
+import adapterFetch from 'alova/fetch'
+
+export * from './url'
+
+export const Alova = createAlova({
+  baseURL: '',
+  statesHook: VueHook,
+  requestAdapter: adapterFetch(),
+  timeout: 3000,
+  cacheLogger: process.env.NODE_ENV === 'development',
+  responded: {
+    onSuccess: async (response, method) => {
+      const res = (response.json && (await response.json())) || response.body
+
+      // 是否返回原生响应头 比如:需要获取响应头时使用该属性
+      if (method.meta?.isReturnNativeResponse) {
+        return res
+      }
+      // 请根据自身情况修改数据结构
+      const { message, code, data } = res
+
+      // 不进行任何处理,直接返回
+      // 用于需要直接获取 code、result、 message 这些信息时开启
+      if (method.meta?.isTransformResponse === false) {
+        return res.data
+      }
+      // debugger
+      // console.log(message, code, data)
+      if (code === 0) {
+        return data
+      }
+
+    }
+  }
+})

+ 2 - 0
src/api/index.ts

@@ -0,0 +1,2 @@
+export * from './module/tts'
+

+ 9 - 0
src/api/module/tts.ts

@@ -0,0 +1,9 @@
+import { Alova, url } from '../alova'
+
+export const fetchTtsList = (num: string) => {
+  return Alova.Get(url.ttsList, {
+    params: {
+      num
+    }
+  })
+}

+ 10 - 0
src/api/url.ts

@@ -0,0 +1,10 @@
+const url = {
+    //tts
+    ttsList: "/service/scene/edit/scrb/textVoiceTransfer/list",
+    ttsDel: "/service/scene/edit/scrb/textVoiceTransfer/delete",
+    ttsSave: "/service/scene/edit/scrb/tts/save",
+    sttSave: '/service/scene/edit/scrb/asr/save'
+
+}
+
+export { url }

+ 31 - 17
src/store/main.ts

@@ -1,11 +1,12 @@
 import { defineStore } from 'pinia'
-import { watch } from 'vue'
+// import { watch } from 'vue'
 
 // useStore could be anything like useUser, useCart
 // the first argument is a unique id of the store across your application
 export const useMainStore = defineStore('main', {
   state: () => {
     return {
+      sceneCode: '',
       counter: 0,
       showDrawer: false,
       sceneRef: null,
@@ -14,31 +15,38 @@ export const useMainStore = defineStore('main', {
       sceneLink: '',
       sceneMode: 'pc',
       sceneConfig: {
-        message:'verify'
+        message: 'verify'
       },
       basicConfig: {
-        mode: 'pc',//true pc false mobile
+        mode: 'pc', //true pc false mobile
         themes: '',
-        autoRotate: false, //true 自动播放 
+        autoRotate: false, //true 自动播放
         joystick: {
-          show:false,
+          show: false,
           position: 'left'
         },
         age: 18
-      },
-      digitalHumanList: [],
+      }
     }
   },
   getters: {
-    sceneURL: ({sceneLink,sceneConfig,sceneMode})=> {
-      if(sceneLink){
-        console.log(sceneLink+`&mobile=${sceneMode == 'mobile' ? 'true' : 'false'}&config=`+JSON.stringify(sceneConfig || {}))
-        return sceneLink+`&mobile=${sceneMode == 'mobile' ? 'true' : 'false'}&config=`+JSON.stringify(sceneConfig || {})
+    sceneURL: ({ sceneLink, sceneConfig, sceneMode }) => {
+      if (sceneLink) {
+        console.log(
+          sceneLink +
+            `&mobile=${sceneMode == 'mobile' ? 'true' : 'false'}&config=` +
+            JSON.stringify(sceneConfig || {})
+        )
+        return (
+          sceneLink +
+          `&mobile=${sceneMode == 'mobile' ? 'true' : 'false'}&config=` +
+          JSON.stringify(sceneConfig || {})
+        )
       }
     },
     count: ({ counter }) => counter,
     getBasicConfig: ({ basicConfig }) => basicConfig,
-    getDigitalHumanList: ({ digitalHumanList }) => digitalHumanList,
+    getDigitalHumanList: ({ digitalHumanList }) => digitalHumanList
   },
   actions: {
     incrementCounter(count: number) {
@@ -48,16 +56,22 @@ export const useMainStore = defineStore('main', {
       this.sceneRef = sceneRef
     },
     setWidthSceneRef(width: number) {
-      this.sceneRef.style.width = `calc(100% - ${width||0}px)`
+      if (this.sceneRef) {
+        const sceneRef = this.sceneRef as never as HTMLElement
+        sceneRef.style.width = `calc(100% - ${width || 0}px)`
+      }
     },
-    setSceneLink(link:string) {
+    setSceneLink(link: string) {
       this.sceneLink = link
     },
-    setSceneMode(mode:string) {
+    setSceneMode(mode: string) {
       this.sceneMode = mode
     },
-    setSceneConfig(config:object) {
-      this.sceneConfig = {...this.sceneConfig,...config}
+    setSceneConfig(config: object) {
+      this.sceneConfig = { ...this.sceneConfig, ...config }
+    },
+    setSceneCode(m: string) {
+      this.sceneCode = m
     }
   }
 })

+ 30 - 18
src/views/basicSettings/index.vue

@@ -34,7 +34,10 @@
             <span>操纵杆</span>
             <n-switch v-model:value="basicConfig.joystick.show" />
           </div>
-          <div class="flex justify-between my-2.5" v-if="basicConfig.joystick.show">
+          <div
+            class="flex justify-between my-2.5"
+            v-if="basicConfig.joystick.show"
+          >
             <n-radio-group
               v-model:value="basicConfig.joystick.position"
               name="radiobuttongroup1"
@@ -52,7 +55,14 @@
 </template>
 
 <script setup lang="ts">
-import { ref, watch, computed, onMounted,onDeactivated, onUnmounted } from 'vue'
+import {
+  ref,
+  watch,
+  computed,
+  onMounted,
+  // onDeactivated,
+  onUnmounted
+} from 'vue'
 import { useMainStore } from '@/store'
 import { sdk } from '@/sdk'
 // import { useMessage } from 'naive-ui'
@@ -87,28 +97,32 @@ const options = [
   }
 ]
 
-watch(basicConfig.value.joystick,
-  (val) => {
-    main.setSceneConfig({joystick:val})
-  }
-)
+watch(basicConfig.value.joystick, (val) => {
+  main.setSceneConfig({ joystick: val })
+})
 
 watch(
   () => basicConfig.value.autoRotate,
   (val) => {
-    sdk.then(sdk=>{
+    sdk.then((sdk) => {
       sdk.Camera.autoRotate(val)
     })
   }
 )
 
-watch(()=>basicConfig.value.mode,(val)=>{
-  main.setSceneMode(val)
-})
+watch(
+  () => basicConfig.value.mode,
+  (val) => {
+    main.setSceneMode(val)
+  }
+)
 
-watch(()=>basicConfig.value.themes,(val)=>{
-  main.setSceneConfig({themes:val})
-})
+watch(
+  () => basicConfig.value.themes,
+  (val) => {
+    main.setSceneConfig({ themes: val })
+  }
+)
 
 watch(
   active,
@@ -131,14 +145,12 @@ function changeActive() {
   console.log('changeActive', active.value)
 }
 onMounted(() => {
-  
   // active.value = true
 })
-onUnmounted(()=>{
-  if(basicConfig.value.mode == 'mobile') {
+onUnmounted(() => {
+  if (basicConfig.value.mode == 'mobile') {
     main.setSceneMode('pc')
   }
-  
 })
 </script>
 

+ 62 - 50
src/views/textToaudio/index.vue

@@ -1,14 +1,15 @@
 <template>
-  <div class="textToaudio p-4" >
+  <div class="textToaudio p-4">
     <div class="tablehader flex justify-between items-center mb-2.5 text-wrap">
       <div class="title">文字语音互转</div>
       <div class="bottomList">
         <n-space>
-          <n-button type="primary"> 音转文 </n-button>
-          <n-button type="primary"> 文转音 </n-button>
+          <n-button type="primary"> 音转文</n-button>
+          <n-button type="primary"> 文转音</n-button>
         </n-space>
       </div>
     </div>
+
     <!-- <n-scrollbar style="max-height: calc(100vh - 100px)" trigger="none"> -->
     <n-data-table
       pagination-behavior-on-filter="first"
@@ -20,11 +21,19 @@
 </template>
 
 <script setup lang="ts">
-import { ref, h, reactive } from 'vue'
-import { NButton,  } from 'naive-ui'
+import { h, reactive, onMounted, watchEffect, ref } from 'vue'
+import { NButton, NTooltip } from 'naive-ui'
+import { fetchTtsList } from '@/api'
+import { useMainStore } from '@/store'
+
 defineProps<{ msg: string }>()
+
+const main = useMainStore()
+
+const data = ref<TTSItem[]>([])
+
 const paginationReactive = reactive({
-  page: 2,
+  page: 1,
   pageSize: 5,
   showSizePicker: true,
   pageSizes: [3, 5, 7],
@@ -36,79 +45,82 @@ const paginationReactive = reactive({
     paginationReactive.page = 1
   }
 })
+
+onMounted(async () => {
+  watchEffect(async () => {
+    if (main.sceneCode) {
+      const res = await fetchTtsList(main.sceneCode)
+      console.log('data', res)
+      data.value = res as never as TTSItem
+    }
+  })
+})
+
+const renderContent = (content) => {
+  return
+}
+
 const columns = [
   {
     title: '序号',
-    key: 'no',
+    key: 'id',
     width: 70
   },
   {
     title: '类型',
     key: 'type',
     render(row) {
-      return row.type == 1 ? h('span', '语音') : h('span', '文字')
+      return row.type === 'asr' ? h('span', '语音') : h('span', '文字')
     }
   },
   {
     title: '内容',
-    key: 'content'
+    key: 'document',
+    width: 400,
+    render(row) {
+      return h(
+        NButton,
+        { trigger: 'hover', placement: 'bottom' },
+        { default: () => 'Send Email' }
+      )
+    }
+    // resizable: true,
   },
   {
     title: '语音文件',
-    key: 'content'
+    key: 'voicePath'
   },
   {
     title: '状态',
     key: 'state',
     render(row) {
-      return row.state == 1 ? h('span', '处理中') : row.state == 0 ? h('span', '已完成') : h('span', '已取消')
+      return row.state == 1
+        ? h('span', '处理中')
+        : row.state == 0
+          ? h('span', '已完成')
+          : h('span', '已取消')
     }
   },
   {
     title: '创建时间',
-    key: 'createTime'
+    key: 'updateTime'
   },
   {
-      title: 'Action',
-      key: 'actions',
-      render(row) {
-        return h(
-          NButton,
-          {
-            size: 'small',
-            onClick: () => sendMail(row)
-          },
-          { default: () => 'Send Email' }
-        )
-      }
+    title: '操作',
+    key: 'actions',
+    render(row) {
+      return h(
+        NButton,
+        {
+          size: 'small',
+          onClick: () => sendMail(row)
+        },
+        { default: () => 'Send Email' }
+      )
     }
-]
-const data = [
-  {
-    key: 1,
-    name: 'John Brown',
-    age: 32,
-    address: 'New York No. 1 Lake Park'
-  },
-  {
-    key: 2,
-    name: 'Jim Green',
-    age: 42,
-    address: 'London No. 1 Lake Park'
-  },
-  {
-    key: 3,
-    name: 'Joe Black',
-    age: 32,
-    address: 'Sidney No. 1 Lake Park'
-  },
-  {
-    key: 4,
-    name: 'Jim Red',
-    age: 32,
-    address: 'London No. 2 Lake Park'
   }
 ]
+
 function sendMail(row) {
   console.log('send email to', row.name, 'with id', row.key)
 }
@@ -127,8 +139,8 @@ code
   padding: 2px 4px
   border-radius: 4px
   color: #304455
+
 .textToaudio
   min-height: 100%
   border-left: 1px solid
-
 </style>

+ 13 - 0
src/views/textToaudio/tts.d.ts

@@ -0,0 +1,13 @@
+interface TTSItem {
+  id: number
+  createTime: string
+  document: string
+  name:string
+  num:string
+  resCode: number
+  status: number
+  taskId: number
+  voiceName: string
+  voicePath: string
+  recStatus: number
+}