优化界面布局: 简化短信列表,增强统计信息详情

Changes:
- 短信列表: 简化为列表视图,只显示号码、时间、完整内容
- 统计信息: 最近接收增加详细参数(签名、IP、详情链接)
- 统计信息: 显示从10条增加到20条
- 优化CSS样式,提升可读性
This commit is contained in:
OpenClaw Agent
2026-02-07 00:18:01 +00:00
parent 2557d5854e
commit b5fce34793
6 changed files with 279 additions and 61 deletions

2
app.py
View File

@@ -230,7 +230,7 @@ def register_routes(app, db):
def statistics(): def statistics():
"""统计信息""" """统计信息"""
stats = db.get_statistics() stats = db.get_statistics()
recent = db.get_recent_messages(10) recent = db.get_recent_messages(20)
from_numbers = db.get_from_numbers() from_numbers = db.get_from_numbers()
return render_template('statistics.html', return render_template('statistics.html',

15
nohup.out Normal file
View File

@@ -0,0 +1,15 @@
[2026-02-06 23:52:11,314] INFO in app: 启动短信接收服务 (环境: development)
[2026-02-06 23:52:11,314] INFO in app: 启动短信接收服务 (环境: development)
[2026-02-06 23:52:11,314] INFO in app: 数据库: /root/.openclaw/workspace/sms-receiver/sms_receiver.db
[2026-02-06 23:52:11,314] INFO in app: 数据库: /root/.openclaw/workspace/sms-receiver/sms_receiver.db
[2026-02-06 23:52:11,314] INFO in app: 监听端口: 9518
[2026-02-06 23:52:11,314] INFO in app: 监听端口: 9518
[2026-02-06 23:52:11,315] INFO in app: 登录已启用: True
[2026-02-06 23:52:11,315] INFO in app: 登录已启用: True
* Serving Flask app 'app'
* Debug mode: off
WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead.
* Running on all addresses (0.0.0.0)
* Running on http://127.0.0.1:9518
* Running on http://199.188.198.12:9518
Press CTRL+C to quit

17
sms_receiver.service Normal file
View File

@@ -0,0 +1,17 @@
[Unit]
Description=SMS Receiver Web Service
After=network.target
[Service]
Type=forking
User=root
WorkingDirectory=/root/.openclaw/workspace/sms-receiver
ExecStart=/root/.openclaw/workspace/sms-receiver/sms_receiverctl.sh start
ExecStop=/root/.openclaw/workspace/sms-receiver/sms_receiverctl.sh stop
ExecReload=/root/.openclaw/workspace/sms-receiver/sms_receiverctl.sh restart
PIDFile=/root/.openclaw/workspace/sms-receiver/sms_receiver.pid
Restart=always
RestartSec=5
[Install]
WantedBy=multi-user.target

90
sms_receiverctl.sh Executable file
View File

@@ -0,0 +1,90 @@
#!/bin/bash
# 短信转发接收端 - 启动/停止/重启/状态脚本
APP_DIR="/root/.openclaw/workspace/sms-receiver"
APP_FILE="$APP_DIR/app.py"
PIDFILE="$APP_DIR/sms_receiver.pid"
LOGFILE="$APP_DIR/sms_receiver.log"
case "$1" in
start)
if [ -f "$PIDFILE" ]; then
PID=$(cat "$PIDFILE")
if ps -p "$PID" > /dev/null 2>&1; then
echo "服务已在运行 (PID: $PID)"
exit 1
else
rm -f "$PIDFILE"
fi
fi
echo "启动短信转发接收端..."
cd "$APP_DIR"
nohup python3 app.py > "$LOGFILE" 2>&1 &
echo $! > "$PIDFILE"
echo "服务已启动 (PID: $(cat $PIDFILE))"
echo "日志文件: $LOGFILE"
echo "监听地址: http://0.0.0.0:9518"
;;
stop)
if [ ! -f "$PIDFILE" ]; then
echo "服务未运行"
exit 1
fi
PID=$(cat "$PIDFILE")
echo "停止服务 (PID: $PID)..."
kill "$PID" 2>/dev/null
sleep 1
if ps -p "$PID" > /dev/null 2>&1; then
echo "强制停止..."
kill -9 "$PID" 2>/dev/null
fi
rm -f "$PIDFILE"
echo "服务已停止"
;;
restart)
$0 stop
sleep 2
$0 start
;;
status)
if [ -f "$PIDFILE" ]; then
PID=$(cat "$PIDFILE")
if ps -p "$PID" > /dev/null 2>&1; then
echo "服务正在运行 (PID: $PID)"
echo "启动时间: $(ps -p $PID -o lstart=)"
echo "内存使用: $(ps -p $PID -o rss= | awk '{print int($1/1024)"MB"}')"
exit 0
else
echo "PID 文件存在但进程未运行,清理..."
rm -f "$PIDFILE"
exit 1
fi
else
echo "服务未运行"
exit 1
fi
;;
log)
tail -f "$LOGFILE"
;;
*)
echo "用法: $0 {start|stop|restart|status|log}"
echo ""
echo "命令说明:"
echo " start - 启动服务"
echo " stop - 停止服务"
echo " restart - 重启服务"
echo " status - 查看状态"
echo " log - 查看实时日志"
exit 1
;;
esac

View File

@@ -138,26 +138,54 @@
border-collapse: collapse; border-collapse: collapse;
} }
.messages-table th, .messages-list {
.messages-table td { background: white;
padding: 12px 15px; border-radius: 10px;
text-align: left; overflow: hidden;
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
}
.list-view {
list-style: none;
}
.list-view li {
padding: 15px;
border-bottom: 1px solid #eee; border-bottom: 1px solid #eee;
transition: background 0.3s;
} }
.messages-table th { .list-view li:hover {
background: #f5f5f5;
font-weight: 600;
color: #333;
}
.messages-table tr:hover {
background: #f9f9f9; background: #f9f9f9;
} }
.list-view li:last-child {
border-bottom: none;
}
.msg-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 8px;
}
.from-number { .from-number {
font-weight: bold; font-weight: bold;
color: #667eea; color: #667eea;
font-size: 15px;
}
.msg-time {
font-size: 12px;
color: #999;
}
.msg-content {
color: #333;
font-size: 14px;
line-height: 1.6;
word-break: break-all;
} }
.sign-verified { .sign-verified {
@@ -351,40 +379,19 @@
</div> </div>
</div> </div>
<div class="messages-table"> <div class="messages-list">
{% if messages %} {% if messages %}
<table> <ul class="list-view">
<thead> {% for msg in messages %}
<tr> <li>
<th>ID</th> <div class="msg-header">
<th>发送方</th> <span class="from-number">{{ msg.from_number }}</span>
<th>内容</th> <span class="msg-time">{{ msg.created_at }}</span>
<th>时间</th> </div>
<th>验证</th> <div class="msg-content">{{ msg.content }}</div>
</tr> </li>
</thead> {% endfor %}
<tbody> </ul>
{% for msg in messages %}
<tr>
<td>{{ msg.id }}</td>
<td><span class="from-number">{{ msg.from_number }}</span></td>
<td>
<a href="/message/{{ msg.id }}" style="color: #333; text-decoration: none;">
{{ msg.content[:50] }}{% if msg.content|length > 50 %}...{% endif %}
</a>
</td>
<td>{{ msg.created_at }}</td>
<td>
{% if msg.sign_verified %}
<span class="sign-verified yes">✓ 已验证</span>
{% else %}
<span class="sign-verified no">✗ 未验证</span>
{% endif %}
</td>
</tr>
{% endfor %}
</tbody>
</table>
{% else %} {% else %}
<div class="empty-state"> <div class="empty-state">
<h3>暂无短信数据</h3> <h3>暂无短信数据</h3>

View File

@@ -95,33 +95,102 @@
padding-bottom: 10px; padding-bottom: 10px;
} }
.recent-list { .detailed-list {
list-style: none; list-style: none;
} }
.recent-list li { .detailed-list li {
padding: 15px; padding: 20px;
border-bottom: 1px solid #eee; border-bottom: 1px solid #eee;
transition: background 0.3s;
} }
.recent-list li:last-child { .detailed-list li:last-child {
border-bottom: none; border-bottom: none;
} }
.recent-list .from { .detailed-list li:hover {
font-weight: bold; background: #f9f9f9;
color: #667eea;
} }
.recent-list .time { .detailed-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 12px;
}
.detailed-info {
display: flex;
align-items: center;
gap: 12px;
}
.detailed-id {
font-size: 12px; font-size: 12px;
color: #999; color: #999;
margin-left: 10px; background: #f0f0f0;
padding: 2px 8px;
border-radius: 3px;
} }
.recent-list .content { .from-number {
font-weight: bold;
color: #667eea;
font-size: 16px;
}
.msg-time {
font-size: 13px;
color: #999;
}
.detailed-content {
margin-top: 12px;
}
.msg-detail {
color: #333; color: #333;
margin-top: 5px; font-size: 14px;
line-height: 1.6;
margin-bottom: 10px;
word-break: break-all;
}
.msg-meta {
display: flex;
align-items: center;
gap: 10px;
flex-wrap: wrap;
}
.meta-tag {
font-size: 12px;
color: #666;
}
.detail-link {
font-size: 12px;
color: #667eea;
text-decoration: none;
padding: 4px 10px;
background: #f0f0f0;
border-radius: 3px;
transition: all 0.3s;
}
.detail-link:hover {
background: #667eea;
color: white;
text-decoration: none;
}
.sign-verified {
display: inline-block;
padding: 4px 10px;
border-radius: 12px;
font-size: 12px;
font-weight: bold;
} }
.numbers-list { .numbers-list {
@@ -213,17 +282,37 @@
<div class="section"> <div class="section">
<h3>📬 最近接收</h3> <h3>📬 最近接收</h3>
{% if recent %} {% if recent %}
<ul class="recent-list"> <ul class="detailed-list">
{% for msg in recent %} {% for msg in recent %}
<li> <li>
<span class="from">{{ msg.from_number }}</span> <div class="detailed-header">
<span class="time">{{ msg.created_at }}</span> <div class="detailed-info">
<div class="content">{{ msg.content[:100] }}{% if msg.content|length > 100 %}...{% endif %}</div> <span class="from-number">{{ msg.from_number }}</span>
<span class="detailed-id">ID: {{ msg.id }}</span>
</div>
<span class="msg-time">{{ msg.created_at }}</span>
</div>
<div class="detailed-content">
<div class="msg-detail">{{ msg.content }}</div>
<div class="msg-meta">
<span class="meta-tag">
{% if msg.sign_verified %}
<span class="sign-verified yes">✓ 已验证</span>
{% else %}
<span class="sign-verified no">✗ 未验证</span>
{% endif %}
</span>
{% if msg.ip_address %}
<span class="meta-tag">🌐 {{ msg.ip_address }}</span>
{% endif %}
<a href="/message/{{ msg.id }}" class="detail-link">查看详情</a>
</div>
</div>
</li> </li>
{% endfor %} {% endfor %}
</ul> </ul>
{% else %} {% else %}
暂无数据 暂无数据
{% endif %} {% endif %}
</div> </div>