From d08acc052ae07fc963ef94062b59a11e0db5f59d Mon Sep 17 00:00:00 2001
From: xcbyy <2578898740@qq.com>
Date: Tue, 13 Oct 2026 16:35:35 +0800
Subject: [PATCH] feat(community): combine marquee scroll with detail modal for
pinned notice
---
pwuniapp/pages/community/index.vue | 429 +++++++++++++++++++++++++-
server/tests/content-security.spec.ts | 13 +
2 files changed, 425 insertions(+), 17 deletions(-)
diff --git a/pwuniapp/pages/community/index.vue b/pwuniapp/pages/community/index.vue
index 7c36557..0a2b985 100644
--- a/pwuniapp/pages/community/index.vue
+++ b/pwuniapp/pages/community/index.vue
@@ -21,10 +21,19 @@
-
-
+
+
+
+
+
+
+
+
+
+ {{ communityNotice.content }}
+
+
+
+
+
+
+ 01
+
+ 文明交友与真实组局
+ 严禁发布虚假、欺诈、低俗或人身攻击信息,发帖请明确时间、地点及AA分摊规则,共建健康同城氛围。
+
+
+
+ 02
+
+ 严禁私域引流与脱网交易
+ 动态、评论与私信中严禁出现微信号、手机号、二维码等私下引流信息,脱网交易不受平台资金与安全保障。
+
+
+
+ 03
+
+ 全天候官方内容安全审查
+ 全平台已接入微信官方文本与图片内容安全识别系统,违规内容秒级拦截,涉嫌严重违规者将实施封号处置。
+
+
+
+ 04
+
+ 同城线下公开安全履约
+ 线下同城搭子组局倡导在正规商圈、餐馆等公开营业场所进行,现场凭借4位数字核销码签到核销。
+
+
+
+
+
+
+
+
+
@@ -325,7 +394,21 @@ import { getPosts, createPost, deletePost, likePost, getPostComments, addPostCom
const isLoading = ref(true);
const currentThemeKey = ref(getCurrentThemeKey());
const navInfo = ref(getNavBarInfo());
-const communityNotice = ref(null);
+const communityNotice = ref({
+ title: '友圈同城互动与公约置顶',
+ content: '欢迎来到同城搭子友圈!文明交友,发布真实组局诉求;平台全天候对动态与评论实施微信官方内容安全过滤,严禁广告引流及私下交易。',
+ tag: '置顶推荐',
+ showInBanner: true
+});
+const noticeModalVisible = ref(false);
+
+const openNoticeDetailModal = () => {
+ noticeModalVisible.value = true;
+};
+
+const closeNoticeDetailModal = () => {
+ noticeModalVisible.value = false;
+};
const availableTopics = ref([
'三里屯探店',
'铜锅涮肉AA',
@@ -1016,10 +1099,12 @@ const submitPublishPost = async () => {
align-items: center;
background: rgba(99, 102, 241, 0.12);
border: 1px solid rgba(99, 102, 241, 0.3);
- border-radius: 12rpx;
- padding: 12rpx 20rpx;
+ border-radius: 14rpx;
+ padding: 12rpx 16rpx 12rpx 20rpx;
margin-bottom: 20rpx;
gap: 14rpx;
+ cursor: pointer;
+ box-sizing: border-box;
.notice-badge {
font-size: 20rpx;
@@ -1032,14 +1117,242 @@ const submitPublishPost = async () => {
letter-spacing: 0.5rpx;
}
- .notice-title-text {
- font-size: 24rpx;
- font-weight: 600;
- color: #F1F5F9;
- white-space: nowrap;
- overflow: hidden;
- text-overflow: ellipsis;
+ .notice-marquee-wrap {
flex: 1;
+ overflow: hidden;
+ white-space: nowrap;
+ position: relative;
+ height: 36rpx;
+ line-height: 36rpx;
+
+ .notice-marquee-content {
+ display: inline-flex;
+ align-items: center;
+ white-space: nowrap;
+ animation: marqueeScroll 24s linear infinite;
+
+ .notice-title-text {
+ font-size: 24rpx;
+ font-weight: 600;
+ color: #F1F5F9;
+ padding-right: 48rpx;
+ }
+
+ .marquee-clone {
+ font-size: 24rpx;
+ font-weight: 600;
+ color: #F1F5F9;
+ padding-right: 48rpx;
+ }
+ }
+ }
+
+ .notice-action-hint {
+ display: flex;
+ align-items: center;
+ gap: 2rpx;
+ flex-shrink: 0;
+ padding-left: 6rpx;
+
+ .hint-text {
+ font-size: 20rpx;
+ color: #818CF8;
+ font-weight: 600;
+ }
+
+ .hint-arrow {
+ width: 22rpx;
+ height: 22rpx;
+ opacity: 0.8;
+ }
+ }
+ }
+
+ @keyframes marqueeScroll {
+ 0% {
+ transform: translateX(0);
+ }
+ 100% {
+ transform: translateX(-50%);
+ }
+ }
+
+ .notice-modal-mask {
+ position: fixed;
+ inset: 0;
+ z-index: 999;
+ background: rgba(0, 0, 0, 0.68);
+ backdrop-filter: blur(8px);
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ padding: 40rpx;
+ box-sizing: border-box;
+
+ .notice-modal-content {
+ width: 100%;
+ max-height: 82vh;
+ background: #151D30;
+ border: 1px solid rgba(99, 102, 241, 0.35);
+ border-radius: 28rpx;
+ box-shadow: 0 16rpx 48rpx rgba(0, 0, 0, 0.45);
+ display: flex;
+ flex-direction: column;
+ overflow: hidden;
+
+ .modal-header {
+ padding: 32rpx 32rpx 20rpx;
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ border-bottom: 1px solid rgba(255, 255, 255, 0.08);
+
+ .modal-header-left {
+ display: flex;
+ align-items: center;
+ gap: 14rpx;
+ flex: 1;
+ overflow: hidden;
+
+ .modal-badge {
+ font-size: 20rpx;
+ font-weight: 700;
+ color: #FFFFFF;
+ background: linear-gradient(135deg, #F43F5E, #E11D48);
+ padding: 4rpx 14rpx;
+ border-radius: 6rpx;
+ flex-shrink: 0;
+ }
+
+ .modal-title {
+ font-size: 30rpx;
+ font-weight: 700;
+ color: #FFFFFF;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+ }
+ }
+
+ .modal-close {
+ width: 56rpx;
+ height: 56rpx;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ background: rgba(255, 255, 255, 0.06);
+ border-radius: 28rpx;
+ flex-shrink: 0;
+
+ .close-icon {
+ width: 28rpx;
+ height: 28rpx;
+ }
+ }
+ }
+
+ .notice-modal-body {
+ max-height: 58vh;
+ padding: 24rpx 32rpx;
+ box-sizing: border-box;
+
+ .notice-lead-card {
+ display: flex;
+ align-items: flex-start;
+ gap: 16rpx;
+ background: rgba(99, 102, 241, 0.15);
+ border: 1px solid rgba(99, 102, 241, 0.3);
+ border-radius: 16rpx;
+ padding: 20rpx;
+ margin-bottom: 24rpx;
+
+ .lead-icon {
+ width: 36rpx;
+ height: 36rpx;
+ flex-shrink: 0;
+ margin-top: 4rpx;
+ }
+
+ .lead-text {
+ font-size: 24rpx;
+ line-height: 1.6;
+ color: #E2E8F0;
+ font-weight: 500;
+ }
+ }
+
+ .notice-rules-section {
+ .rules-header {
+ font-size: 26rpx;
+ font-weight: 700;
+ color: #94A3B8;
+ margin-bottom: 16rpx;
+ letter-spacing: 0.5rpx;
+ }
+
+ .rule-item {
+ display: flex;
+ align-items: flex-start;
+ gap: 16rpx;
+ background: rgba(255, 255, 255, 0.04);
+ border: 1px solid rgba(255, 255, 255, 0.06);
+ border-radius: 16rpx;
+ padding: 20rpx;
+ margin-bottom: 16rpx;
+
+ .rule-index {
+ width: 44rpx;
+ height: 44rpx;
+ border-radius: 12rpx;
+ background: rgba(99, 102, 241, 0.2);
+ color: #818CF8;
+ font-size: 22rpx;
+ font-weight: 800;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ flex-shrink: 0;
+ }
+
+ .rule-body {
+ flex: 1;
+
+ .rule-title {
+ display: block;
+ font-size: 26rpx;
+ font-weight: 700;
+ color: #FFFFFF;
+ margin-bottom: 6rpx;
+ }
+
+ .rule-desc {
+ display: block;
+ font-size: 22rpx;
+ line-height: 1.5;
+ color: #94A3B8;
+ }
+ }
+ }
+ }
+ }
+
+ .notice-modal-footer {
+ padding: 20rpx 32rpx 32rpx;
+ border-top: 1px solid rgba(255, 255, 255, 0.08);
+
+ .modal-confirm-btn {
+ width: 100%;
+ height: 84rpx;
+ line-height: 84rpx;
+ border-radius: 42rpx;
+ background: linear-gradient(135deg, #6366F1 0%, #8B5CF6 100%);
+ color: #FFFFFF;
+ font-size: 28rpx;
+ font-weight: 700;
+ box-shadow: 0 4rpx 16rpx rgba(99, 102, 241, 0.35);
+ margin: 0;
+ }
+ }
}
}
@@ -1769,9 +2082,91 @@ const submitPublishPost = async () => {
font-weight: 700;
}
- .notice-title-text {
- color: #292524;
- font-weight: 600;
+ .notice-marquee-wrap {
+ .notice-marquee-content {
+ .notice-title-text, .marquee-clone {
+ color: #292524;
+ font-weight: 600;
+ }
+ }
+ }
+
+ .notice-action-hint {
+ .hint-text {
+ color: #EA580C;
+ }
+ }
+ }
+
+ .notice-modal-mask {
+ background: rgba(28, 25, 23, 0.6);
+
+ .notice-modal-content {
+ background: #FFFFFF;
+ border: 1px solid #F0ECE4;
+ box-shadow: 0 16rpx 48rpx rgba(234, 88, 12, 0.15);
+
+ .modal-header {
+ border-bottom-color: #F5F5F4;
+
+ .modal-header-left {
+ .modal-badge {
+ background: linear-gradient(135deg, #EA580C, #F97316);
+ }
+ .modal-title {
+ color: #1C1917;
+ }
+ }
+
+ .modal-close {
+ background: #F5F5F4;
+ }
+ }
+
+ .notice-modal-body {
+ .notice-lead-card {
+ background: #FFF7ED;
+ border-color: #FED7AA;
+
+ .lead-text {
+ color: #C2410C;
+ }
+ }
+
+ .notice-rules-section {
+ .rules-header {
+ color: #78716C;
+ }
+
+ .rule-item {
+ background: #FDFBF7;
+ border-color: #F0ECE4;
+
+ .rule-index {
+ background: #FFF7ED;
+ color: #EA580C;
+ }
+
+ .rule-body {
+ .rule-title {
+ color: #1C1917;
+ }
+ .rule-desc {
+ color: #78716C;
+ }
+ }
+ }
+ }
+ }
+
+ .notice-modal-footer {
+ border-top-color: #F5F5F4;
+
+ .modal-confirm-btn {
+ background: linear-gradient(135deg, #EA580C 0%, #C2410C 100%);
+ box-shadow: 0 4rpx 16rpx rgba(234, 88, 12, 0.35);
+ }
+ }
}
}
diff --git a/server/tests/content-security.spec.ts b/server/tests/content-security.spec.ts
index 450cf94..daf1ab6 100644
--- a/server/tests/content-security.spec.ts
+++ b/server/tests/content-security.spec.ts
@@ -1061,6 +1061,19 @@ describe('ContentSecurityService & Compliance Architecture (TDD 微信内容安
expect(content).toContain('.expert-detail-container.theme-warm');
});
+ it('友圈置顶头条公告必须支持跑马灯平滑走字微动与点击呼出社区公约详情弹窗', () => {
+ const communityPath = path.join(rootDir, 'pwuniapp', 'pages', 'community', 'index.vue');
+ const content = fs.readFileSync(communityPath, 'utf-8');
+ expect(content).toContain('notice-marquee-wrap');
+ expect(content).toContain('marqueeScroll');
+ expect(content).toContain('openNoticeDetailModal');
+ expect(content).toContain('noticeModalVisible');
+ expect(content).toContain('notice-modal-mask');
+ expect(content).toContain('notice-modal-content');
+ expect(content).toContain('closeNoticeDetailModal');
+ expect(content).toContain('ICONS.chevronRight');
+ });
+
it('所有状态持久化修复代码与测试严禁包含任何系统 Emoji 违规字符', () => {
const actDetailPath = path.join(rootDir, 'pwuniapp', 'pages', 'activity', 'detail.vue');
const ticketPath = path.join(rootDir, 'pwuniapp', 'pages', 'activity', 'my-ticket.vue');