@@ -176,7 +176,7 @@ window.switchTab = switchTab;
function renderProjects ( ) {
function renderProjects ( ) {
const items = state . data . operations ;
const items = state . data . operations ;
const rows = items . map ( ( x ) => [
const rows = items . map ( ( x ) => [
` <strong> ${ x . project _name } </strong><p class="text-xs text-slate-500"> ${ x . project _version } </p> ` ,
` <strong> ${ x . project _name } </strong> ` ,
text ( x . customer _need || x . notes ) ,
text ( x . customer _need || x . notes ) ,
badge ( x . current _stage || x . project _status ) ,
badge ( x . current _stage || x . project _status ) ,
x . expected _contract _amount ? money ( x . expected _contract _amount ) : "—" ,
x . expected _contract _amount ? money ( x . expected _contract _amount ) : "—" ,
@@ -184,13 +184,22 @@ function renderProjects() {
` <button class="btn btn-ghost btn-sm text-blue-600" onclick="event.stopPropagation(); showTaskModal( ${ x . id } )"><i data-lucide="eye"></i>查看</button> `
` <button class="btn btn-ghost btn-sm text-blue-600" onclick="event.stopPropagation(); showTaskModal( ${ x . id } )"><i data-lucide="eye"></i>查看</button> `
] ) ;
] ) ;
document . querySelector ( "#projects" ) . innerHTML = ` <div class="grid gap-4">
document . querySelector ( "#projects" ) . innerHTML = ` <div class="grid gap-4">
<div class="flex items-center justify-between">
<div class="flex gap-2">
${ [ [ "all" , "全部" ] , [ "项目准备" , "准备" ] , [ "项目执行" , "执行" ] , [ "项目验收" , "验收" ] , [ "验收完毕" , "完毕" ] ] . map ( ( [ k , v ] ) => ` <button class="btn ${ state . opFilter === k ? "btn-primary" : "btn-ghost" } btn-sm" onclick="state.opFilter=' ${ k } '; renderProjects()"> ${ v } </button> ` ) . join ( "" ) }
</div>
<button class="btn btn-primary" onclick="document.querySelector('#project-form').classList.toggle('hidden')">
<i data-lucide="plus"></i>新增项目
</button>
</div>
<div id="project-form" class="hidden">
${ card ( formHtml ( [
${ card ( formHtml ( [
{ label : "项目名称" , input : ` <input name="project_name" required> ` } ,
{ label : "项目名称" , input : ` <input name="project_name" required> ` } ,
{ label: "项目版本", input: ` < input name = "project_version" value = "v1.0" > ` },
{ label: "当前阶段", input: ` < select name = "current_stage" > < option > 项目准备 < / o p t i o n > < o p t i o n > 项 目 执 行 < / o p t i o n > < o p t i o n > 项 目 验 收 < / o p t i o n > < o p t i o n > 验 收 完 毕 < / o p t i o n > < / s e l e c t > ` } ,
{ label: "当前阶段", input: ` < select name = "current_stage" > < option > 项目准备 < / o p t i o n > < o p t i o n > 项 目 执 行 < / o p t i o n > < o p t i o n > 项 目 验 收 < / o p t i o n > < o p t i o n > 验 收 完 毕 < / o p t i o n > < / s e l e c t > ` } ,
{ label : "项目金额" , input : ` <input name="expected_contract_amount" type="number" step="0.01" placeholder="万元"> ` } ,
{ label : "项目金额" , input : ` <input name="expected_contract_amount" type="number" step="0.01" placeholder="万元"> ` } ,
{ label : "负责人" , input : ` <input name="owner"> ` } ,
{ label : "负责人" , input : ` <input name="owner"> ` } ,
] , { handler : "createOperation" , text : "新增项目 " } ) , "p-4" ) }
] , { handler : "createOperation" , text : "确认 新增" } ) , "p-4" ) }
< / d i v >
$ { renderTable ( [ "项目" , "项目说明" , "当前阶段" , "项目金额" , "负责人" , "进展" ] , rows , items . map ( ( x ) => ( { resource : "operations" , id : x . id } ) ) ) }
$ { renderTable ( [ "项目" , "项目说明" , "当前阶段" , "项目金额" , "负责人" , "进展" ] , rows , items . map ( ( x ) => ( { resource : "operations" , id : x . id } ) ) ) }
< / d i v > ` ;
< / d i v > ` ;
}
}
@@ -199,11 +208,12 @@ function showTaskModal(projectId) {
const project = state . data . operations . find ( ( x ) => x . id === projectId ) ;
const project = state . data . operations . find ( ( x ) => x . id === projectId ) ;
const tasks = ( state . data . tasks || [ ] ) . filter ( ( t ) => t . project _id === projectId ) ;
const tasks = ( state . data . tasks || [ ] ) . filter ( ( t ) => t . project _id === projectId ) ;
const phases = [ "项目准备" , "项目执行" , "项目验收" , "验收完毕" ] ;
const phases = [ "项目准备" , "项目执行" , "项目验收" , "验收完毕" ] ;
document . querySelector ( "#taskModal" ) . innerHTML = ` <div class="task-overlay" onclick="closeTaskModal()"><div class="task-panel" onclick="event.stopPropagation()"><div class="flex items-center justify-between border-b border-slate-200 px-6 py-4"><h2 class="text-lg font-bold "> ${ project . project _name } · 任务清单</h2><button class="btn btn-ghost btn-sm " onclick="closeTaskModal()">关闭 </button></div><div class="grid gap-4 p-6 "> ${ phases . map ( ( phase ) => {
document . querySelector ( "#taskModal" ) . innerHTML = ` <div class="task-overlay" onclick="closeTaskModal()"><div class="task-panel" onclick="event.stopPropagation()"><div class="task-header"><h2 class="task-title "> ${ project . project _name } · 任务清单</h2><button class="task-close " onclick="closeTaskModal()"><i data-lucide="x"></i> </button></div><div class="task-body "> ${ phases . map ( ( phase ) => {
const pt = tasks . filter ( ( t ) => t . phase === phase ) ;
const pt = tasks . filter ( ( t ) => t . phase === phase ) ;
return ` <div class="rounded-lg border border-slate-200"><div class="rounded-t-lg bg-slate-50 px-4 py-2.5 font-semibold text-slate-700 text-sm"> ${ phase } ${ pt . length ? ` <span class="text-slate-400 font-norma l">( ${ pt . filter ( t => t . task ) . length } / ${ pt . length } ) </span>` : "" } </div><div class="p-3 grid gap-2 ">${ pt . length ? pt . map ( ( t ) => ` <div class="flex items-start gap-3 rounded-md bg-white px-3 py-2 text-sm"><input type="checkbox" class="mt-0.5" ${ t . task ? "" : "checked disabled" } ><div class="flex-1"><p class="text-slate-800"> ${ t . milestone ? ` <strong> ${ t . milestone } </strong>: ` : "" } ${ t . task } </p> ${ t . owner ? ` <p class="text-xs text-slate-400 mt-0.5">👤 ${ t . owner } ${ t . due _date ? " · 📅 " + t . due _date : "" } </p> ` : "" } </div ></div> ` ) . join ( "" ) : ` <p class="text-sm text-slate-400 py-2 text-center ">暂无任务</p > ` } </div></div> ` ;
return ` <div class="task-group"><div class="task-group-hd"><span class="task-group-icon"><i data-lucide="layers"></i></span><span class="task-group-labe l"> ${ phase } </span><span class="task-group-n"> ${ pt . length } </span></div><div class="task-group-list "> ${ pt . length ? pt . map ( ( t ) => ` <div class="task-row" data-id=" ${ t . id } " ><span class="task-dot"><i data-lucide=" ${ t . status === 'done' ? 'check-circle' : 'circle' } "></i></span><span class="task-name"> ${ t . task } </span ></div>` ) . join ( "" ) : ` <div class="task-none ">暂无任务</div > ` } </div><button class="task-group-add" onclick="event.stopPropagation()">+ 添加任务</button>< /div> ` ;
} ).join("")}</div></div></div> ` ;
} ).join("")}</div></div></div> ` ;
document . querySelector ( "#taskModal" ) . classList . add ( "active" ) ;
document . querySelector ( "#taskModal" ) . classList . add ( "active" ) ;
if ( window . lucide ) window . lucide . createIcons ( ) ;
}
}
window . closeTaskModal = ( ) => document . querySelector ( "#taskModal" ) . classList . remove ( "active" ) ;
window . closeTaskModal = ( ) => document . querySelector ( "#taskModal" ) . classList . remove ( "active" ) ;