feat: 拖拽布局-列表页

flex-api
lichaojun 1 month ago
parent 64babb1a99
commit 2ee0cac94c

@ -123,6 +123,23 @@ mainData = {
} }
``` ```
## 历史任务
* 实现一个列表页列表页里面包含多个index.html生成的模板
* 列表页面的js文件格式请参照index.js的写法包括使用jquery进行初始化等保持代码风格一致
* 列表页面一个子项宽度为400px,从左到右依次排列,超出换行,并且保证换行后每行的每个子项左右间距相同
* 子项高度根据内容自动撑开
* 子项的数据参考data.json
```
子项布局参考
image (占满,固定高度)
name + action btn action btn 点击后弹出选项 1. 复制 2. 删除 3. 编辑 4. 应用)
date
```
* 子项数据直接使用data.json并复制内部子项10份更改id和name保证不重复
@ -143,3 +160,19 @@ mainData = {
- 新的实现方式通过遍历由下划线分割的属性名部分,动态地创建任意层级的嵌套对象。例如,`a_b_c` 会被正确地转换为 `{ a: { b: { c: value } } }` - 新的实现方式通过遍历由下划线分割的属性名部分,动态地创建任意层级的嵌套对象。例如,`a_b_c` 会被正确地转换为 `{ a: { b: { c: value } } }`
- **文件改动**: - **文件改动**:
- `js/index.js`: 更新了 `transformUnderscoreData` 函数的实现逻辑,使其更加灵活和通用。 - `js/index.js`: 更新了 `transformUnderscoreData` 函数的实现逻辑,使其更加灵活和通用。
### 本次会话总结
- **任务**: 优化 `list.html` 列表页的布局和交互功能。
- **布局优化点**:
- **最后一行对齐问题**: 解决了由于 `justify-content: space-around` 导致的最后一行项目居中或分散的问题,通过将 `#list-panel``justify-content` 改为 `flex-start`,确保最后一行从左到右对齐。
- **子项宽度及排版**: 将 `.list-item` 的固定宽度 `400px` 修改为 `calc(25% - 7.5px)`实现了每行4个子项的弹性布局并合理处理了子项间的 `gap` 间距。
- **底部内边距缺失**: 解决了 `#list-panel` 底部 `padding` 显示不全的问题,通过为 `#list-panel` 添加 `width: 100%`,确保其在 flex 父容器中正确撑开。
- **交互优化点**:
- **模板名称显示**: 修复了列表项中模板名称 (`item.name`) 未显示的问题,通过在 `js/list.js` 中动态生成的 HTML 结构中添加 `<span class="list-item-name">${item.name}</span>`
- **操作按钮样式优化**: 优化了点击“...”按钮弹出的操作菜单(`.action-menu`)的样式:
- 为 `.action-menu` 添加 `min-width: 80px;`,防止文字换行。
- 为 `.action-menu button` 添加 `white-space: nowrap;` 禁止文字换行,将 `text-align` 改为 `center`,并增加 `transition` 效果。
- **操作按钮事件**: 为操作菜单中的四个按钮(复制、删除、编辑、应用)添加了点击事件监听,点击时会在控制台打印相应的操作名称。
- **文件改动**:
- `css/list.css`: 修改了 `#list-panel``.action-menu` 的样式,以及 `.list-item``.action-menu button` 的样式。
- `js/list.js`: 修改了 `listItem` 的 HTML 模板以显示名称,并添加了四个操作按钮的点击事件监听器。

@ -0,0 +1,83 @@
#main {
height: unset;
overflow-y: auto; /* 允许垂直滚动 */
}
#list-panel {
display: flex;
flex-wrap: wrap;
justify-content: flex-start;
gap: 10px; /* 调整子项内容间距 */
padding: 20px;
width: 100%;
overflow-y: scroll;
}
.list-item {
width: calc(25% - 7.5px);
background-color: #fff;
border-radius: 8px;
box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1);
display: flex;
flex-direction: column;
}
.list-item-image {
width: 100%;
height: 225px; /* 16:9 aspect ratio for 400px width */
object-fit: cover;
border-top-left-radius: 8px;
border-top-right-radius: 8px;
}
.list-item-content {
padding: 10px 15px; /* 调整子项内容间距 */
display: flex;
justify-content: space-between;
align-items: center;
}
.list-item-name {
font-size: 18px;
font-weight: 600;
}
.list-item-actions {
position: relative;
}
.action-btn {
background: none;
border: none;
cursor: pointer;
font-size: 20px;
}
.action-menu {
display: none;
position: absolute;
right: 0;
top: 30px;
background-color: #fff;
border-radius: 4px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
z-index: 1;
min-width: 80px;
padding: 5px 0;
}
.action-menu button {
display: block;
width: 100%;
padding: 8px 12px;
border: none;
background: none;
text-align: center;
cursor: pointer;
white-space: nowrap;
transition: background-color 0.2s ease;
color: #333;
}
.action-menu button:hover {
background-color: #f0f0f0;
}
.list-item-date {
padding: 0 15px 10px; /* 调整子项内容间距 */
font-size: 12px;
color: #999;
}

File diff suppressed because it is too large Load Diff

@ -0,0 +1,60 @@
(function () {
$(function () {
$.getJSON('data.json', function (data) {
var listPanel = $('#list-panel');
$.each(data, function (index, item) {
var listItem = `
<div class="list-item">
<img class="list-item-image" src="${item.mainData.image}" alt="${item.name}">
<div class="list-item-content">
<span class="list-item-name">${item.name}</span>
<div class="list-item-actions">
<button class="action-btn">...</button>
<div class="action-menu">
<button class="copy-btn">复制</button>
<button class="delete-btn">删除</button>
<button class="edit-btn">编辑</button>
<button class="apply-btn">应用</button>
</div>
</div>
</div>
<div class="list-item-date">
<span>更新时间${item.updateTime}</span>
</div>
</div>
`;
listPanel.append(listItem);
});
// Action button click handler
listPanel.on('click', '.action-btn', function (e) {
e.stopPropagation();
var menu = $(this).siblings('.action-menu');
$('.action-menu').not(menu).hide();
menu.toggle();
});
// Hide menu when clicking outside
$(document).on('click', function () {
$('.action-menu').hide();
});
// Event handlers for action menu buttons
listPanel.on('click', '.copy-btn', function () {
console.log('复制');
});
listPanel.on('click', '.delete-btn', function () {
console.log('删除');
});
listPanel.on('click', '.edit-btn', function () {
console.log('编辑');
});
listPanel.on('click', '.apply-btn', function () {
console.log('应用');
});
});
});
})();

@ -0,0 +1,31 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta
name="viewport"
content="width=device-width, initial-scale=1.0"
/>
<title>模板列表</title>
<link
rel="stylesheet"
href="./css/index.css"
/>
<link
rel="stylesheet"
href="./css/list.css"
/>
<script src="./js/jquery.min.js"></script>
</head>
<body>
<div id="app">
<div id="header">
<h1>模板列表</h1>
</div>
<div id="main">
<div id="list-panel"></div>
</div>
</div>
</body>
</html>
<script src="./js/list.js"></script>
Loading…
Cancel
Save