## 技术选型 - Frontend: HTMX + Alpine.js + Tailwind CSS - Backend: Django 4.x (ASGI mode) - Multi-tenant: django-tenants (Postgres schema isolation) - Database: PostgreSQL + PgBouncer - Cache: Redis - Tasks: Celery + Celery Beat - Storage: Cloudflare R2 (or AWS S3) - CDN: Cloudflare - Server: Gunicorn + Uvicorn workers + Nginx - Monitoring: Sentry + Grafana ## Data Table (数据表格) ![[IMG-20260425085420706.png]] #### 1. Data Table(数据表格)— 核心组件 **你描述的"数据列表"正式名称是:Sortable Data Table with Column Visibility Control** 图中包含的子特性: |子特性|技术实现方式|可行性| |---|---|---| |多列表头,带排序箭头(↑↓)|Django 后端排序 + HTMX 请求 + Tailwind 样式|✅ 完全可行| |行 Checkbox 多选|Alpine.js 管理选中状态|✅ 完全可行| |行高亮(图中蓝色高亮行)|Alpine.js `:class` 绑定|✅ 完全可行| |红色/橙色 Tag 标签(买卖、出租)|Tailwind `badge` 样式|✅ 完全可行| |行内小图标按钮(电梯、满五等)|Tailwind + inline SVG icon|✅ 完全可行| |价格字段带趋势小箭头(↑绿色)|Alpine.js 条件渲染|✅ 完全可行| |列固定宽度 + 横向滚动条|Tailwind `overflow-x-auto` + `min-w`|✅ 完全可行| --- #### 2. Pagination(分页组件) 图中右下角的 `共3629条 < 1 2 3 4 5 … 182 > 20条/页 跳至` |子特性|实现方式|可行性| |---|---|---| |页码导航|Django Paginator + HTMX `hx-get`|✅ 完全可行| |每页条数选择(20条/页)|Alpine.js 下拉 + HTMX 请求|✅ 完全可行| |跳至指定页|Alpine.js 输入框 + HTMX 请求|✅ 完全可行| |省略号(…)页码|Django 后端分页逻辑生成|✅ 完全可行| --- #### 3. Column Visibility Panel(自定义列显示) 图中右上角的 **"自定义列表"** 按钮 |子特性|实现方式|可行性| |---|---|---| |弹出面板,勾选显示/隐藏列|Alpine.js `x-show` + `x-data`|✅ 完全可行| |列显示状态持久化|Alpine.js + `localStorage` 或后端存储|✅ 完全可行| |动态隐藏表格列|Alpine.js `:class="{'hidden': !col.visible}"`|✅ 完全可行| --- #### 4. Toolbar(操作工具栏) 图中顶部的 `房源海报 批量分享 批量收藏 取消收藏 设置保护房 更多▼` |子特性|实现方式|可行性| |---|---|---| |批量操作按钮(依赖 Checkbox 选中状态)|Alpine.js 全局选中状态 + 按钮 disabled 控制|✅ 完全可行| |"更多"下拉菜单(Dropdown Menu)|Alpine.js `x-show` + `@click.away`|✅ 完全可行| |共 N 条(动态数字)|HTMX 局部刷新 或 Alpine.js 绑定|✅ 完全可行| --- #### 5. Export Button(导出按钮) 图中右上角 **"导出"** 按钮 |实现方式|可行性| |---|---| |Django 后端生成 CSV/Excel(用 `openpyxl`),返回文件流|✅ 完全可行,无需前端特殊处理| |异步导出(数据量大时走 Celery 任务,邮件通知)|✅ 你的 Celery 栈已完全支持| --- #### 6. Smart Sort(智能排序) 图中右上角 **"按智能排序"** 标签 | 实现方式 | 可行性 | | ------------------------------- | ------ | | 后端 Django ORM 多字段排序,HTMX 切换排序模式 | ✅ 完全可行 | ## Modal Dialog (模态对话框) ![[IMG-20260425085420782.png]] ### 🪟 组件名称:Modal Dialog(模态对话框) 图中这个"编辑房源价格"弹窗,包含以下子组件: #### 弹窗本体结构 |部位|组件名称|实现方式|可行性| |---|---|---|---| |灰色半透明遮罩层|Backdrop / Overlay|Tailwind `bg-black/50 fixed inset-0`|✅| |白色弹窗卡片|Modal Panel|Tailwind `bg-white rounded-lg shadow-xl`|✅| |顶部标题栏 + ✕ 关闭按钮|Modal Header|Alpine.js `@click="open=false"`|✅| |底部确定/取消按钮组|Modal Footer / Button Group|Tailwind 按钮样式|✅| |拖拽手柄(左上角 ⠿ 图标)|Draggable Handle|需要少量原生 JS 或 Alpine.js 插件|⚠️| #### 弹窗内的表单组件 |组件|名称|实现方式|可行性| |---|---|---|---| |带星号必填标记的标签|Required Field Label|Tailwind `text-red-500` + `*` 字符|✅| |数字输入框 + 单位后缀(万)|Input with Suffix Addon|Tailwind Input Group|✅| |普通文本输入框(售价/备案价)|Text Input|Tailwind `input` 样式|✅| |多行文本域(更改理由)|Textarea|Tailwind `textarea` + 字数统计 `0/200`|✅| |字数计数(右下角 0/200)|Character Counter|Alpine.js `x-model` + `:text="val.length + '/200'"`|✅| --- ### ⚠️ 唯一需要注意的点:弹窗拖拽 图中左上角有一个 **⠿ 拖拽图标**,说明这个弹窗支持**拖动位置**。这个功能: - Alpine.js 原生**不内置**拖拽 - 可以用 **Alpine.js 官方插件 `@alpinejs/drag`** 解决,无需引入额外大型库 ### ✅ 结论 > 这个 Modal 弹窗及其内部所有表单组件,**用 Alpine.js + Tailwind CSS 完全可以实现**,包括开关状态、表单验证、字数统计。拖拽功能用 Alpine 官方插件即可覆盖,无需引入 Vue/React。 ## Tree Select/Cascading Dropdown(树形下拉选择器) ### 🌲 组件名称:Tree Select / Cascading Dropdown(树形下拉选择器) ![[IMG-20260425085420857.png]] #### 结构拆解 |部位|组件名称|说明| |---|---|---| |触发框(点击展开)|Select Trigger Input|显示已选内容,点击展开下拉| |下拉面板|Dropdown Panel|绝对定位浮层,`z-index` 覆盖页面| |可折叠父节点(▶ 沪居地产)|Tree Node / Collapsible Group|点击 ▶ 展开/收起子节点| |子节点列表(上海豪园店等)|Tree Leaf Node|可点击选中| |带头像的叶节点(沪居地产共享)|Tree Leaf with Avatar|头像 + 姓名 + 编号 + 操作链接| |带状态标签的节点(沪居 关闭)|Node with Badge|橙色"关闭"tag| |底部操作行(隐藏离职员工)|Footer Action|固定在下拉底部的全局操作| --- ### 技术实现评估 #### ✅ 可行部分(Alpine.js 处理) ``` 树形数据展开/折叠 → Alpine.js x-data 维护每个节点的 open 状态 选中节点高亮 → Alpine.js :class 绑定 点击外部关闭 → Alpine.js @click.away 头像/Badge/标签 → 纯 Tailwind CSS 底部固定操作行 → Tailwind sticky bottom ``` #### ⚠️ 需要重点关注的点 **这是你上传的三张图里技术难度最高的组件**,原因: 1. **树形数据递归渲染**:HTMX 本身不擅长递归组件,需要 Alpine.js 配合后端返回的 JSON 数据,在前端用 `template` + `x-for` 递归渲染树节点 2. **多级嵌套状态管理**:每个父节点独立维护 `open/close` 状态,需要 Alpine.js `x-data` 设计合理的数据结构 3. **搜索过滤**(如果需要在下拉内搜索员工):需要 Alpine.js 实时过滤树节点,或 HTMX 请求后端过滤 --- ### 💡 实现建议 **方案一(推荐):Alpine.js 纯前端渲染** > 后端一次性返回完整树形 JSON,Alpine.js 前端递归渲染,适合数据量不大的组织架构树 **方案二:HTMX 懒加载节点** > 点击展开节点时,HTMX `hx-get` 请求该节点的子数据,适合层级很深、数据量很大的场景 --- ### ✅ 结论 > 可以实现,但这是你目前三个组件里**唯一需要认真设计前端数据结构**的组件,不能直接套 Flowbite 现成组件(Flowbite 没有 TreeSelect)。建议直接基于 Alpine.js 手写,逻辑量约 80~120 行 JS,可复用。 ## 带搜索的 Tree Select 完整功能清单 ![[IMG-20260425085420932.png]] ### 🔍 带搜索的 Tree Select 完整功能清单 #### 新增的搜索相关特性 | 特性 | 说明 | 实现方式 | 可行性 | | ------------ | -------------- | --------------------------- | --- | | 下拉顶部搜索输入框 | 打开下拉后可直接键入关键词 | Alpine.js `x-model="query"` | ✅ | | 实时过滤节点 | 输入时同步过滤匹配的节点 | Alpine.js computed 过滤 | ⚠️ | | 搜索命中时自动展开父节点 | 子节点匹配时其父节点强制展开 | 需要递归遍历树形数据 | ⚠️ | | 无结果时显示空状态 | "暂无匹配结果" | Alpine.js `x-show` | ✅ | | 清空搜索恢复原始树结构 | 删除关键词后还原展开状态 | Alpine.js 状态重置 | ✅ | ## Data Range Picker (日期范围选择) ![[IMG-20260425085421006.png]] 这个组件的正式名称是 **Date Range Picker(日期范围选择器)**,也叫 **Dual-Month Calendar Picker**。 --- ### 📅 组件名称:Date Range Picker / 双月日历范围选择器 #### 结构拆解 |部位|说明| |---|---| |顶部输入框组(开始日期 → 结束日期)|Range Input Group,两个输入框用箭头连接,点击任意一个触发日历展开| |双月并排日历面板|Dual Calendar Panel,左侧当月、右侧次月,联动翻页| |月份导航(« < 2026年4月 > »)|单箭头切换月,双箭头切换年| |今日高亮(23日红框)|当天日期特殊样式| |选中日期高亮(26日蓝底)|已选日期样式| |范围区间高亮(开始~结束之间蓝色背景)|Range Highlight,区间内日期浅蓝背景| |跨月灰色日期(上下月溢出日)|灰色不可选日期| --- ### 技术实现评估 #### ⚠️ 这是目前为止难度最高的组件 **难点在于:** 1. **双月联动**:左右两个月份需要同步,翻页时右月始终等于左月+1 2. **区间拖选高亮**:鼠标 hover 时实时预览区间,需要精细的状态管理 3. **日期计算**:需要处理月份天数、周几起始、跨年等边界情况 --- ### 💡 强烈推荐:直接用成熟库,不要手写 用 Alpine.js 从零手写一个双月 Date Range Picker 工作量巨大(400~600 行),且边界情况多,极易出 Bug。 #### 推荐方案:**Pikaday** 或 **Flatpickr** |库|特点|与你技术栈的兼容性| |---|---|---| |**Flatpickr**(强烈推荐)|轻量、无依赖、原生支持 Range 模式和双月显示,样式可用 Tailwind 覆盖|✅ 完美兼容,CDN 引入即用| |**Pikaday**|更轻量,但双月需手动配置|✅ 可用,略需配置| **Flatpickr 双月 Range 模式只需三行配置:** javascript ```javascript flatpickr("#dateRange", { mode: "range", showMonths: 2, }); ``` > 样式用 Tailwind 自定义覆盖即可达到图中效果,不破坏你"不混用技术"的原则——Flatpickr 是无框架依赖的纯 JS 工具库,不是 React/Vue 组件。 --- ### ✅ 结论 > **不建议用 Alpine.js 手写**,引入 **Flatpickr**(CDN,约 16KB)是最优解,与你的 HTMX + Alpine.js + Tailwind 技术栈**完全兼容、无冲突**,实现图中效果只需少量配置。 ## Tab Navigation (标签页导航) ### 🗂️ 组件名称:Tabs / Tab Navigation(标签页导航) #### 结构拆解 |部位|说明| |---|---| |Tab 标签栏|横向排列的标签按钮组,当前激活项(修改跟进)有橙色下划线 + 橙色文字| |激活指示器|Active Indicator,图中为橙色底部边框线| |Tab 内容面板|切换标签时显示对应内容区域| |内容区:Timeline(时间线)|按日期分组的操作记录列表,左侧橙色圆点| |内容区:Banner 提示条|顶部"智能总结"广告/提示横条| |内容区:Activity Item(活动记录项)|每条记录含【操作类型】+ 操作人 + 时间 + 详情文字| |每条记录右侧:Visibility Toggle|"公开/隐藏"文字切换按钮| |底部:Load More Button|"查看全部跟进"加载更多按钮| --- ### 技术实现评估 #### Tab 切换本体 这是所有组件里**实现最简单**的之一: html ```html