布局先提交一波
This commit is contained in:
20
index.html
20
index.html
@@ -1,13 +1,13 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Vite + Vue</title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="app"></div>
|
||||
<script type="module" src="/src/main.js"></script>
|
||||
</body>
|
||||
<head>
|
||||
<meta charset="UTF-8"/>
|
||||
<link rel="icon" type="image/svg+xml" href="/vite.svg"/>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
|
||||
<title>语言模型聊天</title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="app"></div>
|
||||
<script type="module" src="/src/main.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
2305
package-lock.json
generated
2305
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -9,6 +9,10 @@
|
||||
"preview": "vite preview"
|
||||
},
|
||||
"dependencies": {
|
||||
"axios": "^1.4.0",
|
||||
"element-plus": "^2.3.4",
|
||||
"sass": "^1.62.1",
|
||||
"sass-loader": "^13.2.2",
|
||||
"vue": "^3.2.47"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
||||
69
src/App.vue
69
src/App.vue
@@ -1,33 +1,44 @@
|
||||
<template>
|
||||
<div id="app" @mousedown="windowMove(true)" @mouseup="windowMove(false)">
|
||||
<Home/>
|
||||
<div id="app">
|
||||
<el-row class="home">
|
||||
<chat class="fill" :config="setting"/>
|
||||
<settings class="mar-l16" v-show="showSettings" v-model="setting"/>
|
||||
</el-row>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {isPc} from '@/util/util.js'
|
||||
import Home from './view/home.vue'
|
||||
import Chat from "./components/chat";
|
||||
import Settings from "./components/settings";
|
||||
import {ChatGPT} from "./utils/models";
|
||||
|
||||
export default {
|
||||
name: 'App',
|
||||
components: {
|
||||
Home
|
||||
components: {Settings, Chat},
|
||||
data() {
|
||||
return {
|
||||
showSettings: true,
|
||||
setting: {
|
||||
model: new ChatGPT()
|
||||
},
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
windowMove(canMove) {
|
||||
if (isPc()) {
|
||||
import("electron").then(({ipcRenderer}) => {
|
||||
ipcRenderer.send('window-move-open', canMove ?? false);
|
||||
});
|
||||
}
|
||||
},
|
||||
handleResize() {
|
||||
console.log("App handleResize")
|
||||
this.showSettings = window.innerWidth > 1150;
|
||||
}
|
||||
},
|
||||
created() {
|
||||
window.addEventListener('resize', this.handleResize)
|
||||
},
|
||||
unmounted() {
|
||||
window.removeEventListener('resize', this.handleResize)
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
@import url(./assets/font/iconfont.css);
|
||||
|
||||
@each $v in (333, 666, 888, 999, '26f', 'f46') {
|
||||
.color-#{$v} {
|
||||
color: \##{$v};
|
||||
@@ -79,17 +90,6 @@ export default {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.iconfont {
|
||||
font-family: "iconfont" !important;
|
||||
font-style: normal;
|
||||
font-size: 25px;
|
||||
vertical-align: middle;
|
||||
color: rgb(117, 120, 137);
|
||||
transition: .3s;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
}
|
||||
|
||||
* {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
@@ -102,7 +102,20 @@ export default {
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar {
|
||||
display: none; /* Chrome Safari */
|
||||
.home {
|
||||
width: 100vw;
|
||||
height: 100vh;
|
||||
padding: 16px;
|
||||
background-color: #272A37;
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
top: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
}
|
||||
|
||||
.fill {
|
||||
flex: 1;
|
||||
min-height: 0;
|
||||
min-width: 0;
|
||||
}
|
||||
</style>
|
||||
|
||||
4
src/assets/clear.svg
Normal file
4
src/assets/clear.svg
Normal file
@@ -0,0 +1,4 @@
|
||||
<svg viewBox="0 0 1024 1024" xmlns="http://www.w3.org/2000/svg" data-v-ea893728="">
|
||||
<path fill="#fff"
|
||||
d="M352 192V95.936a32 32 0 0 1 32-32h256a32 32 0 0 1 32 32V192h256a32 32 0 1 1 0 64H96a32 32 0 0 1 0-64h256zm64 0h192v-64H416v64zM192 960a32 32 0 0 1-32-32V256h704v672a32 32 0 0 1-32 32H192zm224-192a32 32 0 0 0 32-32V416a32 32 0 0 0-64 0v320a32 32 0 0 0 32 32zm192 0a32 32 0 0 0 32-32V416a32 32 0 0 0-64 0v320a32 32 0 0 0 32 32z"></path>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 461 B |
@@ -1,40 +0,0 @@
|
||||
<script setup>
|
||||
import { ref } from 'vue'
|
||||
|
||||
defineProps({
|
||||
msg: String,
|
||||
})
|
||||
|
||||
const count = ref(0)
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<h1>{{ msg }}</h1>
|
||||
|
||||
<div class="card">
|
||||
<button type="button" @click="count++">count is {{ count }}</button>
|
||||
<p>
|
||||
Edit
|
||||
<code>components/HelloWorld.vue</code> to test HMR
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<p>
|
||||
Check out
|
||||
<a href="https://vuejs.org/guide/quick-start.html#local" target="_blank"
|
||||
>create-vue</a
|
||||
>, the official Vue + Vite starter
|
||||
</p>
|
||||
<p>
|
||||
Install
|
||||
<a href="https://github.com/vuejs/language-tools" target="_blank">Volar</a>
|
||||
in your IDE for a better DX
|
||||
</p>
|
||||
<p class="read-the-docs">Click on the Vite and Vue logos to learn more</p>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.read-the-docs {
|
||||
color: #888;
|
||||
}
|
||||
</style>
|
||||
123
src/components/chat.vue
Normal file
123
src/components/chat.vue
Normal file
@@ -0,0 +1,123 @@
|
||||
<template>
|
||||
<section class="chat">
|
||||
<el-row align="middle">
|
||||
<div class="modelInfo">
|
||||
<img :src="config.model.avatar" alt=""/>
|
||||
<div class="fill mar-l8">
|
||||
<b v-text="config.model.name"/>
|
||||
<div class="desc" v-text="config.model.desc"/>
|
||||
</div>
|
||||
</div>
|
||||
<el-row justify="end" class="fill mar-l8">
|
||||
<div class="clear-icon"/>
|
||||
<!-- todo 聊天操作栏-->
|
||||
</el-row>
|
||||
</el-row>
|
||||
<thinking-bar v-show="loading"/>
|
||||
<chat-content class="fill"/>
|
||||
<chat-input/>
|
||||
</section>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import ChatContent from "../components/chatContent";
|
||||
import ChatInput from "../components/chatInput";
|
||||
import ThinkingBar from "../components/thinkingBar";
|
||||
|
||||
export default {
|
||||
name: "chat",
|
||||
components: {ChatContent, ChatInput, ThinkingBar},
|
||||
props: {
|
||||
config: {default: () => ({})}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
loading: true
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
handleResize() {
|
||||
if (window.innerWidth <= 700) {
|
||||
this.$nextTick(() => {
|
||||
document.querySelectorAll('.chat-content')[0].style.height = '93%';
|
||||
this.buttonStatus = false
|
||||
const textareaMsg = document.getElementById("textareaMsg");
|
||||
textareaMsg.style.marginLeft = "0px";
|
||||
this.personInfoSpan = [14, 0, 10];
|
||||
const isMobile = /iPhone|iPad|iPod|Android/i.test(navigator.userAgent)
|
||||
if (isMobile) {
|
||||
document.querySelectorAll('.chatInputs')[0].style.margin = '0%';
|
||||
} else {
|
||||
document.querySelectorAll('.chatInputs')[0].style.margin = '3%';
|
||||
}
|
||||
});
|
||||
} else {
|
||||
this.$nextTick(() => {
|
||||
document.querySelectorAll('.chat-content')[0].style.height = '88%';
|
||||
this.buttonStatus = true
|
||||
this.personInfoSpan = [1, 17, 6];
|
||||
});
|
||||
}
|
||||
},
|
||||
},
|
||||
created() {
|
||||
window.addEventListener('resize', this.handleResize)
|
||||
},
|
||||
unmounted() {
|
||||
window.removeEventListener('resize', this.handleResize)
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.chat {
|
||||
color: #fff;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
.modelInfo {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
line-height: 1.4;
|
||||
|
||||
& > img {
|
||||
border: 2px solid #fff;
|
||||
border-radius: 50%;
|
||||
padding: 4px;
|
||||
width: 45px;
|
||||
height: 45px;
|
||||
}
|
||||
|
||||
b {
|
||||
font-size: 20px;
|
||||
}
|
||||
|
||||
.desc {
|
||||
color: #999;
|
||||
font-size: 14px;
|
||||
}
|
||||
}
|
||||
|
||||
.clear-icon {
|
||||
box-sizing: border-box;
|
||||
height: 40px;
|
||||
background-size: 24px 24px;
|
||||
background-image: url("../assets/clear.svg");
|
||||
background-repeat: no-repeat;
|
||||
background-position: top center;
|
||||
cursor: pointer;
|
||||
opacity: .6;
|
||||
padding-top: 24px;
|
||||
|
||||
&:after {
|
||||
font-size: 12px;
|
||||
content: "清空历史";
|
||||
display: block;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
94
src/components/chatContent.vue
Normal file
94
src/components/chatContent.vue
Normal file
@@ -0,0 +1,94 @@
|
||||
<template>
|
||||
<section class="chatContent" @scroll="onScroll">
|
||||
<div class="chat-wrapper" v-for="item in list" :key="item.id">
|
||||
<div class="chat-friend" v-if="item.uid !== 'jcm'">
|
||||
<div class="chat-text" v-if="item.chatType == 0">
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="2">
|
||||
<svg t="1679666016648" @click="$copy(item.msg, '已复制')" class="icon" viewBox="0 0 1024 1024"
|
||||
version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="6241" width="22" height="22">
|
||||
<path
|
||||
d="M661.333333 234.666667A64 64 0 0 1 725.333333 298.666667v597.333333a64 64 0 0 1-64 64h-469.333333A64 64 0 0 1 128 896V298.666667a64 64 0 0 1 64-64z m-21.333333 85.333333H213.333333v554.666667h426.666667v-554.666667z m191.829333-256a64 64 0 0 1 63.744 57.856l0.256 6.144v575.701333a42.666667 42.666667 0 0 1-85.034666 4.992l-0.298667-4.992V149.333333H384a42.666667 42.666667 0 0 1-42.368-37.674666L341.333333 106.666667a42.666667 42.666667 0 0 1 37.674667-42.368L384 64h447.829333z"
|
||||
fill="#909399" p-id="6242"></path>
|
||||
</svg>
|
||||
</el-col>
|
||||
<el-col :span="21">
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<markdown-it-vue :content="item.msg.trim()"/>
|
||||
</div>
|
||||
<div class="chat-img" v-if="item.chatType == 1">
|
||||
<img :src="item.msg" alt="表情" v-if="item.extend.imgType == 1" style="width: 100px; height: 100px"/>
|
||||
<el-image style="border-radius: 10px" :src="item.msg" :preview-src-list="srcImgList" v-else>
|
||||
</el-image>
|
||||
</div>
|
||||
<div class="chat-img" v-if="item.chatType == 2">
|
||||
<div class="word-file">
|
||||
<FileCard :fileType="item.extend.fileType" :file="item.msg"></FileCard>
|
||||
</div>
|
||||
</div>
|
||||
<div class="info-time">
|
||||
<img :src="item.headImg" alt=""/>
|
||||
<span>{{ item.name }}</span>
|
||||
<span>{{ item.time }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="chat-me" v-else>
|
||||
<div class="chat-text" v-if="item.chatType == 0">
|
||||
<span style="font-size:16px">{{ item.msg }}</span>
|
||||
</div>
|
||||
<div class="chat-img" v-if="item.chatType == 1">
|
||||
<img :src="item.msg" alt="表情" v-if="item.extend.imgType == 1" style="width: 100px; height: 100px"/>
|
||||
<el-image style="max-width: 300px; border-radius: 10px" :src="item.msg" :preview-src-list="srcImgList"
|
||||
v-else>
|
||||
</el-image>
|
||||
</div>
|
||||
<div class="chat-img" v-if="item.chatType == 2">
|
||||
<div class="word-file">
|
||||
<FileCard :fileType="item.extend.fileType" :file="item.msg"></FileCard>
|
||||
</div>
|
||||
</div>
|
||||
<div class="info-time">
|
||||
<span>{{ item.name }}</span>
|
||||
<span>{{ item.time }}</span>
|
||||
<img :src="item.headImg" alt=""/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: "chatContent",
|
||||
data() {
|
||||
return {
|
||||
list:[]
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
onScroll() {
|
||||
const scrollDom = this.$el;
|
||||
const scrollTop = scrollDom.scrollTop;
|
||||
const offsetHeight = scrollDom.offsetHeight;
|
||||
const scrollHeight = scrollDom.scrollHeight;
|
||||
// 当滚动到底部,设置 isAutoScroll 为 true
|
||||
this.isAutoScroll = scrollTop + offsetHeight === scrollHeight;
|
||||
},
|
||||
},
|
||||
created() {
|
||||
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.chatContent {
|
||||
background: #323644;
|
||||
border-radius: 4px;
|
||||
padding: 16px;
|
||||
box-sizing: border-box;
|
||||
overflow-y: auto;
|
||||
}
|
||||
</style>
|
||||
22
src/components/chatInput.vue
Normal file
22
src/components/chatInput.vue
Normal file
@@ -0,0 +1,22 @@
|
||||
<template>
|
||||
<section class="chatInput">
|
||||
|
||||
</section>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: "chatInput",
|
||||
data() {
|
||||
return {}
|
||||
},
|
||||
methods: {},
|
||||
created() {
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.chatInput {
|
||||
}
|
||||
</style>
|
||||
30
src/components/settings.vue
Normal file
30
src/components/settings.vue
Normal file
@@ -0,0 +1,30 @@
|
||||
<template>
|
||||
<section class="settings">
|
||||
|
||||
</section>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: "settings",
|
||||
model: {
|
||||
prop: "settings",
|
||||
event: "input"
|
||||
},
|
||||
props: {
|
||||
settings: {default: () => ({})}
|
||||
},
|
||||
data() {
|
||||
return {}
|
||||
},
|
||||
methods: {},
|
||||
created() {
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.settings {
|
||||
min-width: 400px;
|
||||
}
|
||||
</style>
|
||||
83
src/components/thinkingBar.vue
Normal file
83
src/components/thinkingBar.vue
Normal file
@@ -0,0 +1,83 @@
|
||||
<template>
|
||||
<section class="thinkingBar"/>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: "thinkingBar",
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.thinkingBar {
|
||||
position: relative;
|
||||
margin-top: 16px;
|
||||
height: 2px;
|
||||
background-image: linear-gradient(to right, #eea2a2 0%, #bbc1bf 19%, #57c6e1 42%, #b49fda 79%, #7ac5d8 100%);
|
||||
background-size: 100%;
|
||||
animation: shrink-and-expand 2s ease-in-out infinite;
|
||||
|
||||
&::before,
|
||||
&::after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
top: 0;
|
||||
width: 50%;
|
||||
height: 100%;
|
||||
background: inherit;
|
||||
}
|
||||
|
||||
&::before {
|
||||
border-top-left-radius: 2px;
|
||||
border-bottom-left-radius: 2px;
|
||||
left: 0;
|
||||
transform-origin: left;
|
||||
animation: shrink-left 2s ease-in-out infinite;
|
||||
}
|
||||
|
||||
&::after {
|
||||
border-top-left-radius: 2px;
|
||||
border-bottom-left-radius: 2px;
|
||||
right: 0;
|
||||
transform-origin: right;
|
||||
animation: shrink-right 2s ease-in-out infinite;
|
||||
}
|
||||
|
||||
@keyframes shrink-and-expand {
|
||||
0%,
|
||||
100% {
|
||||
transform: scaleX(1);
|
||||
}
|
||||
|
||||
50% {
|
||||
transform: scaleX(0);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes shrink-left {
|
||||
|
||||
0%,
|
||||
50% {
|
||||
transform: scaleX(1);
|
||||
}
|
||||
|
||||
50.1%,
|
||||
100% {
|
||||
transform: scaleX(0);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes shrink-right {
|
||||
|
||||
0%,
|
||||
50% {
|
||||
transform: scaleX(1);
|
||||
}
|
||||
|
||||
50.1%,
|
||||
100% {
|
||||
transform: scaleX(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
26
src/main.js
26
src/main.js
@@ -1,20 +1,10 @@
|
||||
import { createApp } from 'vue'
|
||||
import './style.css'
|
||||
import ElementPlus from 'element-plus'
|
||||
import 'element-plus/dist/index.css'
|
||||
import {createApp} from 'vue'
|
||||
import App from './App.vue'
|
||||
import ElementUI from 'element-ui';
|
||||
import VueRouter from 'vue-router'
|
||||
import 'element-ui/lib/theme-chalk/index.css';
|
||||
import router from './router/index'
|
||||
import { copyToClipboard } from '@/util/util'
|
||||
import i18n from '@/config/i18n'
|
||||
Vue.use(VueRouter)
|
||||
Vue.config.productionTip = false
|
||||
Vue.use(ElementUI);
|
||||
import axios from "./utils/axios";
|
||||
|
||||
/**
|
||||
* 复制
|
||||
*/
|
||||
const ins = createApp(App)
|
||||
ins.use(VueRouter)
|
||||
ins.use(ElementUI)
|
||||
ins.mount('#app')
|
||||
const app = createApp(App)
|
||||
app.config.globalProperties.$http = axios
|
||||
app.use(ElementPlus)
|
||||
app.mount('#app')
|
||||
|
||||
@@ -1,89 +0,0 @@
|
||||
:root {
|
||||
font-family: Inter, system-ui, Avenir, Helvetica, Arial, sans-serif;
|
||||
line-height: 1.5;
|
||||
font-weight: 400;
|
||||
|
||||
color-scheme: light dark;
|
||||
color: rgba(255, 255, 255, 0.87);
|
||||
background-color: #242424;
|
||||
|
||||
font-synthesis: none;
|
||||
text-rendering: optimizeLegibility;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
-webkit-text-size-adjust: 100%;
|
||||
}
|
||||
|
||||
a {
|
||||
font-weight: 500;
|
||||
color: #646cff;
|
||||
text-decoration: inherit;
|
||||
}
|
||||
a:hover {
|
||||
color: #535bf2;
|
||||
}
|
||||
|
||||
a {
|
||||
font-weight: 500;
|
||||
color: #646cff;
|
||||
text-decoration: inherit;
|
||||
}
|
||||
a:hover {
|
||||
color: #535bf2;
|
||||
}
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
display: flex;
|
||||
place-items: center;
|
||||
min-width: 320px;
|
||||
min-height: 100vh;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: 3.2em;
|
||||
line-height: 1.1;
|
||||
}
|
||||
|
||||
button {
|
||||
border-radius: 8px;
|
||||
border: 1px solid transparent;
|
||||
padding: 0.6em 1.2em;
|
||||
font-size: 1em;
|
||||
font-weight: 500;
|
||||
font-family: inherit;
|
||||
background-color: #1a1a1a;
|
||||
cursor: pointer;
|
||||
transition: border-color 0.25s;
|
||||
}
|
||||
button:hover {
|
||||
border-color: #646cff;
|
||||
}
|
||||
button:focus,
|
||||
button:focus-visible {
|
||||
outline: 4px auto -webkit-focus-ring-color;
|
||||
}
|
||||
|
||||
.card {
|
||||
padding: 2em;
|
||||
}
|
||||
|
||||
#app {
|
||||
max-width: 1280px;
|
||||
margin: 0 auto;
|
||||
padding: 2rem;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: light) {
|
||||
:root {
|
||||
color: #213547;
|
||||
background-color: #ffffff;
|
||||
}
|
||||
a:hover {
|
||||
color: #747bff;
|
||||
}
|
||||
button {
|
||||
background-color: #f9f9f9;
|
||||
}
|
||||
}
|
||||
6
src/utils/axios.js
Normal file
6
src/utils/axios.js
Normal file
@@ -0,0 +1,6 @@
|
||||
import axios from "axios";
|
||||
|
||||
const ins = axios.create({
|
||||
|
||||
})
|
||||
export default ins
|
||||
7
src/utils/env.js
Normal file
7
src/utils/env.js
Normal file
@@ -0,0 +1,7 @@
|
||||
export const OPEN_AI_KEY = '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'
|
||||
//ai头像
|
||||
export const AI_AVATAR = "https://th.bing.com/th?id=ODL.3e2fbff4543f0d3632d34be6d02adc93&w=100&h=100&c=12&pcl=faf9f7&o=6&dpr=1.5&pid=13.1"
|
||||
//用户头像
|
||||
export const USER_AVATAR = "https://avatars.githubusercontent.com/u/20533272?v=4"
|
||||
|
||||
|
||||
31
src/utils/models.js
Normal file
31
src/utils/models.js
Normal file
@@ -0,0 +1,31 @@
|
||||
import {AI_AVATAR} from "./env";
|
||||
|
||||
class BaseModel {
|
||||
constructor(props) {
|
||||
for (const k in props) {
|
||||
this[k] = props[k];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export class ChatGPT extends BaseModel {
|
||||
constructor() {
|
||||
super({
|
||||
avatar: AI_AVATAR,
|
||||
name: 'ChatGPT',
|
||||
id: "gpt-3.5-turbo",
|
||||
desc: "ChatGPT-3.5所基于的模型"
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export class ChatGLM extends BaseModel {
|
||||
constructor() {
|
||||
super({
|
||||
avatar: AI_AVATAR,
|
||||
name: 'ChatGLM',
|
||||
id: "chatglm-6b",
|
||||
desc: "ChatGLM-6B所基于的模型"
|
||||
});
|
||||
}
|
||||
}
|
||||
25
src/utils/tools.js
Normal file
25
src/utils/tools.js
Normal file
@@ -0,0 +1,25 @@
|
||||
/**
|
||||
* 复制到剪切板
|
||||
*/
|
||||
|
||||
export function copyToClipboard(content) {
|
||||
const clipboardData = window.clipboardData
|
||||
if (clipboardData) {
|
||||
clipboardData.clearData()
|
||||
clipboardData.setData('Text', content)
|
||||
return true
|
||||
} else if (document.execCommand) {
|
||||
const el = document.createElement('textarea')
|
||||
el.value = content
|
||||
el.setAttribute('readonly', '')
|
||||
el.style.position = 'absolute'
|
||||
el.style.left = '-9999px'
|
||||
document.body.appendChild(el)
|
||||
el.select()
|
||||
document.execCommand('copy')
|
||||
document.body.removeChild(el)
|
||||
return true
|
||||
}
|
||||
return false
|
||||
|
||||
}
|
||||
@@ -1,7 +1,15 @@
|
||||
import { defineConfig } from 'vite'
|
||||
import vue from '@vitejs/plugin-vue'
|
||||
import {defineConfig} from 'vite'
|
||||
|
||||
// https://vitejs.dev/config/
|
||||
export default defineConfig({
|
||||
plugins: [vue()],
|
||||
resolve: {
|
||||
extensions: ['.mjs', '.js', '.mts', '.json', '.vue']
|
||||
},
|
||||
server: {
|
||||
open: true,
|
||||
host: '0.0.0.0',
|
||||
port: 10109
|
||||
}
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user