Browse Source

Signed-off-by: caner <5658514@qq.com>

caner 3 years ago
parent
commit
ce2c422c14

+ 0 - 4
.eslintignore

@@ -1,4 +0,0 @@
-# 排除eslint检查文件
-/src/utils
-/dist
-/public

+ 0 - 56
.eslintrc.cjs

@@ -1,56 +0,0 @@
-module.exports = {
-  root: true,
-  env: {
-    node: true,
-    browser: true,
-    es2021: true
-  },
-  parserOptions: {
-    ecmaVersion: "latest",
-    parser: '@typescript-eslint/parser',
-    sourceType: "module"
-  },
-  extends: [
-    'plugin:vue/vue3-recommended',
-    'airbnb-base'
-  ],
-  rules: {
-    'no-console': 0, // 禁用打印
-    'comma-dangle': [2, 'never'], // 禁止使用拖尾逗号
-    'no-extra-semi': 2, // 禁止不必要的分号
-    'array-bracket-spacing': [2, 'always'], // 指定数组的元素之间要以空格隔开
-    'jsx-quotes': 0, // 强制使用单引号
-    'max-len': 0, // 强制一行的最大长度
-    semi: [2, 'never'], // 禁止使用分号
-    'linebreak-style': [0, 'error', 'windows'],
-    'import/no-unresolved': 0,
-    'import/extensions': 0,
-    'import/no-absolute-path': 0,
-    'import/no-extraneous-dependencies': 0,
-    'class-methods-use-this': 0,
-    'no-mixed-operators': 0,
-    'eol-last': 0,
-    'import/newline-after-import': 0,
-    'vue/multi-word-component-names': 0,
-    'no-param-reassign': 0,
-    'no-restricted-syntax': 0,
-    'no-underscore-dangle': 0,
-    'no-plusplus': 0,
-    'no-bitwise': 0,
-    'guard-for-in': 0,
-    'func-names': 0,
-    'import/order': 0,
-    'vue/no-deprecated-slot-attribute': 0,
-    'vue/v-on-event-hyphenation': 0,
-    'vue/no-deprecated-filter': 0,
-    'vue/require-explicit-emits': 0,
-    'vue/no-v-html': 0,
-    'vue/order-in-components': 0,
-    'no-unused-vars': 1,
-    'vue/no-reserved-component-names': 0,
-    'no-promise-executor-return': 0,
-    'no-sparse-arrays': 0,
-    'no-nested-ternary': 0,
-    'no-continue': 0
-  }
-}

+ 0 - 28
.gitignore

@@ -1,28 +0,0 @@
-# Logs
-logs
-*.log
-npm-debug.log*
-yarn-debug.log*
-yarn-error.log*
-pnpm-debug.log*
-lerna-debug.log*
-
-node_modules
-dist
-dist-ssr
-*.local
-
-# Editor directories and files
-.vscode/*
-!.vscode/extensions.json
-.idea
-.DS_Store
-*.suo
-*.ntvs*
-*.njsproj
-*.sln
-*.sw?
-yarn.lock
-dist
-package-lock.json
-dist-ssr

+ 0 - 6
README.md

@@ -1,6 +0,0 @@
-## use
-```
-yarn 
-yarn dev
-
-```

+ 0 - 13
index.html

@@ -1,13 +0,0 @@
-<!DOCTYPE html>
-<html lang="en">
-  <head>
-    <meta charset="UTF-8" />
-    <link rel="icon" href="/favicon.ico" />
-    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
-    <title>home</title>
-  </head>
-  <body>
-    <div id="app"></div>
-    <script type="module" src="/src/main.ts"></script>
-  </body>
-</html>

+ 0 - 29
package.json

@@ -1,29 +0,0 @@
-{
-  "name": "vite-project",
-  "private": true,
-  "version": "0.0.0",
-  "type": "module",
-  "scripts": {
-    "dev": "vite",
-    "build": "vue-tsc --noEmit && vite build",
-    "preview": "vite preview"
-  },
-  "dependencies": {
-    "echarts": "^5.4.0",
-    "vue": "^3.2.37"
-  },
-  "devDependencies": {
-    "@typescript-eslint/parser": "^5.40.0",
-    "@vitejs/plugin-vue": "^3.1.2",
-    "eslint": "^8.25.0",
-    "eslint-config-airbnb-base": "^15.0.0",
-    "eslint-plugin-import": "^2.26.0",
-    "eslint-plugin-vue": "^9.6.0",
-    "less": "^4.1.3",
-    "typescript": "^4.8.4",
-    "vite": "^3.1.8",
-    "vite-plugin-compression": "^0.5.1",
-    "vite-plugin-eslint": "^1.8.0",
-    "vue-tsc": "^1.0.8"
-  }
-}

+ 0 - 424
src/App.vue

@@ -1,424 +0,0 @@
-<template>
-  <div
-    v-if="isLogin"
-    class="box"
-  >
-    <video
-      id="v2"
-      autoplay
-      playsinline
-      muted
-    />
-    <div class="maker">
-      <!-- 信号 -->
-      <Signal :signal="signal" />
-      <!-- 手柄 -->
-      <div class="contrl">
-        &#xe72a;
-      </div>
-      <!-- 音频 -->
-      <div class="audio">
-        &#xe6c1;
-      </div>
-      <!-- 喇叭 -->
-      <div class="arcode">
-        &#xe600;
-      </div>
-      <!-- 电量 -->
-      <Battery :quantity="60" />
-    </div>
-    <div class="gauge">
-      <Gauge
-        :value="gauge.value"
-        :gears="gauge.gears"
-      />
-    </div>
-    <Loading v-if="showLoading" />
-  </div>
-  <Login
-    v-else
-    :err="err"
-    @loginBack="login"
-  />
-</template>
-
-<script setup lang='ts'>
-import {
-  onMounted,
-  onUnmounted, provide, reactive, ref, watch
-} from 'vue'
-import Login from '@/components/login.vue'
-import Loading from '@/components/loading.vue'
-import Gauge from '@/components/gauge.vue'
-import Signal from '@/components/signal.vue'
-import Battery from '@/components/battery.vue'
-
-const isLogin = ref(true)
-const err = ref('')
-const showLoading = ref(false)
-const gauge = reactive({
-  value: 40,
-  gears: 1 // 1低速档 | 2 高速档
-})
-const signal = ref(2)
-const audio = reactive({
-  state: false,
-  muted: false,
-  warn: false,
-  Recorder: null as any,
-  chunks: [] as any
-})
-const webRtc: any = {
-  Peer: null,
-  remoteVideo: null,
-  remoteAudioTrak: null,
-  iceServers: [
-    {
-      urls: [ 'stun:caner.top:3478' ]
-    },
-    {
-      urls: 'turn:caner.top:3478',
-      username: 'admin',
-      credential: '123456'
-    }
-  ]
-}
-const conctrl = {
-  state: false,
-  gear: 1,
-  conNumber: 0
-}
-const HOST = 'ws://127.0.0.1:49800'
-let socket = null as any
-const sleep = (ms: number) => new Promise((res) => setTimeout(res, ms))
-let num = 0
-
-// 挡位
-const Gear = (gear: number, speed: number) => {
-  // 低速档
-  if (gear === 1) {
-    if (speed < 116) {
-      // 前
-      speed = 120
-    } else if (speed >= 120 && speed <= 131) {
-      speed = 128
-    } else if (speed > 140) {
-      // 后
-      speed = 140
-    }
-  }
-  // 高速档
-  if (gear === 2) {
-    if (speed < 96) {
-      speed = 96
-    } else if (speed >= 120 && speed <= 131) {
-      speed = 128
-    } else if (speed > 160) {
-      speed = 160
-    }
-  }
-  return speed
-}
-
-// 手柄数据
-const ControlData = () => {
-  const data = navigator.getGamepads()
-  const db = data[0]
-  if (!db) return
-  // 挡位选择AB
-  if (db.buttons[1].touched) conctrl.gear = 2
-  if (db.buttons[0].touched) conctrl.gear = 1
-  // 语音按键R2
-  audio.state = db.buttons[7].touched
-  // 静音X3
-  audio.muted = db.buttons[3].touched
-  // 播放警笛Y2
-  audio.warn = db.buttons[2].touched
-  // console.log(db.buttons);
-  const params = {
-    v0: Math.floor(db.axes[0] * 128 + 128),
-    v1: Math.floor(db.axes[1] * 128 + 128),
-    v2: Math.floor(db.axes[2] * 128 + 128),
-    v3: Gear(conctrl.gear, Math.floor(db.axes[3] * 128 + 128))
-  }
-
-  if (socket) socket.send({ type: 'conctrl', conctrl: params })
-  conctrl.conNumber = requestAnimationFrame(ControlData)
-}
-
-// 手柄连接
-const conControl = () => {
-  conctrl.state = true
-  ControlData()
-}
-
-// 手柄断开连接
-const disControl = () => {
-  conctrl.state = false
-  cancelAnimationFrame(conctrl.conNumber)
-}
-
-// 关闭
-const close = (error: string) => {
-  if (webRtc.Peer) webRtc.Peer.close()
-  if (webRtc.remoteVideo) webRtc.remoteVideo.srcObject = null
-  socket.close()
-  isLogin.value = false
-  showLoading.value = false
-  err.value = error || ''
-  socket = null
-  webRtc.Peer = null
-  window.removeEventListener('gamepadconnected', conControl)
-  window.removeEventListener('gamepaddisconnected', disControl)
-}
-
-// socket连接
-const onOpen = () => {
-  console.log('连接成功!')
-  try {
-    isLogin.value = true
-    // init webrtc
-    webRtc.Peer = new RTCPeerConnection({
-      iceServers: webRtc.iceServers,
-      bundlePolicy: 'max-bundle'
-    })
-
-    // listen state
-    webRtc.Peer.onicegatheringstatechange = () => {
-      console.log('GatheringState: ', webRtc.Peer.iceGatheringState)
-      if (webRtc.Peer.iceGatheringState === 'complete') {
-        const answer = webRtc.Peer.localDescription
-        socket.send(answer)
-      }
-    }
-    // listen track
-    webRtc.Peer.ontrack = async (evt: any) => {
-      console.log('track', evt)
-      webRtc.remoteVideo = document.getElementById('v2')
-      webRtc.remoteVideo.srcObject = { ...evt.streams[0] }
-      if (evt.track.kind === 'audio') webRtc.remoteAudioTrak = { ...evt.streams[0] }
-    }
-    // listen changestate
-    webRtc.Peer.oniceconnectionstatechange = async () => {
-      const state = webRtc.Peer.iceConnectionState
-      console.log('ICE状态', state)
-      if (
-        state === 'failed'
-        || state === 'disconnected'
-        || state === 'closed'
-      ) {
-        close('P2P通信失败')
-      }
-
-      // ICE连接成功|初始化摇杆
-      if (state === 'connected') {
-        // init Control
-        window.addEventListener('gamepadconnected', conControl)
-        window.addEventListener('gamepaddisconnected', disControl)
-        await sleep(3000)
-        showLoading.value = false
-      }
-    }
-  } catch (error) {
-    socket.close()
-    isLogin.value = false
-    err.value = 'webrtc初始化错误'
-  }
-}
-
-// socket信息
-const onMsg = (event: { data: string }) => {
-  console.log(`收到消息啦:${event.data}`)
-}
-
-// socket 连接错误
-const onErr = async () => {
-  isLogin.value = false
-  err.value = '连接错误!'
-  await sleep(3000)
-  if (!socket.userInfo) return
-  err.value = '重连中...'
-  const { roomID, name } = socket.userInfo
-  socket = new WebSocket(`${HOST}/${roomID}/${name}`)
-  socket.onmessage = onMsg
-  socket.onopen = onOpen
-  socket.userInfo = { roomID, name }
-}
-
-// 登录
-const login = (params: { name: string; roomID: string }) => {
-  err.value = '连接中...'
-  if (socket) { socket.close(); socket = null; return }
-  socket = new WebSocket(`${HOST}/${params.roomID}/${params.name}`)
-  socket.onmessage = onMsg
-  socket.onopen = onOpen
-  socket.onerror = onErr
-  socket.userInfo = params
-}
-
-// 发送音频
-const sendAudio = (blob: Blob) => {
-  console.log('发送', blob)
-  if (!socket && !socket.connected) return
-  socket.send({
-    type: 'Meadia',
-    Meadia: blob
-  })
-}
-
-// 初始化声音
-const initRecorder = async () => {
-  try {
-    const stream = await navigator.mediaDevices.getUserMedia({
-      audio: true
-    })
-    audio.Recorder = new MediaRecorder(stream)
-
-    // 事件监听
-    audio.Recorder.ondataavailable = (e: { data: any }) => {
-      audio.chunks.push(e.data)
-    }
-    audio.Recorder.onstart = () => {
-      audio.chunks = []
-    }
-    audio.Recorder.onstop = () => {
-      const blob = new Blob(audio.chunks, {
-        type: 'audio/webm;codecs=opus'
-      })
-      sendAudio(blob)
-    }
-  } catch (error) {
-    err.value = '不支持webrtc音频'
-  }
-}
-
-provide('err', err)
-
-// 静音
-watch(() => audio.muted, (v) => {
-  if (v) {
-    num++
-    const state = !(num % 2)
-    audio.state = state
-    if (socket && socket.connected) socket.send(JSON.stringify({ type: 'contrlAudio', contrlAudio: state }))
-  }
-})
-
-// 鸣笛
-watch(() => audio.warn, (v) => {
-  if (v && socket && socket.connected) socket.send(JSON.stringify({ type: 'warnAudio', warnAudio: v }))
-})
-
-// 发送音频
-watch(() => audio.state, (v) => {
-  if (!audio.Recorder) return
-  if (v) {
-    audio.Recorder.start()
-  } else {
-    audio.Recorder.stop()
-  }
-})
-
-onMounted(() => {
-  initRecorder()
-})
-
-onUnmounted(() => {
-  if (socket) socket.close()
-  if (audio.Recorder) audio.Recorder = null
-  audio.chunks = []
-  socket = null
-})
-</script>
-<style lang="less" scoped>
-.box {
-  video {
-    width: 100%;
-    height: 100%;
-    background: none;
-    object-fit: fill;
-    font-size: 0;
-  }
-
-  .maker {
-    position: fixed;
-    top: 0;
-    left: 50%;
-    width: 555px;
-    height: 30px;
-    transform: translate(-50%, 0);
-    z-index: 1;
-    display: flex;
-    align-items: center;
-    justify-content: center;
-
-    &::before {
-      position: absolute;
-      z-index: 0;
-      content: "";
-      width: 100%;
-      height: 0;
-      border-top: 30px solid rgba(0, 0, 0, 0.25);
-      border-left: 15px solid transparent;
-      border-right: 15px solid transparent;
-    }
-
-    &>div {
-      margin: 0 3px;
-    }
-
-    .audio,
-    .arcode {
-      font-size: 24px;
-      color: rgba(0, 0, 0, 0.3);
-    }
-
-    .contrl {
-      font-size: 32px;
-      color: rgba(0, 0, 0, 0.3);
-    }
-  }
-
-  .gauge {
-    position: fixed;
-    bottom: 0;
-    left: 50%;
-    transform: translate(-50%, 0);
-    width: 500px;
-    height: 185px;
-    z-index: 9;
-  }
-}
-</style>
-<style>
-html,
-body,
-#app {
-  margin: 0;
-  padding: 0;
-  width: 100%;
-  height: 100%;
-  user-select: none;
-  min-width: 1000px;
-  min-height: 900px;
-  /* background: black; */
-}
-
-#app {
-  font-family: "fonts";
-  font-style: normal;
-}
-
-/* 隐藏滚动条 */
-::-webkit-scrollbar {
-  width: 0 !important;
-  display: none;
-}
-
-@font-face {
-  font-family: "fonts";
-  src: url("./assets/iconfont.woff2") format("woff2"),
-    url("./assets/iconfont.woff") format("woff"),
-    url("./assets/iconfont.ttf") format("truetype");
-}
-</style>

BIN
src/assets/iconfont.ttf


BIN
src/assets/iconfont.woff


BIN
src/assets/iconfont.woff2


+ 0 - 109
src/components/battery.vue

@@ -1,109 +0,0 @@
-<template>
-  <div
-    class="electric-panel"
-    :class="bgClass"
-  >
-    <div class="panel">
-      <div
-        class="remainder"
-        :style="{ width: quantity + '%' }"
-      />
-    </div>
-    <div class="berText">
-      50%
-    </div>
-  </div>
-</template>
-
-<script lang="ts" setup>
-import { computed } from 'vue'
-
-const props = defineProps<{
-  quantity:number
-}>()
-const bgClass = computed(() => {
-  if (props.quantity >= 50) {
-    return 'success'
-  } if (props.quantity >= 20) {
-    return 'warning'
-  } if (props.quantity >= 1) {
-    return 'danger'
-  }
-  return 'danger'
-})
-</script>
-
-<style scoped>
-.electric-panel {
-  display: flex;
-  justify-content: center;
-  align-items: center;
-  position: relative;
-  z-index: 3;
-  color: white;
-}
-
-.panel {
-  box-sizing: border-box;
-  width: 22px;
-  height: 14px;
-  position: relative;
-  border: 2px solid #ccc;
-  padding: 1px;
-  border-radius: 3px;
-  margin-right: 5px;
-  transform: rotate(-90deg);
-}
-
-.panel::before {
-  content: "";
-  border-radius: 0 1px 1px 0;
-  height: 6px;
-  background: #ccc;
-  width: 3px;
-  position: absolute;
-  top: 50%;
-  right: -4px;
-  transform: translateY(-50%);
-}
-
-.panel .remainder {
-  border-radius: 1px;
-  position: relative;
-  height: 100%;
-  width: 0%;
-  left: 0;
-  top: 0;
-  background: #fff;
-}
-
-.success .panel {
-  border-color: #40d7c1;
-}
-.success .panel:before {
-  background: #40d7c1;
-}
-.success .remainder {
-  background: #40d7c1;
-}
-
-.warning .panel {
-  border-color: #f90;
-}
-.warning .panel:before {
-  background: #f90;
-}
-.warning .remainder {
-  background: #f90;
-}
-
-.danger .panel {
-  border-color: #ed4014;
-}
-.danger .panel:before {
-  background: #ed4014;
-}
-.danger .remainder {
-  background: #ed4014;
-}
-</style>

+ 0 - 104
src/components/gauge.vue

@@ -1,104 +0,0 @@
-<template>
-  <div id="charts" />
-</template>
-<script lang="ts" setup>
-import * as echarts from 'echarts'
-import { nextTick, onBeforeUnmount, watch } from 'vue'
-
-const props = defineProps<{
-  gears: number,
-  value: number
-}>()
-
-let chart = null as any
-const option = {
-  series: {
-    name: 'Pressure',
-    type: 'gauge',
-    itemStyle: {
-      color: '#FFFFFF'
-    },
-    startAngle: 180,
-    max: 60,
-    endAngle: 0,
-    axisLine: {
-      lineStyle: {
-        width: 1
-      }
-    },
-    axisTick: {
-      distance: 0,
-      length: 10,
-      lineStyle: {
-        color: '#FFFFFF'
-      }
-    },
-    splitLine: {
-      length: 15,
-      distance: 0,
-      lineStyle: {
-        color: '#FFFFFF'
-      }
-    },
-    axisLabel: {
-      distance: 8,
-      color: '#FFFFFF'
-    },
-    progress: {
-      show: true
-    },
-    radius: '160%',
-    center: [ '50%', '90%' ],
-    detail: {
-      offsetCenter: [ 0, -25 ],
-      valueAnimation: true,
-      formatter: (v:number) => `{value|${v.toFixed(0)}}{unit|km/h}\n{num|${props.gears}}`,
-      rich: {
-        value: {
-          fontSize: 20,
-          fontWeight: 'bolder',
-          color: '#FFFFFF'
-        },
-        unit: {
-          fontSize: 20,
-          color: '#FFFFFF',
-          padding: [ 0, 0, 0, 10 ]
-        },
-        num: {
-          fontSize: 20,
-          color: '#FFFFFF',
-          padding: [ 0, 0, 0, 10 ]
-        }
-      }
-    },
-    pointer: {
-      show: false
-    },
-    data: [ props.value ]
-  }
-}
-
-nextTick(() => {
-  const dom = document.getElementById('charts') as HTMLElement
-  chart = echarts.init(dom)
-  chart.setOption(option)
-})
-
-watch(props, (v) => {
-  if (!chart) return
-  option.series.data[0] = v.value
-  chart.setOption(option)
-}, { deep: true })
-
-onBeforeUnmount(() => {
-  if (!chart) return
-  chart.dispose()
-  chart = null
-})
-</script>
-<style scoped>
-#charts {
-  width: 500px;
-  height: 200px;
-}
-</style>

+ 0 - 134
src/components/loading.vue

@@ -1,134 +0,0 @@
-<template>
-  <div class="loading">
-    <figure>
-      <div class="dot white" />
-      <div class="dot" />
-      <div class="dot" />
-      <div class="dot" />
-      <div class="dot" />
-    </figure>
-  </div>
-</template>
-
-<style scoped>
-.loading{
-    position: fixed;
-    width: 100%;
-    height: 100%;
-    top: 0;
-    left: 0;
-    z-index: 9;
-    background: rgba(0, 0, 0, 0.7);
-    font-size: 12px;
-}
-figure {
-  position: absolute;
-  margin: auto;
-  top: 0;
-  bottom: 0;
-  left: 0;
-  right: 0;
-  width: 6.25em;
-  height: 6.25em;
-  animation: rotate 2.4s linear infinite;
-}
-.white {
-  top: 0;
-  bottom: 0;
-  left: 0;
-  right: 0;
-  background: white;
-  animation: flash 2.4s linear infinite;
-  opacity: 0;
-}
-.dot {
-  position: absolute;
-  margin: auto;
-  width: 2.4em;
-  height: 2.4em;
-  border-radius: 100%;
-  transition: all 1s ease;
-}
-.dot:nth-child(2) {
-  top: 0;
-  bottom: 0;
-  left: 0;
-  background: #ff4444;
-  animation: dotsY 2.4s linear infinite;
-}
-.dot:nth-child(3) {
-  left: 0;
-  right: 0;
-  top: 0;
-  background: #ffbb33;
-  animation: dotsX 2.4s linear infinite;
-}
-.dot:nth-child(4) {
-  top: 0;
-  bottom: 0;
-  right: 0;
-  background: #99cc00;
-  animation: dotsY 2.4s linear infinite;
-}
-.dot:nth-child(5) {
-  left: 0;
-  right: 0;
-  bottom: 0;
-  background: #33b5e5;
-  animation: dotsX 2.4s linear infinite;
-}
-
-@keyframes rotate {
-  0% {
-    transform: rotate(0);
-  }
-  10% {
-    width: 6.25em;
-    height: 6.25em;
-  }
-  66% {
-    width: 2.4em;
-    height: 2.4em;
-  }
-  100% {
-    transform: rotate(360deg);
-    width: 6.25em;
-    height: 6.25em;
-  }
-}
-
-@keyframes dotsY {
-  66% {
-    opacity: 0.1;
-    width: 2.4em;
-  }
-  77% {
-    opacity: 1;
-    width: 0;
-  }
-}
-@keyframes dotsX {
-  66% {
-    opacity: 0.1;
-    height: 2.4em;
-  }
-  77% {
-    opacity: 1;
-    height: 0;
-  }
-}
-
-@keyframes flash {
-  33% {
-    opacity: 0;
-    border-radius: 0%;
-  }
-  55% {
-    opacity: 0.6;
-    border-radius: 100%;
-  }
-  66% {
-    opacity: 0;
-  }
-}
-</style>

+ 0 - 107
src/components/login.vue

@@ -1,107 +0,0 @@
-<template>
-  <div class="login">
-    <div>
-      <div class="logo">
-        Lgoin
-      </div>
-      <input
-        v-model="ID"
-        type="text"
-        placeholder="房间"
-        maxlength="20"
-      >
-      <input
-        v-model="name"
-        type="text"
-        placeholder="昵称"
-        maxlength="20"
-      >
-      <div class="err">
-        {{ err || error }}
-      </div>
-      <button @click="verification">
-        加入
-      </button>
-    </div>
-  </div>
-</template>
-<script setup lang='ts'>
-import { inject, ref } from 'vue'
-const err = inject('err')
-const ID = ref('')
-const name = ref('')
-const error = ref()
-const callBack = defineEmits([ 'loginBack' ])
-
-const verification = () => {
-  if (!ID.value) {
-    error.value = '请输入房间号'
-  } else if (!name.value) {
-    error.value = '请输入昵称'
-  } else {
-    callBack('loginBack', { name: name.value, roomID: ID.value })
-  }
-}
-</script>
-<style scoped lang="less">
-.login {
-  width: 100%;
-  height: 100%;
-  font-size: 16px;
-  display: flex;
-  justify-content: center;
-  align-items: center;
-
-  .logo {
-    width: 100px;
-    height: 50px;
-    margin: 0 auto;
-    text-align: center;
-  }
-
-  input {
-    display: block;
-    border: 0;
-    border-bottom: solid 1px #ccc;
-    text-indent: 10px;
-    margin: 0 auto;
-    margin-bottom: 20px;
-    outline: none;
-    border-radius: 0;
-    background: none;
-  }
-
-  button {
-    display: block;
-    width: 130px;
-    height: 30px;
-    background: #79b8fa;
-    border: none;
-    color: white;
-    font-size: 17px;
-    font-weight: 500;
-    border-radius: 5px;
-    cursor: pointer;
-    margin: 0 auto;
-    margin-top: 20px;
-    line-height: 30px;
-  }
-
-  button:hover {
-    background: #2d8cf0;
-  }
-
-  .err {
-    width: 175px;
-    margin: 0 auto;
-    font-size: 12px;
-    color: red;
-    text-align: left;
-    text-indent: 10px;
-  }
-
-  input:nth-child(3) {
-    margin-bottom: 5px;
-  }
-}
-</style>

+ 0 - 128
src/components/signal.vue

@@ -1,128 +0,0 @@
-<template>
-  <div class="signal-box">
-    <ul>
-      <li
-        v-for="(item, idex) in list"
-        :key="idex"
-        :class="item.class"
-      />
-    </ul>
-  </div>
-</template>
-
-<script lang="ts" setup>import { reactive, watch } from 'vue'
-
-const props = defineProps<{
-  signal: number
-}>()
-const list: Array<{ class: string; id: number }> = reactive([
-  {
-    id: 1,
-    class: 'signal-default'
-  },
-  {
-    id: 2,
-    class: 'signal-default'
-  },
-  {
-    id: 3,
-    class: 'signal-default'
-  },
-  {
-    id: 4,
-    class: 'signal-default'
-  },
-  {
-    id: 5,
-    class: 'signal-default'
-  }
-])
-watch(props, (v) => {
-  for (let j = 0; j < list.length; j++) {
-    const el = list[j]
-    if (el.id <= v.signal) {
-      if (v.signal === 1 || v.signal === 2) {
-        el.class = 'signal-red'
-      } else if (v.signal === 3 || v.signal === 4) {
-        el.class = 'signal-yellow'
-      } else if (v.signal === 5) {
-        el.class = 'signal-green'
-      } else {
-        el.class = 'signal-default'
-      }
-    } else {
-      el.class = 'signal-default'
-    }
-  }
-}, { deep: true, immediate: true })
-</script>
-
-<style scoped>
-.signal-box {
-  display: flex;
-  align-items: flex-start;
-  justify-content: center;
-  height: 23px;
-  width: 23px;
-  position: relative;
-  z-index: 3;
-}
-
-span {
-  font-size: 15px;
-  color: white;
-  margin-left: 3px;
-}
-
-ul {
-  height: 21px;
-  margin: 0;
-  padding: 0;
-  display: flex;
-  align-items: flex-end;
-}
-
-li {
-  width: 4px;
-  height: 5px;
-  border-radius: 10px;
-  list-style: none;
-  margin: 0 0.5px;
-}
-
-ul li:nth-child(1) {
-  height: 5px;
-}
-
-ul li:nth-child(2) {
-  height: 9px;
-}
-
-ul li:nth-child(3) {
-  height: 13px;
-}
-
-ul li:nth-child(4) {
-  height: 17px;
-}
-
-ul li:nth-child(5) {
-  height: 21px;
-}
-
-.signal-default {
-  background: rgba(0, 0, 0, 0.3);
-}
-
-.signal-red {
-  background-color: red;
-}
-
-.signal-yellow {
-  background-color: #e7d055;
-}
-
-.signal-green {
-  background-color: #32cd32;
-}
-</style>

+ 0 - 3
src/main.ts

@@ -1,3 +0,0 @@
-import { createApp } from 'vue'
-import App from './App.vue'
-createApp(App).mount('#app')

+ 0 - 398
src/test.vue

@@ -1,398 +0,0 @@
-<template>
-  <div id="app">
-    <template v-if="isLogin">
-      <video id="v2" autoplay playsinline muted></video>
-      <div class="marke">
-        <!-- 信号 -->
-        <Signal :signalValue="signalValue" />
-        <!-- 手柄状态 -->
-        <svg viewBox="0 -50 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" width="30" height="30">
-          <path
-            d="M817.68 803.17a130.23 130.23 0 0 1-125.6-96.37l-14-52.19a54.08 54.08 0 0 0-52.16-40H398.07a54.08 54.08 0 0 0-52.16 40l-14 52.19c-15.54 58-68.21 96.37-125.6 96.37A130 130 0 0 1 80.78 639.51l66.72-249a181.66 181.66 0 0 1 63.19-97.15A177.79 177.79 0 0 1 322 254.58h380a177.79 177.79 0 0 1 111.31 38.79 181.66 181.66 0 0 1 63.19 97.15l66.72 249a130 130 0 0 1-125.54 163.65zM322 274.58A160 160 0 0 0 166.87 395.5v0.13l-66.73 249a110 110 0 0 0 212.5 56.94l14-52.19a74.11 74.11 0 0 1 71.48-54.85h227.81a74.11 74.11 0 0 1 71.48 54.85l14 52.19a110 110 0 0 0 212.5-56.94L857.13 395.5A160 160 0 0 0 702 274.58z"
-            :fill="contrlState ? '#00CED1' : 'rgba(0, 0, 0, 0.3)'"></path>
-          <path
-            d="M580 213.86a12 12 0 0 1 12 12v28H432v-28a12 12 0 0 1 12-12h136m0-20H444a32 32 0 0 0-32 32v48h200v-48a32 32 0 0 0-32-32z"
-            :fill="contrlState ? '#00CED1' : 'rgba(0, 0, 0, 0.3)'"></path>
-          <path
-            d="M512 213.86a10 10 0 0 1-10-10v-63a60.07 60.07 0 0 1 60-60 10 10 0 0 1 0 20 40 40 0 0 0-40 40v63a10 10 0 0 1-10 10zM330 344.86a90 90 0 1 1-90 90 90.1 90.1 0 0 1 90-90m0-20a110 110 0 1 0 110 110 110 110 0 0 0-110-110z"
-            :fill="contrlState ? '#00CED1' : 'rgba(0, 0, 0, 0.3)'"></path>
-          <path
-            d="M330 384.86a50 50 0 1 1-50 50 50.06 50.06 0 0 1 50-50m0-20a70 70 0 1 0 70 70 70 70 0 0 0-70-70zM697 344.86a14 14 0 1 1-14 14 14 14 0 0 1 14-14m0-20a34 34 0 1 0 34 34 34 34 0 0 0-34-34zM697 496.86a14 14 0 1 1-14 14 14 14 0 0 1 14-14m0-20a34 34 0 1 0 34 34 34 34 0 0 0-34-34zM773 420.86a14 14 0 1 1-14 14 14 14 0 0 1 14-14m0-20a34 34 0 1 0 34 34 34 34 0 0 0-34-34zM621 420.86a14 14 0 1 1-14 14 14 14 0 0 1 14-14m0-20a34 34 0 1 0 34 34 34 34 0 0 0-34-34z"
-            :fill="contrlState ? '#00CED1' : 'rgba(0, 0, 0, 0.3)'"></path>
-        </svg>
-        <!-- 音频 -->
-        <Record @callBack="sendAudio" :audioState="audioState" />
-        <!-- 喇叭 -->
-        <svg viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" width="30" height="30">
-          <path :fill="muted ? '#00CED1' : 'rgba(0, 0, 0, 0.3)'"
-            d="M393.707231 292.571429L343.13933 487.619048l46.955908 234.779541-97.523809-45.149912-66.82187-108.359788-21.671958-86.687831 66.82187-113.777778z">
-          </path>
-          <path :fill="muted ? '#00CED1' : 'rgba(0, 0, 0, 0.3)'"
-            d="M451.499118 509.291005a104.747795 61.40388 90 1 0 122.80776 0 104.747795 61.40388 90 1 0-122.80776 0Z">
-          </path>
-          <path :fill="muted ? '#00CED1' : 'rgba(0, 0, 0, 0.3)'"
-            d="M426.215168 781.996473c-3.611993 0-7.223986-1.805996-10.835979-3.611993l-117.389771-86.687831c-36.119929-23.477954-65.015873-57.791887-83.075838-99.329806-10.835979-25.283951-16.253968-52.373898-16.253968-81.269841s5.417989-55.985891 16.253968-81.269842c16.253968-41.537919 45.149912-74.045855 83.075838-97.523809l110.165785-77.657848c9.029982-5.417989 19.865961-3.611993 25.28395 3.611993 5.417989 9.029982 3.611993 19.865961-3.611993 25.28395L319.661376 361.199295c-32.507937 19.865961-55.985891 48.761905-70.433863 81.269841-9.029982 21.671958-14.447972 45.149912-14.447972 68.627866 0 23.477954 3.611993 45.149912 12.641976 66.821869 14.447972 34.313933 37.925926 63.209877 68.627866 83.075838l117.38977 86.687831c7.223986 5.417989 9.029982 18.059965 3.611993 25.28395 0 5.417989-5.417989 9.029982-10.835978 9.029983z">
-          </path>
-          <path :fill="muted ? '#00CED1' : 'rgba(0, 0, 0, 0.3)'"
-            d="M523.738977 830.758377c-108.359788 0-193.241623-140.867725-193.241623-317.855379S415.379189 193.241623 523.738977 193.241623c25.283951 0 50.567901 7.223986 74.045855 23.477954 9.029982 5.417989 10.835979 16.253968 5.41799 25.28395s-16.253968 10.835979-25.283951 5.41799c-18.059965-10.835979-34.313933-18.059965-54.179894-18.059965-84.881834 0-157.121693 130.031746-157.121693 281.73545S438.857143 794.638448 523.738977 794.638448s157.121693-130.031746 157.121693-281.73545c0-74.045855-16.253968-146.285714-46.955908-198.659612-5.417989-9.029982-1.805996-19.865961 7.223986-25.28395 9.029982-5.417989 19.865961-1.805996 25.28395 7.223986 32.507937 59.597884 50.567901 135.449735 50.567902 216.719576C718.786596 689.890653 633.904762 830.758377 523.738977 830.758377z">
-          </path>
-          <path :fill="muted ? '#00CED1' : 'rgba(0, 0, 0, 0.3)'"
-            d="M523.738977 646.546737c-48.761905 0-86.687831-59.597884-86.687831-133.643739S474.977072 379.259259 523.738977 379.259259s86.687831 59.597884 86.687831 133.643739-37.925926 133.643739-86.687831 133.643739z m0-232.973545c-23.477954 0-50.567901 39.731922-50.567901 97.52381s27.089947 97.52381 50.567901 97.523809 50.567901-39.731922 50.567901-97.523809-27.089947-97.52381-50.567901-97.52381z">
-          </path>
-          <path :fill="muted ? '#00CED1' : 'rgba(0, 0, 0, 0.3)'"
-            d="M523.738977 413.573192h-1.805996l-92.105821-10.835979c-9.029982-1.805996-16.253968-10.835979-16.253968-19.865961 1.805996-9.029982 10.835979-16.253968 19.865961-16.253968l92.105821 10.835979c9.029982 1.805996 16.253968 10.835979 16.253968 19.865961 0 9.029982-9.029982 16.253968-18.059965 16.253968zM372.035273 662.800705c-9.029982 0-16.253968-7.223986-18.059964-16.253968-1.805996-9.029982 5.417989-18.059965 16.253968-19.865961l153.5097-16.253968c9.029982-1.805996 18.059965 5.417989 19.865961 16.253968 1.805996 9.029982-5.417989 18.059965-16.253968 19.865961l-153.5097 16.253968h-1.805997z">
-          </path>
-          <path :fill="muted ? '#00CED1' : 'rgba(0, 0, 0, 0.3)'"
-            d="M763.936508 364.811287c-5.417989 0-9.029982-1.805996-12.641975-5.417989-7.223986-7.223986-7.223986-18.059965 0-25.283951l25.28395-25.28395c7.223986-7.223986 18.059965-7.223986 25.283951 0s7.223986 18.059965 0 25.28395L776.578483 359.393298c-3.611993 3.611993-9.029982 5.417989-12.641975 5.417989zM771.160494 720.592593c-5.417989 0-9.029982-1.805996-12.641975-5.41799l-25.283951-25.28395c-7.223986-7.223986-7.223986-18.059965 0-25.283951s18.059965-7.223986 25.283951 0l25.28395 25.283951c7.223986 7.223986 7.223986 18.059965 0 25.28395-3.611993 3.611993-7.223986 5.417989-12.641975 5.41799zM819.922399 529.156966h-54.179895c-10.835979 0-18.059965-7.223986-18.059964-18.059964s7.223986-18.059965 18.059964-18.059965h54.179895c10.835979 0 18.059965 7.223986 18.059964 18.059965s-9.029982 18.059965-18.059964 18.059964z">
-          </path>
-        </svg>
-        <!-- 电量 -->
-        <Battery :quantity="60" />
-      </div>
-      <!-- 码数 -->
-      <div class="gauge">
-        <Gauge :value="SpeedValue" :gears="speed" />
-      </div>
-      <Loading v-if="showLoading" />
-    </template>
-    <Login v-else :err="error" @loginBack="login" />
-  </div>
-</template>
-
-<script>
-const { io } = require("socket.io-client");
-import Login from "@/components/login";
-import Loading from "@/components/loading";
-import Record from "@/components/record";
-import Signal from "@/components/signal";
-import Battery from "@/components/battery";
-import Gauge from "@/components/gauge";
-import { Message } from "view-design";
-
-const sleep = (ms) => new Promise((res) => setTimeout(res, ms));
-export default {
-  components: { Login, Loading, Record, Signal, Battery, Gauge },
-  data() {
-    return {
-      socket: null,
-      // HOST: "wss://car.caner.top",
-      HOST:'ws://127.0.0.1:10086',
-      Peer: null,
-      isLogin: false,
-      error: "",
-      remoteVideo: null,
-      showLoading: true,
-      contrlState: false,
-      audioState: false,
-      mutedState: true,
-      warnAudio: false,// 鸣笛
-      speed: 1, //1低速档 | 2 高速档
-      muted: true,// 是否静音
-      signalValue: 0,
-      SpeedValue: 0,
-      iceServers: [
-        {
-          urls: ["stun:caner.top:3478"],
-        },
-        {
-          urls: "turn:caner.top:3478",
-          username: "admin",
-          credential: "123456",
-        },
-      ],
-      num: 0
-    };
-  },
-  methods: {
-    // 网络连接
-    intSoketRtc(host) {
-      // int socket
-      this.socket = io(host, {
-        autoConnect: false,
-        transports: ["websocket"],
-      });
-
-      // socket
-      this.socket.on("connect", () => {
-        try {
-          this.isLogin = true;
-          // init webrtc
-          this.Peer = new RTCPeerConnection({
-            iceServers: this.iceServers,
-            bundlePolicy: "max-bundle",
-          });
-
-          // listen state
-          this.Peer.onicegatheringstatechange = () => {
-            console.log("GatheringState: ", this.Peer.iceGatheringState);
-            if (this.Peer.iceGatheringState === "complete") {
-              const answer = this.Peer.localDescription;
-              this.socket.emit("msg", answer);
-            }
-          };
-
-          // listen track
-          this.Peer.ontrack = async (evt) => {
-            console.log("track", evt);
-            this.remoteVideo = document.getElementById("v2");
-            this.remoteVideo.srcObject = evt.streams[0];
-            if (evt.track.kind === 'audio') this.remoteAudioTrak = evt.streams[0]
-          };
-
-          // listen changestate
-          this.Peer.oniceconnectionstatechange = async () => {
-            const state = this.Peer.iceConnectionState;
-            console.log("ICE状态", state);
-            if (
-              state === "failed" ||
-              state === "disconnected" ||
-              state === "closed"
-            ) {
-              this.close("P2P通信失败");
-            }
-
-            // ICE连接成功|初始化摇杆
-            if (state === "connected") {
-              // init Control
-              window.addEventListener("gamepadconnected", this.conControl);
-              window.addEventListener("gamepaddisconnected", this.disControl);
-              await sleep(3000);
-              this.showLoading = false;
-            }
-          };
-        } catch (error) {
-          this.socket.disconnect();
-          this.isLogin = false;
-          Message.error({
-            content: "webrtc初始化错误" + error,
-            duration: 3,
-          });
-        }
-      });
-
-      this.socket.on("msg", async (data) => {
-        if (data.type === "offer") {
-          console.log(data.sdp);
-          await this.Peer.setRemoteDescription(data);
-          const answer = await this.Peer.createAnswer();
-          await this.Peer.setLocalDescription(answer);
-        } else if (data.type === "power") {
-          console.log("电量", data);
-        } else if (data.type === "signal") {
-          const v = data.data <= 20 ? Math.floor(data.data / 4) : 5
-          this.signalValue = v || 1
-        } else if (data.type === 'speed') {
-          const v = Math.floor(data.data)
-          this.SpeedValue = v
-        }
-      });
-
-      this.socket.on("joined", async () =>
-        this.socket.emit("msg", { type: "startRTC" })
-      );
-      this.socket.on("leaved", () => this.close("车端断开"));
-      this.socket.on("connect_error", (err) => this.close(err));
-    },
-
-    // 手柄数据
-    ControlData() {
-      const data = navigator.getGamepads();
-      const db = data[0];
-      if (!db) return;
-      // 挡位选择AB
-      if (db.buttons[1].touched) this.speed = 2;
-      if (db.buttons[0].touched) this.speed = 1;
-      // 语音按键R2
-      this.audioState = db.buttons[7].touched
-      // 静音X3
-      this.mutedState = db.buttons[3].touched
-      // 播放警笛Y2
-      this.warnAudio = db.buttons[2].touched
-      // console.log(db.buttons);
-      const params = {
-        v0: Math.floor(db.axes[0] * 128 + 128),
-        v1: Math.floor(db.axes[1] * 128 + 128),
-        v2: Math.floor(db.axes[2] * 128 + 128),
-        v3: this.Gear(this.speed, Math.floor(db.axes[3] * 128 + 128)),
-      };
-
-      if (this.socket && this.socket.connected) this.socket.emit("msg", { type: "conctrl", conctrl: params });
-      requestAnimationFrame(this.ControlData);
-    },
-
-    // 发送语音
-    sendAudio(blob) {
-      if (!this.socket && !this.socket.connected) return;
-      this.socket.emit("msg", {
-        type: "Meadia",
-        Meadia: blob,
-      });
-    },
-
-    // 挡位
-    Gear(speed, num) {
-      // 低速档
-      if (speed === 1) {
-        if (num < 116) {
-          // 前
-          num = 120;
-        } else if (num >= 120 && num <= 131) {
-          num = 128;
-        } else if (num > 140) {
-          // 后
-          num = 140;
-        }
-      }
-      // 高速档
-      if (speed === 2) {
-        if (num < 96) {
-          num = 96;
-        } else if (num >= 120 && num <= 131) {
-          num = 128;
-        } else if (num > 160) {
-          num = 160;
-        }
-      }
-      return num;
-    },
-
-    // 登录
-    login(data) {
-      const socket = new WebSocket(this.HOST+`/${data.roomID}/${data.name}`);
-        //连接发生错误的回调方法
-        socket.onerror = (event)=> {
-            console.log("ws连接错误!");
-        };
-
-        //连接成功建立的回调方法
-        socket.onopen = (event)=> {
-          console.log("连接成功!");
-          socket.send('test')
-        }
-
-        //接收到消息的回调方法
-        socket.onmessage = (event)=> {
-            console.log("收到消息啦:" +event.data);
-        }
-
-        //连接关闭的回调方法
-        socket.onclose = ()=> {
-            console.log("连接关闭!");
-        }      
-      // console.log(666,socket);
-    },
-
-    // 关闭
-    close(err) {
-      if (this.Peer) this.Peer.close();
-      if (this.remoteVideo) this.remoteVideo.srcObject = null;
-      this.socket.disconnect();
-      this.isLogin = false;
-      this.showLoading = false;
-      this.error = err || "";
-      this.socket = null;
-      this.Peer = null
-      this.num = 0
-      cancelAnimationFrame(this.ControlData);
-      window.removeEventListener("gamepadconnected", this.conControl);
-      window.removeEventListener("gamepaddisconnected", this.disControl);
-    },
-
-    // 手柄连接
-    conControl() {
-      this.contrlState = true;
-      this.ControlData();
-    },
-
-    // 手柄断开连接
-    disControl() {
-      this.contrlState = false;
-      cancelAnimationFrame(this.ControlData);
-    },
-  },
-  mounted() {
-    this.intSoketRtc(this.HOST);
-  },
-  watch: {
-    // 静音
-    mutedState(v) {
-      if (v) {
-        this.num++
-        const state = this.num % 2 ? false : true
-        this.muted = state
-        if (this.socket && this.socket.connected) this.socket.emit("msg", { type: "contrlAudio", contrlAudio: state });
-      }
-    },
-    // 鸣笛
-    warnAudio(v) {
-      if (v && this.socket && this.socket.connected) this.socket.emit("msg", { type: "warnAudio", warnAudio: v });
-    }
-  }
-};
-</script>
-
-<style>
-video,
-#app,
-html,
-body {
-  margin: 0;
-  padding: 0;
-  user-select: none;
-  width: 100%;
-  height: 100%;
-  overflow: hidden;
-  min-width: 1000px;
-  min-height: 900px;
-}
-
-video {
-  background: none;
-  object-fit: fill;
-  font-size: 0;
-}
-
-.marke {
-  position: fixed;
-  top: 0;
-  left: 50%;
-  width: 555px;
-  height: 30px;
-  transform: translate(-50%, 0);
-  z-index: 1;
-  display: flex;
-  align-items: center;
-  justify-content: center;
-}
-
-.marke::before {
-  position: absolute;
-  z-index: 0;
-  content: "";
-  width: 100%;
-  height: 0;
-  border-top: 30px solid rgba(0, 0, 0, 0.25);
-  border-left: 15px solid transparent;
-  border-right: 15px solid transparent;
-}
-
-.marke>div {
-  margin: 0 3px;
-}
-
-.gauge {
-  position: fixed;
-  bottom: 0;
-  left: 50%;
-  transform: translate(-50%, 0);
-  width: 500px;
-  height: 185px;
-  z-index: 9;
-}
-
-/* 隐藏滚动条 */
-::-webkit-scrollbar {
-  width: 0 !important;
-  display: none;
-}
-</style>

+ 0 - 7
src/vite-env.d.ts

@@ -1,7 +0,0 @@
-/// <reference types="vite/client" />
-
-declare module '*.vue' {
-  import type { DefineComponent } from 'vue'
-  const component: DefineComponent<{}, {}, any>
-  export default component
-}

+ 0 - 30
tsconfig.json

@@ -1,30 +0,0 @@
-{
-  "compilerOptions": {
-    "target": "ESNext",
-    "useDefineForClassFields": true,
-    "module": "ESNext",
-    "moduleResolution": "Node",
-    "strict": true,
-    "jsx": "preserve",
-    "sourceMap": true,
-    "resolveJsonModule": true,
-    "isolatedModules": true,
-    "esModuleInterop": true,
-    "lib": [
-      "ESNext",
-      "DOM"
-    ],
-    "skipLibCheck": true
-  },
-  "include": [
-    "src/**/*.ts",
-    "src/**/*.d.ts",
-    "src/**/*.tsx",
-    "src/**/*.vue"
-  ],
-  "references": [
-    {
-      "path": "./tsconfig.node.json"
-    }
-  ]
-}

+ 0 - 9
tsconfig.node.json

@@ -1,9 +0,0 @@
-{
-  "compilerOptions": {
-    "composite": true,
-    "module": "ESNext",
-    "moduleResolution": "Node",
-    "allowSyntheticDefaultImports": true
-  },
-  "include": ["vite.config.ts"]
-}

+ 0 - 56
vite.config.ts

@@ -1,56 +0,0 @@
-import { defineConfig } from 'vite'
-import vue from '@vitejs/plugin-vue'
-import eslint from 'vite-plugin-eslint'
-import viteCompression from 'vite-plugin-compression'
-import path from 'path'
-
-// https://vitejs.dev/config/
-export default defineConfig({
-  base: './',
-  resolve: {
-    alias: {
-      /*
-        路径别名
-        若为文件系统路径必须是绝对路径的形式,否则将以别名原样呈现,不会解析为文件系统路径路径
-      */
-      '@': path.resolve(__dirname, './src')
-    }
-  },
-  plugins: [vue(), viteCompression(), eslint({ fix: true, include: ['**/*.ts', '**/*.vue'] })],
-  server: {
-    host: '0.0.0.0',
-    port: 5888,
-    open: true,
-    strictPort: false,
-    https: false
-    // 反向代理
-    // proxy: {
-    //   '/': {
-    //     target: 'http://172.16.1.215:5000',
-    //     changeOrigin: true,
-    //     rewrite: (path) => path.replace(/^\//, '')
-    //   },
-    // }
-  },
-  build: {
-    rollupOptions: {
-      input: {
-        index: path.resolve(__dirname, 'index.html')
-      },
-      output: { // 静态资源分类打包
-        chunkFileNames: 'js/[name]-[hash].js',
-        entryFileNames: 'js/[name]-[hash].js',
-        assetFileNames: 'assets/[name]-[hash].[ext]'
-      }
-    },
-    terserOptions: { // 去掉打印
-      compress: {
-        drop_console: true,
-        drop_debugger: true
-      }
-    }
-  },
-  define: {
-    __VUE_OPTIONS_API__: false
-  }  
-})