新建地点的活动下拉可即时新增,地点行内编辑支持批量改该地点全部到访的活动
站长反馈「已有地点编辑和新建里只有类别没有活动能选」。实测澄清:新建地点卡一直有活动下拉, 只是形态与类别/照片页不一致(旁边常显一个新建框、下拉里没有「+ 新增活动…」);真正完全没有 活动字段的是地点列表行的「编辑」。 - 新建地点卡:活动下拉补「+ 新增活动…」哨兵,旁边的新建框改成选中哨兵才展开; 删掉原来那对 #activity-add/#new-activity-name 监听——三处活动下拉现在共用同一套 `visit-act-*` 委派处理器,重复监听会建出两条活动。 - 地点行内编辑:加「活动(改该地点全部到访)」下拉,默认「(不修改)」不预选当前值 (否则每次改坐标保存都会重写历史到访的类型),并标出当前类型构成;选了真实活动时 提交前 confirm 一次。 - 服务端(places 没有活动列,活动挂在到访上):editPlaceUpdate 解析 activity_id,空值=不修改, 与地点行同一事务内 UPDATE visits 的 activity_id/is_home/is_work,flash 报改了几条; 哨兵值/不存在的 id/别的数据集的活动一律拒。导出无需改动(ZVISIT.ZACTIVITY_ 本就是管理列)。 - 回归 internal/web/place_activity_test.go:批量改(含别的地点不受影响)、空值不修改、越权被拒、 模板契约、以及导出包里那批到访的 ZACTIVITY_ 必须换成新活动的 rond 编号。 - 顺手:TestMovementCleanExport 建出 ROND_CLEAN_OUT 的父目录,别再把「目录不存在」报成导出失败。
This commit is contained in:
@@ -98,15 +98,17 @@
|
||||
<a href="javascript:void(0)" id="activity-delete" class="danger">删除</a>
|
||||
</span>
|
||||
</span>
|
||||
<select name="activity_id" id="activity-select">
|
||||
{{/* 与照片导入页、到访行内编辑同一套:下拉里带「+ 新增活动…」,选中后就地展开新建框 */}}
|
||||
<select name="activity_id" id="activity-select" class="activity-id-inline">
|
||||
<option value="">未指定</option>
|
||||
{{range .Activities}}<option value="{{.ID}}">{{.Name}}</option>{{end}}
|
||||
<option value="__new__">+ 新增活动…</option>
|
||||
</select>
|
||||
</label>
|
||||
<label class="f" style="flex:1 1 170px"><span>新建活动</span>
|
||||
<label class="f visit-act-new" style="flex:1 1 170px;display:none"><span>新建活动</span>
|
||||
<div class="input-btn">
|
||||
<input type="text" id="new-activity-name" placeholder="名称">
|
||||
<button type="button" class="btn" id="activity-add">添加</button>
|
||||
<input type="text" class="visit-act-name" placeholder="名称">
|
||||
<button type="button" class="btn visit-act-add">添加</button>
|
||||
</div>
|
||||
</label>
|
||||
<label class="f" style="flex:1 1 140px"><span>备注</span><input type="text" name="remark" placeholder="可选"></label>
|
||||
@@ -161,7 +163,7 @@
|
||||
<td style="white-space:nowrap">
|
||||
<details class="inline-edit"{{if and $.OpenSrcPK (eq .SrcPK $.OpenSrcPK)}} open{{end}}>
|
||||
<summary class="btn sm">编辑</summary>
|
||||
<form method="post" action="/admin/edit/place/update" style="margin-top:8px;min-width:280px">
|
||||
<form method="post" action="/admin/edit/place/update" data-visit-count="{{.VisitCount}}" style="margin-top:8px;min-width:280px">
|
||||
<input type="hidden" name="src_pk" value="{{.SrcPK}}">
|
||||
<label class="f"><span>名称<b class="req">*</b></span><input type="text" name="name" value="{{.Name}}" required></label>
|
||||
<label class="f"><span>类别</span>
|
||||
@@ -173,6 +175,22 @@
|
||||
</select>
|
||||
</label>
|
||||
<label class="f cat-custom" style="display:none"><span>自定义类别</span><input type="text" name="category_custom" placeholder="如 公园"></label>
|
||||
{{/* 改的是该地点名下**全部到访**的类型,所以默认「(不修改)」、
|
||||
不预选当前值:否则每次改个坐标保存,都会把历史到访重写一遍 */}}
|
||||
<label class="f"><span>活动<span class="muted">(改该地点全部到访)</span></span>
|
||||
<select name="activity_id" class="activity-id-inline">
|
||||
<option value="">(不修改)</option>
|
||||
{{range $.Activities}}<option value="{{.ID}}">{{.Name}}</option>{{end}}
|
||||
<option value="__new__">+ 新增活动…</option>
|
||||
</select>
|
||||
</label>
|
||||
<label class="f visit-act-new" style="display:none"><span>新建活动</span>
|
||||
<div class="input-btn">
|
||||
<input type="text" class="visit-act-name" placeholder="名称">
|
||||
<button type="button" class="btn visit-act-add">添加</button>
|
||||
</div>
|
||||
</label>
|
||||
{{if .ActivityText}}<div class="card-sub" style="margin:0 0 8px">该地点到访当前类型:<span class="mono">{{.ActivityText}}</span></div>{{end}}
|
||||
<div class="row">
|
||||
<label class="f" style="flex:1 1 120px"><span>纬度<b class="req">*</b></span><input type="text" name="lat" value="{{printf "%.6f" .Lat}}" required></label>
|
||||
<label class="f" style="flex:1 1 120px"><span>经度<b class="req">*</b></span><input type="text" name="lon" value="{{printf "%.6f" .Lon}}" required></label>
|
||||
@@ -939,23 +957,11 @@
|
||||
}).catch(function (e) { alert('创建活动失败:' + e); });
|
||||
}
|
||||
|
||||
var actAdd = document.getElementById('activity-add');
|
||||
if (actAdd) {
|
||||
var newActInput = document.getElementById('new-activity-name');
|
||||
var addActivityTop = function () {
|
||||
var sel = document.getElementById('activity-select');
|
||||
createActivity(newActInput.value, function (id) {
|
||||
if (sel) sel.value = id;
|
||||
newActInput.value = '';
|
||||
});
|
||||
};
|
||||
actAdd.addEventListener('click', addActivityTop);
|
||||
newActInput.addEventListener('keydown', function (e) {
|
||||
if (e.key === 'Enter') { e.preventDefault(); addActivityTop(); }
|
||||
});
|
||||
}
|
||||
// 顶部「新建活动」不再单独接事件:它和到访/地点行内编辑共用下面那套
|
||||
// `visit-act-*` 委派处理器(同一个表单里只有一个新建框,重复监听会建出两条)。
|
||||
|
||||
// ---- 到访行内编辑里的「+ 新增活动…」:就地展开新建框,建完选中并收起 ----
|
||||
// ---- 下拉里的「+ 新增活动…」:就地展开新建框,建完选中并收起 ----
|
||||
// 顶部新建地点卡、到访行内编辑、地点行内编辑三处共用(靠 form 里的类名找同伴元素)
|
||||
function inlineActParts(el) {
|
||||
var form = el.closest ? el.closest('form') : null;
|
||||
if (!form) return null;
|
||||
@@ -993,16 +999,23 @@
|
||||
inlineActCreate(t);
|
||||
});
|
||||
// 提交守卫:还停在「+ 新增活动…」上就拦下来。否则 activity_id 会带着 "__new__" 提交,
|
||||
// resolveActivity 解析不出整数就当成「无」,这条到访的类型会被静默清掉。
|
||||
// resolveActivity 解析不出整数就当成「无」,那条记录的类型会被静默清掉。
|
||||
document.addEventListener('submit', function (e) {
|
||||
var f = e.target;
|
||||
if (!f || !f.querySelector) return;
|
||||
var sel = f.querySelector('select.activity-id-inline');
|
||||
if (sel && sel.value === '__new__') {
|
||||
e.preventDefault();
|
||||
alert('类型选了「+ 新增活动…」但还没点「添加」:填个名字再点添加,或改回「(无)」。');
|
||||
alert('活动选了「+ 新增活动…」但还没点「添加」:填个名字再点添加,或把这一项改回默认值。');
|
||||
sel.focus();
|
||||
return;
|
||||
}
|
||||
// 地点行内编辑的「活动」是批量改该地点**全部**到访,动的是历史记录,落库前再问一次
|
||||
if (!f.getAttribute || f.getAttribute('action') !== '/admin/edit/place/update') return;
|
||||
if (!sel || !sel.value) return;
|
||||
var n = f.getAttribute('data-visit-count') || '';
|
||||
if (!window.confirm('把该地点' + (n ? '全部 ' + n + ' 条' : '全部') + '到访的活动都改成「' +
|
||||
sel.options[sel.selectedIndex].textContent + '」?原有记录会被一起改掉。')) e.preventDefault();
|
||||
}, true);
|
||||
|
||||
// ---------- 活动改名 / 删除:作用于下拉里当前选中的那一个 ----------
|
||||
|
||||
Reference in New Issue
Block a user