From 08a9c48731e681acdb85d018d86c5194aa3e0ba7 Mon Sep 17 00:00:00 2001 From: Zhenyu Zheng Date: Tue, 10 Feb 2026 11:41:50 +0800 Subject: [PATCH 01/11] refactor: optimize UI and navigation - move dashboard to bottom of menu, add governance overview link, clarify email notification label --- frontend/src/App.vue | 8 ++++---- frontend/src/views/CommitteeList.vue | 2 +- frontend/src/views/CommunityOverview.vue | 7 ++++--- frontend/src/views/Settings.vue | 2 ++ 4 files changed, 11 insertions(+), 8 deletions(-) diff --git a/frontend/src/App.vue b/frontend/src/App.vue index ea5a73c..4fb3af2 100644 --- a/frontend/src/App.vue +++ b/frontend/src/App.vue @@ -18,10 +18,6 @@ text-color="#bbb" active-text-color="#409eff" > - - - 仪表板 - 社区总览 @@ -68,6 +64,10 @@ 用户管理 + + + 仪表板 + diff --git a/frontend/src/views/CommitteeList.vue b/frontend/src/views/CommitteeList.vue index 49008d4..cb1a296 100644 --- a/frontend/src/views/CommitteeList.vue +++ b/frontend/src/views/CommitteeList.vue @@ -124,7 +124,7 @@ diff --git a/frontend/src/views/CommunityOverview.vue b/frontend/src/views/CommunityOverview.vue index 3f34e63..d16c0f4 100644 --- a/frontend/src/views/CommunityOverview.vue +++ b/frontend/src/views/CommunityOverview.vue @@ -214,11 +214,12 @@ function canManageCommunity(community: Community): boolean { } function viewCommunity(communityId: number) { - // 切换到该社区并跳转到仪表板 + // 切换到该社区并跳转到治理概览 const community = communities.value.find(c => c.id === communityId) if (community) { - // TODO: 实现社区详情页或切换社区 - ElMessage.info('社区详情页待实现') + // 设置当前社区ID并跳转到治理概览 + localStorage.setItem('current_community_id', String(communityId)) + router.push('/governance') } } diff --git a/frontend/src/views/Settings.vue b/frontend/src/views/Settings.vue index 51655ca..73f9610 100644 --- a/frontend/src/views/Settings.vue +++ b/frontend/src/views/Settings.vue @@ -219,3 +219,5 @@ async function handleToggle(ch: ChannelItem) { color: #909399; font-size: 12px; margin-top: 4px; +} + From fb40fec0562c3ffe56c12be65bc4067679a9d4b0 Mon Sep 17 00:00:00 2001 From: Zhenyu Zheng Date: Tue, 10 Feb 2026 11:50:04 +0800 Subject: [PATCH 02/11] feat: enhance committee member form - add contact fields, adjust validation, and update role options --- .../versions/006_add_member_contact_fields.py | 44 ++++++++++++++++ backend/app/models/committee.py | 6 ++- backend/app/schemas/governance.py | 18 ++++--- frontend/src/api/governance.ts | 14 +++-- frontend/src/components/MemberCard.vue | 10 +++- frontend/src/views/CommitteeDetail.vue | 51 +++++++++++++------ 6 files changed, 114 insertions(+), 29 deletions(-) create mode 100644 backend/alembic/versions/006_add_member_contact_fields.py diff --git a/backend/alembic/versions/006_add_member_contact_fields.py b/backend/alembic/versions/006_add_member_contact_fields.py new file mode 100644 index 0000000..a727c84 --- /dev/null +++ b/backend/alembic/versions/006_add_member_contact_fields.py @@ -0,0 +1,44 @@ +"""Add contact fields to committee members + +Revision ID: 006 +Revises: 005 +Create Date: 2026-02-10 + +""" +from alembic import op +import sqlalchemy as sa + + +# revision identifiers, used by Alembic. +revision = '006' +down_revision = '005' +branch_labels = None +depends_on = None + + +def upgrade() -> None: + # Make email and organization NOT NULL + op.alter_column('committee_members', 'email', + existing_type=sa.String(200), + nullable=False) + op.alter_column('committee_members', 'organization', + existing_type=sa.String(200), + nullable=False) + + # Add new optional contact fields + op.add_column('committee_members', sa.Column('gitcode_id', sa.String(100), nullable=True)) + op.add_column('committee_members', sa.Column('github_id', sa.String(100), nullable=True)) + + +def downgrade() -> None: + # Remove new fields + op.drop_column('committee_members', 'github_id') + op.drop_column('committee_members', 'gitcode_id') + + # Revert email and organization to nullable + op.alter_column('committee_members', 'organization', + existing_type=sa.String(200), + nullable=True) + op.alter_column('committee_members', 'email', + existing_type=sa.String(200), + nullable=True) diff --git a/backend/app/models/committee.py b/backend/app/models/committee.py index b20497b..df8ebaf 100644 --- a/backend/app/models/committee.py +++ b/backend/app/models/committee.py @@ -65,10 +65,12 @@ class CommitteeMember(Base): ) name = Column(String(200), nullable=False) - email = Column(String(200), nullable=True, index=True) + email = Column(String(200), nullable=False, index=True) phone = Column(String(50), nullable=True) wechat = Column(String(100), nullable=True) - organization = Column(String(200), nullable=True) + organization = Column(String(200), nullable=False) + gitcode_id = Column(String(100), nullable=True) + github_id = Column(String(100), nullable=True) # 角色标签(中文,可多选,JSON数组) # 可选值: ["主席", "副主席", "委员", "常务委员"] diff --git a/backend/app/schemas/governance.py b/backend/app/schemas/governance.py index 41cdecf..a82a479 100644 --- a/backend/app/schemas/governance.py +++ b/backend/app/schemas/governance.py @@ -58,10 +58,12 @@ class CommitteeBrief(BaseModel): class CommitteeMemberCreate(BaseModel): name: str = Field(..., min_length=1, max_length=200) - email: Optional[str] = None + email: str = Field(..., min_length=1, max_length=200) phone: Optional[str] = None wechat: Optional[str] = None - organization: Optional[str] = None + organization: str = Field(..., min_length=1, max_length=200) + gitcode_id: Optional[str] = None + github_id: Optional[str] = None roles: list[str] = [] term_start: Optional[date] = None term_end: Optional[date] = None @@ -70,10 +72,12 @@ class CommitteeMemberCreate(BaseModel): class CommitteeMemberUpdate(BaseModel): name: Optional[str] = Field(None, min_length=1, max_length=200) - email: Optional[str] = None + email: Optional[str] = Field(None, min_length=1, max_length=200) phone: Optional[str] = None wechat: Optional[str] = None - organization: Optional[str] = None + organization: Optional[str] = Field(None, min_length=1, max_length=200) + gitcode_id: Optional[str] = None + github_id: Optional[str] = None roles: Optional[list[str]] = None term_start: Optional[date] = None term_end: Optional[date] = None @@ -86,10 +90,12 @@ class CommitteeMemberOut(BaseModel): id: int committee_id: int name: str - email: Optional[str] = None + email: str phone: Optional[str] = None wechat: Optional[str] = None - organization: Optional[str] = None + organization: str + gitcode_id: Optional[str] = None + github_id: Optional[str] = None roles: list[str] = [] term_start: Optional[date] = None term_end: Optional[date] = None diff --git a/frontend/src/api/governance.ts b/frontend/src/api/governance.ts index 4214817..17ecb4c 100644 --- a/frontend/src/api/governance.ts +++ b/frontend/src/api/governance.ts @@ -22,10 +22,12 @@ export interface CommitteeMember { id: number committee_id: number name: string - email?: string + email: string phone?: string wechat?: string - organization?: string + organization: string + gitcode_id?: string + github_id?: string roles: string[] term_start?: string term_end?: string @@ -58,10 +60,12 @@ export interface CommitteeUpdate { export interface CommitteeMemberCreate { name: string - email?: string + email: string phone?: string wechat?: string - organization?: string + organization: string + gitcode_id?: string + github_id?: string roles?: string[] term_start?: string term_end?: string @@ -74,6 +78,8 @@ export interface CommitteeMemberUpdate { phone?: string wechat?: string organization?: string + gitcode_id?: string + github_id?: string roles?: string[] term_start?: string term_end?: string diff --git a/frontend/src/components/MemberCard.vue b/frontend/src/components/MemberCard.vue index bb6ce16..718c793 100644 --- a/frontend/src/components/MemberCard.vue +++ b/frontend/src/components/MemberCard.vue @@ -41,6 +41,14 @@ {{ member.wechat }} +
+ + Gitcode: {{ member.gitcode_id }} +
+
+ + GitHub: {{ member.github_id }} +
@@ -75,7 +83,7 @@ diff --git a/frontend/src/views/CommitteeList.vue b/frontend/src/views/CommitteeList.vue index cb1a296..2528645 100644 --- a/frontend/src/views/CommitteeList.vue +++ b/frontend/src/views/CommitteeList.vue @@ -217,10 +217,21 @@ const rules: FormRules = { } onMounted(() => { - if (!communityStore.currentCommunityId) return - loadCommittees() + if (communityStore.currentCommunityId) { + loadCommittees() + } }) +// Watch for community changes +watch( + () => communityStore.currentCommunityId, + (newId) => { + if (newId) { + loadCommittees() + } + } +) + async function loadCommittees() { loading.value = true try { diff --git a/frontend/src/views/ContentList.vue b/frontend/src/views/ContentList.vue index 227947a..2ce4034 100644 --- a/frontend/src/views/ContentList.vue +++ b/frontend/src/views/ContentList.vue @@ -161,9 +161,20 @@ function formatDate(d: string) { } onMounted(() => { - if (!communityStore.currentCommunityId) return - loadData() + if (communityStore.currentCommunityId) { + loadData() + } }) + +// Watch for community changes +watch( + () => communityStore.currentCommunityId, + (newId) => { + if (newId) { + loadData() + } + } +)