Files
shanxia2.0/bak/mobile-ui/shanxia-mp-crm-product-category-demo.html
T
2026-09-12 19:42:20 +08:00

833 lines
27 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
<title>山峡化工 · 产品分类树形展示 Demo</title>
<link rel="stylesheet" href="shanxia-mp-base.css" />
<style>
/* 方案切换条(Demo 专用,非业务 UI) */
.approach-bar {
position: sticky;
top: 0;
z-index: 20;
background: #fff;
border-bottom: 1px solid var(--border);
padding: 10px 12px 8px;
}
.approach-bar__title {
font-size: 11px;
color: var(--text-muted);
margin-bottom: 8px;
}
.approach-tabs {
display: flex;
gap: 6px;
}
.approach-tab {
flex: 1;
padding: 8px 4px;
border-radius: 10px;
font-size: 11px;
font-weight: 600;
color: var(--text-muted);
background: #f3f7f5;
border: 1px solid transparent;
line-height: 1.3;
text-align: center;
}
.approach-tab.active {
color: var(--brand-green-dark);
background: var(--brand-green-soft);
border-color: #b7e6d2;
}
.approach-tab small {
display: block;
font-weight: 400;
font-size: 10px;
opacity: 0.85;
margin-top: 2px;
}
.approach-note {
margin: 10px 12px 0;
padding: 10px 12px;
border-radius: 12px;
background: #fff;
border: 1px solid var(--border);
font-size: 12px;
color: var(--text-muted);
line-height: 1.55;
}
.approach-note strong {
color: var(--text-primary);
font-weight: 600;
}
.approach-note .rec {
display: inline-block;
margin-left: 6px;
padding: 1px 6px;
border-radius: 999px;
background: var(--brand-green-soft);
color: var(--brand-green-dark);
font-size: 10px;
font-weight: 600;
}
.panel { display: none; }
.panel.active { display: block; }
.mp-subpage-back { color: #fff; font-size: 13px; opacity: 0.95; }
.header-tools {
display: flex;
gap: 8px;
align-items: center;
}
.header-tools .mp-header__action {
padding: 0 10px;
font-size: 12px;
}
/* ── 方案 A:缩进展开树 ── */
.tree-list {
margin: 12px;
background: #fff;
border: 1px solid var(--border);
border-radius: 16px;
overflow: hidden;
}
.tree-row {
display: flex;
align-items: center;
gap: 8px;
min-height: 52px;
padding: 10px 12px;
border-bottom: 1px solid var(--border-light);
background: #fff;
}
.tree-row:last-child { border-bottom: none; }
.tree-row:active { background: #f7fbf9; }
.tree-row.is-l2 { background: #fbfdff; }
.tree-row.is-l3 { background: #fafcfb; }
.tree-chevron {
width: 22px;
height: 22px;
border-radius: 6px;
display: flex;
align-items: center;
justify-content: center;
color: var(--text-muted);
font-size: 10px;
flex-shrink: 0;
transition: transform 0.15s ease;
}
.tree-chevron.is-leaf {
visibility: hidden;
}
.tree-chevron.is-open {
transform: rotate(90deg);
color: var(--brand-green);
}
.tree-main {
flex: 1;
min-width: 0;
}
.tree-name {
font-size: 14px;
font-weight: 600;
color: var(--text-primary);
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.tree-meta {
margin-top: 2px;
font-size: 11px;
color: var(--text-muted);
display: flex;
gap: 8px;
align-items: center;
flex-wrap: wrap;
}
.tree-actions {
display: flex;
gap: 4px;
flex-shrink: 0;
}
.icon-btn {
width: 32px;
height: 32px;
border-radius: 8px;
display: flex;
align-items: center;
justify-content: center;
font-size: 14px;
color: var(--brand-green-dark);
background: var(--brand-green-soft);
}
.icon-btn.more {
background: #f1f5f3;
color: var(--text-muted);
}
.children-wrap { display: none; }
.children-wrap.open { display: block; }
/* ── 方案 B:逐级下钻 ── */
.crumb {
display: flex;
align-items: center;
gap: 4px;
padding: 10px 12px 0;
flex-wrap: wrap;
font-size: 12px;
color: var(--text-muted);
}
.crumb a {
color: var(--brand-green-dark);
font-weight: 500;
}
.crumb .sep { opacity: 0.5; }
.crumb .current { color: var(--text-primary); font-weight: 600; }
.drill-list {
margin: 12px;
background: #fff;
border: 1px solid var(--border);
border-radius: 16px;
overflow: hidden;
}
.drill-row {
display: flex;
align-items: center;
gap: 10px;
min-height: 56px;
padding: 12px 14px;
border-bottom: 1px solid var(--border-light);
}
.drill-row:last-child { border-bottom: none; }
.drill-row:active { background: #f7fbf9; }
.drill-icon {
width: 36px;
height: 36px;
border-radius: 10px;
background: var(--brand-green-soft);
color: var(--brand-green-dark);
display: flex;
align-items: center;
justify-content: center;
font-size: 13px;
font-weight: 700;
flex-shrink: 0;
}
.drill-main { flex: 1; min-width: 0; }
.drill-name {
font-size: 15px;
font-weight: 600;
}
.drill-sub {
font-size: 11px;
color: var(--text-muted);
margin-top: 2px;
}
.drill-arrow {
color: var(--text-placeholder);
font-size: 16px;
}
/* ── 方案 C:扁平 + 全路径 ── */
.flat-list {
margin: 12px;
display: flex;
flex-direction: column;
gap: 10px;
}
.flat-card {
background: #fff;
border: 1px solid var(--border);
border-radius: 14px;
padding: 12px 14px;
box-shadow: var(--shadow-sm);
}
.flat-card__head {
display: flex;
justify-content: space-between;
align-items: flex-start;
gap: 8px;
}
.flat-card__title {
font-size: 15px;
font-weight: 600;
}
.flat-card__path {
margin-top: 4px;
font-size: 11px;
color: var(--text-muted);
line-height: 1.4;
}
.flat-card__foot {
margin-top: 10px;
display: flex;
gap: 8px;
justify-content: flex-end;
}
.filter-chips {
display: flex;
gap: 8px;
padding: 0 12px;
margin-top: 10px;
overflow-x: auto;
}
.chip {
flex-shrink: 0;
padding: 6px 12px;
border-radius: 999px;
font-size: 12px;
background: #fff;
border: 1px solid var(--border);
color: var(--text-muted);
}
.chip.active {
background: var(--brand-green-soft);
border-color: #b7e6d2;
color: var(--brand-green-dark);
font-weight: 600;
}
/* 操作菜单 Action Sheet */
.cat-as {
position: fixed;
left: 50%;
bottom: 0;
transform: translateX(-50%) translateY(100%);
width: 100%;
max-width: 420px;
z-index: 210;
padding: 0 12px calc(10px + env(safe-area-inset-bottom, 0px));
transition: transform 0.28s cubic-bezier(0.32, 0.72, 0, 1);
pointer-events: none;
}
.cat-as.is-open {
transform: translateX(-50%) translateY(0);
pointer-events: auto;
}
.cat-as__handle {
width: 36px; height: 4px; border-radius: 999px;
background: rgba(255,255,255,0.55); margin: 0 auto 8px;
}
.cat-as__head {
background: #fff; border-radius: 16px 16px 0 0;
padding: 14px 16px 10px; border-bottom: 1px solid var(--border-light);
}
.cat-as__eyebrow { display: block; font-size: 11px; color: var(--text-muted); margin-bottom: 2px; }
.cat-as__title { display: block; font-size: 16px; font-weight: 700; color: var(--text-primary); }
.cat-as__group {
background: #fff; border-radius: 0 0 16px 16px;
overflow: hidden; margin-bottom: 8px;
}
.cat-as__item {
display: flex; align-items: center; gap: 12px;
min-height: 56px; padding: 12px 14px;
border-bottom: 1px solid var(--border-light);
width: 100%; text-align: left;
}
.cat-as__item:last-child { border-bottom: none; }
.cat-as__item:active { background: #f7fbf9; }
.cat-as__icon {
width: 36px; height: 36px; border-radius: 10px;
display: flex; align-items: center; justify-content: center;
font-size: 13px; font-weight: 700; flex-shrink: 0;
}
.cat-as__icon--edit { color: var(--brand-green-dark); background: var(--brand-green-soft); }
.cat-as__icon--add { color: #087f57; background: #e9f9f2; }
.cat-as__icon--del { color: var(--danger); background: var(--danger-soft); }
.cat-as__meta { flex: 1; min-width: 0; }
.cat-as__name { display: block; font-size: 15px; font-weight: 600; color: var(--text-primary); }
.cat-as__item--danger .cat-as__name { color: var(--danger); }
.cat-as__desc { display: block; margin-top: 2px; font-size: 11px; color: var(--text-muted); }
.cat-as__arrow { color: #c5d5cd; font-size: 18px; }
.cat-as__cancel {
width: 100%; min-height: 50px; background: #fff; border-radius: 16px;
font-size: 15px; font-weight: 600; color: var(--text-muted);
}
.cat-as__cancel:active { background: #f3f7f5; }
.toast {
position: fixed;
left: 50%;
bottom: 40px;
transform: translateX(-50%) translateY(20px);
background: rgba(31, 42, 38, 0.92);
color: #fff;
padding: 10px 16px;
border-radius: 999px;
font-size: 13px;
opacity: 0;
pointer-events: none;
transition: all 0.2s ease;
z-index: 100;
white-space: nowrap;
}
.toast.show {
opacity: 1;
transform: translateX(-50%) translateY(0);
}
</style>
</head>
<body>
<nav class="proto-nav">
<strong>Demo 导航</strong>
<a href="shanxia-mp-index.html">索引</a>
<a href="shanxia-mp-workbench-demo.html">工作台</a>
<a href="shanxia-mp-crm-demo.html">CRM列表</a>
<a class="active" href="shanxia-mp-crm-product-category-demo.html">产品分类树</a>
</nav>
<main class="phone no-tabbar">
<!-- 方案切换 -->
<div class="approach-bar">
<div class="approach-bar__title">移动端树形展示方案对比 · 已采用方案 A(点击切换预览)</div>
<div class="approach-tabs">
<button class="approach-tab active" type="button" data-approach="a">
A 缩进展开
<small>推荐</small>
</button>
<button class="approach-tab" type="button" data-approach="b">
B 逐级下钻
<small>目录式</small>
</button>
<button class="approach-tab" type="button" data-approach="c">
C 扁平路径
<small>搜索友好</small>
</button>
</div>
</div>
<!-- ── 方案 A ── -->
<section class="panel active" id="panel-a">
<p class="approach-note">
<strong>方案 A · 缩进展开树</strong>
<span class="rec">推荐</span><br />
对齐 Web 端树形表格:一屏看全层级,点击箭头展开/折叠;右侧「+」新增子分类、「⋯」编辑/删除。适合管理端 CRUD。
</p>
<header class="mp-header">
<div class="mp-header__row">
<a class="mp-subpage-back" href="shanxia-mp-workbench-demo.html">← 工作台</a>
<div class="header-tools">
<button class="mp-header__action" type="button" id="btn-expand-all">全部展开</button>
<button class="mp-header__action" type="button" data-toast="打开新增分类表单">+ 新增</button>
</div>
</div>
<h1 class="mp-header__title" style="margin-top:8px">产品分类</h1>
<div class="mp-header__search" style="margin-top:10px">
<span class="mp-header__search-dot"></span>搜索分类名称
</div>
</header>
<div class="filter-chips">
<button class="chip active" type="button">全部</button>
<button class="chip" type="button">启用</button>
<button class="chip" type="button">停用</button>
</div>
<div class="tree-list" id="tree-a"></div>
</section>
<!-- ── 方案 B ── -->
<section class="panel" id="panel-b">
<p class="approach-note">
<strong>方案 B · 逐级下钻</strong><br />
类似文件管理器:每次只看当前层;面包屑回退。交互简单、层级深时更清晰,但无法一屏总览整棵树,新增子分类需先进入父级。
</p>
<header class="mp-header">
<div class="mp-header__row">
<a class="mp-subpage-back" href="shanxia-mp-workbench-demo.html">← 工作台</a>
<button class="mp-header__action" type="button" data-toast="在当前层新增分类">+ 新增</button>
</div>
<h1 class="mp-header__title" style="margin-top:8px">产品分类</h1>
<div class="mp-header__search" style="margin-top:10px">
<span class="mp-header__search-dot"></span>搜索分类名称
</div>
</header>
<nav class="crumb" id="drill-crumb"></nav>
<div class="drill-list" id="drill-list"></div>
</section>
<!-- ── 方案 C ── -->
<section class="panel" id="panel-c">
<p class="approach-note">
<strong>方案 C · 扁平列表 + 全路径</strong><br />
把树拍平为卡片列表,用「父 / 子 / 孙」全路径展示归属(分隔符 <code> / </code>)。搜索命中直观,但丢失展开折叠的树感,深层级可读性一般。
</p>
<header class="mp-header">
<div class="mp-header__row">
<a class="mp-subpage-back" href="shanxia-mp-workbench-demo.html">← 工作台</a>
<button class="mp-header__action" type="button" data-toast="打开新增分类表单">+ 新增</button>
</div>
<h1 class="mp-header__title" style="margin-top:8px">产品分类</h1>
<div class="mp-header__search" style="margin-top:10px">
<span class="mp-header__search-dot"></span>搜索分类名称
</div>
</header>
<div class="filter-chips">
<button class="chip active" type="button">全部</button>
<button class="chip" type="button">启用</button>
<button class="chip" type="button">停用</button>
</div>
<div class="flat-list" id="flat-list"></div>
</section>
</main>
<!-- 遮罩 + 操作 Action Sheet -->
<div class="mp-overlay" id="mask"></div>
<div class="cat-as" id="action-sheet">
<div class="cat-as__handle"></div>
<div class="cat-as__head">
<span class="cat-as__eyebrow">操作分类</span>
<span class="cat-as__title" id="sheet-title">分类名称</span>
</div>
<div class="cat-as__group">
<button class="cat-as__item" type="button" data-toast="编辑分类">
<span class="cat-as__icon cat-as__icon--edit">编</span>
<span class="cat-as__meta">
<span class="cat-as__name">编辑</span>
<span class="cat-as__desc">修改名称、上级、状态等</span>
</span>
<span class="cat-as__arrow">›</span>
</button>
<button class="cat-as__item" type="button" data-toast="新增子分类">
<span class="cat-as__icon cat-as__icon--add">子</span>
<span class="cat-as__meta">
<span class="cat-as__name">新增子分类</span>
<span class="cat-as__desc">在此分类下创建下级</span>
</span>
<span class="cat-as__arrow">›</span>
</button>
<button class="cat-as__item cat-as__item--danger" type="button" data-toast="删除(需二次确认)">
<span class="cat-as__icon cat-as__icon--del">删</span>
<span class="cat-as__meta">
<span class="cat-as__name">删除</span>
<span class="cat-as__desc">有子分类或关联产品时不可删</span>
</span>
<span class="cat-as__arrow">›</span>
</button>
</div>
<button class="cat-as__cancel" type="button" id="sheet-close">取消</button>
</div>
<div class="toast" id="toast"></div>
<script>
/**
* 模拟数据:对齐 Web CRM 产品分类树结构
* 字段:id / parentId / categoryName / status / orderNum / children
*/
const TREE = [
{
id: '1', parentId: '0', categoryName: '化工原料', status: '0', orderNum: 1,
children: [
{
id: '11', parentId: '1', categoryName: '有机溶剂', status: '0', orderNum: 1,
children: [
{ id: '111', parentId: '11', categoryName: '醇类', status: '0', orderNum: 1, children: [] },
{ id: '112', parentId: '11', categoryName: '酮类', status: '0', orderNum: 2, children: [] }
]
},
{
id: '12', parentId: '1', categoryName: '无机盐', status: '0', orderNum: 2,
children: [
{ id: '121', parentId: '12', categoryName: '硫酸盐', status: '1', orderNum: 1, children: [] }
]
}
]
},
{
id: '2', parentId: '0', categoryName: '精细化学品', status: '0', orderNum: 2,
children: [
{
id: '21', parentId: '2', categoryName: '催化剂', status: '0', orderNum: 1,
children: []
},
{
id: '22', parentId: '2', categoryName: '助剂', status: '0', orderNum: 2,
children: [
{ id: '221', parentId: '22', categoryName: '分散剂', status: '0', orderNum: 1, children: [] },
{ id: '222', parentId: '22', categoryName: '消泡剂', status: '0', orderNum: 2, children: [] }
]
}
]
},
{
id: '3', parentId: '0', categoryName: '包装耗材', status: '1', orderNum: 3,
children: []
}
]
const statusLabel = (s) => (String(s) === '0' ? '正常' : '停用')
const statusTag = (s) =>
String(s) === '0'
? '<span class="mp-tag mp-tag--success">正常</span>'
: '<span class="mp-tag mp-tag--muted">停用</span>'
/* ── Toast / Sheet ── */
const toastEl = document.getElementById('toast')
function showToast(msg) {
toastEl.textContent = msg
toastEl.classList.add('show')
clearTimeout(showToast._t)
showToast._t = setTimeout(() => toastEl.classList.remove('show'), 1600)
}
const mask = document.getElementById('mask')
const sheet = document.getElementById('action-sheet')
function openSheet(name) {
document.getElementById('sheet-title').textContent = name
mask.classList.add('is-open')
sheet.classList.add('is-open')
}
function closeSheet() {
mask.classList.remove('is-open')
sheet.classList.remove('is-open')
}
document.getElementById('sheet-close').onclick = closeSheet
mask.onclick = closeSheet
document.querySelectorAll('[data-toast]').forEach((el) => {
el.addEventListener('click', () => {
showToast(el.getAttribute('data-toast'))
if (el.closest('.cat-as')) closeSheet()
})
})
/* ── 方案切换 ── */
document.querySelectorAll('.approach-tab').forEach((tab) => {
tab.addEventListener('click', () => {
document.querySelectorAll('.approach-tab').forEach((t) => t.classList.remove('active'))
document.querySelectorAll('.panel').forEach((p) => p.classList.remove('active'))
tab.classList.add('active')
document.getElementById('panel-' + tab.dataset.approach).classList.add('active')
})
})
document.querySelectorAll('.filter-chips .chip').forEach((chip) => {
chip.addEventListener('click', () => {
const group = chip.parentElement
group.querySelectorAll('.chip').forEach((c) => c.classList.remove('active'))
chip.classList.add('active')
showToast('筛选:' + chip.textContent.trim() + '(Demo 仅示意)')
})
})
/* ── 方案 A:缩进展开树 ── */
const expanded = new Set(['1', '11', '2']) // 默认展开部分节点
function childCount(node) {
return (node.children || []).length
}
function renderTreeA() {
const root = document.getElementById('tree-a')
root.innerHTML = ''
function renderNodes(nodes, level, container) {
nodes.forEach((node) => {
const hasKids = childCount(node) > 0
const isOpen = expanded.has(node.id)
const pad = 12 + level * 18
const row = document.createElement('div')
row.className = 'tree-row' + (level === 1 ? ' is-l2' : level >= 2 ? ' is-l3' : '')
row.style.paddingLeft = pad + 'px'
row.innerHTML = `
<button class="tree-chevron ${hasKids ? '' : 'is-leaf'} ${isOpen ? 'is-open' : ''}" type="button" data-toggle="${node.id}" aria-label="展开折叠">▶</button>
<div class="tree-main">
<div class="tree-name">${node.categoryName}</div>
<div class="tree-meta">
${statusTag(node.status)}
<span>排序 ${node.orderNum}</span>
${hasKids ? `<span>${childCount(node)} 个子类</span>` : ''}
</div>
</div>
<div class="tree-actions">
<button class="icon-btn" type="button" data-toast="新增子分类:${node.categoryName}">+</button>
<button class="icon-btn more" type="button" data-more="${node.categoryName}">⋯</button>
</div>
`
container.appendChild(row)
if (hasKids) {
const wrap = document.createElement('div')
wrap.className = 'children-wrap' + (isOpen ? ' open' : '')
wrap.dataset.wrap = node.id
renderNodes(node.children, level + 1, wrap)
container.appendChild(wrap)
}
})
}
renderNodes(TREE, 0, root)
root.querySelectorAll('[data-toggle]').forEach((btn) => {
btn.addEventListener('click', (e) => {
e.stopPropagation()
const id = btn.getAttribute('data-toggle')
if (expanded.has(id)) expanded.delete(id)
else expanded.add(id)
renderTreeA()
})
})
root.querySelectorAll('[data-toast]').forEach((btn) => {
btn.addEventListener('click', (e) => {
e.stopPropagation()
showToast(btn.getAttribute('data-toast'))
})
})
root.querySelectorAll('[data-more]').forEach((btn) => {
btn.addEventListener('click', (e) => {
e.stopPropagation()
openSheet(btn.getAttribute('data-more'))
})
})
}
function collectIds(nodes, set) {
nodes.forEach((n) => {
if (childCount(n)) {
set.add(n.id)
collectIds(n.children, set)
}
})
}
let allExpanded = false
document.getElementById('btn-expand-all').addEventListener('click', () => {
allExpanded = !allExpanded
expanded.clear()
if (allExpanded) collectIds(TREE, expanded)
document.getElementById('btn-expand-all').textContent = allExpanded ? '全部折叠' : '全部展开'
renderTreeA()
})
/* ── 方案 B:逐级下钻 ── */
let drillStack = [{ id: '0', categoryName: '全部', children: TREE }]
function currentDrillNode() {
return drillStack[drillStack.length - 1]
}
function renderDrill() {
const node = currentDrillNode()
const crumb = document.getElementById('drill-crumb')
crumb.innerHTML = drillStack
.map((n, i) => {
if (i === drillStack.length - 1) {
return `<span class="current">${n.categoryName}</span>`
}
return `<a href="#" data-crumb="${i}">${n.categoryName}</a><span class="sep">/</span>`
})
.join('')
crumb.querySelectorAll('[data-crumb]').forEach((a) => {
a.addEventListener('click', (e) => {
e.preventDefault()
const idx = Number(a.getAttribute('data-crumb'))
drillStack = drillStack.slice(0, idx + 1)
renderDrill()
})
})
const list = document.getElementById('drill-list')
const kids = node.children || []
if (!kids.length) {
list.innerHTML = `<div class="drill-row"><div class="drill-main"><div class="drill-name">暂无子分类</div><div class="drill-sub">可点击右上角新增</div></div></div>`
return
}
list.innerHTML = kids
.map((n) => {
const hasKids = childCount(n) > 0
return `
<div class="drill-row" data-enter="${n.id}">
<div class="drill-icon">${n.categoryName.slice(0, 1)}</div>
<div class="drill-main">
<div class="drill-name">${n.categoryName}</div>
<div class="drill-sub">${statusLabel(n.status)} · 排序 ${n.orderNum}${hasKids ? ' · ' + childCount(n) + ' 个子类' : ' · 末级'}</div>
</div>
<button class="icon-btn more" type="button" data-more="${n.categoryName}">⋯</button>
${hasKids ? '<span class="drill-arrow">›</span>' : '<span class="drill-arrow" style="opacity:0">›</span>'}
</div>
`
})
.join('')
list.querySelectorAll('[data-enter]').forEach((row) => {
row.addEventListener('click', (e) => {
if (e.target.closest('[data-more]')) return
const id = row.getAttribute('data-enter')
const next = kids.find((k) => k.id === id)
if (next && childCount(next)) {
drillStack.push(next)
renderDrill()
} else if (next) {
openSheet(next.categoryName)
}
})
})
list.querySelectorAll('[data-more]').forEach((btn) => {
btn.addEventListener('click', (e) => {
e.stopPropagation()
openSheet(btn.getAttribute('data-more'))
})
})
}
/* ── 方案 C:扁平 + 全路径 ── */
function flattenWithPath(nodes, pathParts, out) {
nodes.forEach((n) => {
const path = [...pathParts, n.categoryName]
out.push({ ...n, pathLabel: path.join(' / ') })
if (n.children?.length) flattenWithPath(n.children, path, out)
})
return out
}
function renderFlat() {
const items = flattenWithPath(TREE, [], [])
const list = document.getElementById('flat-list')
list.innerHTML = items
.map(
(n) => `
<article class="flat-card">
<div class="flat-card__head">
<div>
<div class="flat-card__title">${n.categoryName}</div>
<div class="flat-card__path">${n.pathLabel}</div>
</div>
${statusTag(n.status)}
</div>
<div class="flat-card__foot">
<button class="mp-btn mp-btn--ghost" type="button" data-toast="新增子分类:${n.categoryName}">子分类</button>
<button class="mp-btn mp-btn--ghost" type="button" data-more="${n.categoryName}">更多</button>
<button class="mp-btn mp-btn--primary" type="button" data-toast="编辑:${n.categoryName}">编辑</button>
</div>
</article>
`
)
.join('')
list.querySelectorAll('[data-toast]').forEach((btn) => {
btn.addEventListener('click', () => showToast(btn.getAttribute('data-toast')))
})
list.querySelectorAll('[data-more]').forEach((btn) => {
btn.addEventListener('click', () => openSheet(btn.getAttribute('data-more')))
})
}
renderTreeA()
renderDrill()
renderFlat()
</script>
</body>
</html>