待办中心star精选
待办清单:to-do + 站点待办统计
image效果截图
点击放大notes详细介绍
自定义待办:点 「添加待办」按钮弹出对话框填写;点复选框勾选;右侧垃圾桶删除;未完成条数显示在标题徽标上。
站点待办:待审核评论 / 草稿文章 / 隐藏文章三行只读统计,可在设置里逐个关闭;点击行直接跳到对应管理页。
节流:统计结果缓存 5 分钟,反复进后台不会反复查库;右上角 ↻ 可强制刷新。
code配置代码
<div class="abtd"><div class="abtd-head"><div class="abtd-title"><span class="material-icons-round">checklist</span>我的待办<span class="abtd-count"id="abtd-count">0</span></div><div class="abtd-tools"><button class="abtd-iconbtn"type="button"id="abtd-refresh"title="刷新待办数量"aria-label="刷新待办数量"><span class="material-icons-round">refresh</span></button><button class="abtd-iconbtn"type="button"id="abtd-setup"title="待办中心设置"aria-label="待办中心设置"><span class="material-icons-round">tune</span></button></div></div><section class="abtd-todo"id="abtd-todo"></section><button class="abtd-addbtn"id="abtd-addbtn"type="button"><span class="material-icons-round">add</span>添加待办</button><section class="abtd-auto"id="abtd-auto"></section></div><style>.abtd{--abtd-ease:cubic-bezier(.2,0,0,1);display:flex;flex-direction:column;gap:12px}.abtd-head{display:flex;align-items:center;justify-content:space-between;gap:8px}.abtd-title{display:flex;align-items:center;gap:8px;font-size:14px;font-weight:600;color:var(--md-on-surface)}.abtd-title.material-icons-round{font-size:18px;color:var(--md-primary)}.abtd-count{min-width:22px;padding:1px 7px;border-radius:9999px;background:var(--md-primary-container);color:var(--md-on-primary-container);font:500 12px/1.7 ui-monospace,SFMono-Regular,Consolas,monospace;text-align:center}.abtd-tools{display:flex;gap:2px;flex:none}.abtd-iconbtn{display:inline-flex;align-items:center;justify-content:center;width:34px;height:34px;border:0;border-radius:50%;background:transparent;color:var(--md-on-surface-variant);cursor:pointer;transition:background-color.2s var(--abtd-ease),transform.2s var(--abtd-ease)}.abtd-iconbtn:hover{background:var(--md-surface-container-high)}.abtd-iconbtn:active{transform:scale(.94)}.abtd-iconbtn:focus-visible{outline:2px solid color-mix(in srgb,var(--md-primary)55%,transparent);outline-offset:2px}.abtd-iconbtn.material-icons-round{font-size:19px}.abtd-iconbtn.is-busy.material-icons-round{animation:abtd-spin 1s linear infinite}.abtd-list{display:flex;flex-direction:column;gap:4px;max-height:260px;overflow-y:auto;overscroll-behavior:contain;scrollbar-width:thin;padding-right:2px}.abtd-list::-webkit-scrollbar{width:8px}.abtd-list::-webkit-scrollbar-thumb{background:var(--md-outline-variant);border-radius:99px}.abtd-list::-webkit-scrollbar-track{background:transparent}.abtd-item{display:flex;align-items:center;gap:10px;padding:8px 10px;border-radius:14px;background:var(--md-surface-container-high);color:var(--md-on-surface);transition:background-color.18s var(--abtd-ease)}.abtd-item:hover{background:var(--md-surface-container-highest)}.abtd-item.is-done.abtd-text{text-decoration:line-through;color:var(--md-on-surface-variant)}.abtd-check{flex:none;display:inline-flex;align-items:center;justify-content:center;width:28px;height:28px;padding:0;border:0;border-radius:50%;background:transparent;color:var(--md-primary);cursor:pointer}.abtd-check:hover{background:color-mix(in srgb,var(--md-primary)12%,transparent)}.abtd-check.material-icons-round{font-size:21px}.abtd-iconbtn.material-icons-round,.abtd-check.material-icons-round,.abtd-del.material-icons-round,.abtd-addbtn.material-icons-round{display:block;line-height:1}.abtd-text{flex:1;min-width:0;font-size:13.5px;line-height:1.5;word-break:break-word}.abtd-when{flex:none;font-size:11.5px;color:var(--md-on-surface-variant);white-space:nowrap}.abtd-del{flex:none;display:inline-flex;align-items:center;justify-content:center;width:28px;height:28px;padding:0;border:0;border-radius:50%;background:transparent;color:var(--md-on-surface-variant);cursor:pointer;opacity:.6}.abtd-del:hover{opacity:1;color:var(--md-error);background:var(--md-error-container)}.abtd-del.material-icons-round{font-size:18px}.abtd-addbtn{display:flex;align-items:center;justify-content:center;gap:5px;width:100%;height:40px;border:0;border-radius:14px;background:var(--md-primary);color:var(--md-on-primary);font-size:13.5px;font-weight:500;cursor:pointer;transition:filter.2s var(--abtd-ease),transform.2s var(--abtd-ease)}.abtd-addbtn:hover{filter:brightness(1.06)}.abtd-addbtn:active{transform:scale(.99)}.abtd-addbtn:focus-visible{outline:2px solid color-mix(in srgb,var(--md-primary)55%,transparent);outline-offset:2px}.abtd-addbtn.material-icons-round{font-size:18px}.abtd-hint{font-size:12px;color:var(--md-on-surface-variant);line-height:1.6}@keyframes abtd-spin{to{transform:rotate(360deg)}}@media(max-width:520px){.abtd-when{display:none}.abtd-list{max-height:200px}}@media(prefers-reduced-motion:reduce){.abtd-iconbtn,.abtd-item,.abtd-addbtn{transition:none}.abtd-iconbtn.is-busy.material-icons-round{animation:none}}</style>
(function(){'use strict';if(typeof card.__abtdBoot==='function'){card.__abtdBoot();return}var TODO_KEY='todo-center-items';var CFG_KEY='todo-center-config';var COUNT_KEY='todo-center-counts';var COUNT_TTL=5*60*1000;var MAX_TODO=100;var MAX_SCAN=200;var DEFAULT_CFG={showComments:true,showDrafts:true,showHidden:true};var el=ab.ui.el;var items=[];var cfg=pickCfg(null);var counts=null;function $(id){return card.querySelector('#'+id)}function say(text,tone){if(ab.notify)ab.notify(text,tone||'info')}function pickCfg(raw){var out={},k;for(k in DEFAULT_CFG){if(Object.prototype.hasOwnProperty.call(DEFAULT_CFG,k))out[k]=DEFAULT_CFG[k]}if(raw&&typeof raw==='object'){out.showComments=raw.showComments!==false;out.showDrafts=raw.showDrafts!==false;out.showHidden=raw.showHidden!==false}return out}function pickItems(raw){var list=Object.prototype.toString.call(raw)==='[object Array]'?raw:[];var out=[];for(var i=0;i<list.length&&out.length<MAX_TODO;i++){var it=list[i];if(!it||typeof it!=='object'||!it.text)continue;out.push({id:String(it.id||('t'+i)),text:String(it.text).slice(0,200),done:it.done===true,createdAt:parseInt(it.createdAt,10)||0})}return out}function persist(){return ab.data.save(TODO_KEY,items).catch(function(err){say('待办保存失败:'+((err&&err.message)||'未知错误'),'danger')})}function adminUrl(file,query){var base=String((ab.config&&ab.config.pluginSettingsUrl)||'').split('?')[0];var url;if(base){url=base.slice(0,base.lastIndexOf('/')+1)+file}else{var here=location.href.split('?')[0];url=here.slice(0,here.lastIndexOf('/')+1)+file}return query?url+'?'+query:url}function countRows(table,pk,where){if(!ab.db||typeof ab.db.read!=='function'){return Promise.reject(new Error('当前插件版本不支持 ab.db.read,请升级 AB Admin'))}return ab.db.read(table,{columns:[pk],where:where,limit:MAX_SCAN}).then(function(d){return(d&&d.rows)?d.rows.length:0})}var POST_TYPES=['post','post_draft'];function loadCounts(){return Promise.all([countRows('comments','coid',[{field:'status',op:'=',value:'waiting'}]),countRows('contents','cid',[{field:'type',op:'=',value:'post_draft'}]),countRows('contents','cid',[{field:'type',op:'IN',value:POST_TYPES},{field:'status',op:'=',value:'hidden'}])]).then(function(r){return{comments:r[0],drafts:r[1],hidden:r[2]}})}function fmtCount(n){return n>=MAX_SCAN?(MAX_SCAN+'+'):String(n)}function refresh(force){var ready=(force&&ab.data.clearCached)?ab.data.clearCached(COUNT_KEY):Promise.resolve();return ready.then(function(){return ab.data.getCached(COUNT_KEY,COUNT_TTL,loadCounts)}).then(function(c){counts=c||{comments:0,drafts:0,hidden:0};renderAuto();var r=$('abtd-refresh');if(r)r.classList.remove('is-busy')}).catch(function(err){counts=null;renderAuto(true);var box=$('abtd-auto');if(box){box.appendChild(ab.ui.notice({icon:'error_outline',tone:'danger',text:'读取待办数量失败:'+((err&&err.message)||'未知错误')}))}var btn=$('abtd-refresh');if(btn)btn.classList.remove('is-busy')})}function renderCount(){var node=$('abtd-count');if(!node)return;var left=0;for(var i=0;i<items.length;i++)if(!items[i].done)left++;node.textContent=String(left);node.title=left?(left+' 条未完成的待办'):'没有未完成的待办'}function todoRow(item){var row=el('div','abtd-item'+(item.done?' is-done':''));row.setAttribute('data-id',item.id);var check=el('button','abtd-check');check.type='button';check.setAttribute('role','checkbox');check.setAttribute('aria-checked',item.done?'true':'false');check.title=item.done?'标记为未完成':'标记为完成';check.appendChild(ab.ui.icon(item.done?'check_box':'check_box_outline_blank'));check.addEventListener('click',function(){toggle(item.id)});row.appendChild(check);row.appendChild(el('div','abtd-text',item.text));if(item.createdAt)row.appendChild(el('div','abtd-when',ab.format.relative(item.createdAt)));var del=el('button','abtd-del');del.type='button';del.title='删除这条待办';del.appendChild(ab.ui.icon('delete_outline'));del.addEventListener('click',function(){remove(item.id)});row.appendChild(del);return row}function renderTodo(){var box=$('abtd-todo');renderCount();if(!box)return;if(!items.length){ab.ui.mount(box,ab.ui.empty({icon:'task_alt',text:'还没有自定义待办',hint:'点下面的「添加待办」写一条(支持一行一条批量添加)'}));return}var pending=[],done=[],i;for(i=0;i<items.length;i++)(items[i].done?done:pending).push(items[i]);var list=el('div','abtd-list');var ordered=pending.concat(done);for(i=0;i<ordered.length;i++)list.appendChild(todoRow(ordered[i]));ab.ui.mount(box,list)}function valueOf(key){if(!counts)return null;return fmtCount(counts[key]||0)}function renderAuto(){var box=$('abtd-auto');if(!box)return;var rows=[];if(cfg.showComments){rows.push({icon:'pending_actions',label:'待审核评论',value:valueOf('comments'),tone:(counts&&counts.comments>0)?'warn':'default',href:adminUrl('manage-comments.php','status=waiting')})}if(cfg.showDrafts){rows.push({icon:'drafts',label:'草稿文章',value:valueOf('drafts'),href:adminUrl('manage-posts.php','status=draft')})}if(cfg.showHidden){rows.push({icon:'visibility_off',label:'隐藏文章',value:valueOf('hidden'),href:adminUrl('manage-posts.php'),attrs:{title:'后台没有「隐藏」筛选,点开是文章列表(隐藏项带「隐藏」标记)'}})}if(!rows.length){ab.ui.mount(box,ab.ui.notice({icon:'info',text:'三类自动待办都被关掉了,点右上角「设置」可以重新打开'}));return}ab.ui.mount(box,ab.ui.rows(rows))}function newId(){return't'+Date.now()+Math.floor(Math.random()*1000)}function addOne(text){text=String(text==null?'':text).replace(/\s+/g,' ').trim();if(!text)return false;if(items.length>=MAX_TODO){say('待办最多 '+MAX_TODO+' 条,先清理一些','warn');return false}items.unshift({id:newId(),text:text.slice(0,200),done:false,createdAt:Date.now()});return true}function openAdd(){if(typeof ab.ui.dialog!=='function'||typeof ab.ui.field!=='function'){say('当前插件版本不支持弹窗组件,请升级 AB Admin','warn');return}var left=MAX_TODO-items.length;if(left<=0){say('待办最多 '+MAX_TODO+' 条,先清理一些','warn');return}var field=ab.ui.field({label:'待办内容',type:'textarea',value:'',placeholder:'一行一条,可一次填多条\n例如:写发布说明\n清一次首页缓存'});var hint=el('div','abtd-hint','最多还能添加 '+left+' 条;每条 200 字以内,空行会被忽略。');function submit(){var lines=String(field.getValue()==null?'':field.getValue()).split('\n');var added=0;for(var i=lines.length-1;i>=0;i--){if(addOne(lines[i]))added++}if(!added){say('先写点什么吧','warn');return false}persist();renderTodo();say(added>1?('已添加 '+added+' 条待办'):'已添加待办','success');return true}var dlg=ab.ui.dialog({title:'添加待办',icon:'add_task',body:[field,hint],actions:[{text:'取消',tone:'default'},{text:'添加',icon:'check',tone:'primary',primary:true,onClick:function(){submit()}}]});if(field.input&&field.input.addEventListener){field.input.addEventListener('keydown',function(e){if((e.ctrlKey||e.metaKey)&&(e.key==='Enter'||e.keyCode===13)){if(e.preventDefault)e.preventDefault();if(submit()&&dlg&&typeof dlg.close==='function')dlg.close('add')}});ab.timeout(function(){try{field.input.focus()}catch(err){}},60)}return dlg}function toggle(id){for(var i=0;i<items.length;i++){if(items[i].id===id){items[i].done=!items[i].done;break}}persist();renderTodo()}function remove(id){var next=[];for(var i=0;i<items.length;i++)if(items[i].id!==id)next.push(items[i]);items=next;persist();renderTodo();say('已删除待办','info')}function openSetup(){if(typeof ab.ui.dialog!=='function'){say('当前插件版本不支持 ab.ui.dialog,请升级 AB Admin','warn');return}var swComments=ab.ui.switch({label:'显示「待审核评论」',checked:!!cfg.showComments});var swDrafts=ab.ui.switch({label:'显示「草稿文章」',checked:!!cfg.showDrafts});var swHidden=ab.ui.switch({label:'显示「隐藏文章」',checked:!!cfg.showHidden});var tip=el('div','abtd-hint','自动待办的数量来自站点数据库的只读查询,单次最多统计 200 条(超过显示 200+)。草稿按 contents.type=post_draft 统计(Typecho 1.2+ 口径)。自定义待办存在插件数据表里,按登录用户隔离。');ab.ui.dialog({title:'待办中心设置',icon:'tune',body:[swComments,swDrafts,swHidden,tip],actions:[{text:'取消',tone:'default'},{text:'保存',icon:'check',tone:'primary',onClick:function(){var next={showComments:!!swComments.getValue(),showDrafts:!!swDrafts.getValue(),showHidden:!!swHidden.getValue()};cfg=pickCfg(next);renderAuto();ab.data.save(CFG_KEY,next).then(function(){say('设置已保存','success')}).catch(function(err){say('保存失败:'+((err&&err.message)||'未知错误'),'danger')})}}]})}function bind(){var addBtn=$('abtd-addbtn');if(addBtn)addBtn.addEventListener('click',openAdd);var r=$('abtd-refresh');if(r)r.addEventListener('click',function(){r.classList.add('is-busy');say('正在刷新待办数量…','info');refresh(true)});var s=$('abtd-setup');if(s)s.addEventListener('click',openSetup)}function boot(){renderTodo();ab.data.get(CFG_KEY,null).then(function(saved){cfg=pickCfg(saved);renderAuto()}).catch(function(){renderAuto()});ab.data.get(TODO_KEY,[]).then(function(saved){items=pickItems(saved);renderTodo()}).catch(function(err){say('待办读取失败:'+((err&&err.message)||'未知错误'),'danger')});return refresh(false)}card.__abtdBoot=boot;bind();boot()})();
download_for_offline如何导入
Typecho 后台 → 控制台 → 插件 → AB Admin(AdminBeautify)→「概要页卡片设置」
找到 自定义卡片 区域,打开总开关(默认关闭)
点 添加卡片,按下表填写:
| 图标 | checklist |
| 卡片标题 | 待办中心 |
| HTML 内容 | 见上方「HTML 内容」标签页 |
| JavaScript | 见上方「JavaScript」标签页 |
点右下角 保存设置,回到概要页即可看到卡片(顺序可在排序列表里拖动调整)
shield安全信息
verified_user
扫描通过
warning
卡片 JavaScript 会在你的后台页面里执行。本站已做敏感信息、站外请求与越权操作的自动扫描 + 人工审核,但仍请在使用前自行阅读上方代码;发现可疑卡片请到
GitHub 反馈。