diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 00000000..ff05a67c --- /dev/null +++ b/.dockerignore @@ -0,0 +1,4 @@ +.git +frontend/node_modules +.idea +tmp diff --git a/.editorconfig b/.editorconfig index 7f5d6d78..b3caa4ff 100755 --- a/.editorconfig +++ b/.editorconfig @@ -5,11 +5,14 @@ block_comment_start = /* block_comment_end = */ charset = utf-8 indent_style = space -indent_size = 4 +indent_size = 2 end_of_line = lf insert_final_newline = true trim_trailing_whitespace = true +[*.go] +indent_size = 4 + [README.md] indent_style = space indent_size = 4 diff --git a/dev.Dockerfile b/dev.Dockerfile index 5300a950..b7c8df00 100644 --- a/dev.Dockerfile +++ b/dev.Dockerfile @@ -5,7 +5,7 @@ EXPOSE 80 443 # COPY resources/development/sources.list /etc/apt/sources.list -ENV GO_VERSION="1.21.0" +ENV GO_VERSION="1.21.4" ENV GO_ARCH="linux-arm64" ENV GO_TAR="go${GO_VERSION}.${GO_ARCH}.tar.gz" ENV PATH="${PATH}:/usr/local/go/bin" @@ -14,7 +14,15 @@ RUN set -x \ # create nginx user/group first, to be consistent throughout docker variants && addgroup --system --gid 101 nginx \ && adduser --system --disabled-login --ingroup nginx --no-create-home --home /nonexistent --gecos "nginx user" --shell /bin/false --uid 101 nginx \ - && apt update && apt install -y wget nginx gcc curl + && apt update && apt install gcc curl gnupg2 ca-certificates lsb-release ubuntu-keyring wget -y \ + && curl https://nginx.org/keys/nginx_signing.key | gpg --dearmor \ + | tee /usr/share/keyrings/nginx-archive-keyring.gpg >/dev/null \ + && echo "deb [signed-by=/usr/share/keyrings/nginx-archive-keyring.gpg] \ + http://nginx.org/packages/ubuntu `lsb_release -cs` nginx" \ + | tee /etc/apt/sources.list.d/nginx.list + +RUN echo "Package: *\nPin: origin nginx.org\nPin: release o=nginx\nPin-Priority: 900\n" | tee /etc/apt/preferences.d/99nginx \ + && apt update && apt install nginx -y RUN wget https://go.dev/dl/${GO_TAR} && \ rm -rf /usr/local/go && tar -C /usr/local -xzf ${GO_TAR} && rm -f ${GO_TAR} diff --git a/frontend/.vscode/extensions.json b/frontend/.vscode/extensions.json index 26d404c1..57011895 100644 --- a/frontend/.vscode/extensions.json +++ b/frontend/.vscode/extensions.json @@ -1,5 +1,5 @@ { - "recommendations": [ - "Vue.volar" - ] + "recommendations": [ + "Vue.volar" + ] } diff --git a/frontend/.yarnrc.yml b/frontend/.yarnrc.yml deleted file mode 100644 index 09b10123..00000000 --- a/frontend/.yarnrc.yml +++ /dev/null @@ -1 +0,0 @@ -nodeLinker: pnp diff --git a/frontend/components.d.ts b/frontend/components.d.ts index df6a2501..1cbf169d 100644 --- a/frontend/components.d.ts +++ b/frontend/components.d.ts @@ -3,11 +3,9 @@ // @ts-nocheck // Generated by unplugin-vue-components // Read more: https://github.com/vuejs/core/pull/3399 -import '@vue/runtime-core' - export {} -declare module '@vue/runtime-core' { +declare module 'vue' { export interface GlobalComponents { AAlert: typeof import('ant-design-vue/es')['Alert'] AAvatar: typeof import('ant-design-vue/es')['Avatar'] @@ -87,5 +85,9 @@ declare module '@vue/runtime-core' { StdDataEntryComponentsStdSelect: typeof import('./src/components/StdDataEntry/components/StdSelect.vue')['default'] StdDataEntryComponentsStdSelector: typeof import('./src/components/StdDataEntry/components/StdSelector.vue')['default'] StdDataEntryStdFormItem: typeof import('./src/components/StdDataEntry/StdFormItem.vue')['default'] + SwitchAppearanceIconsVPIconMoon: typeof import('./src/components/SwitchAppearance/icons/VPIconMoon.vue')['default'] + SwitchAppearanceIconsVPIconSun: typeof import('./src/components/SwitchAppearance/icons/VPIconSun.vue')['default'] + SwitchAppearanceSwitchAppearance: typeof import('./src/components/SwitchAppearance/SwitchAppearance.vue')['default'] + VPSwitchVPSwitch: typeof import('./src/components/VPSwitch/VPSwitch.vue')['default'] } } diff --git a/frontend/gettext.config.js b/frontend/gettext.config.js index 88c8639f..48bb7d5f 100644 --- a/frontend/gettext.config.js +++ b/frontend/gettext.config.js @@ -1,7 +1,7 @@ const i18n = require('./i18n.json') module.exports = { - output: { - locales: Object.keys(i18n), - }, + output: { + locales: Object.keys(i18n), + }, } diff --git a/frontend/i18n.json b/frontend/i18n.json index 078a874b..ff4c7c1c 100644 --- a/frontend/i18n.json +++ b/frontend/i18n.json @@ -1,8 +1,8 @@ { - "en": "En", - "zh_CN": "简", - "zh_TW": "繁", - "fr_FR": "Fr", - "es": "Es", - "ru_RU": "Ru" + "en": "En", + "zh_CN": "简", + "zh_TW": "繁", + "fr_FR": "Fr", + "es": "Es", + "ru_RU": "Ru" } diff --git a/frontend/index.html b/frontend/index.html index 5124b453..afed1f96 100644 --- a/frontend/index.html +++ b/frontend/index.html @@ -1,15 +1,15 @@ - - - - - <%- title %> + + + + + <%- title %>
diff --git a/frontend/package.json b/frontend/package.json index eef2446e..e0d95ab1 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -1,61 +1,58 @@ { - "name": "nginx-ui-frontend-next", - "private": true, - "version": "2.0.0-beta.4", - "type": "commonjs", - "scripts": { - "dev": "vite", - "build": "vite build", - "preview": "vite preview", - "gettext:extract": "vue-gettext-extract", - "gettext:compile": "vue-gettext-compile" - }, - "dependencies": { - "@ant-design/icons-vue": "^6.1.0", - "@formkit/auto-animate": "^0.8.0", - "@types/lodash": "^4.14.188", - "@types/marked": "^4.0.8", - "@types/nprogress": "^0.2.0", - "@types/sortablejs": "^1.15.0", - "@vue/reactivity": "^3.3.4", - "@vue/shared": "^3.3.4", - "ant-design-vue": "^3.2.17", - "apexcharts": "^3.36.3", - "axios": "^1.6.0", - "dayjs": "^1.11.7", - "highlight.js": "^11.7.0", - "lodash": "^4.17.21", - "marked": "^4.2.5", - "nprogress": "^0.2.0", - "pinia": "^2.0.28", - "pinia-plugin-persistedstate": "^3.0.2", - "reconnecting-websocket": "^4.4.0", - "sortablejs": "^1.15.0", - "vite-plugin-build-id": "^0.2.3", - "vue": "^3.2.47", - "vue-github-button": "https://github.com/0xJacky/vue-github-button", - "vue-router": "^4.1.6", - "vue3-ace-editor": "2.2.2", - "vue3-apexcharts": "^1.4.1", - "vue3-gettext": "^2.5.0-alpha.1", - "vuedraggable": "^4.1.0", - "xterm": "^5.1.0", - "xterm-addon-attach": "^0.8.0", - "xterm-addon-fit": "^0.7.0" - }, - "devDependencies": { - "@vitejs/plugin-vue": "^4.2.1", - "@vitejs/plugin-vue-jsx": "^3.0.1", - "@vue/compiler-sfc": "^3.3.4", - "@zougt/vite-plugin-theme-preprocessor": "^1.4.8", - "ace-builds": "^1.30.0", - "less": "^4.1.3", - "typescript": "^5.0.4", - "unplugin-vue-components": "^0.24.1", - "vite": "^4.5.0", - "vite-plugin-html": "^3.2.0", - "vite-svg-loader": "^4.0.0", - "vue-tsc": "^1.6.1" - }, - "packageManager": "yarn@3.6.4" + "name": "nginx-ui-frontend-next", + "private": true, + "version": "2.0.0-beta.4", + "type": "commonjs", + "scripts": { + "dev": "vite", + "build": "vite build", + "preview": "vite preview", + "gettext:extract": "vue-gettext-extract", + "gettext:compile": "vue-gettext-compile" + }, + "dependencies": { + "@ant-design/icons-vue": "^7.0.1", + "@formkit/auto-animate": "^0.8.0", + "@types/lodash": "^4.14.202", + "@types/nprogress": "^0.2.0", + "@types/sortablejs": "^1.15.0", + "@vue/reactivity": "^3.3.9", + "@vue/shared": "^3.3.9", + "ant-design-vue": "4.0.7", + "apexcharts": "^3.36.3", + "axios": "^1.6.2", + "dayjs": "^1.11.10", + "highlight.js": "^11.9.0", + "lodash": "^4.17.21", + "marked": "^10.0.0", + "nprogress": "^0.2.0", + "pinia": "^2.1.7", + "pinia-plugin-persistedstate": "^3.0.2", + "reconnecting-websocket": "^4.4.0", + "sortablejs": "^1.15.0", + "vite-plugin-build-id": "^0.2.3", + "vue": "^3.3.9", + "vue-github-button": "https://github.com/0xJacky/vue-github-button", + "vue-router": "^4.2.5", + "vue3-ace-editor": "2.2.4", + "vue3-apexcharts": "^1.4.4", + "vue3-gettext": "^3.0.0-beta.2", + "vuedraggable": "^4.1.0", + "xterm": "^5.3.0", + "xterm-addon-attach": "^0.9.0", + "xterm-addon-fit": "^0.8.0" + }, + "devDependencies": { + "@vitejs/plugin-vue": "^4.5.0", + "@vitejs/plugin-vue-jsx": "^3.1.0", + "@vue/compiler-sfc": "^3.3.9", + "ace-builds": "^1.31.2", + "less": "^4.2.0", + "typescript": "^5.3.2", + "unplugin-vue-components": "^0.25.2", + "vite": "^5.0.2", + "vite-plugin-html": "^3.2.0", + "vite-svg-loader": "^5.1.0", + "vue-tsc": "^1.8.22" + } } diff --git a/frontend/src/App.vue b/frontend/src/App.vue index c7b00ad7..37654e9d 100644 --- a/frontend/src/App.vue +++ b/frontend/src/App.vue @@ -2,39 +2,42 @@ // This starter template is using Vue 3 + + diff --git a/frontend/src/api/analytic.ts b/frontend/src/api/analytic.ts index 9ca6edb4..388ccc9b 100644 --- a/frontend/src/api/analytic.ts +++ b/frontend/src/api/analytic.ts @@ -1,9 +1,9 @@ import http from '@/lib/http' const analytic = { - init() { - return http.get('/analytic/init') - } + init() { + return http.get('/analytic/init') + } } export default analytic diff --git a/frontend/src/api/auth.ts b/frontend/src/api/auth.ts index f33d72f2..1f484e81 100644 --- a/frontend/src/api/auth.ts +++ b/frontend/src/api/auth.ts @@ -5,28 +5,28 @@ const user = useUserStore() const {login, logout} = user const auth = { - async login(name: string, password: string) { - return http.post('/login', { - name: name, - password: password - }).then(r => { - login(r.token) - }) - }, - async casdoorLogin(code: string, state: string) { - await http.post("/casdoor_callback", { - code: code, - state: state, - }) - .then((r) => { - login(r.token) - }) - }, - logout() { - return http.delete('/logout').then(async () => { - logout() - }) - } + async login(name: string, password: string) { + return http.post('/login', { + name: name, + password: password + }).then(r => { + login(r.token) + }) + }, + async casdoorLogin(code: string, state: string) { + await http.post('/casdoor_callback', { + code: code, + state: state + }) + .then((r) => { + login(r.token) + }) + }, + logout() { + return http.delete('/logout').then(async () => { + logout() + }) + } } export default auth diff --git a/frontend/src/api/auto_cert.ts b/frontend/src/api/auto_cert.ts index 46c6910f..ff38b1ea 100644 --- a/frontend/src/api/auto_cert.ts +++ b/frontend/src/api/auto_cert.ts @@ -1,13 +1,13 @@ import http from '@/lib/http' const auto_cert = { - get_dns_providers() { - return http.get('/auto_cert/dns/providers') - }, + get_dns_providers() { + return http.get('/auto_cert/dns/providers') + }, - get_dns_provider(code: string) { - return http.get('/auto_cert/dns/provider/' + code) - } + get_dns_provider(code: string) { + return http.get('/auto_cert/dns/provider/' + code) + } } export default auto_cert diff --git a/frontend/src/api/curd.ts b/frontend/src/api/curd.ts index 3ba11b40..b662a62e 100644 --- a/frontend/src/api/curd.ts +++ b/frontend/src/api/curd.ts @@ -1,34 +1,34 @@ import http from '@/lib/http' class Curd { - protected readonly baseUrl: string - protected readonly plural: string + protected readonly baseUrl: string + protected readonly plural: string - get_list = this._get_list.bind(this) - get = this._get.bind(this) - save = this._save.bind(this) - destroy = this._destroy.bind(this) + get_list = this._get_list.bind(this) + get = this._get.bind(this) + save = this._save.bind(this) + destroy = this._destroy.bind(this) - constructor(baseUrl: string, plural: string | null = null) { - this.baseUrl = baseUrl - this.plural = plural ?? this.baseUrl + 's' - } + constructor(baseUrl: string, plural: string | null = null) { + this.baseUrl = baseUrl + this.plural = plural ?? this.baseUrl + 's' + } - _get_list(params: any = null) { - return http.get(this.plural, {params: params}) - } + _get_list(params: any = null) { + return http.get(this.plural, {params: params}) + } - _get(id: any = null) { - return http.get(this.baseUrl + (id ? '/' + id : '')) - } + _get(id: any = null) { + return http.get(this.baseUrl + (id ? '/' + id : '')) + } - _save(id: any = null, data: any, config: any = undefined) { - return http.post(this.baseUrl + (id ? '/' + id : ''), data, config) - } + _save(id: any = null, data: any, config: any = undefined) { + return http.post(this.baseUrl + (id ? '/' + id : ''), data, config) + } - _destroy(id: any = null) { - return http.delete(this.baseUrl + '/' + id) - } + _destroy(id: any = null) { + return http.delete(this.baseUrl + '/' + id) + } } export default Curd diff --git a/frontend/src/api/domain.ts b/frontend/src/api/domain.ts index a6c3aec9..6e783af8 100644 --- a/frontend/src/api/domain.ts +++ b/frontend/src/api/domain.ts @@ -1,35 +1,35 @@ import Curd from '@/api/curd' import http from '@/lib/http' -import {AxiosRequestConfig} from "axios/index"; +import {AxiosRequestConfig} from 'axios/index' class Domain extends Curd { - enable(name: string, config: AxiosRequestConfig) { - return http.post(this.baseUrl + '/' + name + '/enable', undefined, config) - } + enable(name: string, config: AxiosRequestConfig) { + return http.post(this.baseUrl + '/' + name + '/enable', undefined, config) + } - disable(name: string) { - return http.post(this.baseUrl + '/' + name + '/disable') - } + disable(name: string) { + return http.post(this.baseUrl + '/' + name + '/disable') + } - get_template() { - return http.get('template') - } + get_template() { + return http.get('template') + } - add_auto_cert(domain: string, data: any) { - return http.post('auto_cert/' + domain, data) - } + add_auto_cert(domain: string, data: any) { + return http.post('auto_cert/' + domain, data) + } - remove_auto_cert(domain: string) { - return http.delete('auto_cert/' + domain) - } + remove_auto_cert(domain: string) { + return http.delete('auto_cert/' + domain) + } - duplicate(name: string, data: any) { - return http.post(this.baseUrl + '/' + name + '/duplicate', data) - } + duplicate(name: string, data: any) { + return http.post(this.baseUrl + '/' + name + '/duplicate', data) + } - advance_mode(name: string, data: any) { - return http.post(this.baseUrl + '/' + name + '/advance', data) - } + advance_mode(name: string, data: any) { + return http.post(this.baseUrl + '/' + name + '/advance', data) + } } const domain = new Domain('/domain') diff --git a/frontend/src/api/install.ts b/frontend/src/api/install.ts index 4f15603f..df3209b2 100644 --- a/frontend/src/api/install.ts +++ b/frontend/src/api/install.ts @@ -1,12 +1,12 @@ import http from '@/lib/http' const install = { - get_lock() { - return http.get('/install') - }, - install_nginx_ui(data: any) { - return http.post('/install', data) - } + get_lock() { + return http.get('/install') + }, + install_nginx_ui(data: any) { + return http.post('/install', data) + } } export default install diff --git a/frontend/src/api/nginx_log.ts b/frontend/src/api/nginx_log.ts index b38e4242..e44347fc 100644 --- a/frontend/src/api/nginx_log.ts +++ b/frontend/src/api/nginx_log.ts @@ -1,15 +1,15 @@ import http from '@/lib/http' export interface INginxLogData { - type: string - conf_name: string - server_idx: number - directive_idx: number + type: string + conf_name: string + server_idx: number + directive_idx: number } const nginx_log = { - page(page = 0, data: INginxLogData) { - return http.post('/nginx_log?page=' + page, data) - } + page(page = 0, data: INginxLogData) { + return http.post('/nginx_log?page=' + page, data) + } } export default nginx_log diff --git a/frontend/src/api/ngx.ts b/frontend/src/api/ngx.ts index 62e3db1b..96f9de97 100644 --- a/frontend/src/api/ngx.ts +++ b/frontend/src/api/ngx.ts @@ -1,33 +1,33 @@ import http from '@/lib/http' const ngx = { - build_config(ngxConfig: any) { - return http.post('/ngx/build_config', ngxConfig) - }, + build_config(ngxConfig: any) { + return http.post('/ngx/build_config', ngxConfig) + }, - tokenize_config(content: string) { - return http.post('/ngx/tokenize_config', {content}) - }, + tokenize_config(content: string) { + return http.post('/ngx/tokenize_config', {content}) + }, - format_code(content: string) { - return http.post('/ngx/format_code', {content}) - }, + format_code(content: string) { + return http.post('/ngx/format_code', {content}) + }, - status() { - return http.get('/nginx/status') - }, + status() { + return http.get('/nginx/status') + }, - reload() { - return http.post('/nginx/reload') - }, + reload() { + return http.post('/nginx/reload') + }, - restart() { - return http.post('/nginx/restart') - }, + restart() { + return http.post('/nginx/restart') + }, - test() { - return http.post('/nginx/test') - } + test() { + return http.post('/nginx/test') + } } export default ngx diff --git a/frontend/src/api/openai.ts b/frontend/src/api/openai.ts index ea3e24ea..218cb0d7 100644 --- a/frontend/src/api/openai.ts +++ b/frontend/src/api/openai.ts @@ -1,9 +1,9 @@ import http from '@/lib/http' const openai = { - store_record(data: any) { - return http.post('/chat_gpt_record', data) - } + store_record(data: any) { + return http.post('/chat_gpt_record', data) + } } export default openai diff --git a/frontend/src/api/settings.ts b/frontend/src/api/settings.ts index 30e03c31..0666b9b5 100644 --- a/frontend/src/api/settings.ts +++ b/frontend/src/api/settings.ts @@ -1,12 +1,12 @@ import http from '@/lib/http' const settings = { - get() { - return http.get('/settings') - }, - save(data: any) { - return http.post('/settings', data) - } + get() { + return http.get('/settings') + }, + save(data: any) { + return http.post('/settings', data) + } } export default settings diff --git a/frontend/src/api/template.ts b/frontend/src/api/template.ts index 43e53c36..840b001c 100644 --- a/frontend/src/api/template.ts +++ b/frontend/src/api/template.ts @@ -2,25 +2,25 @@ import Curd from '@/api/curd' import http from '@/lib/http' class Template extends Curd { - get_config_list() { - return http.get('template/configs') - } + get_config_list() { + return http.get('template/configs') + } - get_block_list() { - return http.get('template/blocks') - } + get_block_list() { + return http.get('template/blocks') + } - get_config(name: string) { - return http.get('template/config/' + name) - } + get_config(name: string) { + return http.get('template/config/' + name) + } - get_block(name: string) { - return http.get('template/block/' + name) - } + get_block(name: string) { + return http.get('template/block/' + name) + } - build_block(name: string, data: any) { - return http.post('template/block/' + name, data) - } + build_block(name: string, data: any) { + return http.post('template/block/' + name, data) + } } diff --git a/frontend/src/api/upgrade.ts b/frontend/src/api/upgrade.ts index 2deeb1a0..1ae29ecb 100644 --- a/frontend/src/api/upgrade.ts +++ b/frontend/src/api/upgrade.ts @@ -1,16 +1,16 @@ import http from '@/lib/http' const upgrade = { - get_latest_release(channel: string) { - return http.get('/upgrade/release', { - params: { - channel - } - }) - }, - current_version() { - return http.get('/upgrade/current') - } + get_latest_release(channel: string) { + return http.get('/upgrade/release', { + params: { + channel + } + }) + }, + current_version() { + return http.get('/upgrade/current') + } } export default upgrade diff --git a/frontend/src/assets/svg/ChatGPT_logo.svg b/frontend/src/assets/svg/ChatGPT_logo.svg index 8147382a..6a90920f 100644 --- a/frontend/src/assets/svg/ChatGPT_logo.svg +++ b/frontend/src/assets/svg/ChatGPT_logo.svg @@ -1 +1,8 @@ - \ No newline at end of file + + + + diff --git a/frontend/src/assets/svg/cpu.svg b/frontend/src/assets/svg/cpu.svg index 90c2326b..c24a421b 100644 --- a/frontend/src/assets/svg/cpu.svg +++ b/frontend/src/assets/svg/cpu.svg @@ -1 +1,11 @@ - \ No newline at end of file + + + + + diff --git a/frontend/src/assets/svg/memory.svg b/frontend/src/assets/svg/memory.svg index b6cbf943..a58cc081 100644 --- a/frontend/src/assets/svg/memory.svg +++ b/frontend/src/assets/svg/memory.svg @@ -1 +1,8 @@ - \ No newline at end of file + + + + diff --git a/frontend/src/assets/svg/pulse.svg b/frontend/src/assets/svg/pulse.svg index abfd589a..82a5a890 100644 --- a/frontend/src/assets/svg/pulse.svg +++ b/frontend/src/assets/svg/pulse.svg @@ -1 +1,8 @@ - \ No newline at end of file + + + + diff --git a/frontend/src/components/Breadcrumb/Breadcrumb.vue b/frontend/src/components/Breadcrumb/Breadcrumb.vue index d51867df..c100dcec 100644 --- a/frontend/src/components/Breadcrumb/Breadcrumb.vue +++ b/frontend/src/components/Breadcrumb/Breadcrumb.vue @@ -3,43 +3,43 @@ import {computed, ref} from 'vue' import {useRoute} from 'vue-router' interface bread { - name: any - path: string + name: any + path: string } const name = ref() const route = useRoute() const breadList = computed(() => { - let _breadList: bread[] = [] + let _breadList: bread[] = [] - name.value = route.name + name.value = route.name - route.matched.forEach(item => { - //item.name !== 'index' && this.breadList.push(item) - _breadList.push({ - name: item.name, - path: item.path - }) + route.matched.forEach(item => { + //item.name !== 'index' && this.breadList.push(item) + _breadList.push({ + name: item.name, + path: item.path }) + }) - return _breadList + return _breadList }) diff --git a/frontend/src/components/Chart/UsageProgressLine.vue b/frontend/src/components/Chart/UsageProgressLine.vue index 6d3307cc..0b1b7e8f 100644 --- a/frontend/src/components/Chart/UsageProgressLine.vue +++ b/frontend/src/components/Chart/UsageProgressLine.vue @@ -2,51 +2,51 @@ import {computed} from 'vue' const props = withDefaults(defineProps<{ - percent: number + percent: number }>(), { - percent: 0 + percent: 0 }) const color = computed(() => { - if (props.percent < 80) { - return '#1890ff' - } else if (props.percent >= 80 && props.percent < 90) { - return '#faad14' - } else { - return '#ff6385' - } + if (props.percent < 80) { + return '#1890ff' + } else if (props.percent >= 80 && props.percent < 90) { + return '#faad14' + } else { + return '#ff6385' + } }) const fixed_percent = computed(() => { - return parseFloat(props.percent.toFixed(2)) + return parseFloat(props.percent.toFixed(2)) }) diff --git a/frontend/src/components/ChatGPT/ChatGPT.vue b/frontend/src/components/ChatGPT/ChatGPT.vue index b995aa64..aad8b731 100644 --- a/frontend/src/components/ChatGPT/ChatGPT.vue +++ b/frontend/src/components/ChatGPT/ChatGPT.vue @@ -19,11 +19,11 @@ const emit = defineEmits(['update:history_messages']) const history_messages = computed(() => props.history_messages) onMounted(() => { - messages.value = props.history_messages + messages.value = props.history_messages }) watch(history_messages, () => { - messages.value = props.history_messages + messages.value = props.history_messages }) const {current} = useGettext() @@ -34,153 +34,153 @@ const loading = ref(false) const ask_buffer = ref('') async function request() { - loading.value = true - const t = ref({ - role: 'assistant', - content: '' - }) - const user = useUserStore() + loading.value = true + const t = ref({ + role: 'assistant', + content: '' + }) + const user = useUserStore() - const {token} = storeToRefs(user) + const {token} = storeToRefs(user) - console.log('fetching...') + console.log('fetching...') - messages.value.push(t.value) + messages.value.push(t.value) - emit('update:history_messages', messages.value) + emit('update:history_messages', messages.value) - let res = await fetch(urlJoin(window.location.pathname, '/api/chat_gpt'), { - method: 'POST', - headers: {'Accept': 'text/event-stream', Authorization: token.value}, - body: JSON.stringify({messages: messages.value.slice(0, messages.value?.length - 1)}) - }) - // read body as stream - console.log('reading...') - let reader = res.body!.getReader() + let res = await fetch(urlJoin(window.location.pathname, '/api/chat_gpt'), { + method: 'POST', + headers: {'Accept': 'text/event-stream', Authorization: token.value}, + body: JSON.stringify({messages: messages.value.slice(0, messages.value?.length - 1)}) + }) + // read body as stream + console.log('reading...') + let reader = res.body!.getReader() - // read stream - console.log('reading stream...') + // read stream + console.log('reading stream...') - let buffer = '' + let buffer = '' - let hasCodeBlockIndicator = false + let hasCodeBlockIndicator = false - while (true) { - let {done, value} = await reader.read() - if (done) { - console.log('done') - loading.value = false - store_record() - break - } - - apply(value) + while (true) { + let {done, value} = await reader.read() + if (done) { + console.log('done') + loading.value = false + store_record() + break } - function apply(input: any) { - const decoder = new TextDecoder('utf-8') - const raw = decoder.decode(input) + apply(value) + } - // console.log(input, raw) + function apply(input: any) { + const decoder = new TextDecoder('utf-8') + const raw = decoder.decode(input) - const line = raw.split('\n\n') + // console.log(input, raw) - line?.forEach(v => { - const data = v.slice('event:message\ndata:'.length) - if (!data) { - return - } - const content = JSON.parse(data).content + const line = raw.split('\n\n') - if (!hasCodeBlockIndicator) { - hasCodeBlockIndicator = content.indexOf('`') > -1 - } + line?.forEach(v => { + const data = v.slice('event:message\ndata:'.length) + if (!data) { + return + } + const content = JSON.parse(data).content - for (let c of content) { - buffer += c - if (hasCodeBlockIndicator) { - if (isCodeBlockComplete(buffer)) { - t.value.content = buffer - hasCodeBlockIndicator = false - } else { - t.value.content = buffer + '\n```' - } - } else { - t.value.content = buffer - } - } - }) - } + if (!hasCodeBlockIndicator) { + hasCodeBlockIndicator = content.indexOf('`') > -1 + } - function isCodeBlockComplete(text: string) { - const codeBlockRegex = /```/g - const matches = text.match(codeBlockRegex) - if (matches) { - return matches.length % 2 === 0 + for (let c of content) { + buffer += c + if (hasCodeBlockIndicator) { + if (isCodeBlockComplete(buffer)) { + t.value.content = buffer + hasCodeBlockIndicator = false + } else { + t.value.content = buffer + '\n```' + } } else { - return true + t.value.content = buffer } + } + }) + } + + function isCodeBlockComplete(text: string) { + const codeBlockRegex = /```/g + const matches = text.match(codeBlockRegex) + if (matches) { + return matches.length % 2 === 0 + } else { + return true } + } } async function send() { - if (!messages.value) { - messages.value = [] - } - if (messages.value.length === 0) { - messages.value.push({ - role: 'user', - content: props.content + '\n\nCurrent Language Code: ' + current - }) - } else { - messages.value.push({ - role: 'user', - content: ask_buffer.value - }) - ask_buffer.value = '' - } - await request() + if (!messages.value) { + messages.value = [] + } + if (messages.value.length === 0) { + messages.value.push({ + role: 'user', + content: props.content + '\n\nCurrent Language Code: ' + current + }) + } else { + messages.value.push({ + role: 'user', + content: ask_buffer.value + }) + ask_buffer.value = '' + } + await request() } const renderer = new marked.Renderer() renderer.code = (code, lang: string) => { - const language = hljs.getLanguage(lang) ? lang : 'nginx' - const highlightedCode = hljs.highlight(code, {language}).value - return `
${highlightedCode}
` + const language = hljs.getLanguage(lang) ? lang : 'nginx' + const highlightedCode = hljs.highlight(code, {language}).value + return `
${highlightedCode}
` } marked.setOptions({ - renderer: renderer, - langPrefix: 'hljs language-', // highlight.js css expects a top-level 'hljs' class. - pedantic: false, - gfm: true, - breaks: false, - sanitize: false, - smartypants: true, - xhtml: false + renderer: renderer, + langPrefix: 'hljs language-', // highlight.js css expects a top-level 'hljs' class. + pedantic: false, + gfm: true, + breaks: false, + sanitize: false, + smartypants: true, + xhtml: false }) function store_record() { - openai.store_record({ - file_name: props.path, - messages: messages.value - }) + openai.store_record({ + file_name: props.path, + messages: messages.value + }) } function clear_record() { - openai.store_record({ - file_name: props.path, - messages: [] - }) - messages.value = [] - emit('update:history_messages', []) + openai.store_record({ + file_name: props.path, + messages: [] + }) + messages.value = [] + emit('update:history_messages', []) } async function regenerate(index: number) { - editing_idx.value = -1 - messages.value = messages.value.slice(0, index) - await request() + editing_idx.value = -1 + messages.value = messages.value.slice(0, index) + await request() } const editing_idx = ref(-1) @@ -190,120 +190,120 @@ const show = computed(() => messages?.value?.length === 0)