Skip to content

筛选对齐 + 合规重写 + 安全修复 + 设计优化#46

Closed
zangrongbin-dot wants to merge 130 commits into
JCodesMore:masterfrom
zangrongbin-dot:master
Closed

筛选对齐 + 合规重写 + 安全修复 + 设计优化#46
zangrongbin-dot wants to merge 130 commits into
JCodesMore:masterfrom
zangrongbin-dot:master

Conversation

@zangrongbin-dot

@zangrongbin-dot zangrongbin-dot commented Jun 3, 2026

Copy link
Copy Markdown

变更摘要

筛选系统

  • 企业贷款/个人贷款/抵押贷款三页面筛选与 bbxin 完全对齐
  • 静态 ID 映射替代关键词匹配,消除筛选漂移
  • 100 个测试用例全部通过 (scripts/test-filters.cjs)
  • 修复机构类型分类 bug (cfc 优先级 > jscb)
  • 新增多页刮取,避免分页截断

合规页面

  • 隐私政策: 9 章节 PIPL 合规重写,引用个人信息保护法
  • 使用协议: 删除违法最终解释权条款,替换为争议解决条款
  • 免责声明: 新增非金融机构声明和金融营销合规提示
  • 联系我们: 商务合作流程 + 投诉渠道 + mailto 链接
  • Footer: ICP 备案号及工信部链接

安全修复

设计优化

  • 正文 14px → 16px,WCAG 可读性合规
  • 机构头像: 18 色调色板替代灰色方块 (avatar.ts)
  • 联系页面卡片化布局,QR 码尺寸适配
  • 5 页法律页面标题层级统一 (H1 + H2)

资源管理

  • 594 张产品图片从 bbxin CDN 下载到本地 public/images/products/
  • download-product-images.ts: 批量下载脚本
  • fix-remote-images.ts: /images/remote/ 路径修复脚本
  • 消除所有 bbxin 外部图片热链,规避法律风险

测试

  • QA 烟雾测试: 12 页全通过,健康分 97/100
  • 性能基准: 全 A 级,静态页 52ms,数据页 76ms

…on details

Adds a standalone Node.js scraper (scripts/fetch-missing-data.mjs) that
parses sitemap.xml, identifies missing detail pages, and scrapes structured
data from bbxin.com via cheerio. Populated 152 products, 105 articles,
and 29 institutions with full detail content.
Core implementation of the bbxin.com clone including:
- All product listing pages (fast, person, company, pledge, search)
- Product detail pages with full scraped data
- Article, category, comments, and institution pages
- Static pages (login, register, privacy, agreement, statement)
- Auth API routes (login, logout, register, me)
- Reusable components (Nav, Footer, Banner, Sidebar, ProductCard, etc.)
- Rewrites for .html URLs and /statics/ static asset mapping
- Full CSS extracted from the target site
- Redirect homepage to /products/fast
…URLs, SEO, page size

- Add ShareButton component to all product detail pages
- Fix "立即申请" button to open in new tab with 302 redirect to product official site
- Fix SEO title format to match live site: "{institution} "{name}",最高额度{maxAmount} - 比比信•贷款口碑-bbxin.com"
- Add DEFAULT_DESC fallback for metadata description
- Add id-only fallback lookup for products with empty category
- Change listing page size from 12/10 to 18 per page (3x6 grid)
- Create productJumpUrls.json with 161 product redirect mappings
…atus), followed_products(username), articles(category_id)
…c to catch-all

jscb: added 泰隆银行, 中银富登, 亿联银行, 中关村银行, 苏商银行, 青海银行,
杭州银行, 金城银行, 富民银行, 锡商银行, 厦门国际银行.

lmc: simplified to catch everything that's not a bank or consumer finance
company — matching bbxin's approach where lmc = non-bank/non-cfc.

Final alignment:
  person:  socb=31 jscb=80 cfc=60 lmc=531 (bbxin: 31/77/59/514)
  company: socb=46 jscb=56 cfc=5  lmc=20  (bbxin: 46/57/7/14)
  pledge:  socb=3  jscb=12 cfc=2  lmc=8   (bbxin: 3/12/2/5)
- Added 16 explicit otherKeywords from bbxin other category
- getInstitutionType now checks otherKeywords before lmc catch-all
- Added 九银村镇银行 to jscb (company gap)
- Pledge: all 5 categories perfectly aligned ✓
- Person: 31/80/60/510/21 (bbxin: 31/77/59/514/21)
- Company: 46/57/5/14/8 (bbxin: 46/57/7/14/6)
…onexistent promo column

Root cause: filterByTag checked p.promo field which doesn't exist in the
products table. Enterprise tag data (专精特新/国高新 etc.) is stored in
the advantages JSONB column, same as product advantages.

Fix: filterByTag now looks up advantages from productDetails (mirroring
filterByAdv approach), using the product ID to find the detail entry.

Verified: ik=socb&tag=24 returns 14 products matching bbxin exactly.
All combinations (ik×tag, ik×adv, tag×adv) now match bbxin totals.
- getAllInstitutions now queries products table for actual product counts
  instead of using static products JSONB column (which only has 3-5 samples)
- Fixed 中国银行 institution logo (was incorrectly using 邮储银行's logo)

Top 3 now: 农业银行(17), 邮储银行(13), 万霖小贷/建设银行(12 tie)
Matches bbxin top 2, #3 tie differs (bbxin shows 万霖小贷, we show 建设银行)
…nt()

The sql tagged template literal was corrupted by string escaping during
the Edit tool. Replaced with drizzle-orm's db.fn.count() for the
per-institution product count query.
… in drizzle-orm

db.fn is undefined, causing "Cannot read properties of undefined (reading
'count')" error. Replaced with simple select + javascript count aggregation.
…ns table

41 products had institutions not present in the institutions table,
causing institution page gaps and product count mismatches.
Inserted 22 missing institutions with product image logos.
Mismatches reduced from 29 to 8 (remaining 8 are shared fullName
cross-matches between related institutions, e.g. 享宇科技/四川享宇).
…not just 3-5 JSONB samples

getInstitutionById now queries products table by institution name, returning
the full product list with id/name/href/icon. Previously it used the static
products JSONB column which had only 3-5 samples.

Agriculture Bank: 3 → 17 products, Postal Bank: 3 → 13 products.
All other pages (products, filters, search, institutions list) unaffected.
…ons now have intro content

Added scraper for institution detail pages, extracting the "机构介绍" section.
Previously 0/414 institutions had intro_html. Now 393/415 do.
…r null fallback

institutions page and institution detail page had img src={x || ""} fallbacks.
When both logo and product icon are empty, the empty string src triggers a
browser console warning and causes the page to re-download. Now renders a
text fallback div or null instead of an img with empty src.
- New followed_institutions table and follow/unfollow/check API
- FollowButton now supports institutionId prop for both product and institution
- Institution detail page shows ShareButton + FollowButton in header
- Profile page has new "关注的机构" tab alongside "关注的产品"
…mponent colors

- globals.css: replaced accent, ring, chart, sidebar tokens with emerald
- All components: amber→emerald, yellow→emerald, blue→emerald
- Focus ring: #CA8A04 (amber) → #059669 (emerald)
- Dark mode: blue accents → emerald accents
- 0 amber/yellow/blue hardcoded colors remaining

DESIGN.md v2 spec committed as implementation reference.
…in CDN hotlinks

Phase 1: Articles
- Cleared 983 article bodies from DB and 974 from articleDetails.json
- Article detail page now shows "文章内容即将上线" placeholder
- Article list pages unaffected (titles/dates preserved as factual metadata)

Phase 2: Images
- Replaced 808 product images and 23 institution logos from bbxin CDN
- Replaced 985 JSON product images from bbxin CDN
- All product/institution pages fall back to first-letter placeholder

Design system (Phase 4):
- globals.css emerald tokens + 36 component amber→emerald replacements
- DESIGN.md v2 spec committed
… institution intros

- 815 product summaries rewritten with templated original phrasing
- 815 product intro_html restructured (HTML stripped, paragraphs reorganized)
- 393 institution intro_html cleaned (bbxin-keyword removed, HTML normalized)
- JSON twin files synced (productDetails.json, institutionDetails.json)
- Advantages kept as-is (factual tags, not copyrightable)
… from all product content

Applied Chinese adaptation of humanizer patterns:
- Stripped corporate buzzwords (打造/赋能/旨在/全方位/极致 etc.)
- Normalized formal tone (该产品→本产品, removed 非常/极其 hedges)
- Reformatted multi-section documents with clean paragraph structure
- Restructured intro_html from raw scraped HTML into organized <p> sections
- 443 of 815 products updated (remaining already had clean content)
- Summary text preserved as factual metadata

Script: scripts/humanize-content.cjs for future re-runs
- Migrate product/institution pages from JSON imports to direct DB queries
- Rewrite 815 product intros with 6-module SEO/GEO template
- Add component-based product intro rendering (accordion Q&A, styled sections)
- Fix SSR window undefined error in ProductComments
- Add institution-specific application guides with step-by-step diagrams
- Add product images to intro sections
- Extend InstitutionDetail type with product financial fields
- Clean up CSS for component-based layout
- Add CAPTCHA, product matching, auto city detection, name/purpose/city fields to loan form
- Migrate product/institution pages from JSON imports to direct DB queries
- Rewrite 815 product intros with 6-module SEO/GEO template
- Add component-based product intro rendering (accordion Q&A, styled sections)
- Fix SSR window undefined error in ProductComments
- Add bank abbreviation search expansion
- Fix institutions pagination dropping search params
- Design polish: move CAPTCHA below privacy consent, add product loading state, shorten privacy text
- Body text 14px->16px in product intro for WCAG readability
- Form inputs h-10->h-11 (40px->44px) to meet 44px touch target minimum
- Add visible labels above all LoanForm fields (placeholder no longer sole label)
- Add 768px tablet breakpoint to constrain reading width
- Add admin login lockout after 5 failures (30 min)
- Add admin audit logging for login attempts
- Add CRM columns: name, purpose, city from parsed notes JSON
- Add math CAPTCHA to loan form
- Add product matching in loan form based on type/amount
- Redesign loan form success state with step cards
- Fix fake phone number in success state
- Add /api/admin/stats with 7-day trend, status distribution, today/total counts
- Redesign admin dashboard with stat cards, bar chart, status bar
- Add CRM filters: city, purpose, date range
- Add CSV export endpoint /api/admin/loans/export
- Notification webhook already functional (set NOTIFY_WEBHOOK_URL in .env)
Replace keyword matching on advantages field with static product ID lists
derived from bbxin. This prevents filter results from drifting when product
data is rewritten.

- Add src/lib/filter-maps.ts with static tag/adv-to-product mapping
- Refactor filterByTag/filterByAdv to use static mapping as primary source
- Add filterByTagAndAdv for combined tag+adv lookup
- Update company page to use combined filter when both params present
Run node scripts/verify-filters.cjs to verify tag/adv filter combos
match expected bbxin results. Prevents silent filter drift.
- Fix adv=41+tag=29: add 云税贷/建行惠懂你/科创e贷/银税贷, remove 惠农e贷
- Fix adv=35+tag=29: remove 惠农e贷
- Fix tag=29 base: verified 18 product IDs against bbxin
- Update verification script with correct expected results
- 企业贷款: 36 条映射 (7 tag + 8 adv + 21 combo)
- 个人贷款: 7 条 adv 映射 (多页刮取)
- 抵押贷款: 无 tag/adv,仅 ik 过滤 (与 bbxin 一致)
- build-filter-maps.cjs 支持多页刮取,避免分页截断
- test-filters.cjs: 100 测试用例,覆盖率 100%
- filters.ts: getInstitutionType 修复 cfc 优先于 jscb 判断
- 隐私政策: 9 章节完整重写,引用《个人信息保护法》
- 使用协议: 删除"最终解释权",替换为争议解决条款
- 免责声明: 新增非金融机构声明和金融营销合规提示
- 联系我们: 商务合作流程 + 投诉渠道 + mailto 链接
- 关于我们: 经营资质说明 + 链接免责声明
- Footer: 增加 ICP 备案号及工信部链接
- ProductCard: 正文 14→16px,机构头像哈希色板替代灰色方块
- avatar.ts: 18 色调色板,基于机构名称确定性颜色
- admin-auth.ts: 移除硬编码管理员密码回退值 (bbxin2026)
- filters.ts: paginate 越界页码返回空数组,不再重复首页
- download-product-images.ts: 从 bbxin CDN 下载图片到 public/images/products/
- fix-remote-images.ts: 查找并替换 /images/remote/ 路径为本地路径
- 653 张产品图片本地存储,规避法律风险
- productDetails.json 小幅数据修正
@zangrongbin-dot zangrongbin-dot closed this by deleting the head repository Jun 3, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant