Files
workspace/code/app/app-rn4/text.html
T
2026-04-26 21:00:34 +08:00

264 lines
4.8 KiB
HTML

<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8" />
<title>附件组件(最终版)</title>
<style>
body {
margin: 0;
font-family: Arial;
background: #f5f6f8;
}
/* grid */
.grid {
padding: 12px;
display: grid;
grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
gap: 12px;
}
/* card */
.card {
position: relative;
background: #fff;
border-radius: 10px;
border: 1px solid transparent;
display: flex;
flex-direction: column;
cursor: pointer;
}
.card:hover {
border-color: #1677ff;
}
.card.selected {
background: #eaf2ff;
border-color: #1677ff;
}
/* checkbox(左上) */
.check {
position: absolute;
top: 6px;
left: 6px;
z-index: 5;
}
/* 状态(右上) */
.status {
position: absolute;
top: 6px;
right: 6px;
background: #ff4d4f;
color: #fff;
font-size: 10px;
padding: 2px 5px;
border-radius: 3px;
}
/* thumb */
.thumb {
height: 90px;
background: #f0f2f5;
display:flex;
align-items:center;
justify-content:center;
}
.thumb img {
width:100%;
height:100%;
object-fit:cover;
}
/* info */
.info {
padding: 8px;
}
.name {
font-size: 13px;
}
.meta {
font-size: 12px;
color: #888;
}
/* actions */
.actions {
display: flex;
border-top: 1px solid #eee;
}
.actions button {
flex: 1;
border: none;
background: #fff;
padding: 6px 0;
cursor: pointer;
font-size: 12px;
}
.actions button:hover {
background: #f5f6f8;
}
.danger {
color: #ff4d4f;
}
.more-menu {
position: absolute;
bottom: 35px;
right: 6px;
background: #fff;
border: 1px solid #eee;
border-radius: 6px;
box-shadow: 0 2px 8px rgba(0,0,0,0.1);
display: none;
}
.more-menu div {
padding: 6px 10px;
cursor: pointer;
}
.more-menu div:hover {
background: #f5f6f8;
}
</style>
</head>
<body>
<div class="grid" id="grid"></div>
<script>
const files = [
{ id: 1, name: "合同.pdf", type: "doc", size: "800KB", date: "2026-04-25" },
{ id: 2, name: "设计图.png", type: "img", url: "https://picsum.photos/400/300?1", size: "1.2MB", date: "2026-04-24", status: "未上传" }
];
let selected = new Set();
function render() {
const grid = document.getElementById("grid");
grid.innerHTML = "";
files.forEach(f => {
const card = document.createElement("div");
card.className = "card" + (selected.has(f.id) ? " selected" : "");
card.onclick = () => toggleSelect(f.id);
/* checkbox */
const check = document.createElement("input");
check.type = "checkbox";
check.className = "check";
check.checked = selected.has(f.id);
check.onclick = (e) => {
e.stopPropagation();
toggleSelect(f.id);
};
/* 状态 */
if (f.status) {
const st = document.createElement("div");
st.className = "status";
st.innerText = f.status;
card.appendChild(st);
}
/* thumb */
const thumb = document.createElement("div");
thumb.className = "thumb";
if (f.type === "img") {
thumb.innerHTML = `<img src="${f.url}">`;
} else {
thumb.innerText = "📄";
}
/* info */
const info = document.createElement("div");
info.className = "info";
info.innerHTML = `
<div class="name">${f.name}</div>
<div class="meta">${f.date} · ${f.size}</div>
`;
/* actions */
const actions = document.createElement("div");
actions.className = "actions";
const btnView = createBtn("预览", () => preview(f));
const btnDown = createBtn("下载", () => alert("下载 " + f.name));
const btnDelete = createBtn("删除", () => deleteFile(f.id), "danger");
/* 更多 */
const btnMore = document.createElement("button");
btnMore.innerText = "⋯";
const menu = document.createElement("div");
menu.className = "more-menu";
menu.innerHTML = `
<div>重命名</div>
<div>查看详情</div>
`;
btnMore.onclick = (e) => {
e.stopPropagation();
menu.style.display = menu.style.display === "block" ? "none" : "block";
};
document.addEventListener("click", () => {
menu.style.display = "none";
});
actions.append(btnView, btnDown, btnDelete, btnMore);
card.append(check, thumb, info, actions, menu);
grid.appendChild(card);
});
}
function createBtn(text, fn, cls="") {
const btn = document.createElement("button");
btn.innerText = text;
btn.className = cls;
btn.onclick = (e) => {
e.stopPropagation();
fn();
};
return btn;
}
function toggleSelect(id) {
if (selected.has(id)) selected.delete(id);
else selected.add(id);
render();
}
function preview(f) {
alert("预览 " + f.name);
}
function deleteFile(id) {
if (!confirm("确定删除?")) return;
const i = files.findIndex(f => f.id === id);
if (i > -1) files.splice(i, 1);
selected.delete(id);
render();
}
render();
</script>
</body>
</html>