chore: 修复登录页与前端开发服务器配置

- vite dev server 端口改为 5000 并启用 strictPort,端口冲突时拒绝启动
- AGENTS.md 更新前端目录结构说明(移除已删除的 ERB/enterprise 目录)及端口文档
- v3 登录页精简:移除 useBranding/globalConfig 依赖,去掉忘记密码链接
- 中文登录表单翻译优化(Email → 电子邮件)
This commit is contained in:
Rogee
2026-07-29 14:49:20 +08:00
parent 83386dff75
commit 7ed53bec47
4 changed files with 19 additions and 30 deletions
+13 -4
View File
@@ -19,9 +19,6 @@ backend/ # Go backend (the Go module lives here)
tests/ # e2e tests + test helpers
frontend/ # Chatwoot Vue 3 frontend (vendored for customization)
app/javascript/ # Vue SPA source (dashboard, widget, sdk, portal, superadmin)
app/views/ # ERB templates (vite-plugin-ruby entrypoint resolution)
config/vite.json # Vite-Rails bridge config
enterprise/ # Enterprise edition frontend overlay
package.json # pnpm + Vite + Vue 3 toolchain
deploy/ # Deployment artifacts
docker/ # Dockerfile, Dockerfile.dev, docker-compose.{yml,dev,prod,test}.yml
@@ -145,7 +142,7 @@ Key decoupling changes:
# From repo root — unified dev workflow
pnpm install # install all workspace deps
pnpm dev:backend # start Go backend (air hot-reload, port 3000)
pnpm dev:frontend # start Vite dev server (port 3036, proxies API to :3000)
pnpm dev:frontend # start Vite dev server (port 5000, proxies API to :3000)
pnpm dev # start both concurrently
# Frontend-only (from frontend/)
@@ -165,3 +162,15 @@ Default `CHATWOOT_DIR` points to `../frontend`.
- Do not add Go files to `backend/scripts/legacy/` expecting them to be excluded — `go build ./...` compiles them; keep that directory for one-off scripts only.
- Do not commit `.env`, `coverage.out`, `bin/`, or `tmp/`.
- Do not rewrite git history or force-push without explicit instruction.
<!-- CODEGRAPH_START -->
## CodeGraph
In repositories indexed by CodeGraph (a `.codegraph/` directory exists at the repo root), reach for it BEFORE grep/find or reading files when you need to understand or locate code:
- **MCP tool** (when available): `codegraph_explore` answers most code questions in one call — the relevant symbols' verbatim source plus the call paths between them, including dynamic-dispatch hops grep can't follow. Name a file or symbol in the query to read its current line-numbered source. If it's listed but deferred, load it by name via tool search.
- **Shell** (always works): `codegraph explore "<symbol names or question>"` prints the same output.
If there is no `.codegraph/` directory, skip CodeGraph entirely — indexing is the user's decision.
<!-- CODEGRAPH_END -->
@@ -2,8 +2,8 @@
"LOGIN": {
"TITLE": "登录到Chatwoot",
"EMAIL": {
"LABEL": "Email",
"PLACEHOLDER": "实例 {'@'}companyname.com",
"LABEL": "电子邮件",
"PLACEHOLDER": "电子邮件",
"ERROR": "请输入一个有效的电子邮件"
},
"PASSWORD": {
@@ -1,13 +1,11 @@
<script>
// utils and composables
import { login } from '../../api/auth';
import { mapGetters } from 'vuex';
import { useAlert } from 'dashboard/composables';
import { required, email } from '@vuelidate/validators';
import { useVuelidate } from '@vuelidate/core';
import { SESSION_STORAGE_KEYS } from 'dashboard/constants/sessionStorage';
import SessionStorage from 'shared/helpers/sessionStorage';
import { useBranding } from 'shared/composables/useBranding';
// components
import SimpleDivider from '../../components/Divider/SimpleDivider.vue';
@@ -46,9 +44,7 @@ export default {
authError: { type: String, default: '' },
},
setup() {
const { replaceInstallationName } = useBranding();
return {
replaceInstallationName,
v$: useVuelidate(),
};
},
@@ -84,7 +80,6 @@ export default {
};
},
computed: {
...mapGetters({ globalConfig: 'globalConfig/get' }),
allowedLoginMethods() {
return window.chatwootConfig.allowedLoginMethods || ['email'];
},
@@ -227,14 +222,8 @@ export default {
<template>
<main
class="flex flex-col w-full min-h-screen py-20 bg-n-brand/5 dark:bg-n-background sm:px-6 lg:px-8"
class="flex flex-col items-center justify-center w-full min-h-screen bg-n-brand/5 dark:bg-n-background sm:px-6 lg:px-8"
>
<section class="max-w-5xl mx-auto">
<h2 class="text-3xl font-medium text-center text-n-slate-12">
{{ replaceInstallationName($t('LOGIN.TITLE')) }}
</h2>
</section>
<!-- MFA Verification Section -->
<section v-if="mfaRequired" class="mt-11">
<MfaVerification
@@ -300,17 +289,7 @@ export default {
:placeholder="$t('LOGIN.PASSWORD.PLACEHOLDER')"
:has-error="v$.credentials.password.$error"
@input="v$.credentials.password.$touch"
>
<p v-if="!globalConfig.disableUserProfileUpdate">
<router-link
to="auth/reset/password"
class="text-sm text-link"
tabindex="4"
>
{{ $t('LOGIN.FORGOT_PASSWORD') }}
</router-link>
</p>
</FormInput>
/>
<NextButton
lg
type="submit"
+2 -1
View File
@@ -83,7 +83,8 @@ export default defineConfig({
// Dev server: SPA mode for dashboard + widget.html route
server: {
host: '0.0.0.0',
port: 3036,
port: 5000,
strictPort: true, // port conflict → refuse to start instead of auto-incrementing
// Serve widget.html for /widget path (widget iframe), index.html for SPA routes
historyApiFallback: {
rewrites: [