Files

118 lines
5.8 KiB
PHP
Raw Permalink Normal View History

<?php
/**
* 名册导入(v24 用户 2026-10-03 第 1 条)。
*
* 页面就两件事:挑文件 → 看结果。所以做成**一页**(提交后同页出报告),
* 不跳到"导入历史"之类的第二页 —— 一次导入看完就该结束。
*
* @param array $groups 我能用的分组(导入进来的人可以先归到一组)
* @param array|null $report ContactImporter::run 的结果(null = 还没导入)
*/
$report = $report ?? null;
$canMove = \App\Auth::canWrite();
/* 🔴 v54(用户 2026-10-16 第 2 条):打标签的候选 —— 设置页配的词表 ∪ 我用过的词。
⚠️ 显式给默认值(模板可能被别处 require、未必总带上这个键)。 */
$tagChoices = $tagChoices ?? [];
$groups = $groups ?? [];
?>
<div class="page-head">
<h1>导入联系人</h1>
<span class="sub">从手机 / 邮箱导出的通讯录批量加进名册</span>
<div class="actions">
<a class="btn btn-ghost btn-sm" href="<?= e(url('people')) ?>">返回名册</a>
</div>
</div>
<div class="card card-pad">
<h2 class="cinema-h2">选一份文件</h2>
<p class="small muted" style="margin:0 0 14px">
支持 <b>.vcf</b>(vCard,iPhone / 安卓 / 谷歌联系人 / Outlook 都能导出)与
<b>.csv / .txt</b>(表头里有「姓名 / 手机 / 邮箱」之类就能认,中英文表头都行)。
<br>
导入规则:<b>手机号或姓名已经在名册里的,不会重复建人</b>,
只把「他还没有的信息」补上去(已有的一律不动);其余才新建。
</p>
<form method="post" action="<?= e(url('people/import')) ?>" enctype="multipart/form-data">
<?= csrf_field() ?>
<div class="form-grid">
<div class="field full">
<label class="is-req" for="imp-file">联系人文件</label>
<?php /* 🔴 v30:与 ics 导入同一条(用户第 1 条)—— 导入型上传**不走暂存**。
文件走 PHP 临时文件,路由读完即弃,不落存储、不建附件行。
⚠️ 不这么改的话,拖进来的文件只到暂存区、`<input>.files` 是空的,
required 的原生校验会弹「请选择一个文本。」(与 ics 完全同一个坑)。 */
$sdName = 'contacts'; $sdId = 'imp-file';
$sdAccept = '.vcf,.csv,.txt,text/vcard,text/csv,text/plain';
$sdMultiple = false; $sdRequired = true; $sdStage = false;
require __DIR__ . '/../_stage_drop.php'; ?>
</div>
<?php /* 🔴 v54(用户 2026-10-16 第 2 条):原来这里是「加进哪一组」的下拉。
用户原话:「现在已经没有分组的概念了,**全部都是标签的概念**。」
⇒ 换成**打标签**(与「添加成员」页同一个契约:`name=tags`)。
导入进来的新人会自动带上这串标签(owner=我)。 */ ?>
<div class="field">
<label for="imp-tags">给导入的人打标签(可留空)</label>
<?php if (!empty($tagChoices)): ?>
<div class="pt-picks pf-picks" style="margin-bottom:8px">
<?php foreach ($tagChoices as $tg): ?>
<label class="pt-pick">
<input type="checkbox" value="<?= e((string)$tg) ?>">
<span>#<?= e((string)$tg) ?></span>
</label>
<?php endforeach; ?>
</div>
<?php endif; ?>
<?php /* 回显刚填的标签(导入失败重渲时不该让人重打一遍)——
`clean` 归一后再拼,输入什么分隔符都能正确回显。 */ ?>
<input class="input" id="imp-tags" name="tags" maxlength="300"
value="<?= e(implode(' ', \App\PersonTag::clean((string)($_POST['tags'] ?? '')))) ?>"
placeholder="如:同事 老同学(用空格分开)" autocomplete="off">
<span class="tip">只影响<b>新建</b>的那些人;已有的人身上原来的标签不动。</span>
</div>
</div>
<div class="btn-row">
<button class="btn" type="submit">开始导入</button>
</div>
</form>
</div>
<?php if ($report): ?>
<div class="card card-pad">
<h2 class="cinema-h2">
导入结果
<span class="hint">新增 <?= (int)$report['added'] ?> · 补充 <?= (int)$report['updated'] ?> · 无需改动 <?= (int)$report['skipped'] ?></span>
</h2>
<?php if (!$report['people']): ?>
<p class="empty-hint">文件里没有可导入的联系人。</p>
<?php else: ?>
<?php /* ⚠️ 报告的是"这条记录做了什么",逐条列出来:
批量操作最怕"导完不知道改了什么"(尤其"补充"这一类会动到已有的人)。 */ ?>
<div class="table-wrap">
<table class="table">
<thead><tr><th>联系人</th><th>结果</th><th>补上了什么</th></tr></thead>
<tbody>
<?php foreach ($report['people'] as $row): ?>
<?php
$act = (string)$row['action'];
$word = $act === 'added' ? '新建' : ($act === 'updated' ? '补充信息' : '无需改动');
$cls = $act === 'added' ? 'led-asset' : ($act === 'updated' ? 'led-asset' : '');
?>
<tr>
<td><?= e((string)$row['name']) ?></td>
<td class="<?= $cls ?>"><?= e($word) ?></td>
<td class="small muted">
<?= $row['added'] ? e(implode('、', (array)$row['added'])) : '—' ?>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
<?php endif; ?>
<div class="btn-row" style="margin-top:14px">
<a class="btn btn-ghost" href="<?= e(url('people')) ?>">去看名册</a>
<a class="btn btn-ghost" href="<?= e(url('people/import')) ?>">再导一份</a>
</div>
</div>
<?php endif; ?>