优化docker打包镜像文件过大的问题 (#415)
* chore: 更新文档 * Improve zh-TW locale (#379) * fix: 移动端样式 * feat: typo * fix: 调整滚动回原样 * ⚡优化docker打包镜像文件过大 --------- Co-authored-by: ChenZhaoYu <790348264@qq.com> Co-authored-by: Peter Dave Hello <hsu@peterdavehello.org>
This commit is contained in:
parent
ffd4da91cf
commit
60b7874f65
|
@ -1,6 +1,6 @@
|
||||||
|
**/node_modules
|
||||||
|
*/node_modules
|
||||||
node_modules
|
node_modules
|
||||||
Dockerfile
|
Dockerfile
|
||||||
.git
|
.*
|
||||||
.husky
|
*/.*
|
||||||
.github
|
|
||||||
.vscode
|
|
||||||
|
|
14
Dockerfile
14
Dockerfile
|
@ -4,7 +4,11 @@ FROM node:lts-alpine AS builder
|
||||||
COPY ./ /app
|
COPY ./ /app
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
|
||||||
RUN npm install pnpm -g && pnpm install && pnpm run build
|
RUN apk add --no-cache git \
|
||||||
|
&& npm install pnpm -g \
|
||||||
|
&& pnpm install \
|
||||||
|
&& pnpm run build \
|
||||||
|
&& rm -rf /root/.npm /root/.pnpm-store /usr/local/share/.cache /tmp/*
|
||||||
|
|
||||||
# service
|
# service
|
||||||
FROM node:lts-alpine
|
FROM node:lts-alpine
|
||||||
|
@ -13,8 +17,12 @@ COPY /service /app
|
||||||
COPY --from=builder /app/dist /app/public
|
COPY --from=builder /app/dist /app/public
|
||||||
|
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
RUN npm install pnpm -g && pnpm install
|
RUN apk add --no-cache git \
|
||||||
|
&& npm install pnpm -g \
|
||||||
|
&& pnpm install --only=production \
|
||||||
|
&& rm -rf /root/.npm /root/.pnpm-store /usr/local/share/.cache /tmp/*
|
||||||
|
|
||||||
|
|
||||||
EXPOSE 3002
|
EXPOSE 3002
|
||||||
|
|
||||||
CMD ["pnpm", "run", "start"]
|
CMD ["pnpm", "run", "start"]
|
||||||
|
|
|
@ -84,6 +84,12 @@ For all parameter variables, check [here](#docker-parameter-example) or see:
|
||||||
|
|
||||||
[✓] Formatting and beautifying code-like message types
|
[✓] Formatting and beautifying code-like message types
|
||||||
|
|
||||||
|
[✓] Access rights control
|
||||||
|
|
||||||
|
[✓] Data import and export
|
||||||
|
|
||||||
|
[✓] Save message to local image
|
||||||
|
|
||||||
[✓] Multilingual interface
|
[✓] Multilingual interface
|
||||||
|
|
||||||
[✓] Interface themes
|
[✓] Interface themes
|
||||||
|
|
|
@ -83,6 +83,12 @@ API_REVERSE_PROXY=
|
||||||
|
|
||||||
[✓] 对代码等消息类型的格式化美化处理
|
[✓] 对代码等消息类型的格式化美化处理
|
||||||
|
|
||||||
|
[✓] 访问权限控制
|
||||||
|
|
||||||
|
[✓] 数据导入、导出
|
||||||
|
|
||||||
|
[✓] 保存消息到本地图片
|
||||||
|
|
||||||
[✓] 界面多语言
|
[✓] 界面多语言
|
||||||
|
|
||||||
[✓] 界面主题
|
[✓] 界面主题
|
||||||
|
|
|
@ -51,7 +51,7 @@ const themeOptions: { label: string; key: Theme; icon: string }[] = [
|
||||||
]
|
]
|
||||||
|
|
||||||
const languageOptions: { label: string; key: Language; value: Language }[] = [
|
const languageOptions: { label: string; key: Language; value: Language }[] = [
|
||||||
{ label: '中文', key: 'zh-CN', value: 'zh-CN' },
|
{ label: '简体中文', key: 'zh-CN', value: 'zh-CN' },
|
||||||
{ label: '繁體中文', key: 'zh-TW', value: 'zh-TW' },
|
{ label: '繁體中文', key: 'zh-TW', value: 'zh-TW' },
|
||||||
{ label: 'English', key: 'en-US', value: 'en-US' },
|
{ label: 'English', key: 'en-US', value: 'en-US' },
|
||||||
]
|
]
|
||||||
|
@ -151,38 +151,41 @@ function handleImportButtonClick(): void {
|
||||||
<div class="flex items-center space-x-4">
|
<div class="flex items-center space-x-4">
|
||||||
<span class="flex-shrink-0 w-[100px]">{{ $t('setting.chatHistory') }}</span>
|
<span class="flex-shrink-0 w-[100px]">{{ $t('setting.chatHistory') }}</span>
|
||||||
|
|
||||||
<NButton @click="exportData">
|
<div class="flex flex-wrap items-center gap-4">
|
||||||
<template #icon>
|
<NButton size="small" @click="exportData">
|
||||||
<SvgIcon icon="ri:download-2-fill" />
|
<template #icon>
|
||||||
</template>
|
<SvgIcon icon="ri:download-2-fill" />
|
||||||
{{ $t('common.export') }}
|
</template>
|
||||||
</NButton>
|
{{ $t('common.export') }}
|
||||||
|
</NButton>
|
||||||
|
|
||||||
<input id="fileInput" type="file" style="display:none" @change="importData">
|
<input id="fileInput" type="file" style="display:none" @change="importData">
|
||||||
<NButton @click="handleImportButtonClick">
|
<NButton size="small" @click="handleImportButtonClick">
|
||||||
<template #icon>
|
<template #icon>
|
||||||
<SvgIcon icon="ri:upload-2-fill" />
|
<SvgIcon icon="ri:upload-2-fill" />
|
||||||
</template>
|
</template>
|
||||||
{{ $t('common.import') }}
|
{{ $t('common.import') }}
|
||||||
</NButton>
|
</NButton>
|
||||||
|
|
||||||
<NPopconfirm placement="bottom" @positive-click="clearData">
|
<NPopconfirm placement="bottom" @positive-click="clearData">
|
||||||
<template #trigger>
|
<template #trigger>
|
||||||
<NButton>
|
<NButton size="small">
|
||||||
<template #icon>
|
<template #icon>
|
||||||
<SvgIcon icon="ri:close-circle-line" />
|
<SvgIcon icon="ri:close-circle-line" />
|
||||||
</template>
|
</template>
|
||||||
{{ $t('common.clear') }}
|
{{ $t('common.clear') }}
|
||||||
</NButton>
|
</NButton>
|
||||||
</template>
|
</template>
|
||||||
{{ $t('chat.clearHistoryConfirm') }}
|
{{ $t('chat.clearHistoryConfirm') }}
|
||||||
</NPopconfirm>
|
</NPopconfirm>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex items-center space-x-4">
|
<div class="flex items-center space-x-4">
|
||||||
<span class="flex-shrink-0 w-[100px]">{{ $t('setting.theme') }}</span>
|
<span class="flex-shrink-0 w-[100px]">{{ $t('setting.theme') }}</span>
|
||||||
<div class="flex items-center space-x-4">
|
<div class="flex flex-wrap items-center gap-4">
|
||||||
<template v-for="item of themeOptions" :key="item.key">
|
<template v-for="item of themeOptions" :key="item.key">
|
||||||
<NButton
|
<NButton
|
||||||
|
size="small"
|
||||||
:type="item.key === theme ? 'primary' : undefined"
|
:type="item.key === theme ? 'primary' : undefined"
|
||||||
@click="appStore.setTheme(item.key)"
|
@click="appStore.setTheme(item.key)"
|
||||||
>
|
>
|
||||||
|
@ -195,9 +198,10 @@ function handleImportButtonClick(): void {
|
||||||
</div>
|
</div>
|
||||||
<div class="flex items-center space-x-4">
|
<div class="flex items-center space-x-4">
|
||||||
<span class="flex-shrink-0 w-[100px]">{{ $t('setting.language') }}</span>
|
<span class="flex-shrink-0 w-[100px]">{{ $t('setting.language') }}</span>
|
||||||
<div class="flex items-center space-x-4">
|
<div class="flex flex-wrap items-center gap-4">
|
||||||
<template v-for="item of languageOptions" :key="item.key">
|
<template v-for="item of languageOptions" :key="item.key">
|
||||||
<NButton
|
<NButton
|
||||||
|
size="small"
|
||||||
:type="item.key === language ? 'primary' : undefined"
|
:type="item.key === language ? 'primary' : undefined"
|
||||||
@click="appStore.setLanguage(item.key)"
|
@click="appStore.setLanguage(item.key)"
|
||||||
>
|
>
|
||||||
|
@ -208,7 +212,7 @@ function handleImportButtonClick(): void {
|
||||||
</div>
|
</div>
|
||||||
<div class="flex items-center space-x-4">
|
<div class="flex items-center space-x-4">
|
||||||
<span class="flex-shrink-0 w-[100px]">{{ $t('setting.resetUserInfo') }}</span>
|
<span class="flex-shrink-0 w-[100px]">{{ $t('setting.resetUserInfo') }}</span>
|
||||||
<NButton @click="handleReset">
|
<NButton size="small" @click="handleReset">
|
||||||
{{ $t('common.reset') }}
|
{{ $t('common.reset') }}
|
||||||
</NButton>
|
</NButton>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -31,7 +31,7 @@ const show = computed({
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<NModal v-model:show="show" :auto-focus="false">
|
<NModal v-model:show="show" :auto-focus="false">
|
||||||
<NCard role="dialog" aria-modal="true" :bordered="false" style="width: 100%; max-width: 640px">
|
<NCard role="dialog" aria-modal="true" :bordered="false" style="width: 95%; max-width: 640px">
|
||||||
<NTabs v-model:value="active" type="line" animated>
|
<NTabs v-model:value="active" type="line" animated>
|
||||||
<NTabPane name="General" tab="General">
|
<NTabPane name="General" tab="General">
|
||||||
<template #tab>
|
<template #tab>
|
||||||
|
|
|
@ -16,7 +16,7 @@ export default {
|
||||||
unauthorizedTips: '未经授权,请先进行验证。',
|
unauthorizedTips: '未经授权,请先进行验证。',
|
||||||
},
|
},
|
||||||
chat: {
|
chat: {
|
||||||
placeholder: '来说点什么...(Shift + Enter = 换行)',
|
placeholder: '来说点什么吧...(Shift + Enter = 换行)',
|
||||||
placeholderMobile: '来说点什么...',
|
placeholderMobile: '来说点什么...',
|
||||||
copy: '复制',
|
copy: '复制',
|
||||||
copied: '复制成功',
|
copied: '复制成功',
|
||||||
|
|
|
@ -3,9 +3,9 @@ export default {
|
||||||
delete: '刪除',
|
delete: '刪除',
|
||||||
save: '儲存',
|
save: '儲存',
|
||||||
reset: '重設',
|
reset: '重設',
|
||||||
export: '導出',
|
export: '匯出',
|
||||||
import: '導入',
|
import: '匯入',
|
||||||
clear: '清空',
|
clear: '清除',
|
||||||
yes: '是',
|
yes: '是',
|
||||||
no: '否',
|
no: '否',
|
||||||
noData: '暫無資料',
|
noData: '暫無資料',
|
||||||
|
@ -16,12 +16,12 @@ export default {
|
||||||
unauthorizedTips: '未經授權,請先進行驗證。',
|
unauthorizedTips: '未經授權,請先進行驗證。',
|
||||||
},
|
},
|
||||||
chat: {
|
chat: {
|
||||||
placeholder: '來講點什麼...(Shift + Enter = 換行)',
|
placeholder: '來說點什麼...(Shift + Enter = 換行)',
|
||||||
placeholderMobile: '來講點什麼...',
|
placeholderMobile: '來說點什麼...',
|
||||||
copy: '複製',
|
copy: '複製',
|
||||||
copied: '複製成功',
|
copied: '複製成功',
|
||||||
copyCode: '複製代碼',
|
copyCode: '複製代碼',
|
||||||
clearChat: '清空對話',
|
clearChat: '清除對話',
|
||||||
clearChatConfirm: '是否清空對話?',
|
clearChatConfirm: '是否清空對話?',
|
||||||
exportImage: '儲存對話為圖片',
|
exportImage: '儲存對話為圖片',
|
||||||
exportImageConfirm: '是否將對話儲存為圖片?',
|
exportImageConfirm: '是否將對話儲存為圖片?',
|
||||||
|
@ -39,6 +39,7 @@ export default {
|
||||||
name: '名稱',
|
name: '名稱',
|
||||||
description: '描述',
|
description: '描述',
|
||||||
resetUserInfo: '重設使用者資訊',
|
resetUserInfo: '重設使用者資訊',
|
||||||
|
chatHistory: '紀錄',
|
||||||
theme: '主題',
|
theme: '主題',
|
||||||
language: '語言',
|
language: '語言',
|
||||||
api: 'API',
|
api: 'API',
|
||||||
|
|
|
@ -113,6 +113,7 @@ async function onConversation() {
|
||||||
requestOptions: { prompt: message, options: { ...options } },
|
requestOptions: { prompt: message, options: { ...options } },
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
scrollToBottom()
|
||||||
}
|
}
|
||||||
catch (error) {
|
catch (error) {
|
||||||
//
|
//
|
||||||
|
|
Loading…
Reference in New Issue