# -*- coding: utf-8 -*-
"""任免表管理：给干部加批注（后台）
 - 任免表表格行内新增「批注」入口：弹窗可查看/新增/删除该干部的批注
 - 走既有接口 POST/GET/DELETE /api/admin/cadres/{id}/notes、/api/admin/notes/{id}
 - 批注随数据包下发；PAD 端在任免审批表下方「批注信息」按干部匹配显示
 - PAD 端补显示「关联栏目」（否则后台选了栏目等于白选）
"""
import shutil, time

BK = time.strftime('%Y%m%d%H%M%S')
A = '/data/www/files/rmsys-app/backend/src/Rmsys.Api/wwwroot/admin.html'
PADS = ['/data/www/files/rmsys-app/android/app/src/main/assets/web/pad.html',
        '/data/www/files/rmsys-app/backend/src/Rmsys.Api/wwwroot/pad.html']

def bk(p): shutil.copy2(p, p + '.bakN.' + BK)

# ==================== 后台 ====================
s = open(A, encoding='utf-8').read(); bk(A)

# 1) 任免表行内操作加「批注」
old_ops = """       + opsCell([['预览','previewCadre('+c.id+')','pri'],['删除','delCadre('+c.id+')','del']])"""
new_ops = """       + opsCell([['预览','previewCadre('+c.id+')','pri'],['批注','noteDialog('+c.id+')'],['删除','delCadre('+c.id+')','del']])"""
assert s.count(old_ops) == 1, "任免表行内操作未命中"
s = s.replace(old_ops, new_ops, 1)

# 2) 批注弹窗与增删函数（放在 previewCadre 之前）
anchor = "function previewCadre(id){"
note_js = r'''/* ===================== 干部批注（任免表管理） =====================
   批注挂干部名下，随数据包下发；PAD 端显示在任免审批表下方「批注信息」。 */
var NOTE_CADRE = null;
function noteDialog(cadreId){
  var c = null; CADRES.forEach(function(x){ if(x.id === cadreId) c = x; });
  if(!c) return;
  NOTE_CADRE = c;
  ensureAuth().then(function(ok){
    if(!ok) return;
    var h = '<div class="modal-h"><h3>批注 · '+esc(c.name)+'</h3><div class="spacer"></div><button class="x" onclick="closeModal()">&times;</button></div>';
    h += '<div class="modal-b">'
       + '<div class="sec-note">批注挂在干部本人名下，随<b>数据包</b>下发到 PAD，显示在任免审批表下方「批注信息」。'
       + '新增或修改后须<b>重新生成数据包</b>，PAD 才能看到最新批注。</div>'
       + '<div class="form-grid">'
       +   '<div class="fld"><label>关联栏目（可选）</label><select id="nt_field">'
       +     ['','拟任职务','拟免职务','现任职务','出生年月','学历学位','简历','其他']
               .map(function(f){ return '<option value="'+f+'">'+(f || '不指定')+'</option>'; }).join('')
       +   '</select></div>'
       + '</div>'
       + '<div class="fld" style="margin-top:10px;"><label>批注内容 <i>*</i></label>'
       +   '<textarea id="nt_body" rows="3" placeholder="例如：该同志档案已审核，个人有关事项报告已核实，纪检监察机关意见已听取。"></textarea></div>'
       + '<div class="bar" style="margin-top:8px;">'
       +   '<button class="btn pri" onclick="doAddNote()">保存批注</button>'
       +   '<span style="font-size:12.5px;color:var(--ink3);">同一干部可多条，PAD 按录入顺序显示</span>'
       + '</div>'
       + '<div id="nt_list" style="margin-top:8px;">加载中…</div>'
       + '</div>';
    h += '<div class="modal-f"><div class="spacer"></div><button class="btn" onclick="closeModal()">关闭</button></div>';
    openModal(h, true);
    loadNotes(c.id);
  });
}
function loadNotes(cadreId){
  apiCall('/api/admin/cadres/'+cadreId+'/notes', 'GET').then(function(d){
    var box = document.getElementById('nt_list'); if(!box) return;
    if(!d || !d.length){ box.innerHTML = '<div class="empty">该同志暂无批注</div>'; return; }
    box.innerHTML = '<div style="font-size:13px;color:var(--ink3);margin-bottom:6px;">已有批注（'+d.length+' 条）</div>'
      + d.map(function(n){
          return '<div style="display:flex;gap:10px;align-items:flex-start;background:#FBF4E0;border:1px solid #E5CE8E;'
            + 'border-radius:8px;padding:10px 12px;margin-bottom:8px;">'
            + '<div style="flex:1;min-width:0;">'
            +   '<div style="font-size:12.5px;color:#8E6F14;font-weight:700;">'
            +     esc(n.author || '—')+' · '+esc(n.at || '')
            +     (n.fieldName ? ('　【'+esc(n.fieldName)+'】') : '')+'</div>'
            +   '<div style="font-size:14px;color:#4A4034;line-height:1.75;white-space:pre-wrap;">'+esc(n.content)+'</div>'
            + '</div>'
            + '<a class="lnk del" onclick="doDelNote('+n.id+')">删除</a>'
            + '</div>';
        }).join('');
  }).catch(function(e){
    var box = document.getElementById('nt_list'); if(box) box.innerHTML = '<div class="empty">批注加载失败：'+esc(e.message)+'</div>';
  });
}
function doAddNote(){
  if(!NOTE_CADRE) return;
  var body = {
    meetingId: ROLE.meeting,
    fieldName: ($('nt_field').value || null),
    content: ($('nt_body').value || '').trim(),
    source: 'admin'
  };
  if(!body.content){ toast('请填写批注内容', 'wr'); return; }
  apiCall('/api/admin/cadres/'+NOTE_CADRE.id+'/notes', 'POST', body).then(function(d){
    if(!d || d.__needLogin){ toast('登录已失效，请重新登录', 'wr'); ensureAuth(); return; }
    if(!d.ok){ toast(d.message || '保存失败', 'wr'); return; }
    $('nt_body').value = '';
    toast('批注已保存（重新生成数据包后 PAD 可见）', 'ok');
    NOTE_CADRE.notes = (NOTE_CADRE.notes || 0) + 1;
    loadNotes(NOTE_CADRE.id);
    renderMaterials();
  }).catch(function(e){ toast('保存失败：'+e.message, 'wr'); });
}
function doDelNote(id){
  apiCall('/api/admin/notes/'+id, 'DELETE').then(function(d){
    if(!d || d.__needLogin){ toast('登录已失效，请重新登录', 'wr'); ensureAuth(); return; }
    if(!d.ok){ toast(d.message || '删除失败', 'wr'); return; }
    toast('批注已删除', 'ok');
    if(NOTE_CADRE){
      NOTE_CADRE.notes = Math.max(0, (NOTE_CADRE.notes || 1) - 1);
      loadNotes(NOTE_CADRE.id);
      renderMaterials();
    }
  }).catch(function(e){ toast('删除失败：'+e.message, 'wr'); });
}

'''
assert s.count(anchor) == 1
s = s.replace(anchor, note_js + anchor, 1)
open(A, 'w', encoding='utf-8').write(s)
print("✓ 后台：任免表行内「批注」+ 批注弹窗（查看/新增/删除）")

# ==================== PAD：批注显示关联栏目 ====================
OLD = """          return '<div class="note"><div class="nh"><span>'+esc(n.by)+'</span><span>'+esc(n.at)+'</span></div>'
               + '<div class="nt">'+esc(n.text)+'</div></div>';"""
NEW = """          return '<div class="note"><div class="nh"><span>'+esc(n.by)+'</span><span>'+esc(n.at)+'</span>'
               + (n.field?('<span style="color:#A8171C;">【'+esc(n.field)+'】</span>'):'')+'</div>'
               + '<div class="nt">'+esc(n.text)+'</div></div>';"""
for p in PADS:
    t = open(p, encoding='utf-8').read(); bk(p)
    assert t.count(OLD) == 1, p
    open(p, 'w', encoding='utf-8').write(t.replace(OLD, NEW, 1))
    print("✓ PAD 批注显示关联栏目：", p.split('/')[-3])

print("\n备份后缀 .bakN." + BK)
