ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Js的Lit框架,实现任务看板,可拖放,最小代码,敏捷,极限编程

Js的Lit框架,实现任务看板,可拖放,最小代码,敏捷,极限编程 任务看板代码最小代码创建一个 project-card-temp.html!DOCTYPE html html langzh-CN head meta charsetUTF-8 / meta nameviewport contentwidthdevice-width, initial-scale1.0 / title任务看板/title style /* 基础重置与全局样式 */ :root { --bg-color: #f5f6f8; --lane-bg: #f0f2f5; --card-bg: #ffffff; --text-main: #1f2937; --text-sub: #6b7280; --border-color: #e5e7eb; --primary: #3b82f6; } * { box-sizing: border-box; margin: 0; padding: 0; } body { font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, sans-serif; background: var(--bg-color); color: var(--text-main); height: 100vh; display: flex; flex-direction: column; overflow: hidden; } /style !-- 引入 Lit -- script typeimportmap { imports: { lit: https://esm.sh/lit3, lit/directives/: https://esm.sh/lit3/directives/ } } /script /head body div idapp styleheight: 100%; width: 100%;/div script typemodule import { LitElement, html, css } from lit; // // 主看板组件 // class TaskBoard extends LitElement { static styles css :host { display: flex; flex-direction: column; height: 100%; } /* 顶部工具栏 */ header { display: flex; align-items: center; padding: 12px 24px; background: var(--card-bg); border-bottom: 1px solid var(--border-color); gap: 16px; box-shadow: 0 1px 3px rgba(0,0,0,0.04); } .btn-back { border: 1px solid var(--border-color); background: transparent; padding: 6px 12px; border-radius: 4px; cursor: pointer; color: var(--text-sub); font-size: 14px; display: flex; align-items: center; gap: 4px; } .header-title h1 { font-size: 18px; margin-bottom: 4px; } .header-meta { font-size: 12px; color: var(--text-sub); display: flex; gap: 12px; } .header-controls { margin-left: auto; display: flex; gap: 12px; align-items: center; } .control-box { border: 1px solid var(--border-color); border-radius: 6px; padding: 6px 12px; font-size: 14px; display: flex; align-items: center; background: var(--card-bg); } .control-box input { border: none; outline: none; font-size: 14px; background: transparent; width: 140px;} /* 标签筛选栏 */ .filter-bar { padding: 12px 24px; display: flex; align-items: center; gap: 8px; font-size: 13px; color: var(--text-sub); } .tag-filter { background: #e0e7ff; color: #3730a3; padding: 4px 12px; border-radius: 12px; font-size: 12px; font-weight: 500; } /* 泳道容器 */ .board-area { display: flex; gap: 16px; padding: 16px 24px; flex: 1; overflow-x: auto; } ; static properties { items: { type: Array }, lanes: { type: Array }, }; constructor() { super(); this.items [ { id: 1, title: img2threejs-showcase, tags: [美术], path: F:\\360Downloads\\2027Unity, date: 2026-10-03, status: todo }, { id: 2, title: 咸鱼游戏第一步, tags: [], path: , date: 2026-10-03, status: todo }, { id: 3, title: 性能压力测试, tags: [性能], path: , date: 2026-10-05, status: planning }, ]; this.lanes [ { id: planning, name: 待规划, color: #6366f1 }, { id: todo, name: 待办, color: #3b82f6 }, { id: progress, name: 进行中, color: #f59e0b }, { id: done, name: 已完成, color: #10b981 }, ]; } render() { return html header button classbtn-back‹ 返回会话/button div classheader-title h1任务看板/h1 div classheader-meta spanHost 时区 Asia/Shanghai/span span• revision 10/span /div /div div classheader-controls div classcontrol-box 项目: 全部项目 span stylemargin-left:4px; font-size:10px;▼/span /div div classcontrol-box input typetext placeholder筛选任务... / /div /div /header div classfilter-bar 按标签筛选 span classtag-filter美术/span /div div classboard-area ${this.lanes.map( (lane) { const laneItems this.items.filter(i i.status lane.id); return html lane-column .title${lane.name} .color${lane.color} .items${laneItems} .status${lane.id} card-drop${this._onDrop} /lane-column ; } )} /div ; } _onDrop(e) { const { id, targetStatus } e.detail; const item this.items.find(i i.id id); if (item item.status ! targetStatus) { item.status targetStatus; this.requestUpdate(); } } } // // 泳道列组件 // class LaneColumn extends LitElement { static styles css :host { display: block; min-width: 300px; flex: 1; } .lane { background: var(--lane-bg); border-radius: 8px; height: 100%; display: flex; flex-direction: column; padding: 12px; } .lane-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 12px; font-size: 14px; font-weight: 600; } .header-left { display: flex; align-items: center; gap: 6px; } .color-dot { width: 8px; height: 8px; border-radius: 50%; } .header-count { background: rgba(0,0,0,0.05); padding: 2px 8px; border-radius: 10px; font-size: 12px; } .card-container { flex: 1; overflow-y: auto; min-height: 100px; } .empty-state { color: var(--text-sub); font-size: 13px; text-align: center; margin-top: 40px; } ; static properties { title: { type: String }, color: { type: String }, items: { type: Array }, status: { type: String }, dragOver: { type: Boolean, state: true }, }; render() { return html div classlane div classlane-header div classheader-left div classcolor-dot stylebackground: ${this.color}/div ${this.title} /div div classheader-count${this.items.length}/div /div div classcard-container dragover${this._onDragOver} dragleave${this._onDragLeave} drop${this._onDrop} ${this.items.length 0 ? htmldiv classempty-state这个状态还没有任务/div : this.items.map(item htmltask-card .item${item}/task-card) } /div /div ; } _onDragOver(e) { e.preventDefault(); this.dragOver true; } _onDragLeave() { this.dragOver false; } _onDrop(e) { e.preventDefault(); this.dragOver false; const id e.dataTransfer.getData(text/plain); this.dispatchEvent(new CustomEvent(card-drop, { bubbles: true, composed: true, detail: { id, targetStatus: this.status } })); } } // // 任务卡片组件 // class TaskCard extends LitElement { static styles css :host { display: block; margin-bottom: 10px; } .card { background: var(--card-bg); border-radius: 6px; padding: 12px; box-shadow: 0 1px 2px rgba(0,0,0,0.05); cursor: grab; border: 1px solid var(--border-color); transition: box-shadow 0.2s, transform 0.1s; } .card:hover { box-shadow: 0 4px 12px rgba(0,0,0,0.08); transform: translateY(-1px); } .card.dragging { opacity: 0.4; cursor: grabbing; } .card-title { font-size: 14px; font-weight: 500; margin-bottom: 8px; color: var(--text-main); } .tags { display: flex; gap: 6px; flex-wrap: wrap; margin-bottom: 8px; } .tag { background: #e0e7ff; color: #3730a3; padding: 2px 8px; border-radius: 4px; font-size: 11px; } .card-meta { font-size: 11px; color: var(--text-sub); display: flex; flex-direction: column; gap: 2px; } ; static properties { item: { type: Object }, dragging: { type: Boolean, state: true } }; render() { const { title, tags, path, date } this.item; return html div classcard ${this.dragging ? dragging : } draggabletrue dragstart${this._onDragStart} dragend${this._onDragEnd} div classcard-title${title}/div div classtags ${tags.map(t htmlspan classtag${t}/span)} /div div classcard-meta ${path ? htmlspan${path}/span : } span更新于 ${date}/span /div /div ; } _onDragStart(e) { e.dataTransfer.setData(text/plain, this.item.id); this.dragging true; } _onDragEnd() { this.dragging false; } } // 注册组件 customElements.define(task-board, TaskBoard); customElements.define(lane-column, LaneColumn); customElements.define(task-card, TaskCard); // 渲染到页面 document.getElementById(app).innerHTML task-board/task-board; /script /body /html效果图参考--无厘头 - Unity 3d旋转代码没什么用参考/// summary /// 最近做的一个旋转控制。。。。。。最近做了2~3次但是每次都不知道怎么做出来的 /// /summary /// param nameangle/param /// param namesender/param public void DoUpdateRotate(float angle, BEUITwitchButton sender) { //var realAngle Mathf.Abs( angle) % 360; var realAngle sender.transform.rotation.eulerAngles.z; realAngle realAngle % 360; Debug.LogError($SELF{transform.rotation.eulerAngles.y} do target real realAngle); if (realAngle265 realAngle 275) { transform.rotation Quaternion.Euler(0, -270, 0); } else if (realAngle220 realAngle 230) { transform.rotation Quaternion.Euler(0, -225, 0); } else if(realAngle175 realAngle185) { transform.rotation Quaternion.Euler(0, -180, 0); } else if (realAngle 130 realAngle140) { transform.rotation Quaternion.Euler(0, -135, 0); } else if (realAngle 85 realAngle95) { transform.rotation Quaternion.Euler(0, -90, 0); }else if (realAngle 40 realAngle50) { transform.rotation Quaternion.Euler(0, -45, 0); }else if (realAngle 5 || realAngle 355) { transform.rotation Quaternion.Euler(0, 0, 0); } }
返回列表