134 lines
14 KiB
HTML
134 lines
14 KiB
HTML
<!DOCTYPE html>
|
||
<html lang="zh-CN">
|
||
<head>
|
||
<meta charset="UTF-8">
|
||
<meta name="staff-csrf-token" content="{{ g.staff.csrf_token }}">
|
||
<meta name="staff-username" content="{{ g.staff.username }}">
|
||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||
<title>客服工作台 · 柏悦物流</title>
|
||
<link rel="icon" href="{{ url_for('static', filename='fa.jpg') }}">
|
||
<link rel="stylesheet" href="{{ url_for('static', filename='css/theme.css') }}">
|
||
<link rel="stylesheet" href="{{ url_for('static', filename='css/admin.css') }}">
|
||
</head>
|
||
<body>
|
||
<header class="topbar">
|
||
<div class="app-identity">
|
||
<a class="brand" href="/admin/dashboard"><span class="brand-mark"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="m4 7 8-4 8 4v10l-8 4-8-4Z"/><path d="m4 7 8 4 8-4M12 11v10M8 5l8 4"/></svg></span><span class="brand-name">柏悦物流</span></a>
|
||
<span class="nav-divider" aria-hidden="true"></span><h1>客服工作台</h1>
|
||
</div>
|
||
<div class="topbar-actions">
|
||
<span id="nightBadge" class="night-badge" hidden>非工作时段</span>
|
||
<button id="ticket-inbox-toggle" class="ticket-inbox-toggle" type="button" aria-label="查看待处理留言" aria-controls="service-tools">留言 <span id="ticket-pending-count">—</span></button>
|
||
<button id="ticket-overdue-toggle" class="ticket-overdue-toggle" type="button" aria-label="查看超时留言" aria-controls="service-tools">超时 <span id="ticket-overdue-count">—</span></button>
|
||
<button id="notifications-toggle" class="icon-button" type="button" aria-label="开启浏览器通知" title="开启浏览器通知" aria-pressed="false">🔔</button>
|
||
<a class="workspace-link" href="/">客户入口 ↗</a>
|
||
<details class="data-overview" id="data-overview">
|
||
<summary><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.6" aria-hidden="true"><path d="M4 4v16h17M8 16v-5M13 16V7M18 16V3"/></svg>数据概览</summary>
|
||
<div class="stats" aria-label="历史对话统计">
|
||
<h2>历史对话与反馈</h2>
|
||
<div class="stat"><span>历史对话</span><b id="s1">—</b></div>
|
||
<div class="stat"><span>历史消息</span><b id="s2">—</b></div>
|
||
<div class="stat"><span>今日新对话</span><b id="s3">—</b></div>
|
||
<div class="stat"><span>有帮助</span><b id="s4">—</b></div>
|
||
<div class="stat"><span>需改进</span><b id="s5">—</b></div>
|
||
<div class="stat"><span>服务评价</span><b id="s6">—</b></div>
|
||
<a class="export-link" href="/api/export_chat">导出 Excel ↗</a>
|
||
</div>
|
||
</details>
|
||
<button id="staff-logout" class="staff-logout" type="button">退出登录</button>
|
||
</div>
|
||
</header>
|
||
<div id="staff-logout-status" class="sync-status" role="alert" hidden></div>
|
||
<div id="sync-status" class="sync-status" role="status" hidden>会话连接中断,正在重试…</div>
|
||
<div id="ticket-alert" class="ticket-alert" role="status" aria-live="polite" hidden><span id="ticket-alert-text"></span><button id="ticket-alert-view" type="button" class="ticket-action">查看待处理留言</button></div>
|
||
<main class="layout">
|
||
<aside class="conv-list" id="session-browser" aria-label="会话列表">
|
||
<div class="list-heading">
|
||
<h2>客户会话</h2><p>查看咨询,及时接待与回复</p>
|
||
<div class="session-search-wrap"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.7" aria-hidden="true"><circle cx="10.5" cy="10.5" r="6.5"/><path d="m16 16 4 4"/></svg><input id="session-search" type="search" aria-label="搜索客户会话" placeholder="搜索会话或消息" autocomplete="off"></div>
|
||
<button id="history-search-toggle" class="text-button" type="button">搜索历史记录 ↗</button>
|
||
</div>
|
||
<div class="session-tabs" role="tablist" aria-label="会话状态">
|
||
<button id="tab-active" type="button" role="tab" aria-selected="true" aria-controls="sessionList">接待中 <span id="active-count" class="section-count">0</span></button>
|
||
<button id="tab-queue" type="button" role="tab" aria-selected="false" aria-controls="queue" tabindex="-1">排队中 <span id="queue-count" class="section-count">0</span><span id="queue-overdue-count" class="queue-overdue-count">超时 0</span></button>
|
||
</div>
|
||
<div class="session-scroll">
|
||
<div id="sessionList" role="tabpanel" aria-labelledby="tab-active"><div class="list-empty">暂无进行中的会话</div></div>
|
||
<div id="queue" role="tabpanel" aria-labelledby="tab-queue" hidden><div class="list-empty">正在加载会话…</div></div>
|
||
</div>
|
||
<div class="list-footer"><span><span class="list-footer-mark" aria-hidden="true"></span>柏悦物流 · 客户服务</span><button id="tools-from-list" type="button" aria-controls="service-tools" aria-expanded="false">服务资料</button></div>
|
||
</aside>
|
||
<section class="chat-area" id="chatArea" aria-label="会话内容">
|
||
<header class="chat-header">
|
||
<button id="sessions-back" class="sessions-back" type="button" aria-label="返回会话列表">‹</button>
|
||
<div class="participant-avatar" aria-hidden="true">客</div>
|
||
<div class="participant-copy"><h2 id="chatTitle">会话接待</h2><p id="chat-subtitle">选择一段会话,开始回复客户</p></div>
|
||
<div class="chat-header-actions">
|
||
<button id="tools-toggle" class="tools-toggle" type="button" aria-label="资料与快捷回复" aria-controls="service-tools" aria-expanded="false"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.6" aria-hidden="true"><rect x="4" y="3" width="16" height="18" rx="2"/><circle cx="9" cy="9" r="2"/><path d="M6 16a3 3 0 0 1 6 0M14 8h3M14 12h3M14 16h3"/></svg><span>资料与回复</span></button>
|
||
<button id="transfer-session" class="close" type="button" onclick="transferSession()">转接</button>
|
||
<button id="close-session" class="close" type="button" onclick="closeSession()">结束会话</button>
|
||
</div>
|
||
</header>
|
||
<div class="empty" id="emptyTip"><div>
|
||
<div class="empty-illustration"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="m4 7 8-4 8 4v10l-8 4-8-4Z"/><path d="m4 7 8 4 8-4M12 11v10M8 5l8 4"/></svg></div>
|
||
<h2>选择会话,开始接待</h2><p>在会话列表查看客户咨询,<br>新咨询可从「排队中」接入。</p>
|
||
</div></div>
|
||
<div id="chatContent" class="session-panel" style="display:none">
|
||
<div id="chatBox" role="log" aria-live="polite" aria-label="会话消息"></div>
|
||
<footer class="agent-composer">
|
||
<div class="composer-heading"><label for="replyText">回复客户</label><div class="emoji-control"><button id="agent-emoji-toggle" class="text-button" type="button" aria-label="选择表情" aria-expanded="false" aria-controls="agent-emoji-panel">😊 表情</button><div id="agent-emoji-panel" class="emoji-picker" hidden></div></div><span>Shift + Enter 换行</span></div>
|
||
<div class="input-bar">
|
||
<textarea id="replyText" rows="2" aria-label="回复客户" placeholder="输入回复内容,按 Enter 发送…"></textarea>
|
||
<div class="input-actions"><span>常用回复可在「资料与回复」中选择</span><button id="reply-send" type="button" onclick="sendReply()">发送</button></div>
|
||
</div>
|
||
<p id="reply-status" class="reply-status" role="status" hidden></p>
|
||
</footer>
|
||
</div>
|
||
</section>
|
||
<aside class="side" id="service-tools" aria-label="客户信息与回复" aria-hidden="true" inert>
|
||
<header class="side-heading"><h2>服务资料</h2><button id="tools-close" type="button" class="icon-button" aria-label="关闭服务资料">×</button></header>
|
||
<section class="card"><h3>客户信息</h3><div class="info-row" id="cInfo">选择会话后查看客户信息</div><p class="info-hint">咨询运费时,可先确认运单号、货物重量、尺寸与目的地。</p></section>
|
||
<section class="card"><h3><label for="noteInput">会话备注</label></h3><textarea id="noteInput" class="note-input" rows="3" placeholder="填写本次会话的跟进事项" disabled></textarea><button id="note-save" type="button" class="quick" disabled>保存备注</button></section>
|
||
<section class="card"><h3>常用回复</h3>
|
||
<p class="card-caption">点击填入草稿,编辑后再发送</p>
|
||
<button type="button" class="quick" onclick="quickReply('您好,请问有什么可以帮您?')">您好,有什么可以帮您?</button>
|
||
<button type="button" class="quick" onclick="quickReply('请提供运单号,我帮您查询。')">请提供运单号,我帮您查询</button>
|
||
<button type="button" class="quick" onclick="quickReply('已为您催促,请稍候。')">已为您催促,请稍候</button>
|
||
<button type="button" class="quick" onclick="quickReply('感谢您的咨询,祝您生活愉快!')">感谢咨询,祝您生活愉快</button>
|
||
</section>
|
||
<section class="card ticket-workspace" aria-labelledby="tickets-title">
|
||
<div class="ticket-row"><h3 id="tickets-title">离线留言</h3><span id="ticket-section-count" class="ticket-section-count">待处理 —</span></div>
|
||
<p id="ticket-summary-status" class="ticket-summary-status" role="status"></p>
|
||
<p class="ticket-timing-rule">超时提醒:30 分钟未领取,或领取后 20 分钟未完成。</p>
|
||
<form id="ticket-search-form" class="ticket-search-form" role="search" aria-label="搜索离线留言">
|
||
<label for="ticket-search">搜索留言</label><input id="ticket-search" type="search" maxlength="100" placeholder="手机号、关键词、负责人或备注" autocomplete="off">
|
||
<div class="ticket-search-actions"><button id="ticket-search-submit" type="submit" class="ticket-action ticket-primary">搜索</button><button id="ticket-search-clear" type="button" class="ticket-action" hidden>清除搜索</button></div>
|
||
</form>
|
||
<div class="ticket-toolbar"><label for="ticket-filter">状态</label><select id="ticket-filter"><option value="all">全部</option><option value="pending">待处理</option><option value="processing">处理中</option><option value="completed">已完成</option></select><label class="ticket-overdue-filter"><input id="ticket-overdue-filter" type="checkbox"> 只看超时</label><button id="ticket-refresh" type="button" class="ticket-action">刷新</button></div>
|
||
<div id="ticketList"><div class="list-empty">正在加载留言…</div></div>
|
||
<button id="ticket-more" type="button" class="ticket-action" hidden>加载更早留言</button>
|
||
<div id="ticket-selected" class="ticket-detail" hidden>
|
||
<div class="ticket-row"><h4>留言详情</h4><span id="ticket-state" class="ticket-state"></span></div>
|
||
<p id="ticket-meta" class="ticket-meta"></p><p id="ticket-content" class="ticket-content"></p>
|
||
<p id="ticket-owner" class="ticket-owner"></p><p id="ticket-overdue-hint" class="ticket-overdue-hint" hidden></p>
|
||
<label for="ticket-note" class="ticket-note-label">处理备注</label>
|
||
<textarea id="ticket-note" rows="4" maxlength="2000" placeholder="记录联系情况、处理结果或后续跟进事项" readonly></textarea>
|
||
<p id="ticket-server-note" class="ticket-server-note" hidden></p>
|
||
<button id="ticket-rebase" type="button" class="ticket-action" hidden>已核对,使用我的备注</button>
|
||
<div class="ticket-actions"><button id="ticket-claim" type="button" class="ticket-action ticket-primary" hidden>领取留言</button><button id="ticket-save" type="button" class="ticket-action" hidden>保存备注</button><button id="ticket-complete" type="button" class="ticket-action ticket-primary" hidden>标记已完成</button></div>
|
||
<p id="ticket-activity" class="ticket-meta"></p>
|
||
<section id="ticket-history" class="ticket-history" aria-labelledby="ticket-history-title"><div class="ticket-row"><h4 id="ticket-history-title">处理记录</h4><button id="ticket-history-reload" type="button" class="ticket-action">刷新记录</button></div><p id="ticket-history-status" class="ticket-meta" role="status"></p><ol id="ticket-history-list" class="ticket-history-list"></ol><button id="ticket-history-more" type="button" class="ticket-action" hidden>加载更早记录</button></section>
|
||
</div>
|
||
<p id="ticket-status-message" class="ticket-feedback" role="status" aria-live="polite"></p>
|
||
</section>
|
||
</aside>
|
||
</main>
|
||
<button class="tools-backdrop" id="tools-backdrop" type="button" aria-label="关闭服务资料"></button>
|
||
<dialog id="searchResult" class="search-dialog" aria-labelledby="search-title"><header><h2 id="search-title">搜索历史记录</h2><button id="search-close" class="icon-button" type="button" aria-label="关闭搜索">×</button></header><form id="history-search-form"><label class="sr-only" for="searchBox">历史消息关键词</label><input id="searchBox" type="search" placeholder="输入关键词搜索聊天记录" required><button type="submit" class="quick">搜索</button></form><div id="searchBody" aria-live="polite">请输入关键词搜索历史消息</div></dialog>
|
||
<script src="{{ url_for('static', filename='js/support.js') }}"></script>
|
||
<script src="{{ url_for('static', filename='js/admin_tools.js') }}"></script>
|
||
<script src="{{ url_for('static', filename='js/admin_tickets.js') }}"></script>
|
||
<script src="{{ url_for('static', filename='js/admin.js') }}"></script>
|
||
</body>
|
||
</html>
|