ux refine
This commit is contained in:
+121
-29
@@ -61,6 +61,13 @@ button,
|
||||
border-radius: 8px;
|
||||
cursor: pointer;
|
||||
padding: 10px 14px;
|
||||
text-decoration: none;
|
||||
line-height: 1.2;
|
||||
}
|
||||
|
||||
.button-primary {
|
||||
background: #0b57d0;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.button-secondary {
|
||||
@@ -69,9 +76,21 @@ button,
|
||||
border: 1px solid #cbd5e1;
|
||||
}
|
||||
|
||||
.button-danger {
|
||||
background: #b42318;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.button-small {
|
||||
padding: 8px 12px;
|
||||
font-size: 0.92rem;
|
||||
}
|
||||
|
||||
.button:hover,
|
||||
button:hover {
|
||||
opacity: 0.92;
|
||||
button:hover,
|
||||
.button:focus-visible,
|
||||
button:focus-visible {
|
||||
opacity: 0.94;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
@@ -92,6 +111,10 @@ button:hover {
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.page-header {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.stack {
|
||||
display: grid;
|
||||
gap: 12px;
|
||||
@@ -178,9 +201,14 @@ button:hover {
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.detail-image-compact {
|
||||
max-width: 180px;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.thumb-image {
|
||||
display: block;
|
||||
width: 88px;
|
||||
width: 64px;
|
||||
max-width: 100%;
|
||||
height: auto;
|
||||
border-radius: 8px;
|
||||
@@ -189,7 +217,7 @@ button:hover {
|
||||
}
|
||||
|
||||
.compact-thumb {
|
||||
flex: 0 0 88px;
|
||||
flex: 0 0 64px;
|
||||
}
|
||||
|
||||
.dense-list {
|
||||
@@ -197,21 +225,39 @@ button:hover {
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.overview-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.compact-row {
|
||||
display: grid;
|
||||
grid-template-columns: auto 1fr auto;
|
||||
gap: 12px;
|
||||
gap: 10px;
|
||||
align-items: start;
|
||||
padding: 10px 12px;
|
||||
padding: 8px 10px;
|
||||
border: 1px solid #ddd;
|
||||
border-radius: 10px;
|
||||
background: #fafafa;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.compact-row-box {
|
||||
grid-template-columns: 1fr auto;
|
||||
}
|
||||
|
||||
.overview-card {
|
||||
grid-template-columns: 1fr;
|
||||
gap: 8px;
|
||||
align-content: start;
|
||||
min-height: 150px;
|
||||
}
|
||||
|
||||
.overview-card-box {
|
||||
min-height: 140px;
|
||||
}
|
||||
|
||||
.compact-row-container {
|
||||
border-left: 4px solid #d98700;
|
||||
}
|
||||
@@ -227,6 +273,12 @@ button:hover {
|
||||
.compact-main h2,
|
||||
.compact-main h3 {
|
||||
margin-bottom: 4px;
|
||||
font-size: 1rem;
|
||||
}
|
||||
|
||||
.overview-card .compact-main h2,
|
||||
.overview-card .compact-main h3 {
|
||||
font-size: 1.02rem;
|
||||
}
|
||||
|
||||
.row-title-line {
|
||||
@@ -240,24 +292,54 @@ button:hover {
|
||||
.row-meta-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
|
||||
gap: 4px 12px;
|
||||
gap: 2px 10px;
|
||||
color: #555;
|
||||
font-size: 0.95rem;
|
||||
font-size: 0.9rem;
|
||||
}
|
||||
|
||||
.overview-card .row-meta-grid {
|
||||
grid-template-columns: 1fr;
|
||||
gap: 2px;
|
||||
}
|
||||
|
||||
.row-note {
|
||||
margin-top: 6px;
|
||||
margin-top: 4px;
|
||||
margin-bottom: 0;
|
||||
color: #333;
|
||||
font-size: 0.95rem;
|
||||
font-size: 0.9rem;
|
||||
}
|
||||
|
||||
.row-actions {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 6px;
|
||||
align-items: flex-end;
|
||||
white-space: nowrap;
|
||||
.clickable-card {
|
||||
cursor: pointer;
|
||||
transition: border-color 0.15s ease, box-shadow 0.15s ease, background 0.15s ease;
|
||||
}
|
||||
|
||||
.clickable-card:hover,
|
||||
.clickable-card:focus-within {
|
||||
border-color: #9fb8e8;
|
||||
box-shadow: 0 0 0 3px rgba(11, 87, 208, 0.08);
|
||||
background: #fcfdff;
|
||||
}
|
||||
|
||||
.detail-card-compact {
|
||||
display: grid;
|
||||
grid-template-columns: auto 1fr;
|
||||
gap: 12px 16px;
|
||||
align-items: start;
|
||||
}
|
||||
|
||||
.detail-meta-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
|
||||
gap: 4px 12px;
|
||||
}
|
||||
|
||||
.detail-note {
|
||||
grid-column: 1 / -1;
|
||||
}
|
||||
|
||||
.section-heading h2 {
|
||||
margin-bottom: 2px;
|
||||
}
|
||||
|
||||
.meta,
|
||||
@@ -324,18 +406,6 @@ button:hover {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.link-button {
|
||||
background: none;
|
||||
border: none;
|
||||
color: #b42318;
|
||||
padding: 0;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.link-button:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
@media (max-width: 720px) {
|
||||
.container {
|
||||
margin: 0;
|
||||
@@ -356,6 +426,28 @@ button:hover {
|
||||
|
||||
.thumb-image,
|
||||
.compact-thumb {
|
||||
width: 100px;
|
||||
width: 72px;
|
||||
}
|
||||
|
||||
.detail-card-compact {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 900px) {
|
||||
.overview-grid {
|
||||
grid-template-columns: repeat(3, minmax(0, 1fr));
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 1280px) {
|
||||
.overview-grid {
|
||||
grid-template-columns: repeat(4, minmax(0, 1fr));
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 1600px) {
|
||||
.overview-grid {
|
||||
grid-template-columns: repeat(5, minmax(0, 1fr));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,6 +15,24 @@
|
||||
{% block content %}{% endblock %}
|
||||
</main>
|
||||
<script>
|
||||
document.addEventListener("click", function (event) {
|
||||
const card = event.target.closest(".clickable-card[data-href]");
|
||||
if (!card) return;
|
||||
if (event.target.closest("a, button, form, input, textarea, select, label")) return;
|
||||
|
||||
window.location.href = card.dataset.href;
|
||||
});
|
||||
|
||||
document.addEventListener("keydown", function (event) {
|
||||
const card = event.target.closest(".clickable-card[data-href]");
|
||||
if (!card) return;
|
||||
if (event.key !== "Enter" && event.key !== " ") return;
|
||||
if (event.target.closest("a, button, form, input, textarea, select, label")) return;
|
||||
|
||||
event.preventDefault();
|
||||
window.location.href = card.dataset.href;
|
||||
});
|
||||
|
||||
document.addEventListener("keydown", function (event) {
|
||||
if (event.key !== "Enter") return;
|
||||
if (event.target.tagName === "TEXTAREA") return;
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
{% endif %}
|
||||
</p>
|
||||
</div>
|
||||
<a href="/boxes">返回箱子列表</a>
|
||||
<a class="button button-secondary button-small" href="/boxes">返回箱子列表</a>
|
||||
</div>
|
||||
|
||||
<form method="post" action="{{ form_action }}" class="stack form-panel" enctype="multipart/form-data">
|
||||
@@ -55,7 +55,7 @@
|
||||
<img src="/boxes/{{ box.id }}/image" alt="{{ box.name }}" class="detail-image">
|
||||
<button
|
||||
type="submit"
|
||||
class="link-button"
|
||||
class="button button-danger button-small"
|
||||
formaction="/boxes/{{ box.id }}/image/delete"
|
||||
formmethod="post"
|
||||
>
|
||||
@@ -63,6 +63,8 @@
|
||||
</button>
|
||||
</section>
|
||||
{% endif %}
|
||||
<button type="submit">{{ submit_label }}</button>
|
||||
<div class="form-actions">
|
||||
<button type="submit" class="button button-primary">{{ submit_label }}</button>
|
||||
</div>
|
||||
</form>
|
||||
{% endblock %}
|
||||
|
||||
@@ -12,17 +12,23 @@
|
||||
<h1>箱子总览</h1>
|
||||
<p class="muted">这里管理顶层搬家容器,例如纸箱、行李箱或大收纳箱。</p>
|
||||
</div>
|
||||
<a class="button" href="/boxes/new">新建箱子</a>
|
||||
<a class="button button-primary" href="/boxes/new">新建箱子</a>
|
||||
</div>
|
||||
|
||||
{% if boxes %}
|
||||
<div class="dense-list">
|
||||
<div class="overview-grid">
|
||||
{% for box in boxes %}
|
||||
<section class="compact-row compact-row-box">
|
||||
<section
|
||||
class="compact-row compact-row-box clickable-card overview-card overview-card-box"
|
||||
data-href="/boxes/{{ box.id }}"
|
||||
tabindex="0"
|
||||
role="link"
|
||||
aria-label="查看箱子 {{ box.name }}"
|
||||
>
|
||||
<div class="compact-main">
|
||||
<div class="row-title-line">
|
||||
<span class="type-tag type-box">Box</span>
|
||||
<h2><a href="/boxes/{{ box.id }}">{{ box.name }}</a></h2>
|
||||
<h2>{{ box.name }}</h2>
|
||||
</div>
|
||||
<div class="row-meta-grid">
|
||||
<span>物品数:{{ box.items|length }}</span>
|
||||
@@ -31,17 +37,13 @@
|
||||
</div>
|
||||
{% if box.note %}<p class="row-note">{{ box.note }}</p>{% endif %}
|
||||
</div>
|
||||
<div class="row-actions">
|
||||
<a href="/boxes/{{ box.id }}">查看详情</a>
|
||||
<a href="/boxes/{{ box.id }}/edit">编辑</a>
|
||||
</div>
|
||||
</section>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% else %}
|
||||
<section class="card">
|
||||
<p>还没有箱子。</p>
|
||||
<a href="/boxes/new">创建第一个箱子</a>
|
||||
<a class="button button-primary" href="/boxes/new">创建第一个箱子</a>
|
||||
</section>
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
|
||||
@@ -13,33 +13,44 @@
|
||||
<p class="muted">查看这个箱子的基本信息,以及它下面的直接物品。</p>
|
||||
</div>
|
||||
<div class="actions">
|
||||
<a href="/boxes">返回箱子列表</a>
|
||||
<a href="/search">去搜索</a>
|
||||
<a class="button" href="/boxes/{{ box.id }}/items/new">添加物品</a>
|
||||
<a class="button button-secondary button-small" href="/boxes">返回箱子列表</a>
|
||||
<a class="button button-secondary button-small" href="/search">去搜索</a>
|
||||
<a class="button button-primary" href="/boxes/{{ box.id }}/items/new">添加物品</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<section class="card">
|
||||
<section class="card detail-card detail-card-compact">
|
||||
{% if box.image_blob %}
|
||||
<img src="/boxes/{{ box.id }}/image" alt="{{ box.name }}" class="detail-image">
|
||||
<img src="/boxes/{{ box.id }}/image" alt="{{ box.name }}" class="detail-image detail-image-compact">
|
||||
{% endif %}
|
||||
<p><strong>房间:</strong> {{ box.room or '-' }}</p>
|
||||
<p><strong>状态:</strong> {{ box.status or '-' }}</p>
|
||||
<p><strong>备注:</strong> {{ box.note or '-' }}</p>
|
||||
<div class="detail-meta-grid">
|
||||
<p><strong>房间:</strong> {{ box.room or '-' }}</p>
|
||||
<p><strong>状态:</strong> {{ box.status or '-' }}</p>
|
||||
<p class="detail-note"><strong>备注:</strong> {{ box.note or '-' }}</p>
|
||||
</div>
|
||||
<div class="actions">
|
||||
<a href="/boxes/{{ box.id }}/edit">编辑箱子</a>
|
||||
<a class="button button-secondary button-small" href="/boxes/{{ box.id }}/edit">编辑箱子</a>
|
||||
<form method="post" action="/boxes/{{ box.id }}/delete">
|
||||
<button type="submit" class="link-button">删除箱子</button>
|
||||
<button type="submit" class="button button-danger button-small">删除箱子</button>
|
||||
</form>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="stack">
|
||||
<h2>物品</h2>
|
||||
<div class="section-heading">
|
||||
<h2>内部物品</h2>
|
||||
<p class="muted">重点浏览区域,点击任意一行可进入物品详情。</p>
|
||||
</div>
|
||||
{% if box.items %}
|
||||
<div class="dense-list">
|
||||
<div class="overview-grid">
|
||||
{% for item in box.items %}
|
||||
<article class="compact-row {{ 'compact-row-container' if item.is_container else 'compact-row-item' }}">
|
||||
<article
|
||||
class="compact-row clickable-card overview-card {{ 'compact-row-container' if item.is_container else 'compact-row-item' }}"
|
||||
data-href="/items/{{ item.id }}"
|
||||
tabindex="0"
|
||||
role="link"
|
||||
aria-label="查看物品 {{ item.name }}"
|
||||
>
|
||||
{% if item.image_blob %}
|
||||
<img src="/items/{{ item.id }}/image" alt="{{ item.name }}" class="thumb-image compact-thumb">
|
||||
{% endif %}
|
||||
@@ -48,24 +59,14 @@
|
||||
<span class="type-tag {{ 'type-container' if item.is_container else 'type-item' }}">
|
||||
{{ "容器型 Item" if item.is_container else "Item" }}
|
||||
</span>
|
||||
<h3><a href="/items/{{ item.id }}">{{ item.name }}</a></h3>
|
||||
<h3>{{ item.name }}</h3>
|
||||
</div>
|
||||
<div class="row-meta-grid">
|
||||
<span>数量:{{ item.quantity if item.quantity is not none else 1 }}</span>
|
||||
<span>是否容器:{{ "是" if item.is_container else "否" }}</span>
|
||||
{% if item.note %}<span>有备注</span>{% endif %}
|
||||
</div>
|
||||
{% if item.note %}<p class="row-note">{{ item.note }}</p>{% endif %}
|
||||
</div>
|
||||
<div class="row-actions">
|
||||
<a href="/items/{{ item.id }}">查看详情</a>
|
||||
<a href="/items/{{ item.id }}/edit">编辑</a>
|
||||
{% if item.is_container %}
|
||||
<a href="/items/{{ item.id }}">查看内部内容</a>
|
||||
{% endif %}
|
||||
<form method="post" action="/items/{{ item.id }}/delete">
|
||||
<button type="submit" class="link-button">删除</button>
|
||||
</form>
|
||||
</div>
|
||||
</article>
|
||||
{% endfor %}
|
||||
</div>
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
{% endif %}
|
||||
</p>
|
||||
</div>
|
||||
<a href="/boxes/{{ box.id }}">返回箱子</a>
|
||||
<a class="button button-secondary button-small" href="/boxes/{{ box.id }}">返回箱子</a>
|
||||
</div>
|
||||
|
||||
<form method="post" action="{{ form_action }}" class="stack form-panel" enctype="multipart/form-data">
|
||||
@@ -69,7 +69,7 @@
|
||||
<img src="/items/{{ item.id }}/image" alt="{{ item.name }}" class="detail-image">
|
||||
<button
|
||||
type="submit"
|
||||
class="link-button"
|
||||
class="button button-danger button-small"
|
||||
formaction="/items/{{ item.id }}/image/delete"
|
||||
formmethod="post"
|
||||
>
|
||||
@@ -78,9 +78,9 @@
|
||||
</section>
|
||||
{% endif %}
|
||||
<div class="form-actions">
|
||||
<button type="submit" name="submit_action" value="save">{{ submit_label }}</button>
|
||||
<button type="submit" name="submit_action" value="save" class="button button-primary">{{ submit_label }}</button>
|
||||
{% if not item %}
|
||||
<button type="submit" name="submit_action" value="save_and_add_next" class="button-secondary">
|
||||
<button type="submit" name="submit_action" value="save_and_add_next" class="button button-secondary">
|
||||
保存并添加下一个
|
||||
</button>
|
||||
{% endif %}
|
||||
|
||||
@@ -17,22 +17,23 @@
|
||||
<p class="muted">位于箱子 <a href="/boxes/{{ item.box.id }}">{{ item.box.name }}</a> 中</p>
|
||||
</div>
|
||||
<div class="actions">
|
||||
<a href="/boxes/{{ item.box.id }}">返回箱子</a>
|
||||
<a href="/search">去搜索</a>
|
||||
<a href="/items/{{ item.id }}/edit">编辑物品</a>
|
||||
<a class="button button-secondary button-small" href="/boxes/{{ item.box.id }}">返回箱子</a>
|
||||
<a class="button button-secondary button-small" href="/search">去搜索</a>
|
||||
<a class="button button-secondary button-small" href="/items/{{ item.id }}/edit">编辑物品</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<section class="card">
|
||||
<section class="card detail-card detail-card-compact">
|
||||
{% if item.image_blob %}
|
||||
<img src="/items/{{ item.id }}/image" alt="{{ item.name }}" class="detail-image">
|
||||
<img src="/items/{{ item.id }}/image" alt="{{ item.name }}" class="detail-image detail-image-compact">
|
||||
{% endif %}
|
||||
<p><strong>是否容器:</strong> {{ "是" if item.is_container else "否" }}</p>
|
||||
<p><strong>数量:</strong> {{ item.quantity if item.quantity is not none else '-' }}</p>
|
||||
<p><strong>备注:</strong> {{ item.note or '-' }}</p>
|
||||
<div class="detail-meta-grid">
|
||||
<p><strong>数量:</strong> {{ item.quantity if item.quantity is not none else '-' }}</p>
|
||||
<p class="detail-note"><strong>备注:</strong> {{ item.note or '-' }}</p>
|
||||
</div>
|
||||
<div class="actions">
|
||||
<form method="post" action="/items/{{ item.id }}/delete">
|
||||
<button type="submit" class="link-button">删除物品</button>
|
||||
<button type="submit" class="button button-danger button-small">删除物品</button>
|
||||
</form>
|
||||
</div>
|
||||
</section>
|
||||
@@ -40,13 +41,22 @@
|
||||
{% if item.is_container %}
|
||||
<section class="stack">
|
||||
<div class="page-header">
|
||||
<h2>子物品</h2>
|
||||
<a class="button" href="/items/{{ item.id }}/subitems/new">添加子物品</a>
|
||||
<div class="section-heading">
|
||||
<h2>内部子物品</h2>
|
||||
<p class="muted">当前容器里装的内容,点击任意一行可进入对应编辑上下文。</p>
|
||||
</div>
|
||||
<a class="button button-primary" href="/items/{{ item.id }}/subitems/new">添加子物品</a>
|
||||
</div>
|
||||
{% if item.subitems %}
|
||||
<div class="dense-list">
|
||||
<div class="overview-grid">
|
||||
{% for subitem in item.subitems %}
|
||||
<article class="compact-row compact-row-subitem">
|
||||
<article
|
||||
class="compact-row clickable-card compact-row-subitem overview-card"
|
||||
data-href="/subitems/{{ subitem.id }}/edit"
|
||||
tabindex="0"
|
||||
role="link"
|
||||
aria-label="查看子物品 {{ subitem.name }}"
|
||||
>
|
||||
{% if subitem.image_blob %}
|
||||
<img src="/subitems/{{ subitem.id }}/image" alt="{{ subitem.name }}" class="thumb-image compact-thumb">
|
||||
{% endif %}
|
||||
@@ -61,12 +71,6 @@
|
||||
</div>
|
||||
{% if subitem.note %}<p class="row-note">备注:{{ subitem.note }}</p>{% endif %}
|
||||
</div>
|
||||
<div class="row-actions">
|
||||
<a href="/subitems/{{ subitem.id }}/edit">编辑</a>
|
||||
<form method="post" action="/subitems/{{ subitem.id }}/delete">
|
||||
<button type="submit" class="link-button">删除</button>
|
||||
</form>
|
||||
</div>
|
||||
</article>
|
||||
{% endfor %}
|
||||
</div>
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
value="{{ query }}"
|
||||
placeholder="例如:锅、电源线、冬衣、文件袋"
|
||||
>
|
||||
<button type="submit">搜索</button>
|
||||
<button type="submit" class="button button-primary">搜索</button>
|
||||
</form>
|
||||
</section>
|
||||
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
{% endif %}
|
||||
</p>
|
||||
</div>
|
||||
<a href="/items/{{ item.id }}">返回物品</a>
|
||||
<a class="button button-secondary button-small" href="/items/{{ item.id }}">返回物品</a>
|
||||
</div>
|
||||
|
||||
<form method="post" action="{{ form_action }}" class="stack form-panel" enctype="multipart/form-data">
|
||||
@@ -64,7 +64,7 @@
|
||||
<img src="/subitems/{{ subitem.id }}/image" alt="{{ subitem.name }}" class="detail-image">
|
||||
<button
|
||||
type="submit"
|
||||
class="link-button"
|
||||
class="button button-danger button-small"
|
||||
formaction="/subitems/{{ subitem.id }}/image/delete"
|
||||
formmethod="post"
|
||||
>
|
||||
@@ -73,9 +73,9 @@
|
||||
</section>
|
||||
{% endif %}
|
||||
<div class="form-actions">
|
||||
<button type="submit" name="submit_action" value="save">{{ submit_label }}</button>
|
||||
<button type="submit" name="submit_action" value="save" class="button button-primary">{{ submit_label }}</button>
|
||||
{% if not subitem %}
|
||||
<button type="submit" name="submit_action" value="save_and_add_next" class="button-secondary">
|
||||
<button type="submit" name="submit_action" value="save_and_add_next" class="button button-secondary">
|
||||
保存并添加下一个
|
||||
</button>
|
||||
{% endif %}
|
||||
|
||||
+44
-1
@@ -769,7 +769,9 @@ def test_box_detail_page_renders_clear_hierarchy_and_dense_list_structure(client
|
||||
assert response.status_code == 200
|
||||
assert "Box" in response.text
|
||||
assert "厨房箱" in response.text
|
||||
assert "compact-row" in response.text
|
||||
assert "overview-grid" in response.text
|
||||
assert f'data-href="/items/{item.id}"' in response.text
|
||||
assert "是否容器" not in response.text
|
||||
|
||||
|
||||
def test_item_detail_page_renders_clear_hierarchy(client, db_session):
|
||||
@@ -785,6 +787,47 @@ def test_item_detail_page_renders_clear_hierarchy(client, db_session):
|
||||
assert "容器型 Item" in response.text
|
||||
assert "书房箱" in response.text
|
||||
assert "SubItem" in response.text
|
||||
assert f'data-href="/subitems/{subitem.id}/edit"' in response.text
|
||||
assert "overview-grid" in response.text
|
||||
|
||||
|
||||
def test_box_detail_page_shows_primary_and_secondary_cta_buttons(client, db_session):
|
||||
box = Box(name="操作箱")
|
||||
db_session.add(box)
|
||||
db_session.commit()
|
||||
|
||||
response = client.get(f"/boxes/{box.id}")
|
||||
|
||||
assert response.status_code == 200
|
||||
assert "button button-primary" in response.text
|
||||
assert "button button-secondary" in response.text
|
||||
assert "删除箱子" in response.text
|
||||
|
||||
|
||||
def test_boxes_overview_uses_clickable_cards_without_detail_edit_buttons(client, db_session):
|
||||
box = Box(name="可点击箱子")
|
||||
db_session.add(box)
|
||||
db_session.commit()
|
||||
|
||||
response = client.get("/boxes")
|
||||
|
||||
assert response.status_code == 200
|
||||
assert f'data-href="/boxes/{box.id}"' in response.text
|
||||
assert "查看详情" not in response.text
|
||||
assert "编辑</a>" not in response.text
|
||||
|
||||
|
||||
def test_item_detail_page_shows_primary_action_for_adding_subitems(client, db_session):
|
||||
box = Box(name="容器箱")
|
||||
item = Item(name="收纳盒", box=box, is_container=True)
|
||||
db_session.add_all([box, item])
|
||||
db_session.commit()
|
||||
|
||||
response = client.get(f"/items/{item.id}")
|
||||
|
||||
assert response.status_code == 200
|
||||
assert "添加子物品" in response.text
|
||||
assert "button button-primary" in response.text
|
||||
|
||||
|
||||
def test_creating_regular_item_redirects_back_to_parent_box(client, db_session):
|
||||
|
||||
Reference in New Issue
Block a user