tangning 10 mesi fa
parent
commit
921922fd5b

+ 2 - 15
README.md

@@ -1,18 +1,5 @@
-![validation status](https://github.com/ChronosMasterOfAllTime/vue-vite-tw-ts/actions/workflows/validate.yml/badge.svg)
-
-# Vue 3 + Typescript + Vite
-
-This template should help get you started developing with Vue 3 and Typescript in Vite. The template uses Vue 3 `<script setup>` SFCs, check out the [script setup docs](https://v3.vuejs.org/api/sfc-script-setup.html#sfc-script-setup) to learn more.
-
-## Recommended IDE Setup
-
-- [VSCode](https://code.visualstudio.com/) + [Volar](https://marketplace.visualstudio.com/items?itemName=johnsoncodehk.volar)
-
-## Type Support For `.vue` Imports in TS
-
-Since TypeScript cannot handle type information for `.vue` imports, they are shimmed to be a generic Vue component type by default. In most cases this is fine if you don't really care about component prop types outside of templates. However, if you wish to get actual prop types in `.vue` imports (for example to get props validation when using manual `h(...)` calls), you can enable Volar's `.vue` type support plugin by running `Volar: Switch TS Plugin on/off` from VSCode command palette.
-
-## Getting started
+## 4DKK sdk文档
+https://docs.4dkankan.com/#/zh-cn/guide/quickstart
 
 - Install [node LTS](https://nodejs.org/en/download/)
   - Currently 18.x (deprecated) and 20.x (current) are supported

+ 68 - 28
src/App.vue

@@ -1,27 +1,18 @@
 <template>
-  <n-config-provider data-cy="app" :theme="theme" :theme-overrides="themeOverrides" :class="{ dark: mode }">
+  <n-config-provider
+    data-cy="app"
+    :theme="theme"
+    :theme-overrides="themeOverrides"
+    :class="{ dark: mode }"
+  >
     <n-layout position="absolute" style="height: 100vh">
       <n-layout-header style="padding: 24px" bordered>
         <div class="flex justify-between items-center">
-          <div class="back" style="position: relative; top: 4px">
+          <div class="back" style="position: relative; top: 4px; color: #fff">
             <n-icon size="24" :component="ChevronBackOutline" />
             <span style="position: relative; top: -6px">返回我的场景</span>
           </div>
           <n-button type="primary"> 保存 </n-button>
-          <!-- <n-switch data-cy="dark-mode" v-model:value="mode">
-            <template #checked> Dark </template>
-            <template #unchecked> Light </template>
-            <template #checked-icon>
-              <n-icon>
-                <moon />
-              </n-icon>
-            </template>
-            <template #unchecked-icon>
-              <n-icon>
-                <sun />
-              </n-icon>
-            </template>
-          </n-switch> -->
         </div>
       </n-layout-header>
       <n-layout
@@ -40,17 +31,25 @@
           :native-scrollbar="false"
           bordered
         >
-          <n-menu :options="menuOptions" @update:value="handleUpdateValue" />
+          <n-menu v-model:value="activeKey" :options="menuOptions" @update:value="handleUpdateValue" />
         </n-layout-sider>
         <n-layout-content
           content-class="layoutContent"
           :native-scrollbar="false"
         >
           <div class="app-wrap">
-            <div class="app-scene" ref="sceneRef"></div>
+            <div
+              class="app-scene"
+              ref="sceneRef"
+              :style="{ width: sceneRefWidth, opacity: showScene ? 0 : 1 }"
+            ></div>
           </div>
-          <div class="app-view">
-            <router-view />
+          <div class="app-view pointer-events-none" id="drawer-target">
+            <n-message-provider>
+              <n-dialog-provider>
+                <router-view />
+              </n-dialog-provider>
+            </n-message-provider>
           </div>
         </n-layout-content>
       </n-layout>
@@ -60,10 +59,17 @@
 
 <script setup lang="ts">
 import { useSDK } from '@/sdk'
-import { darkTheme, lightTheme } from 'naive-ui'
-import { computed, ref, watchEffect, h, onMounted } from 'vue'
+import {
+  darkTheme,
+  lightTheme,
+  NDialogProvider,
+  NMessageProvider
+} from 'naive-ui'
+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'
+import { useRouter, useRoute } from 'vue-router'
 import {
   ChevronBackOutline,
   Layers,
@@ -76,14 +82,40 @@ import {
 const darkStore = localStorage.getItem('dark')
 import { RouterLink } from 'vue-router'
 import { NIcon, useMessage } from 'naive-ui'
+const route = useRoute()
+const activeKey = ref(route.name)
+
+const showScene = ref(false)
+watch(
+  () => route.name,
+  () => {
+    console.log('activeKeys', route.name)
+    activeKey.value = route.name
+    if (route.name === 'textToaudio') {
+      showScene.value = true
+    } else {
+      showScene.value = false
+    }
+    console.log('watch', route.name)
+  }
+)
 const prefersDark: boolean = darkStore
   ? darkStore === 'true'
   : window.matchMedia('(prefers-color-scheme: dark)').matches
 
 const mode = ref<boolean>(prefersDark)
 const theme = computed(() => (mode.value ? darkTheme : lightTheme))
-const sceneRef = ref()
+const sceneRefWidth = computed(() => {
+  console.log('route', route, route.name === 'basicSettings')
+  if (route.name === 'basicSettings' || route.name === 'topicNavigation')
+    return `calc(100% - ${240}px)`
+  if (route.name === 'message') return `calc(100% - ${0}px)`
+  return `calc(100% - ${mode.sceneRefWidth}px)`
+})
 
+const sceneRef = ref()
+const main = useMainStore()
+const { setSceneRef } = main
 watchEffect(() => {
   localStorage.setItem('dark', `${mode.value}`)
 })
@@ -185,11 +217,11 @@ const handleUpdateValue = (value: string) => {
 const sdk = useSDK()
 sdk.use('MinMap')
 
-onMounted(()=>{
+onMounted(() => {
   sdk.mount(sceneRef.value)
   sdk.render()
+  setSceneRef(sceneRef.value)
 })
-
 </script>
 
 <style lang="sass">
@@ -209,7 +241,7 @@ onMounted(()=>{
   width: 100%
   height: 100%
   z-index: 10
-.app-view 
+.app-view
   z-index: 100
   pointer-events: none
 
@@ -218,6 +250,14 @@ onMounted(()=>{
   height: 100%
 
 [xui_min_map]
-  right:10px
-  top:10px
+  right: 10px
+  top: 10px
+.required
+  padding-left: 10px
+  position: relative
+  &:after
+    content: " *"
+    color: red
+    position: absolute
+    left: 0
 </style>

+ 9 - 1
src/components/global/vendor/naive.ts

@@ -20,6 +20,10 @@ import {
   NSwitch,
   NDataTable,
   NSpace,
+  NDrawer,
+  NRadioGroup,
+  NSelect,
+  NRadioButton
 } from 'naive-ui'
 
 export default create({
@@ -43,6 +47,10 @@ export default create({
     NScrollbar,
     NSwitch,
     NDataTable,
-    NSpace
+    NSpace,
+    NDrawer,
+    NRadioGroup,
+    NSelect,
+    NRadioButton
   ]
 })

+ 6 - 5
src/router/index.ts

@@ -5,11 +5,12 @@ const router = createRouter({
   routes: [
     {
       path: '/',
-      name: 'home',
-      component: () => import('@/views/HelloWorld.vue'),
-      props: {
-        msg: 'Hello Vue 3 + TypeScript + Vite + Tailwind CSS/UI + Pinia + Vue Router'
-      }
+      redirect: '/basicSettings',
+      // name: 'home',
+      // component: () => import('@/views/HelloWorld.vue'),
+      // props: {
+      //   msg: 'Hello Vue 3 + TypeScript + Vite + Tailwind CSS/UI + Pinia + Vue Router'
+      // }
     },{
       path: '/basicSettings',
       name: 'basicSettings',

+ 25 - 3
src/store/main.ts

@@ -1,19 +1,41 @@
 import { defineStore } from 'pinia'
+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 {
-      counter: 0
+      counter: 0,
+      showDrawer: false,
+      sceneRef: null,
+      sceneRefWidth: 0,
+      digitalHumanList: [],
+      basicConfig: {
+        view: true,//true pc false mobile
+        theme: 0,
+        panorama: false, //true 自动播放 
+        lever: false, //true 显示
+        leverPosition: 'left', //left right center 
+        age: 18
+      },
+      digitalHumanList: [],
     }
   },
   getters: {
-    count: ({ counter }) => counter
+    count: ({ counter }) => counter,
+    getBasicConfig: ({ basicConfig }) => basicConfig,
+    getDigitalHumanList: ({ digitalHumanList }) => digitalHumanList,
   },
   actions: {
     incrementCounter(count: number) {
       this.counter += count
-    }
+    },
+    setSceneRef(sceneRef: any) {
+      this.sceneRef = sceneRef
+    },
+    setWidthSceneRef(width: number) {
+      this.sceneRef.style.width = `calc(100% - ${width||0}px)`
+    },
   }
 })

+ 10 - 0
src/styles/index.sass

@@ -5,3 +5,13 @@
 // FONTS    
 
 @import "fonts/index.sass"
+pointerNo
+  pointer-events: none
+pointer
+  pointer-events: auto
+.n-layout-header
+  background: rgba(0, 21, 41, 1)
+  border-color: rgb(0, 21, 41) !important
+.n-scrollbar
+  background: rgba(0, 21, 41, 1)
+  border-color: rgb(0, 21, 41) !important

+ 100 - 5
src/views/basicSettings/index.vue

@@ -1,20 +1,115 @@
 <template>
-  <div>基础设置页面</div>
+  <div class="pointer-events-auto">
+  <div @click="changeActive">基础设置页面{{ active }}</div>
+  <!-- 基础设置页面 -->
+    <n-drawer
+      v-model:show="active"
+      :width="240"
+      placement="right"
+      :trap-focus="false"
+      :block-scroll="false"
+      :show-mask="false"
+      to="#drawer-target"
+    >
+      <n-drawer-content title="基础设置">
+        <div class="drawerContent m-5">
+          <div class="text-lg my-2.5" @click="active = false">基础设置</div>
+          <n-radio-group
+            v-model:value="basicConfig.view"
+            name="radiobuttongroup1"
+          >
+            <n-radio-button :value="true" label="pc端" />
+            <n-radio-button :value="false" label="移动端" />
+          </n-radio-group>
+          <div class="text-sm my-2.5" @click="changeActive">展示页面风格</div>
+          <n-select
+            v-model:value="basicConfig.theme"
+            placeholder="选择主题"
+            :options="options"
+          />
+          <div class="flex justify-between my-2.5">
+            <span>全景图自动播放</span>
+            <n-switch v-model:value="basicConfig.panorama" />
+          </div>
+          <div class="flex justify-between my-2.5">
+            <span>操纵杆</span>
+            <n-switch v-model:value="basicConfig.lever" />
+          </div>
+          <div class="flex justify-between my-2.5" v-if="basicConfig.lever">
+            <n-radio-group
+              v-model:value="basicConfig.leverPosition"
+              name="radiobuttongroup1"
+              size="small"
+            >
+              <n-radio-button value="left" label="靠左" />
+              <n-radio-button value="center" label="居中" />
+              <n-radio-button value="right" label="靠右" />
+            </n-radio-group>
+          </div>
+        </div>
+      </n-drawer-content>
+    </n-drawer>
+  </div>
 </template>
 
 <script setup lang="ts">
+import { ref, watch, computed, onMounted } from 'vue'
+import { useMainStore } from '@/store'
+// import { useMessage } from 'naive-ui'
 defineProps<{ msg: string }>()
+const main = useMainStore()
+const { setWidthSceneRef } = main
+const active = ref(true)
+const basicConfig = computed(() => {
+  return main.basicConfig
+})
+// const message = useMessage()
+const fileList = ref([])
+const options = [
+  {
+    label: '默认',
+    value: 0
+  },
+  {
+    label: '科技感',
+    value: 1
+  },
+  {
+    label: '红色元素',
+    value: 2
+  }
+]
 
+watch(
+  active,
+  (newValue) => {
+    // setWidthSceneRef(newValue ? 240 : 0)
+  },
+  { immediate: true, deep: true }
+)
+function handleChange(file, event) {
+  console.log(event)
+  // message.success((event?.target).response)
+  const ext = file.name.split('.')[1]
+  file.name = `更名.${ext}`
+  file.url = '__HTTPS__://www.mocky.io/v2/5e4bafc63100007100d8b70f'
+  return file
+}
+function changeActive() {
+  console.log('changeActive', active.value)
+  active.value = active.value?false:true
+  console.log('changeActive', active.value)
+
+}
+onMounted(()=>{
+  // active.value = true
+})
 </script>
 
 <style lang="sass" scoped>
 a
   color: #42b983
 
-label
-  margin: 0 0.5em
-  font-weight: bold
-
 code
   background-color: #eee
   padding: 2px 4px

+ 190 - 13
src/views/digitalHuman/index.vue

@@ -1,23 +1,200 @@
 <template>
-  <div>数字人播报</div>
+  <!-- 基础设置页面 class="pointer-events-auto"-->
+  <div>
+    <n-drawer
+      v-model:show="active"
+      :width="240"
+      placement="right"
+      :trap-focus="false"
+      :block-scroll="false"
+      :show-mask="false"
+      :mask-closable="false"
+      to="#drawer-target"
+    >
+      <n-drawer-content title="数字人播报">
+        <div class="drawerContent m-5">
+          <div class="text-lg my-2.5">数字人播报</div>
+          <div class="list" v-if="!editData.show">
+            <div class="butlist">
+              <n-space>
+                <n-button type="primary" @click="handleShow(1)">+ 3D</n-button>
+                <n-button type="primary" @click="handleShow(2)"
+                  >+ 视频</n-button
+                >
+              </n-space>
+            </div>
+            <div class="list my-2">
+              <div class="listItem">
+                <div class="3D flex justify-between justify-items-center">
+                  <span>
+                    <n-icon size="17" color="#000">
+                      <LogoAppleAr class="relative top-0.5" />
+                    </n-icon>
+                    企业荣誉
+                  </span>
+                  <n-popover placement="bottom" trigger="click">
+                    <template #trigger>
+                      <n-icon size="17" color="#000">
+                        <EllipsisHorizontal />
+                      </n-icon>
+                    </template>
+                    <div class="butList w-12 pointer-events-auto">
+                      <div class="butItem">编辑</div>
+                      <div class="butItem">移动</div>
+                      <div class="butItem">删除</div>
+                    </div>
+                  </n-popover>
+                </div>
+                <div class="video flex justify-between justify-items-center">
+                  <span>
+                    <n-icon size="17" color="#000">
+                      <Videocam class="relative top-0.5" />
+                    </n-icon>
+                    企业荣誉
+                  </span>
+                  <n-popover placement="bottom" trigger="click">
+                    <template #trigger>
+                      <n-icon size="17" color="#000">
+                        <EllipsisHorizontal />
+                      </n-icon>
+                    </template>
+                    <div class="butList w-12 pointer-events-auto">
+                      <div class="butItem">编辑</div>
+                      <div class="butItem">移动</div>
+                      <div class="butItem">删除</div>
+                    </div>
+                  </n-popover>
+                </div>
+              </div>
+            </div>
+          </div>
+          <div v-else>
+            <n-upload
+              action="https://www.mocky.io/v2/5e4bafc63100007100d8b70f"
+              :default-file-list="editData.data.fileList"
+              list-type="image-card"
+            >
+              <div class="uploadText text-center">
+                <n-icon size="48" :depth="3">
+                  <Add />
+                </n-icon>
+                <div>点击上传</div>
+              </div>
+            </n-upload>
+            <div class="required my-2.5">
+              上传视频前请查看<span>操作提示</span>
+            </div>
+            <n-radio-group
+              v-model:value="basicConfig.view"
+              name="radiobuttongroup1"
+              size="small"
+            >
+              <n-radio-button value="left" label="缩放" />
+              <n-radio-button value="center" label="移位" />
+              <n-radio-button value="right" label="旋转" />
+            </n-radio-group>
+            <!-- <div class="text-sm my-2.5">展示页面风格</div>
+            <n-select
+              v-model:value="basicConfig.theme"
+              placeholder="选择主题"
+              :options="options"
+            /> -->
+            <div v-if="basicConfig.view == 'left'">
+              <div class="flex justify-between my-2.5">
+                <span>Scalex</span>
+                <n-input-number :style="{ width: '60%' }" />
+              </div>
+              <div class="flex justify-between my-2.5">
+                <span>Scaley</span>
+                <n-input-number :style="{ width: '60%' }" />
+              </div>
+              <div class="flex justify-between my-2.5">
+                <span>Scalez</span>
+                <n-input-number :style="{ width: '60%' }" />
+              </div>
+            </div>
+            <div v-else>
+              <div class="flex justify-between my-2.5">
+                <span>Scaley</span>
+                <n-input-number :style="{ width: '60%' }" />
+              </div>
+              <div class="flex justify-between my-2.5">
+                <span>Scalez</span>
+                <n-input-number :style="{ width: '60%' }" />
+              </div>
+            </div>
+            <div class="">讲解语音</div>
+            <div class="flex justify-between my-2.5">
+              <n-select v-model:value="editData.value" :options="editData.options" />
+            </div>
+          </div>
+        </div>
+      </n-drawer-content>
+    </n-drawer>
+  </div>
 </template>
 
 <script setup lang="ts">
+import { ref, watch, computed, onMounted, reactive, onUnmounted } from 'vue'
+import {
+  LogoAppleAr,
+  EllipsisHorizontal,
+  Videocam,
+  Add
+} from '@vicons/ionicons5'
+import { NPopover, NUpload, NInputNumber } from 'naive-ui'
+import { useMainStore } from '@/store'
 defineProps<{ msg: string }>()
+const main = useMainStore()
+const active = ref(true)
+const editData = reactive({
+  show: false,
+  type: '',
+  value: '',
+  options: [
+    {
+      label: 'Nowhere Man',
+      value: 'song4'
+    },
+    {
+      label: 'Think For Yourself',
+      value: 'song5'
+    },
+    {
+      label: 'The Word',
+      value: 'song6'
+    }
+  ],
 
+  data: {
+    fileList: []
+  }
+})
+const activeType = ref('list')
+const { setWidthSceneRef } = main
+const digitalHumanList = computed(() => {
+  return main.digitalHumanList
+})
+const basicConfig = computed(() => {
+  return main.basicConfig
+})
+function handleShow(type: number) {
+  editData.show = true
+  editData.type = type === 1 ? '3D' : 'video'
+}
+onMounted(() => {
+  active.value = true
+  // setWidthSceneRef(240)
+})
+onUnmounted(() => {
+  // setWidthSceneRef(0)
+})
 </script>
 
 <style lang="sass" scoped>
-a
-  color: #42b983
-
-label
-  margin: 0 0.5em
-  font-weight: bold
-
-code
-  background-color: #eee
-  padding: 2px 4px
-  border-radius: 4px
-  color: #304455
+.list
+  .listItem
+    div
+      display: flex
+      justify-content: space-between
 </style>

+ 3 - 3
src/views/textToaudio/index.vue

@@ -1,5 +1,5 @@
 <template>
-  <div class="textToaudio m-4">
+  <div class="textToaudio m-4" >
     <div class="tablehader flex justify-between items-center mb-2.5">
       <div class="title">文字语音互转</div>
       <div class="bottomList">
@@ -38,9 +38,9 @@ const paginationReactive = reactive({
 })
 const columns = [
   {
-    title: 'No',
+    title: '序号',
     key: 'no',
-    width: 50
+    width: 70
   },
   {
     title: '类型',

+ 114 - 5
src/views/topicNavigation/index.vue

@@ -1,25 +1,134 @@
 <template>
-  <div>专题导航</div>
+  <div>
+    <n-drawer
+      v-model:show="active"
+      :width="240"
+      placement="right"
+      :trap-focus="false"
+      :block-scroll="false"
+      :show-mask="false"
+      :mask-closable="false"
+      to="#drawer-target"
+    >
+      <n-drawer-content title="专题导航">
+        <div class="drawerContent m-5">
+          <div class="text-lg my-2.5">专题导航</div>
+          <div class="list" v-if="show">
+            <div class="butlist text-center pb-2">
+              <n-button type="primary" @click="handleShow">+ 添加</n-button>
+            </div>
+            <div class="list my-2">
+              <div class="listItem">
+                <div class="video flex justify-between justify-items-center">
+                  <span>
+                    <n-icon size="17" color="#000">
+                      <WalkSharp class="relative top-0.5" />
+                    </n-icon>
+                    企业荣誉
+                  </span>
+                  <n-popover placement="bottom" trigger="click">
+                    <template #trigger>
+                      <n-icon size="17" color="#000">
+                        <EllipsisHorizontal />
+                      </n-icon>
+                    </template>
+                    <div class="butList w-12 pointer-events-auto">
+                      <div class="butItem">编辑</div>
+                      <div class="butItem">删除</div>
+                    </div>
+                  </n-popover>
+                </div>
+              </div>
+            </div>
+          </div>
+          <div v-else class="showList">
+            <div class="doclist">
+              <div
+                class="docItem flex justify-between py-1"
+                v-for="(item, index) in doclist"
+                :key="index"
+              >
+                <n-radio
+                  :checked="item.checked"
+                  :value="item.name"
+                  :name="item.name"
+                  @click="handleChange(item)"
+                >
+                  {{ item.name }}
+                </n-radio>
+                <n-icon @click="handleConfirm" size="17" color="red">
+                  <TrashOutline />
+                </n-icon>
+              </div>
+              <div class="backBut text-center mt-2">
+                <n-button type="primary" @click="handleShow"
+                  >确认并返回列表</n-button
+                >
+              </div>
+            </div>
+          </div>
+        </div>
+      </n-drawer-content>
+    </n-drawer>
+  </div>
 </template>
 
 <script setup lang="ts">
+import { ref } from 'vue'
 import { useSDK } from '@/sdk'
-import {   onMounted, onUnmounted } from 'vue';
+import { onMounted, onUnmounted } from 'vue'
+import { NRadio, NPopover, useDialog, useMessage } from 'naive-ui'
+import { WalkSharp, TrashOutline, EllipsisHorizontal } from '@vicons/ionicons5'
 const sdk = useSDK()
 
-onMounted(()=>{
-  sdk.Scene.whenLoaded(()=>{
+onMounted(() => {
+  sdk.Scene.whenLoaded(() => {
     sdk.Scene.hideFloorCadImage()
     sdk.WalkManager.edit.enter()
   })
 })
 
-onUnmounted(()=>{
+onUnmounted(() => {
   sdk.Scene.showFloorCadImage()
   sdk.WalkManager.edit.exit()
   sdk.Camera.panorama()
 })
 
+defineProps<{ msg: string }>()
+const dialog = useDialog()
+const message = useMessage()
+const active = ref(true)
+const show = ref(true)
+const doclist = ref([
+  { name: 'test1', checked: false },
+  { name: 'test2', checked: false },
+  { name: 'test3', checked: false },
+  { name: 'test4', checked: false },
+  { name: 'test5', checked: false },
+  { name: 'test6', checked: false },
+  { name: 'test7', checked: false }
+])
+const handleShow = () => {
+  show.value = !show.value
+}
+const handleConfirm = () => {
+  dialog.warning({
+    title: '提示',
+    content: '确认删除此点位?',
+    positiveText: '确定',
+    negativeText: '取消',
+    onPositiveClick: () => {
+      message.success('确定')
+    },
+    onNegativeClick: () => {
+      message.error('不确定')
+    }
+  })
+}
+const handleChange = (item) => {
+  console.log(item, 'handleChange')
+  item.checked = !item.checked
+}
 </script>
 
 <style lang="sass" scoped>