一大波更新
parent
bd97d5aebc
commit
4f6c1399e2
|
@ -30,6 +30,7 @@ export default {
|
||||||
'es.shim': '//jscdn.ink/es.shim/latest/index.js',
|
'es.shim': '//jscdn.ink/es.shim/latest/index.js',
|
||||||
vue: '//jscdn.ink/vue/3.2.47/vue.runtime.esm-browser.prod.js',
|
vue: '//jscdn.ink/vue/3.2.47/vue.runtime.esm-browser.prod.js',
|
||||||
wkit: '//jscdn.ink/wkit/latest/index.js',
|
wkit: '//jscdn.ink/wkit/latest/index.js',
|
||||||
|
'@bd/ui/': '//jscdn.ink/@bd/ui/latest/',
|
||||||
'@bd/core': '//jscdn.ink/wkit/latest/index.js',
|
'@bd/core': '//jscdn.ink/wkit/latest/index.js',
|
||||||
fetch: '//jscdn.ink/@bytedo/fetch/latest/next.js'
|
fetch: '//jscdn.ink/@bytedo/fetch/latest/next.js'
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
{
|
{
|
||||||
"name": "fite-app",
|
"name": "chatgpt-client",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"start": "fite dev",
|
"start": "fite dev",
|
||||||
"build": "fite build"
|
"build": "fite build"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"fite": "^1.1.6"
|
"fite": "^1.1.7"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
28
src/app.vue
28
src/app.vue
|
@ -4,15 +4,28 @@
|
||||||
<Aside />
|
<Aside />
|
||||||
<Chat />
|
<Chat />
|
||||||
</div>
|
</div>
|
||||||
|
<wc-layer ref="preferences" mask>
|
||||||
|
<Preferences />
|
||||||
|
<wc-icon class="close" name="close" @click="$refs.preferences.close()" />
|
||||||
|
</wc-layer>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import Topbar from './views/topbar.vue'
|
import Topbar from './views/topbar.vue'
|
||||||
import Aside from './views/aside.vue'
|
import Aside from './views/aside.vue'
|
||||||
import Chat from './views/chat.vue'
|
import Chat from './views/chat.vue'
|
||||||
|
import Preferences from './views/preferences.vue'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: { Topbar, Aside, Chat }
|
components: { Topbar, Aside, Chat, Preferences },
|
||||||
|
mounted() {
|
||||||
|
this.openPreferencesPanel()
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
openPreferencesPanel() {
|
||||||
|
this.$refs.preferences.show()
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
@ -44,3 +57,16 @@ body {
|
||||||
height: calc(100% - 48px);
|
height: calc(100% - 48px);
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.close {
|
||||||
|
position: absolute;
|
||||||
|
right: 16px;
|
||||||
|
top: 12px;
|
||||||
|
--size: 16px;
|
||||||
|
cursor: pointer;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
color: var(--color-red-1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
|
@ -0,0 +1,27 @@
|
||||||
|
/**
|
||||||
|
* {}
|
||||||
|
* @author yutent<yutent.io@gmail.com>
|
||||||
|
* @date 2023/05/31 10:27:01
|
||||||
|
*/
|
||||||
|
|
||||||
|
export default {
|
||||||
|
tables: [
|
||||||
|
/**
|
||||||
|
* @column id {String} 设置项
|
||||||
|
* @column value {String} 设置项的值
|
||||||
|
*/
|
||||||
|
{ name: 'preferences', primaryKey: 'id' },
|
||||||
|
/**
|
||||||
|
* @column id {String} 会话ID
|
||||||
|
* @column name {String} 会话名称
|
||||||
|
*/
|
||||||
|
{ name: 'conversations', primaryKey: 'id' },
|
||||||
|
/**
|
||||||
|
* @column id {String} 记录ID
|
||||||
|
* @column conversation {String} 所属会话ID
|
||||||
|
* @column role {String} 角色, system/user/assistant
|
||||||
|
* @column content {String} 消息内容
|
||||||
|
*/
|
||||||
|
{ name: 'records', primaryKey: 'id', indexes: ['conversation'] }
|
||||||
|
]
|
||||||
|
}
|
|
@ -4,6 +4,51 @@
|
||||||
* @date 2023/05/29 18:33:42
|
* @date 2023/05/29 18:33:42
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
export function createStore(name, version = 1) {
|
||||||
|
let req = window.indexedDB.open(name, version)
|
||||||
|
let _ = defer()
|
||||||
|
|
||||||
|
req.addEventListener('upgradeneeded', ev => {
|
||||||
|
_.resolve(ev.target.result)
|
||||||
|
})
|
||||||
|
req.addEventListener('error', ev => {
|
||||||
|
_.reject(ev.target.result.error)
|
||||||
|
})
|
||||||
|
return _.promise
|
||||||
|
}
|
||||||
|
|
||||||
|
export function deleteStore(name) {
|
||||||
|
let req = window.indexedDB.deleteDatabase(name)
|
||||||
|
let _ = defer()
|
||||||
|
|
||||||
|
req.addEventListener('success', ev => {
|
||||||
|
_.resolve()
|
||||||
|
})
|
||||||
|
req.addEventListener('error', ev => {
|
||||||
|
_.reject(ev.target.result.error)
|
||||||
|
})
|
||||||
|
return _.promise
|
||||||
|
}
|
||||||
|
|
||||||
|
export function createTable(db, { name, config }) {
|
||||||
|
var opt = {}
|
||||||
|
var table
|
||||||
|
if (config.primaryKey) {
|
||||||
|
opt.keyPath = config.primaryKey
|
||||||
|
}
|
||||||
|
if (config.autoIncrement) {
|
||||||
|
opt.autoIncrement = config.autoIncrement
|
||||||
|
}
|
||||||
|
|
||||||
|
table = db.createObjectStore(name, opt)
|
||||||
|
|
||||||
|
if (config.indexes && config.indexes.length) {
|
||||||
|
for (let it of config.indexes) {
|
||||||
|
table.createIndex(it + '_idx', it)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export function getStore(name) {
|
export function getStore(name) {
|
||||||
let req = window.indexedDB.open(name)
|
let req = window.indexedDB.open(name)
|
||||||
let _ = defer()
|
let _ = defer()
|
||||||
|
|
|
@ -6,6 +6,11 @@
|
||||||
|
|
||||||
import 'es.shim'
|
import 'es.shim'
|
||||||
|
|
||||||
|
import '@bd/ui/space/index.js'
|
||||||
|
import '@bd/ui/layer/index.js'
|
||||||
|
import '@bd/ui/tabs/index.js'
|
||||||
|
import '@bd/ui/slider/index.js'
|
||||||
|
|
||||||
import { createApp } from 'vue'
|
import { createApp } from 'vue'
|
||||||
import App from './app.vue'
|
import App from './app.vue'
|
||||||
|
|
||||||
|
|
15
src/store.js
15
src/store.js
|
@ -1,16 +1,23 @@
|
||||||
import { reactive } from 'vue'
|
import { reactive } from 'vue'
|
||||||
|
|
||||||
const store = reactive({
|
const store = reactive({
|
||||||
API_KEY: localStorage.getItem('API_KEY'),
|
|
||||||
BASE_URL: localStorage.getItem('BASE_URL'),
|
|
||||||
|
|
||||||
conversations: [],
|
conversations: [],
|
||||||
conversation: {
|
conversation: {
|
||||||
id: '',
|
id: '',
|
||||||
tokens: 0,
|
tokens: 0,
|
||||||
records: []
|
records: []
|
||||||
},
|
},
|
||||||
records: []
|
records: [],
|
||||||
|
|
||||||
|
gpt: {
|
||||||
|
apiKey: localStorage.getItem('API_KEY') || '',
|
||||||
|
baseUrl: localStorage.getItem('BASE_URL') || '//api.openai.com',
|
||||||
|
model: 'gpt-3.5-turbo',
|
||||||
|
temperature: 0.8,
|
||||||
|
top_p: 1,
|
||||||
|
presence_penalty: 1,
|
||||||
|
frequency_penalty: 0
|
||||||
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
export default function (app) {
|
export default function (app) {
|
||||||
|
|
|
@ -0,0 +1,130 @@
|
||||||
|
<template>
|
||||||
|
<wc-tabs class="preferences" type="card" :tab="tab">
|
||||||
|
<wc-tab>
|
||||||
|
<span slot="label"> 常规<wc-icon name="home"></wc-icon> </span>
|
||||||
|
<div class="form">
|
||||||
|
<wc-space>
|
||||||
|
<span class="label">接口域名: </span>
|
||||||
|
<wc-input placeholder="baseUrl" v-model="$store.gpt.baseUrl" />
|
||||||
|
</wc-space>
|
||||||
|
<wc-space>
|
||||||
|
<span class="label">APIKEY: </span>
|
||||||
|
<wc-input
|
||||||
|
placeholder="填写你自己的apikey"
|
||||||
|
v-model="$store.gpt.apiKey"
|
||||||
|
/>
|
||||||
|
</wc-space>
|
||||||
|
<wc-space>
|
||||||
|
<span class="label">模型: </span>
|
||||||
|
<wc-select>
|
||||||
|
<wc-option></wc-option>
|
||||||
|
</wc-select>
|
||||||
|
</wc-space>
|
||||||
|
</div>
|
||||||
|
</wc-tab>
|
||||||
|
|
||||||
|
<wc-tab>
|
||||||
|
<span slot="label"> 模型调整<wc-icon name="option"></wc-icon> </span>
|
||||||
|
<div class="form">
|
||||||
|
<wc-space>
|
||||||
|
<span class="label">temperature: </span>
|
||||||
|
<wc-slider
|
||||||
|
:step="0.01"
|
||||||
|
:max="2"
|
||||||
|
:min="0"
|
||||||
|
v-model="$store.gpt.temperature"
|
||||||
|
/>
|
||||||
|
</wc-space>
|
||||||
|
<wc-space>
|
||||||
|
<span class="label">top_p: </span>
|
||||||
|
<wc-slider
|
||||||
|
:step="0.01"
|
||||||
|
:max="1"
|
||||||
|
:min="0"
|
||||||
|
v-model="$store.gpt.top_p"
|
||||||
|
/>
|
||||||
|
</wc-space>
|
||||||
|
<wc-space>
|
||||||
|
<span class="label">presence_penalty: </span>
|
||||||
|
<wc-slider
|
||||||
|
:step="0.01"
|
||||||
|
:max="2"
|
||||||
|
:min="-2"
|
||||||
|
v-model="$store.gpt.presence_penalty"
|
||||||
|
/>
|
||||||
|
</wc-space>
|
||||||
|
<wc-space>
|
||||||
|
<span class="label">frequency_penalty: </span>
|
||||||
|
<wc-slider
|
||||||
|
:step="0.01"
|
||||||
|
:max="2"
|
||||||
|
:min="-2"
|
||||||
|
v-model="$store.gpt.frequency_penalty"
|
||||||
|
/>
|
||||||
|
</wc-space>
|
||||||
|
</div>
|
||||||
|
</wc-tab>
|
||||||
|
|
||||||
|
<wc-tab>
|
||||||
|
<span slot="label"> 关于<wc-icon name="info"></wc-icon> </span>
|
||||||
|
<div class="about">
|
||||||
|
<p>
|
||||||
|
本项目为免费开源项目, 并不提供chatgpt的apiKey,
|
||||||
|
需要你自己注册申请自己的apiKey方可使用。我们不提供任何关于注册,申请账号的服务。
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
本项目没有自己服务端, 所以不需要注册, 也不需要登录,
|
||||||
|
更不会保存你的任何信息, 你的一切操作,以及产生的数据, 全是在本地储存。
|
||||||
|
所以, 当你清除本地缓存, 或更换浏览器, 或更换电脑时,
|
||||||
|
一切数据都将不复存在。
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
使用本项目时, 请遵循所在地区/国家的相关法律法规, 由此产生的一切问题,
|
||||||
|
与作者本人无关。
|
||||||
|
</p>
|
||||||
|
<p>你使用本项目时, 即默认你已知晓并同意以上说明。</p>
|
||||||
|
</div>
|
||||||
|
</wc-tab>
|
||||||
|
</wc-tabs>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
tab: 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.preferences {
|
||||||
|
width: 640px;
|
||||||
|
height: 480px;
|
||||||
|
border-radius: 3px;
|
||||||
|
|
||||||
|
.form {
|
||||||
|
padding: 32px;
|
||||||
|
|
||||||
|
.label {
|
||||||
|
width: 80px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.about {
|
||||||
|
padding: 32px;
|
||||||
|
|
||||||
|
p {
|
||||||
|
margin-bottom: 16px;
|
||||||
|
text-indent: 2em;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
wc-space {
|
||||||
|
wc-input {
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -1,7 +1,7 @@
|
||||||
<template>
|
<template>
|
||||||
<main class="noselect topbar">
|
<main class="noselect topbar">
|
||||||
<section class="btns"><i></i><i></i><i></i></section>
|
<section class="btns"><i></i><i></i><i></i></section>
|
||||||
<div class="option">•••</div>
|
<div class="option" @click="openPanel">•••</div>
|
||||||
</main>
|
</main>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
@ -11,6 +11,11 @@ export default {
|
||||||
return {
|
return {
|
||||||
content: '这是关于我们页面'
|
content: '这是关于我们页面'
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
openPanel() {
|
||||||
|
this.$root.openPreferencesPanel()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
@ -45,5 +50,6 @@ export default {
|
||||||
}
|
}
|
||||||
.option {
|
.option {
|
||||||
font-size: 22px;
|
font-size: 22px;
|
||||||
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
Loading…
Reference in New Issue