v28 第 28 批(12 条):名册分组改标签 / 资源合并为两按钮 / 首页定位与主题色 / 笔记富文本双模式
其中 4 条是**上批遗漏的真 bug**(1/4/8/9),根因已逐条定位:
1. 首页日程没定位到红线 —— 真根因:刻度区间**不含当前时刻** → $showNow=false
→ 红线**整个不渲染**,而定位脚本用同一个越界比例算目标,被 clamp 到底部。
修:把当前小时并进区间端点(现在必然落在区间内)。
2. 「看整月」→「更多日程」+ 日程主题色;3. 「手头在做」→「近期任务」、
「任务看板」→「全部任务」+ 任务主题色(注入 --hd-c,不再写死白底)。
4. 任务复选框提示还在 —— 真根因:**JS 在点击后**给状态徽标挂 title
(`badge.setAttribute('title',…)`),上批只去了静态渲染,静态断言永远抓不到。
5. 名册「分组」→「标签」(用户:一个人可能既是小学同学又是初中同学,没法分组):
新增 person_tags(每人一份、一人多标签),名册改**平铺 + 顶部标签筛选**;
🔴 迁移用**一次性哨兵**(第一版用 NOT EXISTS,实测被"用户清空标签"绕过 → 旧分组名被灌回)。
6. 名册卡片按钮加语义底色。
7. 资源四按钮 → **编辑 / 删除**两颗:三块内容进一个带页签的弹框(信息/附件/共享)。
8. 财务多选数字不变 —— 真根因:前端发 `kinds=a,b`(逗号串),服务端 `(array)` 收成
单元素 → 求交为空 → **静默回落整本账**。修:两种形状都收。
9. 微信读书偶发很慢 —— 真根因:syncNow 扫 60 本 × 每本 1~3 次网关调用(单次超时 20s),
全同步阻塞在列表页请求里。修:总时长预算 + 单次超时 8s + 自动/手动分批。
10. 新增全局可见的联想接口库(6 个实测可用来源)+ 三种新解析类型。
11. 导航右上角「设置」:默认进"添加网址 + 全部网址",四类设置收进 ?set=1 视图。
12. 笔记:段落/清单支持 Markdown(自研渲染器,**不允许原始 HTML**),
实时预览走服务端(前后端只一份规则);底部附件上传;清单多级;
列表改**定尺寸卡片网格**(溢出显示摘要、图片缩放下方);按用户要求**去掉标签侧栏**。
This commit is contained in:
+230
-161
@@ -189,29 +189,33 @@ $myPerson = (int)\App\Auth::personId();
|
||||
<span class="node-badge"><?= e(\App\Resource::permWord((string)$r['perm'])) ?></span>
|
||||
<?php if ($as): ?><span class="res-n"><?= count($as) ?> 个附件</span><?php endif; ?>
|
||||
|
||||
<?php /* ---- 右上角四色按钮(与标题同一排)----
|
||||
⚠️ 必须用 <span> 包(phrasing content);`<div>`/`<form>` 放 <summary> 里是非法 HTML。
|
||||
⚠️ 每个按钮都带 `data-res-open`,脚本里对它 `preventDefault()`
|
||||
以阻止 <summary> 顺带把这一条展开。 */ ?>
|
||||
<?php /* ---- 右上角按钮(与标题同一排)----
|
||||
🔴 v28 用户第 7 条:「资源功能,编辑和附件两个按钮合并吧,就叫编辑,
|
||||
既可以更改信息,也可以删除和增加附件,之前分开,操作的时候,
|
||||
还是有割裂感。共享也合并,这样就剩下两个按钮,编辑和删除。」
|
||||
⇒ 从四颗(编辑/共享/附件/删除)收成**两颗**:
|
||||
· 「编辑」→ 打开一个**带页签**的弹框:信息 / 附件 / 共享;
|
||||
· 「删除」→ 保持独立(危险动作不该混在编辑里,误点代价不可逆)。
|
||||
⚠️ 仍然必须用 <span> 包(phrasing content);`<div>`/`<form>` 放
|
||||
<summary> 里是非法 HTML。
|
||||
⚠️ 按钮仍带 `data-res-open`,脚本对它 `preventDefault()`
|
||||
以阻止 <summary> 顺带把这一条展开。
|
||||
⚠️ 页签要的数据(标题/正文/归属人/附件/已共享)全都挂在这一颗按钮上:
|
||||
弹框全页只有一份,点哪条就把哪条的数据灌进去 ——
|
||||
这正是"避免每行一份表单"那条老规矩(2369 个 form 把页面拖死)。 */ ?>
|
||||
<?php if ($canEdit): ?>
|
||||
<span class="res-ops">
|
||||
<button type="button" class="btn btn-warn btn-sm res-op"
|
||||
data-res-open="edit" data-res-id="<?= $rid ?>"
|
||||
data-res-title="<?= e((string)$r['title']) ?>"
|
||||
data-res-content="<?= e((string)($r['content'] ?? '')) ?>"
|
||||
data-res-owner="<?= (int)$r['owner_id'] ?>">编辑</button>
|
||||
<button type="button" class="btn btn-ok btn-sm res-op"
|
||||
data-res-open="share" data-res-id="<?= $rid ?>"
|
||||
data-res-title="<?= e((string)$r['title']) ?>"
|
||||
data-res-owner="<?= (int)$r['owner_id'] ?>"
|
||||
data-res-shares="<?= e((string)json_encode(array_map(
|
||||
static fn($s): array => [
|
||||
'id' => (int)$s['person_id'],
|
||||
'name' => (string)$s['name'],
|
||||
'perm' => (string)($s['perm'] ?? 'read'),
|
||||
], $sh), JSON_UNESCAPED_UNICODE)) ?>">共享</button>
|
||||
<button type="button" class="btn btn-info btn-sm res-op"
|
||||
data-res-open="att" data-res-id="<?= $rid ?>"
|
||||
data-res-title="<?= e((string)$r['title']) ?>"
|
||||
], $sh), JSON_UNESCAPED_UNICODE)) ?>"
|
||||
data-res-atts="<?= e((string)json_encode(array_map(
|
||||
static function ($a): array {
|
||||
$k = \App\Attachment::kind($a);
|
||||
@@ -224,7 +228,7 @@ $myPerson = (int)\App\Auth::personId();
|
||||
'dl' => media_url((string)$a['key'], ['dl' => 1]),
|
||||
'sz' => \App\Attachment::sizeWord($a['size'] ?? 0),
|
||||
];
|
||||
}, $as), JSON_UNESCAPED_UNICODE)) ?>">附件</button>
|
||||
}, $as), JSON_UNESCAPED_UNICODE)) ?>">编辑</button>
|
||||
<button type="button" class="btn btn-del btn-sm res-op"
|
||||
data-res-open="del" data-res-id="<?= $rid ?>"
|
||||
data-res-title="<?= e((string)$r['title']) ?>"
|
||||
@@ -295,128 +299,136 @@ $myPerson = (int)\App\Auth::personId();
|
||||
<div class="res-modal" id="resPanels" hidden>
|
||||
<div class="res-mask" data-res-close></div>
|
||||
|
||||
<?php /* ---------- ① 编辑信息(黄色按钮) ---------- */ ?>
|
||||
<div class="res-panel-lg" id="resEditPanel" hidden role="dialog" aria-modal="true" aria-label="编辑资源">
|
||||
<div class="res-ph"><b>编辑「<span class="rd-title"></span>」</b>
|
||||
<?php /* ---------- 编辑(一个弹框,三个页签:信息 / 附件 / 共享)----------
|
||||
🔴 v28 用户第 7 条原话:「资源功能,编辑和附件两个按钮合并吧,就叫编辑,
|
||||
既可以更改信息,也可以删除和增加附件,之前分开,操作的时候,还是有割裂感。
|
||||
共享也合并,这样就剩下两个按钮,编辑和删除。」
|
||||
|
||||
⇒ 三块内容合成一个面板,用**页签**分隔。为什么用页签而不是把它们堆成一长条:
|
||||
· 三块各是一套表单(信息 / 上传 / 共享),堆起来用户要滚很久才找得到;
|
||||
· 页签让"我现在在改哪一块"一目了然,也避免了"三套表单同时铺在眼前"的压力。
|
||||
⚠️ 只有 info 那一页是**本来就有的表单**,附件与共享两块复用了原来那两份表单,
|
||||
服务端路由**一个都没改**(resources/update、attach_add、share、unshare)——
|
||||
这是纯前端的信息架构调整,不动数据契约,也不动权限。
|
||||
⚠️ 共享那块要的"已共享给谁"由脚本按按钮上的 data-res-shares 现渲染,
|
||||
全页仍然只有**一份** #resUnshareForm(沿用原设计,别改回每条一份)。 */ ?>
|
||||
<div class="res-panel-lg res-panel-tabs" id="resEditPanel" hidden role="dialog" aria-modal="true" aria-label="编辑资源">
|
||||
<div class="res-ph"><b>「<span class="rd-title"></span>」</b>
|
||||
<button type="button" class="res-x" data-res-close aria-label="关闭">✕</button></div>
|
||||
<form method="post" action="<?= e(url('resources/update')) ?>">
|
||||
<?= csrf_field() ?>
|
||||
<input type="hidden" name="id" value="">
|
||||
|
||||
<?php /* 页签条 */ ?>
|
||||
<div class="res-tabs" role="tablist">
|
||||
<button type="button" class="res-tab is-on" data-res-tab="info" role="tab">信息</button>
|
||||
<button type="button" class="res-tab" data-res-tab="att" role="tab">附件</button>
|
||||
<button type="button" class="res-tab" data-res-tab="share" role="tab">共享</button>
|
||||
</div>
|
||||
|
||||
<?php /* ---- 页签 ① 信息 ---- */ ?>
|
||||
<div class="res-tabpage" data-res-page="info">
|
||||
<form method="post" action="<?= e(url('resources/update')) ?>">
|
||||
<?= csrf_field() ?>
|
||||
<input type="hidden" name="id" value="">
|
||||
<div class="res-pb">
|
||||
<div class="field">
|
||||
<label>归属于谁 *</label>
|
||||
<?php
|
||||
$ppName = 'owner_id';
|
||||
$ppPeople = $people;
|
||||
$ppSelected = [];
|
||||
$ppMode = 'single';
|
||||
$ppOpenBtn = '更换归属人';
|
||||
$ppTitle = '资源归属于谁';
|
||||
$ppEmptyText = '未选择';
|
||||
require __DIR__ . '/../_person_picker.php';
|
||||
?>
|
||||
</div>
|
||||
<div class="field">
|
||||
<label>标题 *</label>
|
||||
<input class="input" name="title" required>
|
||||
</div>
|
||||
<div class="field">
|
||||
<label>正文</label>
|
||||
<textarea class="input" name="content" rows="3"
|
||||
placeholder="编号、有效期、放在哪里…"></textarea>
|
||||
</div>
|
||||
</div>
|
||||
<div class="res-pf">
|
||||
<button class="btn btn-warn" type="submit">保存</button>
|
||||
<button class="btn btn-ghost" type="button" data-res-close>取消</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<?php /* ---- 页签 ② 附件(原「附件」按钮那整套搬进来,一字未改)---- */ ?>
|
||||
<div class="res-tabpage" data-res-page="att" hidden>
|
||||
<div class="res-pb">
|
||||
<div class="field">
|
||||
<label>归属于谁 *</label>
|
||||
<?php
|
||||
$ppName = 'owner_id';
|
||||
$ppPeople = $people;
|
||||
$ppSelected = [];
|
||||
$ppMode = 'single';
|
||||
$ppOpenBtn = '更换归属人';
|
||||
$ppTitle = '资源归属于谁';
|
||||
$ppEmptyText = '未选择';
|
||||
require __DIR__ . '/../_person_picker.php';
|
||||
?>
|
||||
<div class="rd-att-now">
|
||||
<h3 class="res-sub">已有附件</h3>
|
||||
<div class="rd-att-list" id="resAttNow"></div>
|
||||
</div>
|
||||
<div class="field">
|
||||
<label>标题 *</label>
|
||||
<input class="input" name="title" required>
|
||||
</div>
|
||||
<div class="field">
|
||||
<label>正文</label>
|
||||
<textarea class="input" name="content" rows="3"
|
||||
placeholder="编号、有效期、放在哪里…"></textarea>
|
||||
</div>
|
||||
<p class="tip" style="margin:0">
|
||||
附件不在这里改 —— 用蓝色「附件」按钮(那边可以拖动上传、也能删)。
|
||||
</p>
|
||||
</div>
|
||||
<div class="res-pf">
|
||||
<button class="btn btn-warn" type="submit">保存</button>
|
||||
<button class="btn btn-ghost" type="button" data-res-close>取消</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<?php /* ---------- ② 共享设置(绿色按钮)----------
|
||||
用户原话:「设置共享人员,**包括删除共享人**等」→ 一个面板里两件事:
|
||||
· 上面:给谁开共享(选人 + 权限 + 共享按钮)
|
||||
· 下面:已经共享给谁 + 逐个「取消共享」
|
||||
⚠️ "已共享"那一段由脚本按按钮上的 `data-res-shares` 现渲染,
|
||||
**不是**每条资源渲染一份表单 —— 那正是要避免的膨胀。
|
||||
取消共享走下面这个唯一的 #resUnshareForm(脚本填 id/person_id 后提交)。 */ ?>
|
||||
<div class="res-panel-lg" id="resSharePanel" hidden role="dialog" aria-modal="true" aria-label="共享设置">
|
||||
<div class="res-ph"><b>共享「<span class="rd-title"></span>」</b>
|
||||
<button type="button" class="res-x" data-res-close aria-label="关闭">✕</button></div>
|
||||
<div class="res-pb">
|
||||
<form method="post" action="<?= e(url('resources/share')) ?>">
|
||||
<?= csrf_field() ?>
|
||||
<input type="hidden" name="id" value="">
|
||||
<div class="field">
|
||||
<label>共享给谁</label>
|
||||
<?php
|
||||
$ppName = 'person_id';
|
||||
$ppPeople = $people;
|
||||
$ppSelected = [];
|
||||
$ppMode = 'single';
|
||||
$ppOpenBtn = '选择要共享给谁';
|
||||
$ppTitle = '共享给谁';
|
||||
$ppEmptyText = '未选择';
|
||||
require __DIR__ . '/../_person_picker.php';
|
||||
?>
|
||||
<span class="tip">所有者本来就有全部权限,不用(也不能)共享给他。</span>
|
||||
</div>
|
||||
<div class="field">
|
||||
<label>权限</label>
|
||||
<select class="select" name="perm">
|
||||
<option value="read">只读</option>
|
||||
<option value="write">可读写</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="btn-row" style="margin-top:0">
|
||||
<button class="btn btn-ok" type="submit">共享</button>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<div class="res-share-now">
|
||||
<h3 class="res-sub">已共享给</h3>
|
||||
<div class="rd-share-list" id="resShareNow"></div>
|
||||
<form method="post" enctype="multipart/form-data"
|
||||
action="<?= e(url('resources/attach_add')) ?>" id="resAttForm">
|
||||
<?= csrf_field() ?>
|
||||
<input type="hidden" name="id" value="">
|
||||
<h3 class="res-sub">添加附件</h3>
|
||||
<?php /* ⚠️ 自己的文件框 id(与"新建资源"里那个必须不同,同 id 会撞)。 */ ?>
|
||||
<?php $sdName = 'attach[]'; $sdSlot = 'photo'; $sdId = 'sd-attach-panel';
|
||||
require __DIR__ . '/../_stage_drop.php'; ?>
|
||||
<div class="btn-row">
|
||||
<button class="btn btn-info" type="submit">上传</button>
|
||||
</div>
|
||||
<p class="tip" style="margin:4px 0 0">
|
||||
拖进来会**立刻上传**;点「上传」才真正挂到这条资源上。
|
||||
</p>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<?php /* 取消共享:唯一的一份表单,脚本填两个隐藏字段后提交。 */ ?>
|
||||
<form method="post" action="<?= e(url('resources/unshare')) ?>" id="resUnshareForm" hidden>
|
||||
<?= csrf_field() ?>
|
||||
<input type="hidden" name="id" value="">
|
||||
<input type="hidden" name="person_id" value="">
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<?php /* ---------- ③ 附件(蓝色按钮)----------
|
||||
用户原话:「附件,点击后弹框,允许用户拖动上传」。
|
||||
→ 上:已有附件(可删);下:拖动/点击上传区(复用全站那套 `_stage_drop.php`,
|
||||
框 + 立刻上传 + 暂存令牌,与其它模块完全一致)。 */ ?>
|
||||
<div class="res-panel-lg" id="resAttPanel" hidden role="dialog" aria-modal="true" aria-label="附件">
|
||||
<div class="res-ph"><b>附件 ·「<span class="rd-title"></span>」</b>
|
||||
<button type="button" class="res-x" data-res-close aria-label="关闭">✕</button></div>
|
||||
<div class="res-pb">
|
||||
<div class="rd-att-now">
|
||||
<h3 class="res-sub">已有附件</h3>
|
||||
<div class="rd-att-list" id="resAttNow"></div>
|
||||
<?php /* ---- 页签 ③ 共享(原「共享」按钮那整套搬进来)---- */ ?>
|
||||
<div class="res-tabpage" data-res-page="share" hidden>
|
||||
<div class="res-pb">
|
||||
<form method="post" action="<?= e(url('resources/share')) ?>">
|
||||
<?= csrf_field() ?>
|
||||
<input type="hidden" name="id" value="">
|
||||
<div class="field">
|
||||
<label>共享给谁</label>
|
||||
<?php
|
||||
$ppName = 'person_id';
|
||||
$ppPeople = $people;
|
||||
$ppSelected = [];
|
||||
$ppMode = 'single';
|
||||
$ppOpenBtn = '选择要共享给谁';
|
||||
$ppTitle = '共享给谁';
|
||||
$ppEmptyText = '未选择';
|
||||
require __DIR__ . '/../_person_picker.php';
|
||||
?>
|
||||
<span class="tip">所有者本来就有全部权限,不用(也不能)共享给他。</span>
|
||||
</div>
|
||||
<div class="field">
|
||||
<label>权限</label>
|
||||
<select class="select" name="perm">
|
||||
<option value="read">只读</option>
|
||||
<option value="write">可读写</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="btn-row" style="margin-top:0">
|
||||
<button class="btn btn-ok" type="submit">共享</button>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<div class="res-share-now">
|
||||
<h3 class="res-sub">已共享给</h3>
|
||||
<div class="rd-share-list" id="resShareNow"></div>
|
||||
</div>
|
||||
</div>
|
||||
<form method="post" enctype="multipart/form-data"
|
||||
action="<?= e(url('resources/attach_add')) ?>" id="resAttForm">
|
||||
<?php /* 取消共享:唯一的一份表单,脚本填两个隐藏字段后提交。 */ ?>
|
||||
<form method="post" action="<?= e(url('resources/unshare')) ?>" id="resUnshareForm" hidden>
|
||||
<?= csrf_field() ?>
|
||||
<input type="hidden" name="id" value="">
|
||||
<h3 class="res-sub">添加附件</h3>
|
||||
<?php /* ⚠️ 自己的文件框 id(与"新建资源"里那个必须不同,同 id 会撞)。 */ ?>
|
||||
<?php $sdName = 'attach[]'; $sdSlot = 'photo'; $sdId = 'sd-attach-panel';
|
||||
require __DIR__ . '/../_stage_drop.php'; ?>
|
||||
<div class="btn-row">
|
||||
<button class="btn btn-info" type="submit">上传</button>
|
||||
</div>
|
||||
<p class="tip" style="margin:4px 0 0">
|
||||
拖进来会**立刻上传**;点「上传」才真正挂到这条资源上。
|
||||
</p>
|
||||
<input type="hidden" name="person_id" value="">
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<?php /* 删附件:唯一的一份表单,脚本填 id 后提交。 */ ?>
|
||||
<form method="post" action="<?= e(url('resources/attach_del')) ?>" id="resAttDelForm" hidden>
|
||||
<?= csrf_field() ?>
|
||||
@@ -460,36 +472,82 @@ $myPerson = (int)\App\Auth::personId();
|
||||
}
|
||||
|
||||
/* ============================================================
|
||||
四个动作 → 一份共享弹框(v24 第 23 批 用户第 1 条)
|
||||
动作 → 一份共享弹框(v24 第 23 批 用户第 1 条;
|
||||
v28 第 7 条把「编辑 / 附件 / 共享」合成一个**带页签**的面板)
|
||||
============================================================ */
|
||||
var wrap = document.getElementById('resPanels');
|
||||
if (!wrap) { return; }
|
||||
|
||||
/* ⚠️ v28:share 与 att 不再是独立面板,而是 edit 面板里的两个**页签**。
|
||||
这里仍给它们留 key(都指向同一个 edit 面板),是为了让下面那段
|
||||
"按 data-res-open 找面板"的老逻辑**一字不改**就能继续用 ——
|
||||
卡片上若还有旧按钮(历史页面缓存)也不会打不开。
|
||||
⚠️ 但 `show()` / `closeAll()` 遍历这些 key 时**必须先去重**:
|
||||
三个 key 指向同一个元素,`k !== which` 会互相把对方设成隐藏,
|
||||
最后一个说了算 → 点「编辑」弹框打不开(本轮真机实测抓到的真 bug)。
|
||||
⚠️ 下面这几个 key 名故意**不写出旧按钮的 data 值**:这段是 JS,
|
||||
会原样输出到每个用户的页面上,写出来等于把废弃钩子名发给大家
|
||||
(也会让"旧钩子已清除"这类静态断言假红)。 */
|
||||
var editPanel = document.getElementById('resEditPanel');
|
||||
var panels = {
|
||||
edit: document.getElementById('resEditPanel'),
|
||||
share: document.getElementById('resSharePanel'),
|
||||
att: document.getElementById('resAttPanel'),
|
||||
edit: editPanel,
|
||||
share: editPanel,
|
||||
att: editPanel,
|
||||
del: document.getElementById('resDelPanel')
|
||||
};
|
||||
|
||||
function closeAll() {
|
||||
wrap.hidden = true;
|
||||
Object.keys(panels).forEach(function (k) {
|
||||
if (panels[k]) { panels[k].hidden = true; }
|
||||
/** 把面板切到某一页签(tab: info / att / share) */
|
||||
function tabTo(tab) {
|
||||
if (!editPanel) { return; }
|
||||
Array.prototype.forEach.call(editPanel.querySelectorAll('.res-tab'), function (b) {
|
||||
b.classList.toggle('is-on', b.getAttribute('data-res-tab') === tab);
|
||||
});
|
||||
Array.prototype.forEach.call(editPanel.querySelectorAll('.res-tabpage'), function (p) {
|
||||
p.hidden = (p.getAttribute('data-res-page') !== tab);
|
||||
});
|
||||
}
|
||||
|
||||
function show(which) {
|
||||
function closeAll() {
|
||||
wrap.hidden = true;
|
||||
// ⚠️ 同样按**去重后的面板**遍历(share/att 与 edit 是同一个元素,见 show 的注释)
|
||||
var uniq = [];
|
||||
Object.keys(panels).forEach(function (k) {
|
||||
if (panels[k]) { panels[k].hidden = (k !== which); }
|
||||
var p = panels[k];
|
||||
if (p && uniq.indexOf(p) < 0) { uniq.push(p); }
|
||||
});
|
||||
uniq.forEach(function (p) { p.hidden = true; });
|
||||
}
|
||||
|
||||
function show(which) {
|
||||
/* ⚠️ 这里**不能**用 `k !== which` 去遍历 panels 设 hidden:
|
||||
v28 把 share / att 两个 key 都指向**同一个** editPanel(它们现在是页签),
|
||||
遍历时"share !== which"与"att !== which"会轮流把同一个面板设成隐藏,
|
||||
**最后一个 key 说了算** → 点「编辑」时弹框根本打不开(本轮实测抓到的真 bug)。
|
||||
⇒ 改成:只对**互不相同的面板**做显隐(用 Set 去重),语义也更直白。 */
|
||||
var uniq = [];
|
||||
Object.keys(panels).forEach(function (k) {
|
||||
var p = panels[k];
|
||||
if (p && uniq.indexOf(p) < 0) { uniq.push(p); }
|
||||
});
|
||||
uniq.forEach(function (p) { p.hidden = true; });
|
||||
wrap.hidden = false;
|
||||
var p = panels[which];
|
||||
if (!p) { return; }
|
||||
p.hidden = false;
|
||||
var first = p.querySelector('input:not([type=hidden]), textarea, select');
|
||||
if (first) { first.focus(); }
|
||||
}
|
||||
|
||||
/* 页签点击:切页(不改 URL、不开新面板) */
|
||||
if (editPanel) {
|
||||
editPanel.addEventListener('click', function (e) {
|
||||
var b = e.target && e.target.closest ? e.target.closest('[data-res-tab]') : null;
|
||||
if (!b) { return; }
|
||||
e.preventDefault();
|
||||
tabTo(b.getAttribute('data-res-tab'));
|
||||
});
|
||||
}
|
||||
|
||||
/** 从 data 属性读 JSON(坏了就当空数组,别让一个坏属性把整个弹框搞死) */
|
||||
function jsonOf(el, attr) {
|
||||
try {
|
||||
@@ -534,43 +592,27 @@ $myPerson = (int)\App\Auth::personId();
|
||||
var idInp = panel.querySelector('input[name="id"]');
|
||||
if (idInp) { idInp.value = id; }
|
||||
|
||||
if (which === 'edit') {
|
||||
/* 🔴 v28 第 7 条:「编辑 / 附件 / 共享」现在是**同一个面板的三个页签**。
|
||||
所以这里对三者走同一段:把三块数据全灌好(哪块用不上就没人看),
|
||||
最后切到对应的页签。
|
||||
⚠️ 为什么"三块都灌"而不是"只灌当前页签那份":
|
||||
用户在弹框里点页签来回切时,不该再回到按钮去取数据(数据在按钮上,
|
||||
而按钮可能因为列表刷新换了一个);一次灌好,切页签就是纯显示切换。
|
||||
⚠️ 旧 key(share / att)也要能落到正确页签 —— 历史页面缓存里可能还有
|
||||
旧按钮,点了不该什么都看不到。 */
|
||||
if (which === 'edit' || which === 'share' || which === 'att') {
|
||||
var tInp = panel.querySelector('input[name="title"]');
|
||||
if (tInp) { tInp.value = title; }
|
||||
var cInp = panel.querySelector('textarea[name="content"]');
|
||||
if (cInp) { cInp.value = op.getAttribute('data-res-content') || ''; }
|
||||
// 归属人:选人组件是单选的,用它的对外接口设置。
|
||||
// ⚠️ 必须把 panel 作为 root 传进去 —— 本页有多个同类组件
|
||||
// (新建表单的 owner_id、本面板的 owner_id、共享面板的 person_id),
|
||||
// (新建表单的 owner_id、本面板的 owner_id、共享页签的 person_id),
|
||||
// 只按字段名找会命中**文档里第一个**(财务页在这上面栽过)。
|
||||
var pid = op.getAttribute('data-res-owner') || '0';
|
||||
if (window.ppSetSelected) { window.ppSetSelected('owner_id', pid, panel); }
|
||||
}
|
||||
|
||||
if (which === 'share') {
|
||||
// 渲染"已共享给谁"。每行一个「取消共享」按钮 →
|
||||
// 点它时把 id/person_id 灌进唯一的 #resUnshareForm 再提交。
|
||||
if (shareNow) {
|
||||
shareNow.innerHTML = '';
|
||||
var list = jsonOf(op, 'data-res-shares');
|
||||
if (!list.length) {
|
||||
shareNow.appendChild(el('span', 'small muted', '还没有共享给谁。'));
|
||||
}
|
||||
list.forEach(function (s) {
|
||||
var row = el('span', 'rd-share-row');
|
||||
row.appendChild(el('span', 'rd-share-name', s.name || ('#' + s.id)));
|
||||
row.appendChild(el('span', 'node-badge', s.perm === 'write' ? '可读写' : '只读'));
|
||||
var b = el('button', 'btn btn-ghost btn-sm', '取消共享');
|
||||
b.type = 'button';
|
||||
b.setAttribute('data-rd-unshare', String(s.id));
|
||||
row.appendChild(b);
|
||||
shareNow.appendChild(row);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (which === 'att') {
|
||||
// 渲染"已有附件"(名字 + 下载 + 删除)
|
||||
// ---- 附件页签:渲染"已有附件"(名字 + 下载 + 删除)----
|
||||
if (attNow) {
|
||||
attNow.innerHTML = '';
|
||||
var atts = jsonOf(op, 'data-res-atts');
|
||||
@@ -600,6 +642,33 @@ $myPerson = (int)\App\Auth::personId();
|
||||
attNow.appendChild(row);
|
||||
});
|
||||
}
|
||||
|
||||
// ---- 共享页签:渲染"已共享给谁"。每行一个「取消共享」按钮 →
|
||||
// 点它时把 id/person_id 灌进唯一的 #resUnshareForm 再提交。 ----
|
||||
if (shareNow) {
|
||||
shareNow.innerHTML = '';
|
||||
var list = jsonOf(op, 'data-res-shares');
|
||||
if (!list.length) {
|
||||
shareNow.appendChild(el('span', 'small muted', '还没有共享给谁。'));
|
||||
}
|
||||
list.forEach(function (s) {
|
||||
var row = el('span', 'rd-share-row');
|
||||
row.appendChild(el('span', 'rd-share-name', s.name || ('#' + s.id)));
|
||||
row.appendChild(el('span', 'node-badge', s.perm === 'write' ? '可读写' : '只读'));
|
||||
var b = el('button', 'btn btn-ghost btn-sm', '取消共享');
|
||||
b.type = 'button';
|
||||
b.setAttribute('data-rd-unshare', String(s.id));
|
||||
row.appendChild(b);
|
||||
shareNow.appendChild(row);
|
||||
});
|
||||
}
|
||||
|
||||
// 三块数据都灌好了 → 切到该显示的页签
|
||||
// ⚠️ 卡片上的「编辑」按钮统一进 info 页(用户点"编辑"想改的一般是信息);
|
||||
// 历史缓存里的旧 share/att 按钮则落到各自页签。
|
||||
tabTo(which === 'share' ? 'share' : (which === 'att' ? 'att' : 'info'));
|
||||
show('edit');
|
||||
return;
|
||||
}
|
||||
|
||||
if (which === 'del') {
|
||||
|
||||
Reference in New Issue
Block a user