mrh hace 2 años
padre
commit
dd22cdaad0

+ 4 - 0
.env

@@ -0,0 +1,4 @@
+# BASE_URL=192.168.1.11
+BASE_URL=swl-8l9.pages.dev
+VITE_BASE_URL=https://swl-8l9.pages.dev
+VITE_API_URLS=https://open-douyin-cf.magong.site,https://open-douyin-wk.magong.site,http://sv-v2.magong.site:8600

+ 0 - 47
dev-document.md

@@ -1,47 +0,0 @@
-
-## 立项
-假设你是一名专业的产品经理,基于vue3和element-pluse创建一个内网穿透的项目,以下是项目的大体思路:
-- 左侧导航栏,包含组件路由:用户, 列表, 应用, 设置, 关于
-  - 用户页面包含头像、退出登录、账户余额等信息
-  - 列表包含内网穿透的隧道列表信息,http、SRV、SSH、TCP 等列表对应的域名绑定,添加隧道、启动隧道等信息
-  - 应用包含内网穿透所支持的应用插件、推荐
-  - 设置是关于软件设置
-  - 关于页面包含软件信息,使用帮助,建议反馈
-在页面主体区域对应每一个导航栏的页面。
-根据这些思路完善、补充,写一个产品文档。
-
-# 产品文档
-
-## 项目概述
-该项目是一个基于Vue3和Element Plus的内网穿透管理系统。它旨在提供一个简单易用的界面,使用户能够轻松管理其内网穿透隧道,并通过左侧导航栏快速访问各个功能模块。本文档将详细介绍项目的各项功能和设计。
-
-## 功能模块
-
-### 左侧导航栏
-左侧导航栏是系统的核心导航功能。它包含以下组件路由:
-
-1. **用户页面**:用于显示用户个人信息,包括头像、退出登录功能以及账户余额等信息。
-2. **列表页面**:提供内网穿透隧道的列表信息。支持HTTP、SRV、SSH、TCP等类型隧道的管理,包括域名绑定、隧道添加和启动功能。
-3. **应用页面**:展示内网穿透所支持的应用插件及推荐。用户可以在此页面方便地探索各种应用插件。
-4. **设置页面**:用于管理软件的相关设置,提供个性化设置选项,以及其他必要的系统配置选项。
-5. **关于页面**:包含软件的相关信息、使用帮助以及建议反馈功能。用户可以在这里找到对软件的详细介绍和使用说明。
-
-### 页面主体区域
-页面主体区域对应每一个导航栏的页面,并展示相应页面的详细信息和功能。具体细节如下:
-
-1. **用户页面**:展示用户的个人信息,并提供退出登录和账户余额查看等功能。
-2. **列表页面**:展示内网穿透的隧道列表信息,包括不同类型隧道的详细信息和管理功能。
-3. **应用页面**:展示内网穿透所支持的应用插件及推荐,让用户能够快速了解和选择适合自己需求的插件。
-4. **设置页面**:提供软件的相关设置功能,包括个性化设置选项和系统配置选项等。
-5. **关于页面**:展示软件的详细信息,使用帮助和建议反馈功能,让用户能够了解软件的背景和使用方法,并提供反馈渠道。
-
-## 技术实现
-本项目基于Vue3框架和Element Plus组件库开发,使用内网穿透技术实现网络访问隧道。我们将充分利用Vue3的响应式特性和Element Plus的丰富组件,提供用户友好的交互界面和丰富的功能实现。同时,我们将注重系统的稳定性和安全性,确保用户信息和数据的安全可靠。
-
-## 未来规划
-在未来的版本中,我们将进一步完善用户体验,提升系统性能和安全性。同时,我们也将不断增加新的功能模块和应用插件,丰富系统的功能和应用场景,以满足不同用户的需求。
-
-以上是对项目的初步规划和设计,我们将不断优化和完善系统,为用户提供更好的服务和体验。如有任何疑问或建议,欢迎随时联系我们的团队。感谢您对我们项目的支持和关注!
-
-
-将以上文档总结成5个句话,让公司所有人知道要做什么、应该怎么做

+ 17 - 3
index.html

@@ -2,7 +2,7 @@
   <head>
     <meta charset="UTF-8" />
     <meta name="viewport" content="width=device-width,initial-scale=1.0" />
-    <script src="https://unpkg.com/vue@next"></script>
+    <!-- <script src="https://unpkg.com/vue@next"></script> -->
     <!-- import CSS -->
     <link rel="stylesheet" href="https://unpkg.com/element-plus/dist/index.css">
     <!-- import JavaScript -->
@@ -10,8 +10,22 @@
     <title>Element Plus demo</title>
   </head>
   <body>
-    <div id="app"></div>
+    <div id="app">
+        <style>
+        html,
+        body,
+        #app {
+          position: relative;
+          display: flex;
+          align-items: center;
+          justify-content: center;
+          width: 100%;
+          height: 100%;
+          overflow: hidden;
+        }
+
+        </style>
+    </div>
     <script type="module" src="/src/main.js"></script>
-    </script>
   </body>
 </html>

+ 0 - 42
main.js

@@ -1,42 +0,0 @@
-const { app, BrowserWindow} = require('electron')
-const WinState = require('electron-win-state').default
-const path = require('path')
-
-const createWindow = () => {
-    const winState = new WinState({
-        defaultWidth: 1000,
-        defaultHeight:800
-    })
-    const win = new BrowserWindow({
-        ...winState.winOptions,
-        webPreferences:{
-            // 新版 electron 必须关闭沙盒模式才能使用 clipboard
-            sandbox: false,
-            preload: path.resolve(__dirname, './preload/index.js')
-        },
-        show: false
-    })
-    win.loadURL('http://localhost:5173')
-    win.webContents.openDevTools()
-    winState.manage(win)
-    // 等页面加载渲染完后,才显示窗口,避免刚启动时看到页面空白
-    win.on('ready-to-show', () => {
-        win.show()
-    })
-}
-
-app.whenReady().then(() => {
-    createWindow()
-    // darwin系统关闭窗口但是它还在后台运行
-    // 所以检测APP是否在活动,如果还在就重新创建
-    app.on('activate', () => {
-        if (BrowserWindow.getAllWindows().length ===0){
-            createWindow()
-        }
-    })
-})
-
-app.on('window-all-closed', () => {
-    app.quit()
-})
-

La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 683 - 138
package-lock.json


+ 9 - 9
package.json

@@ -1,26 +1,26 @@
 {
-  "name": "readit",
+  "name": "siweilian",
   "private": true,
   "version": "0.0.0",
-  "main": "main.js",
   "scripts": {
     "dev": "vite",
     "build": "vite build",
     "preview": "vite preview",
-    "start": "nodemon --exec electron . -w ./ --ext .js,.html,.css,.vue"
+    "start": "nodemon"
   },
   "dependencies": {
-    "electron": "^26.2.1",
-    "electron-win-state": "^1.1.22",
-    "element-plus": "^2.4.1",
+    "element-plus": "^2.5.3",
     "nodemon": "^3.0.1",
-    "vue": "^3.3.4"
+    "vue": "^3.3.4",
+    "vue-router": "^4.2.5",
+    "vue3-video-play": "^1.3.2"
   },
   "devDependencies": {
     "@vitejs/plugin-vue": "^4.2.3",
-    "electron": "^27.0.3",
+    "axios": "^1.6.7",
     "unplugin-auto-import": "^0.16.7",
     "unplugin-vue-components": "^0.25.2",
-    "vite": "^4.4.5"
+    "vite": "^4.4.5",
+    "wrangler": "^3.24.0"
   }
 }

+ 1 - 6
src/App.vue

@@ -1,14 +1,9 @@
 <script setup>
     import { ref } from 'vue'
-    import Home from './views/Home.vue'
-
-    const count = ref(0)
     
 </script>
-
 <template>
-  <Home></Home>
-  <p>count: {{ count }}</p>
+    <router-view />
 </template>
 
 <style lang="css">

+ 7 - 4
src/main.js

@@ -1,12 +1,15 @@
-import ElementPlus from 'element-plus'
-import 'element-plus/dist/index.css'
 import '@/assets/common.css'
 import App from './App.vue'
 import { createApp } from 'vue'
-
-
+import router from './router' 
+import ElementPlus from 'element-plus'
+import 'element-plus/dist/index.css'
+// import vue3videoPlay from "vue3-video-play"; // 引入组件
+// import "vue3-video-play/dist/style.css"; // 引入css
 const app = createApp(App)
 
+// app.use(vue3videoPlay);
 app.use(ElementPlus)
+app.use(router)
 app.mount('#app')
 

+ 31 - 0
src/router/index.js

@@ -0,0 +1,31 @@
+// router/index.js  
+import { createRouter, createWebHistory } from 'vue-router'  
+import Home from '../views/home/index.vue' // 确保你有这个文件  
+import Account from '../views/account/index.vue' // 确保你有这个文件  
+import Verify from '../views/home/verify.vue'
+
+const routes = [  
+  {  
+    path: '/',  
+    name: 'Home',  
+    component: Home  
+  },  
+  {  
+    path: '/account',  
+    name: 'Account',  
+    component: Account  
+  },
+  {  
+    path: '/verify',  
+    name: 'verify',  
+    component: Verify  
+  }  
+ 
+]  
+  
+const router = createRouter({  
+  history: createWebHistory(process.env.BASE_URL),  
+  routes  
+})  
+  
+export default router

+ 0 - 19
src/views/Home.vue

@@ -1,19 +0,0 @@
-<script setup>
-    import { ref } from 'vue'
-    import ElementPlus from 'element-plus'
-    import 'element-plus/dist/index.css'
-</script>
-
-<template>
-    <main>
-        <el-button>Element button</el-button>
-    </main>
-</template>
-
-<style lang="css">
-    main{
-        color: brown;
-        border-color: brown;
-        background-color: bisque;
-    }
-</style>

+ 13 - 0
src/views/account/index.vue

@@ -0,0 +1,13 @@
+<template lang="">
+    <div>
+        account
+    </div>
+</template>
+<script>
+export default {
+    
+}
+</script>
+<style lang="">
+    
+</style>

+ 160 - 0
src/views/home/capacity.vue

@@ -0,0 +1,160 @@
+<template lang="">
+    <div class="capacity">
+     <el-row class="capacity-item">
+        <el-scrollbar >
+            <div class="scrollbar-flex-content">
+                <el-button type="primary" round>抖音评论</el-button>
+                <el-button type="primary" round>回复私信</el-button>
+                <el-button type="primary" round>自主学习</el-button>
+                <el-button type="primary" round>永久记忆</el-button>
+                <el-button type="primary" round>功能扩展</el-button>
+            </div>
+        </el-scrollbar>
+    </el-row>
+
+    <el-carousel indicator-position="outside" height="600px">
+        <el-carousel-item style="height: 600px" v-for="item in 4" :key="item">
+            <el-card class="box-card" shadow="hover">
+                <el-row >
+                    <el-col >
+                        <el-text class="capacity-title" >抖音作品评论区自动回复</el-text>
+                    </el-col>
+                </el-row>
+                <el-row >
+                    <el-col >
+                        <el-text class="capacity-txt" >根据视频内容和给定的知识,在评论区自动回复观众问题</el-text>
+                    </el-col>
+                </el-row>
+                <videoPlay v-bind="options"
+                poster="https://cdn.jsdelivr.net/gh/xdlumia/files/video-play/ironMan.jpg"
+                ></videoPlay>
+            </el-card>
+        </el-carousel-item>
+  </el-carousel>
+    <!-- <div class="capacity-info">
+        <el-carousel height="auto">
+            <el-carousel-item   v-for="item in 4" :key="item">
+                <el-card class="box-card" shadow="hover">
+                    <div v-for="o in 4" :key="o" class="text item">{{ 'List item ' + o }}</div>
+                </el-card>
+            </el-carousel-item>
+        </el-carousel>
+    </div> -->
+
+    </div>
+</template>
+<script setup>
+import "vue3-video-play/dist/style.css";
+import "vue3-video-play/dist/style.css";
+// 官方导入方式不对,必须要这样导入才能使用
+import { videoPlay } from "vue3-video-play/dist/index.mjs";
+import {ref,onMounted} from "vue"
+const options = ref({
+  width: "800px", //播放器宽度
+  height: "450px", //播放器高度
+  color: "#409eff", //主题色
+  title: "", //视频名称
+  src: "https://cdn.jsdelivr.net/gh/xdlumia/files/video-play/IronMan.mp4", //视频源
+  muted: false, //静音
+  webFullScreen: false,
+  speedRate: ["0.75", "1.0", "1.25", "1.5", "2.0"], //播放倍速
+  autoPlay: false, //自动播放
+  loop: false, //循环播放
+  mirror: false, //镜像画面
+  ligthOff: false, //关灯模式
+  volume: 0.3, //默认音量大小
+  control: true, //是否显示控制
+  controlBtns: [
+    "audioTrack",
+    "quality",
+    "speedRate",
+    "volume",
+    "setting",
+    "pip",
+    "pageFullScreen",
+    "fullScreen",
+  ], //显示所有按钮,
+});
+
+</script>
+<style lang="css" scoped>
+.capacity-title {
+    color: rgb(6, 6, 6);  
+    font-size: 22px;
+    margin-top: 10px;
+}
+.capacity-txt {
+    color: rgb(94, 91, 91);  
+    font-size: 12px;
+    margin-top: 15px;
+}
+.el-col {
+    flex-grow: 1;
+    display: flex;
+    justify-content: center;
+    align-items: center;
+}
+
+.el-card {
+    margin: 10px;
+    height: 100%;
+    width: 100%;
+}
+.el-carousel__item  {
+  display: flex;
+  color: #475669;
+  opacity: 0.75;
+  height: 100%;
+  margin: 0;
+}
+
+/* .el-carousel__item .el-card {
+    height: 450px;
+    background-color: #FBFCFF;
+} */
+/* .el-card .el-carousel-item{
+    max-width: 380px;
+} */
+/* 
+.el-scrollbar__wrap
+{
+  overflow-x: hidden;
+}
+
+.el-scrollbar__bar.is-horizontal{
+  height: 0 !important;
+} */
+
+/* .scrollbar-flex-content {
+  display: flex;
+} */
+
+/* --------------- 能力一行 ------------------------ */
+.capacity-item .el-button:focus {
+    background: #ffffff !important;
+    font-weight: bold;
+    border-color: #01a8f9 !important;
+}
+
+
+.capacity-item .el-button{
+    background-color: transparent;
+    border: 0px;
+    color: black;
+    margin-left: 0;
+    padding: 10px;
+}
+
+.capacity-item{
+    height: 40px;
+    overflow-x: auto; 
+    display: flex; 
+    justify-content: center;
+    align-items: center;
+}
+
+.capacity-item::-webkit-scrollbar {  
+  display: none; /* 隐藏WebKit浏览器的滚动条 */  
+} 
+
+</style>

+ 28 - 0
src/views/home/head.vue

@@ -0,0 +1,28 @@
+<template lang="">
+    <div >
+        <el-row style="height: 100%;">
+            <el-col :span="9">
+                    <el-avatar id="logo" :size="30" :src="avatarUrl" />
+                    <el-text id="pro_name" class="title-text" >思维链</el-text>
+            </el-col>
+        </el-row>
+    </div>
+</template>
+
+<script setup>
+const avatarUrl='https://s3.magong.site/swl/web/avatar.jpg'  
+
+</script>
+
+<style lang="css" scoped>
+.el-col {
+  display: flex;
+  align-items: center;
+}
+#pro_name {
+    color: rgb(36, 36, 36);  
+    font-size: 18px;
+    margin-left: 15px;
+}
+
+</style>

+ 37 - 0
src/views/home/index.vue

@@ -0,0 +1,37 @@
+<template lang="">
+    <div id="div-home">
+      <el-container >
+        <el-header >
+            <Head></Head>
+        </el-header>
+        
+        <el-main >
+            <Main></Main>
+        </el-main>
+      </el-container>
+    </div>
+</template>
+<script setup>
+import Main from './main.vue'; 
+import Head from './head.vue'; 
+
+</script>
+<style lang="css" scoped >
+#div-home .el-container {
+    height: 100vh; 
+    display: flex; 
+    flex-direction: column;
+}
+
+.el-main{
+    background-color: rgb(233,241,253);
+}
+
+/* .el-main .el-col {
+    flex-grow: 1;
+  display: flex;
+  justify-content: center;
+  align-items: center;
+} */
+
+</style>

+ 57 - 0
src/views/home/main-info.vue

@@ -0,0 +1,57 @@
+<template lang="">
+    <div class="main-info">
+        <el-row >
+        <el-col id="pro_slogan">
+            <el-text  tag="b">一个拥有自主思维的AI员工</el-text>
+        </el-col>
+    </el-row>
+    <el-row>
+        <el-col>
+            <el-text >大模型4.0,长期记忆,能力扩展,按需付费</el-text>
+        </el-col>
+    </el-row>
+    <el-row>
+        <el-col class="login-btn">
+            <el-button round size="large" type="primary" style="width: 150px;" @click="clickLogin">立即体验</el-button>
+        </el-col>
+    </el-row>
+    </div>
+
+</template>
+<script setup>
+const redirect_uri = import.meta.env.VITE_BASE_URL + "/verify_callback";
+const scanCodeUrl = `https://open.douyin.com/platform/oauth/connect/?client_key=aw6aipmfdtplwtyq&response_type=code&scope=user_info,renew_refresh_token,trial.whitelist&redirect_uri=${redirect_uri}`
+const clickLogin = () => {
+    window.location.href = scanCodeUrl;
+}
+
+</script>
+<style lang="css" scoped>
+.el-col {
+    flex-grow: 1;
+    display: flex;
+    justify-content: center;
+    align-items: center;
+}
+.main-info {
+    height: 160px;
+    margin-top: 20px;
+    margin-bottom: 8px;
+}
+
+
+.login-btn {
+    margin-top: 20px;
+    margin-bottom: 10px;
+}
+
+
+#pro_slogan{
+    height: 20px;
+    margin-bottom: 20px;
+}
+#pro_slogan .el-text {
+    color: rgb(36, 36, 36);  
+    font-size: 22px;
+}
+</style>

+ 20 - 0
src/views/home/main.vue

@@ -0,0 +1,20 @@
+<template>
+    <MainInfo></MainInfo>
+    <Capacity></Capacity>    
+</template>
+
+
+<script setup>
+    import { ref } from 'vue'
+    import ElementPlus from 'element-plus'
+    import 'element-plus/dist/index.css'
+    import MainInfo from './main-info.vue'
+    import Capacity from './capacity.vue'
+</script>
+
+
+<style lang="css" scoped>
+
+
+
+</style>

+ 121 - 0
src/views/home/verify.vue

@@ -0,0 +1,121 @@
+<template lang="">
+    <div id="verify-root">
+    <div class="verify" style="border-radius: 8px; box-shadow: var(--el-box-shadow-lighter);">
+        <el-row >
+            <el-col >
+                <el-text type="success" size="large"  tag="b">扫码成功</el-text>
+            </el-col>
+        </el-row>
+        <el-row>
+            <el-col>
+                <el-text>正在跳转到</el-text>  
+            </el-col>
+        </el-row>
+        <el-row>
+            <el-col>
+                <!-- 使用 v-if 控制链接的显示,只有在登录成功后才显示 -->  
+                <el-link v-if="isLoggedIn" type="primary" @click="navigateToAccount">我的主页</el-link>  
+                <!-- 添加加载状态的文本 -->  
+                <el-text v-else>{{info}}...</el-text>  
+            </el-col>
+        </el-row>
+    </div>
+    </div>
+</template>
+
+<script setup>
+import { ref, onMounted, nextTick } from 'vue';  
+import axios from 'axios'; // 确保已经安装了axios  
+  
+const isLoggedIn = ref(false);  
+const info = ref('正在验证登录信息...')
+async function tryLoginWithUrls(apiUrls, code, state, index = 0) {  
+  if (index >= apiUrls.length) {  
+    // 所有URL都尝试过了,抛出错误或处理失败  
+    throw new Error('所有服务器登录尝试均失败');  
+  }  
+  
+  const apiUrl = apiUrls[index];  
+  try {  
+    const response = await axios.post(`${apiUrl}/login`, { code, state });  
+    if (response.data.success) {  
+      isLoggedIn.value = true;  
+      await nextTick();  
+      await nextTick();  
+      navigateToAccount();  
+    } else {  
+      // 可以选择在这里再次尝试,或者直接失败  
+      throw new Error('登录失败: 无效的响应数据');  
+    }  
+  } catch (error) {  
+    console.error(`尝试登录服务器${apiUrl}失败:`, error);  
+    // 尝试下一个URL  
+    return tryLoginWithUrls(apiUrls, code, state, index + 1);  
+  }  
+}
+onMounted(async () => {  
+  try {  
+    const queryString = window.location.search;  
+    const urlParams = new URLSearchParams(queryString);  
+    const code = urlParams.get('code');  
+    const state = urlParams.get('state');  
+  
+    const apiUrls = import.meta.env.VITE_API_URLS.split(',');  
+    await tryLoginWithUrls(apiUrls, code, state);  
+  } catch (error) {  
+    info.value = '登录失败:' + error.message;  
+    console.error('最终登录失败:', error);  
+  }  
+});
+
+// 跳转函数  
+const navigateToAccount = () => {  
+  window.location.href = '/account';  
+};  
+</script>
+
+<style lang="css" scoped>
+#verify-root{
+    display: flex;  
+    justify-content: center; /* 控制水平居中 */  
+    align-items: center; /* 控制垂直居中 */  
+    flex-direction: column; /* 确保子元素按列排列,这对于多行文本或元素很重要 */  
+    /* background-color: rgb(240, 240, 242);; */
+    background-color: rgb(233,241,253);
+    height: 100vh;
+}
+.el-col{
+    display: flex;  
+    justify-content: center; /* 控制水平居中 */  
+    align-items: center; /* 控制垂直居中 */  
+    flex-direction: column; /* 确保子元素按列排列,这对于多行文本或元素很重要 */  
+
+}
+.verify { 
+    display: flex; /* 添加此行 */  
+    flex-direction: column; /* 添加此行 */  
+    justify-content: center; /* 添加此行以垂直居中 */  
+    align-items: center; /* 如果需要,也可以水平居中 */  
+    height: 60%; /* 使得容器占据整个视口的高度,这样内容可以在其中垂直居中 */  
+    width: 80vw;
+    max-width: 300px;
+    max-height: 500px;
+    border-radius: 8px;  
+    box-shadow: var(--el-box-shadow-lighter);  
+    background-color: rgb(255, 255, 255);;
+}
+/* .el-text {
+    color: rgb(36, 36, 36);  
+    font-size: 22px;
+} */
+
+/* .verify {
+    height: 100vh;
+}
+.el-col {
+    flex-grow: 1;
+    display: flex;
+    justify-content: center;
+    align-items: center;
+} */
+</style>

+ 9 - 1
vite.config.js

@@ -10,5 +10,13 @@ export default defineConfig({
     alias:{
       '@': path.resolve(__dirname, './src')
     }
-  }
+  },
+  server: {  
+    host: '0.0.0.0', // 监听所有地址,允许外部访问  
+    port: 18889,      // 指定端口号  
+    // 其他配置项...  
+  }, 
+    define: {  
+        'process.env.BASE_URL': JSON.stringify(process.env.BASE_URL || '/')  
+    }  
 })

Algunos archivos no se mostraron porque demasiados archivos cambiaron en este cambio