feat: 2026-07-11 全量更新 - 代办集成+会议室预定+知识迭代修复+UI统一+Bug修复

== 已部署上线 (9项) ==
- 代办事项真实数据源集成 (企微审批API 8bug修复链)
- H5/坐席端 Logo样式统一+绿色背景
- 视频引导页修复 (localStorage key v2)
- 坐席端 v9 Vue版本修复 (ElMessage._context)
- 截图按钮 v10 修复 (getDisplayMedia user gesture)
- 扫码样式恢复+H5扫码登录跳转修复
- H5截图快捷键提示

== 代码完成待部署 (3项) ==
- 知识迭代3Bug修复 (#8 POST端点/#7 MERGE幂等/#6 过期检查)
- 会议室预定-小鱼易联终端 (40文件, 40/40测试通过)
- IT资产升级审批推送 (asset_service.py)

== 需求文档 (2项) ==
- 坐席端AI辅助消息框-PRD (4项新功能确认)
- 坐席端布局优化建议 v2.0 (7天计划)

== 新增文档 ==
- 日报-2026-07-11.md
- 知识迭代Bug修复报告-20260711.md
- 会议室预定-部署指南.md
- CHANGELOG.md 更新

== 测试 ==
- test_todo_integration.py: 40/40
- test_meetingroom.py: 40/40
- test_bugfix_ki_suggestions.py: 21/21
This commit is contained in:
Simon
2026-07-11 23:13:10 +08:00
parent 3d152fc8eb
commit bea288e414
928 changed files with 85169 additions and 54205 deletions
@@ -0,0 +1,7 @@
fp='/opt/wecom-it-desk/nginx/nginx.conf'
c=open(fp).read()
p='\n # 真实 IP 还原(2026-06-15 v0.5.1)\n set_real_ip_from 10.0.0.0/8;\n set_real_ip_from 172.16.0.0/12;\n set_real_ip_from 192.168.0.0/16;\n set_real_ip_from 10.212.0.0/16;\n real_ip_header X-Forwarded-For;\n real_ip_recursive on;\n'
o='error_log /var/log/nginx/error.log warn;'
n=c.replace(o,o+p,1)
open(fp,'w').write(n)
print('patched, +%d bytes'%(len(n)-len(c)))
@@ -0,0 +1,54 @@
#!/usr/bin/env python3
"""
修复 docker-compose.yml 中 REDIS_URL 默认值的 URL-encode 问题。
背景:
- 2026-06-15 故障:REDIS_URL 里的密码 R3d!s@2026#Secure 含 @ # 两个 URL 保留字符,
Python redis 库解析时密码被截断成 R3d!s,导致鉴权失败 → Redis 连接超时
- 修复:把密码 URL-encode(@→%40, #→%23, !→%21)
- ⚠️ 关键: 只 URL-encode REDIS_URL 那行的密码,redis-server --requirepass
和 healthcheck 的 redis-cli -a 都必须保持**明文**(否则 Redis 容器启动失败/鉴权失败)
用法:
sudo python3 /tmp/patch-redis-url.py
"""
fp = '/opt/wecom-it-desk/docker-compose.yml'
# 读取当前内容
with open(fp, encoding='utf-8') as f:
c = f.read()
# 旧值(精确匹配 REDIS_URL 那一行,带 redis://://@ 上下文,避免误改 --requirepass)
old = 'REDIS_URL=redis://:${REDIS_PASSWORD:-R3d!s@2026#Secure}@redis:6379/0'
# 新值:URL-encode 后的密码(!→%21, @→%40, #→%23),仅 REDIS_URL 这一行
new = 'REDIS_URL=redis://:${REDIS_PASSWORD:-R3d%21s%402026%23Secure}@redis:6379/0'
# 检查是否已经修复过(幂等性)
if old in c:
print('[OK] 检测到未编码版本,准备修复...')
c2 = c.replace(old, new, 1) # 只替换第一次出现(更安全)
with open(fp, 'w', encoding='utf-8') as f:
f.write(c2)
delta = len(c2) - len(c)
print('[OK] 已修复:REDIS_URL 行的密码已 URL-encode')
print(f'[OK] 文件长度变化:{delta:+d} 字节')
elif new in c:
print('[OK] 已经修复过,跳过(幂等性 OK)')
else:
print('[ERROR] 既没找到旧值也没找到新值,请人工检查 docker-compose.yml')
print('---')
print('当前 REDIS_URL 相关配置:')
import subprocess
result = subprocess.run(['grep', '-n', 'REDIS_URL\\|REDIS_PASSWORD\\|--requirepass\\|redis-cli', fp],
capture_output=True, text=True)
print(result.stdout)
exit(1)
# 验证:确保 --requirepass 和 redis-cli 仍然是明文(没被误改)
import subprocess
result = subprocess.run(['grep', '-nE', 'REDIS_URL|--requirepass|redis-cli.*-a', fp],
capture_output=True, text=True)
print('---')
print('当前所有密码相关行(应只有 REDIS_URL 一行是 URL-encoded,其他保持明文):')
print(result.stdout)
@@ -0,0 +1,20 @@
fp = '/opt/wecom-it-desk/nginx/nginx.conf'
with open(fp) as f:
c = f.read()
patch = '''
# ------------------------------------------------------------------
# 真实 IP 还原(2026-06-15 v0.5.1 修复)
# ------------------------------------------------------------------
set_real_ip_from 10.0.0.0/8;
set_real_ip_from 172.16.0.0/12;
set_real_ip_from 192.168.0.0/16;
set_real_ip_from 10.212.0.0/16;
real_ip_header X-Forwarded-For;
real_ip_recursive on;
'''
old = 'error_log /var/log/nginx/error.log warn;'
new = old + patch
new_c = c.replace(old, new, 1)
with open(fp, 'w') as f:
f.write(new_c)
print('patched, +{} bytes'.format(len(new_c) - len(c)))
@@ -0,0 +1,30 @@
#!/usr/bin/env python3
import os
import psycopg2
# 从环境变量获取 DATABASE_URL
db_url = os.environ.get('DATABASE_URL')
if not db_url:
# 尝试从 docker-compose 生成的变量拼接
db_url = "postgresql://wecom_user:wecom_pass@10.90.5.110:5432/wecom_it_desk"
conn = psycopg2.connect(db_url)
cur = conn.cursor()
# A表
cur.execute("SELECT COUNT(*) FROM config_change_logs")
a_count = cur.fetchone()[0]
# B表 audit_logs 中 action='config_change' 的数量
cur.execute("SELECT COUNT(*) FROM audit_logs WHERE action = 'config_change'")
b_config_change_count = cur.fetchone()[0]
# B表总数
cur.execute("SELECT COUNT(*) FROM audit_logs")
b_total = cur.fetchone()[0]
print(f"config_change_logs (A): {a_count}")
print(f"audit_logs (B) - config_change events: {b_config_change_count}")
print(f"audit_logs (B) - total: {b_total}")
conn.close()