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:
@@ -0,0 +1,71 @@
|
||||
#!/usr/bin/env python3
|
||||
"""生成超时提醒通知图片"""
|
||||
from PIL import Image, ImageDraw, ImageFont
|
||||
import os
|
||||
|
||||
# 图片尺寸(企微图片消息建议尺寸)
|
||||
WIDTH = 600
|
||||
HEIGHT = 300
|
||||
|
||||
# 创建图片
|
||||
img = Image.new('RGB', (WIDTH, HEIGHT))
|
||||
draw = ImageDraw.Draw(img)
|
||||
|
||||
# 绘制渐变背景(从蓝色到青色)
|
||||
for y in range(HEIGHT):
|
||||
# 计算渐变比例
|
||||
ratio = y / HEIGHT
|
||||
# 蓝色 (0, 120, 215) -> 青色 (0, 180, 160)
|
||||
r = int(0 + (0 - 0) * ratio)
|
||||
g = int(120 + (180 - 120) * ratio)
|
||||
b = int(215 + (160 - 215) * ratio)
|
||||
draw.line([(0, y), (WIDTH, y)], fill=(r, g, b))
|
||||
|
||||
# 绘制标题
|
||||
try:
|
||||
# 尝试使用系统字体
|
||||
title_font = ImageFont.truetype("msyh.ttc", 36) # 微软雅黑
|
||||
subtitle_font = ImageFont.truetype("msyh.ttc", 22)
|
||||
button_font = ImageFont.truetype("msyh.ttc", 28)
|
||||
except:
|
||||
# 回退到默认字体
|
||||
title_font = ImageFont.load_default()
|
||||
subtitle_font = ImageFont.load_default()
|
||||
button_font = ImageFont.load_default()
|
||||
|
||||
# 标题
|
||||
draw.text((30, 30), "🔔 您的IT咨询即将关闭", fill=(255, 255, 255), font=title_font)
|
||||
|
||||
# 副标题
|
||||
draw.text((30, 90), "请尽快回复坐席,否则咨询将自动结束", fill=(220, 220, 220), font=subtitle_font)
|
||||
|
||||
# 绘制3D水晶按钮
|
||||
btn_x, btn_y = 30, 160
|
||||
btn_w, btn_h = 540, 70
|
||||
|
||||
# 按钮阴影
|
||||
draw.rounded_rectangle([btn_x+4, btn_y+4, btn_x+btn_w+4, btn_y+btn_h+4], radius=15, fill=(180, 180, 180))
|
||||
|
||||
# 按钮主体(渐变效果用多层矩形模拟)
|
||||
for i in range(btn_h):
|
||||
ratio = i / btn_h
|
||||
# 浅蓝色 -> 深蓝色
|
||||
r = int(30 + (0 - 30) * ratio)
|
||||
g = int(160 + (100 - 160) * ratio)
|
||||
b = int(255 + (200 - 255) * ratio)
|
||||
draw.rectangle([btn_x, btn_y+i, btn_x+btn_w, btn_y+i+1], fill=(r, g, b))
|
||||
|
||||
# 按钮高光效果
|
||||
draw.rounded_rectangle([btn_x, btn_y, btn_x+btn_w, btn_y+btn_h//3], radius=15, fill=(255, 255, 255, 80))
|
||||
|
||||
# 按钮文字
|
||||
draw.text((btn_x + btn_w//2 - 70, btn_y + 20), "立即回复 →", fill=(255, 255, 255), font=button_font)
|
||||
|
||||
# 底部提示
|
||||
draw.text((30, 250), "点击上方按钮进入智能IT服务台", fill=(180, 180, 180), font=subtitle_font)
|
||||
|
||||
# 保存图片
|
||||
output_path = "/tmp/reminder_notification.png"
|
||||
img.save(output_path)
|
||||
print(f"✅ 图片已生成: {output_path}")
|
||||
print(f" 尺寸: {WIDTH}x{HEIGHT}")
|
||||
@@ -0,0 +1,100 @@
|
||||
#!/usr/bin/env python3
|
||||
"""设计一张精美的IT咨询超时提醒卡片"""
|
||||
from PIL import Image, ImageDraw, ImageFont
|
||||
import os
|
||||
|
||||
# 卡片尺寸
|
||||
WIDTH, HEIGHT = 700, 400
|
||||
|
||||
# 创建图片
|
||||
img = Image.new('RGBA', (WIDTH, HEIGHT), (0, 0, 0, 0))
|
||||
draw = ImageDraw.Draw(img)
|
||||
|
||||
# ============== 背景层 ==============
|
||||
# 渐变背景 (蓝 → 青)
|
||||
for y in range(HEIGHT):
|
||||
ratio = y / HEIGHT
|
||||
r = int(7 + (124 - 7) * ratio) # 7 → 124
|
||||
g = int(193 + (217 - 193) * ratio) # 193 → 217
|
||||
b = int(255 + (245 - 255) * ratio) # 255 → 245
|
||||
draw.line([(0, y), (WIDTH, y)], fill=(r, g, b, 255))
|
||||
|
||||
# ============== 装饰元素 ==============
|
||||
# 顶部装饰条
|
||||
draw.rectangle([0, 0, WIDTH, 6], fill=(255, 255, 255, 80))
|
||||
|
||||
# 底部椭圆高光
|
||||
draw.ellipse([WIDTH//2 - 200, HEIGHT - 80, WIDTH//2 + 200, HEIGHT + 20],
|
||||
fill=(255, 255, 255, 30))
|
||||
|
||||
# ============== 主标题 ==============
|
||||
try:
|
||||
title_font = ImageFont.truetype("/usr/share/fonts/truetype/dejavu/DejaVuSans-Bold.ttf", 42)
|
||||
subtitle_font = ImageFont.truetype("/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf", 26)
|
||||
button_font = ImageFont.truetype("/usr/share/fonts/truetype/dejavu/DejaVuSans-Bold.ttf", 32)
|
||||
time_font = ImageFont.truetype("/usr/share/fonts/truetype/dejavu/DejaVuSans-Bold.ttf", 56)
|
||||
except:
|
||||
title_font = ImageFont.load_default()
|
||||
subtitle_font = ImageFont.load_default()
|
||||
button_font = ImageFont.load_default()
|
||||
time_font = ImageFont.load_default()
|
||||
|
||||
# 标题
|
||||
draw.text((50, 50), "🔔 您的IT咨询", fill=(255, 255, 255), font=title_font)
|
||||
|
||||
# 副标题
|
||||
draw.text((50, 110), "将会在 2 分钟后关闭", fill=(220, 240, 255), font=subtitle_font)
|
||||
|
||||
# ============== 3D水晶按钮 ==============
|
||||
btn_x, btn_y = 50, 200
|
||||
btn_w, btn_h = 600, 90
|
||||
|
||||
# 1. 阴影层 (偏移)
|
||||
shadow_offset = 8
|
||||
draw.rounded_rectangle(
|
||||
[btn_x + shadow_offset, btn_y + shadow_offset,
|
||||
btn_x + btn_w + shadow_offset, btn_y + btn_h + shadow_offset],
|
||||
radius=20, fill=(0, 80, 150, 120))
|
||||
|
||||
# 2. 按钮主体 (渐变)
|
||||
for i in range(btn_h):
|
||||
ratio = i / btn_h
|
||||
# 蓝 → 青渐变
|
||||
r = int(7 + (0 - 7) * ratio)
|
||||
g = int(193 + (200 - 193) * ratio)
|
||||
b = int(255 + (220 - 255) * ratio)
|
||||
draw.rectangle(
|
||||
[btn_x, btn_y + i, btn_x + btn_w, btn_y + i + 1],
|
||||
fill=(r, g, b, 255))
|
||||
|
||||
# 3. 高光层 (水晶效果)
|
||||
# 顶部高光
|
||||
draw.rounded_rectangle(
|
||||
[btn_x, btn_y, btn_x + btn_w, btn_y + btn_h // 2.5],
|
||||
radius=20, fill=(255, 255, 255, 60))
|
||||
|
||||
# 中间高光线
|
||||
draw.line([(btn_x + 30, btn_y + 25), (btn_x + btn_w - 30, btn_y + 25)],
|
||||
fill=(255, 255, 255, 100), width=3)
|
||||
|
||||
# 4. 按钮边框
|
||||
draw.rounded_rectangle(
|
||||
[btn_x, btn_y, btn_x + btn_w, btn_y + btn_h],
|
||||
radius=20, outline=(255, 255, 255, 80), width=2)
|
||||
|
||||
# 5. 按钮文字
|
||||
btn_text = "⚡ 立即回复"
|
||||
text_bbox = draw.textbbox((0, 0), btn_text, font=button_font)
|
||||
text_width = text_bbox[2] - text_bbox[0]
|
||||
draw.text((btn_x + (btn_w - text_width) // 2, btn_y + (btn_h - 28) // 2),
|
||||
btn_text, fill=(255, 255, 255), font=button_font)
|
||||
|
||||
# ============== 底部提示 ==============
|
||||
draw.text((50, 320), "请尽快回复坐席,否则咨询将自动结束",
|
||||
fill=(200, 220, 240, 200), font=subtitle_font)
|
||||
|
||||
# 保存
|
||||
output_path = "/tmp/it_reminder_card.png"
|
||||
img.save(output_path, format='PNG')
|
||||
print(f"✅ 卡片已生成: {output_path}")
|
||||
print(f" 尺寸: {WIDTH}x{HEIGHT}")
|
||||
@@ -95,6 +95,10 @@ services:
|
||||
- DIFY_WINGMAN_API_URL=${DIFY_WINGMAN_API_URL:-}
|
||||
- DIFY_WINGMAN_API_KEY=${DIFY_WINGMAN_API_KEY:-}
|
||||
- DIFY_WINGMAN_TIMEOUT=${DIFY_WINGMAN_TIMEOUT:-30}
|
||||
# 审批意图识别 Dify 应用
|
||||
- APPROVAL_DIFY_BASE_URL=${APPROVAL_DIFY_BASE_URL:-}
|
||||
- APPROVAL_DIFY_API_KEY=${APPROVAL_DIFY_API_KEY:-}
|
||||
- APPROVAL_CONFIDENCE_THRESHOLD=${APPROVAL_CONFIDENCE_THRESHOLD:-0.7}
|
||||
# Mock 登录(生产环境默认关闭,如需临时调试请在 .env 中显式设置为 true)
|
||||
- MOCK_LOGIN_ENABLED=${MOCK_LOGIN_ENABLED:-false}
|
||||
# 企微 SSO 认证(v0.7.1 新增)
|
||||
|
||||
@@ -0,0 +1,104 @@
|
||||
#!/usr/bin/env python3
|
||||
"""在服务器上生成通知图片并上传到企微"""
|
||||
import asyncio
|
||||
import sys
|
||||
|
||||
sys.path.insert(0, '/app')
|
||||
|
||||
from PIL import Image, ImageDraw, ImageFont
|
||||
from app.services.wecom_service import WecomService
|
||||
|
||||
|
||||
async def generate_image():
|
||||
"""生成通知图片"""
|
||||
WIDTH, HEIGHT = 600, 300
|
||||
|
||||
img = Image.new('RGB', (WIDTH, HEIGHT))
|
||||
draw = ImageDraw.Draw(img)
|
||||
|
||||
# 渐变背景
|
||||
for y in range(HEIGHT):
|
||||
ratio = y / HEIGHT
|
||||
r = int(0 + (0 - 0) * ratio)
|
||||
g = int(120 + (180 - 120) * ratio)
|
||||
b = int(215 + (160 - 215) * ratio)
|
||||
draw.line([(0, y), (WIDTH, y)], fill=(r, g, b))
|
||||
|
||||
# 字体
|
||||
try:
|
||||
title_font = ImageFont.truetype("/usr/share/fonts/truetype/dejavu/DejaVuSans-Bold.ttf", 32)
|
||||
subtitle_font = ImageFont.truetype("/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf", 20)
|
||||
button_font = ImageFont.truetype("/usr/share/fonts/truetype/dejavu/DejaVuSans-Bold.ttf", 24)
|
||||
except:
|
||||
title_font = ImageFont.load_default()
|
||||
subtitle_font = ImageFont.load_default()
|
||||
button_font = ImageFont.load_default()
|
||||
|
||||
# 标题
|
||||
draw.text((30, 30), "IT咨询即将关闭", fill=(255, 255, 255), font=title_font)
|
||||
draw.text((30, 85), "请尽快回复坐席,否则将自动结束", fill=(220, 220, 220), font=subtitle_font)
|
||||
|
||||
# 3D按钮
|
||||
btn_x, btn_y = 30, 150
|
||||
btn_w, btn_h = 540, 60
|
||||
|
||||
# 阴影
|
||||
draw.rounded_rectangle([btn_x+3, btn_y+3, btn_x+btn_w+3, btn_y+btn_h+3], radius=12, fill=(100, 100, 100))
|
||||
|
||||
# 按钮主体
|
||||
for i in range(btn_h):
|
||||
ratio = i / btn_h
|
||||
r = int(20 + (100 - 20) * ratio)
|
||||
g = int(150 + (200 - 150) * ratio)
|
||||
b = int(220 + (255 - 220) * ratio)
|
||||
draw.rectangle([btn_x, btn_y+i, btn_x+btn_w, btn_y+i+1], fill=(r, g, b))
|
||||
|
||||
# 高光
|
||||
draw.rounded_rectangle([btn_x, btn_y, btn_x+btn_w, btn_y+btn_h//3], radius=12, fill=(255, 255, 255, 60))
|
||||
|
||||
# 按钮文字
|
||||
draw.text((btn_x + btn_w//2 - 60, btn_y + 18), "立即回复", fill=(255, 255, 255), font=button_font)
|
||||
|
||||
# 保存到内存
|
||||
from io import BytesIO
|
||||
buffer = BytesIO()
|
||||
img.save(buffer, format='PNG')
|
||||
buffer.seek(0)
|
||||
return buffer.getvalue()
|
||||
|
||||
|
||||
async def upload_and_send():
|
||||
"""上传图片并发送消息"""
|
||||
print("🎨 正在生成通知图片...")
|
||||
image_data = await generate_image()
|
||||
print(f" 图片已生成, 大小: {len(image_data)} bytes")
|
||||
|
||||
# 创建企微服务
|
||||
wecom = WecomService()
|
||||
|
||||
try:
|
||||
print("📤 正在上传图片到企微...")
|
||||
# 上传临时素材 - 传入二进制数据
|
||||
media_id = await wecom.upload_temp_media("image", image_data, "reminder.png")
|
||||
|
||||
if not media_id or media_id.startswith("ERROR"):
|
||||
print(f"❌ 上传失败: {media_id}")
|
||||
return
|
||||
|
||||
print(f" 上传成功! media_id: {media_id}")
|
||||
|
||||
print("📨 正在发送图片消息...")
|
||||
# 发送图片消息
|
||||
result = await wecom.send_image_message("sxn", media_id)
|
||||
|
||||
if result.get("errcode") == 0:
|
||||
print(f"✅ 发送成功! msgid: {result.get('msgid')}")
|
||||
else:
|
||||
print(f"❌ 发送失败: {result}")
|
||||
|
||||
finally:
|
||||
await wecom.close()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(upload_and_send())
|
||||
@@ -0,0 +1,129 @@
|
||||
#!/usr/bin/env python3
|
||||
"""生成精美通知卡片"""
|
||||
from PIL import Image, ImageDraw, ImageFont
|
||||
from io import BytesIO
|
||||
|
||||
def create_card():
|
||||
W, H = 600, 320
|
||||
|
||||
# 创建画布
|
||||
img = Image.new('RGBA', (W, H), (0, 0, 0, 0))
|
||||
draw = ImageDraw.Draw(img)
|
||||
|
||||
# ==================== 卡片背景 ====================
|
||||
# 主背景 - 柔和蓝渐变
|
||||
for y in range(H):
|
||||
ratio = y / H
|
||||
r = int(30 + (60 - 30) * ratio)
|
||||
g = int(100 + (160 - 100) * ratio)
|
||||
b = int(200 + (220 - 200) * ratio)
|
||||
draw.line([(0, y), (W, y)], fill=(r, g, b, 255))
|
||||
|
||||
# 卡片主体圆角
|
||||
card_x, card_y = 10, 10
|
||||
card_w, card_h = W - 20, H - 20
|
||||
|
||||
# 绘制圆角矩形作为底板
|
||||
draw.rounded_rectangle(
|
||||
[card_x, card_y, card_x + card_w, card_y + card_h],
|
||||
radius=20, fill=(255, 255, 255, 240)
|
||||
)
|
||||
|
||||
# ==================== 顶部装饰 ====================
|
||||
# 装饰线条
|
||||
draw.line([(card_x + 20, card_y + 20), (card_x + card_w - 20, card_y + 20)], fill=(7, 193, 96, 200), width=3)
|
||||
|
||||
# ==================== 图标区域 ====================
|
||||
# 时钟图标(圆形背景)
|
||||
icon_x, icon_y = 60, 70
|
||||
draw.ellipse([icon_x - 25, icon_y - 25, icon_x + 25, icon_y + 25], fill=(7, 193, 96, 30))
|
||||
draw.ellipse([icon_x - 20, icon_y - 20, icon_x + 20, icon_y + 20], outline=(7, 193, 96, 255), width=2)
|
||||
|
||||
# 时针
|
||||
draw.line([icon_x, icon_y, icon_x, icon_y - 10], fill=(7, 193, 96, 255), width=2)
|
||||
# 分针
|
||||
draw.line([icon_x, icon_y, icon_x + 8, icon_y + 5], fill=(7, 193, 96, 255), width=2)
|
||||
# 中心点
|
||||
draw.ellipse([icon_x - 2, icon_y - 2, icon_x + 2, icon_y + 2], fill=(7, 193, 96, 255))
|
||||
|
||||
# ==================== 标题文字 ====================
|
||||
try:
|
||||
title_font = ImageFont.truetype("C:/Windows/Fonts/msyh.ttc", 28)
|
||||
subtitle_font = ImageFont.truetype("C:/Windows/Fonts/msyh.ttc", 16)
|
||||
btn_font = ImageFont.truetype("C:/Windows/Fonts/msyh.ttc", 20)
|
||||
except:
|
||||
try:
|
||||
title_font = ImageFont.truetype("C:/Windows/Fonts/simhei.ttf", 28)
|
||||
subtitle_font = ImageFont.truetype("C:/Windows/Fonts/simhei.ttf", 16)
|
||||
btn_font = ImageFont.truetype("C:/Windows/Fonts/simhei.ttf", 20)
|
||||
except:
|
||||
title_font = ImageFont.load_default()
|
||||
subtitle_font = ImageFont.load_default()
|
||||
btn_font = ImageFont.load_default()
|
||||
|
||||
# 主标题
|
||||
title = "IT咨询即将关闭"
|
||||
draw.text((100, 55), title, fill=(40, 40, 40), font=title_font)
|
||||
|
||||
# 副标题
|
||||
subtitle = "请尽快回复坐席,否则咨询将自动结束"
|
||||
draw.text((100, 95), subtitle, fill=(120, 120, 120), font=subtitle_font)
|
||||
|
||||
# ==================== 3D水晶按钮 ====================
|
||||
btn_x, btn_y = 40, 150
|
||||
btn_w, btn_h = 520, 60
|
||||
btn_radius = 15
|
||||
|
||||
# 按钮阴影
|
||||
draw.rounded_rectangle(
|
||||
[btn_x + 4, btn_y + 4, btn_x + btn_w + 4, btn_y + btn_h + 4],
|
||||
radius=btn_radius, fill=(0, 0, 0, 40)
|
||||
)
|
||||
|
||||
# 按钮主体 - 渐变
|
||||
for i in range(btn_h):
|
||||
ratio = i / btn_h
|
||||
# 绿色渐变
|
||||
r = int(7 + (20 - 7) * ratio)
|
||||
g = int(193 + (180 - 193) * ratio)
|
||||
b = int(96 + (60 - 96) * ratio)
|
||||
draw.rectangle([btn_x, btn_y + i, btn_x + btn_w, btn_y + i + 1], fill=(r, g, b))
|
||||
|
||||
# 按钮顶部高光
|
||||
draw.rounded_rectangle(
|
||||
[btn_x, btn_y, btn_x + btn_w, btn_y + btn_h // 2],
|
||||
radius=btn_radius, fill=(255, 255, 255, 40)
|
||||
)
|
||||
|
||||
# 按钮边框
|
||||
draw.rounded_rectangle(
|
||||
[btn_x, btn_y, btn_x + btn_w, btn_y + btn_h],
|
||||
radius=btn_radius, outline=(5, 150, 70, 100), width=1
|
||||
)
|
||||
|
||||
# 按钮文字
|
||||
btn_text = "立即回复"
|
||||
# 计算文字居中
|
||||
bbox = draw.textbbox((0, 0), btn_text, font=btn_font)
|
||||
text_w = bbox[2] - bbox[0]
|
||||
text_x = btn_x + (btn_w - text_w) // 2
|
||||
text_y = btn_y + (btn_h - (bbox[3] - bbox[1])) // 2 - 2
|
||||
draw.text((text_x, text_y), btn_text, fill=(255, 255, 255), font=btn_font)
|
||||
|
||||
# ==================== 底部提示 ====================
|
||||
tip = "点击卡片直接跳转到咨询页面"
|
||||
draw.text((card_x + 20, card_y + card_h - 30), tip, fill=(150, 150, 150), font=subtitle_font)
|
||||
|
||||
# 保存
|
||||
buffer = BytesIO()
|
||||
img.save(buffer, format='PNG')
|
||||
buffer.seek(0)
|
||||
return buffer.getvalue()
|
||||
|
||||
|
||||
# 本地测试
|
||||
if __name__ == "__main__":
|
||||
data = create_card()
|
||||
with open("D:/资料/03-项目开发/wecom_it_smart_desk/deploy-server/it_reminder_card_v2.png", "wb") as f:
|
||||
f.write(data)
|
||||
print("✅ 卡片已保存")
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 19 KiB |
@@ -108,9 +108,13 @@ http {
|
||||
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
|
||||
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
|
||||
add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-eval' https://res.wx.qq.com; style-src 'self' 'unsafe-inline' https://res.wx.qq.com; connect-src 'self' wss://itsupport.servyou.com.cn https://itsupport.servyou.com.cn https://qyapi.weixin.qq.com; img-src 'self' data: https://res.wx.qq.com; font-src 'self' data:;" always;
|
||||
add_header Permissions-Policy "camera=(), microphone=(), geolocation=(), payment=()" always;
|
||||
# 修复:microphone=() 完全禁用麦克风,导致坐席端 Web Speech API 无法使用
|
||||
# 改为 microphone=(self) 允许同源页面使用麦克风(浏览器仍会弹窗询问用户)
|
||||
add_header Permissions-Policy "camera=(), microphone=(self), geolocation=(), payment=()" always;
|
||||
add_header Cross-Origin-Opener-Policy "same-origin" always;
|
||||
add_header Cross-Origin-Embedder-Policy "require-corp" always;
|
||||
# 修复:COEP require-corp 阻止加载企微 JS-SDK 跨域脚本(res.wx.qq.com 不发 CORP 头)
|
||||
# 本应用不使用 SharedArrayBuffer / cross-origin isolation,移除 COEP 不影响功能
|
||||
# add_header Cross-Origin-Embedder-Policy "require-corp" always;
|
||||
add_header Cross-Origin-Resource-Policy "same-origin" always;
|
||||
server_tokens off;
|
||||
location = /health {
|
||||
|
||||
@@ -108,9 +108,13 @@ http {
|
||||
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
|
||||
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
|
||||
add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-eval' https://res.wx.qq.com; style-src 'self' 'unsafe-inline' https://res.wx.qq.com; connect-src 'self' wss://itsupport.servyou.com.cn https://itsupport.servyou.com.cn https://qyapi.weixin.qq.com; img-src 'self' data: https://res.wx.qq.com; font-src 'self' data:;" always;
|
||||
add_header Permissions-Policy "camera=(), microphone=(), geolocation=(), payment=()" always;
|
||||
# 修复:microphone=() 完全禁用麦克风,导致坐席端 Web Speech API 无法使用
|
||||
# 改为 microphone=(self) 允许同源页面使用麦克风(浏览器仍会弹窗询问用户)
|
||||
add_header Permissions-Policy "camera=(), microphone=(self), geolocation=(), payment=()" always;
|
||||
add_header Cross-Origin-Opener-Policy "same-origin" always;
|
||||
add_header Cross-Origin-Embedder-Policy "require-corp" always;
|
||||
# 修复:COEP require-corp 阻止加载企微 JS-SDK 跨域脚本(res.wx.qq.com 不发 CORP 头)
|
||||
# 本应用不使用 SharedArrayBuffer / cross-origin isolation,移除 COEP 不影响功能
|
||||
# add_header Cross-Origin-Embedder-Policy "require-corp" always;
|
||||
add_header Cross-Origin-Resource-Policy "same-origin" always;
|
||||
server_tokens off;
|
||||
location = /health {
|
||||
@@ -125,7 +129,7 @@ http {
|
||||
location /itagent/ {
|
||||
alias /usr/share/nginx/html/itagent/;
|
||||
index index.html;
|
||||
try_files $uri $uri/ /index.html;
|
||||
try_files $uri $uri/ /itagent/index.html;
|
||||
}
|
||||
location /itadmin/ {
|
||||
allow 10.0.0.0/8;
|
||||
@@ -206,7 +210,7 @@ http {
|
||||
proxy_read_timeout 300s;
|
||||
}
|
||||
location = / {
|
||||
return 302 /itportal/;
|
||||
return 302 /itagent/;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
#!/usr/bin/env python3
|
||||
"""发送最佳实践的企业微信模板卡片"""
|
||||
import asyncio
|
||||
import sys
|
||||
|
||||
sys.path.insert(0, '/app')
|
||||
|
||||
from app.services.wecom_service import WecomService
|
||||
|
||||
|
||||
async def main():
|
||||
wecom = WecomService()
|
||||
|
||||
try:
|
||||
print("📤 发送最佳实践模板卡片...")
|
||||
|
||||
result = await wecom.send_template_card_message(
|
||||
user_id="sxn",
|
||||
|
||||
# 主标题区域
|
||||
main_title="您的IT咨询即将关闭",
|
||||
main_title_desc="请尽快回复坐席,否则咨询将自动结束",
|
||||
|
||||
# 副标题
|
||||
sub_title_text="点击下方按钮直接跳转到咨询页面",
|
||||
|
||||
# 高亮区域 - 突出剩余时间
|
||||
emphasis_title="2分钟",
|
||||
emphasis_desc="剩余处理时间",
|
||||
|
||||
# 跳转按钮列表
|
||||
jump_list=[
|
||||
{
|
||||
"type": 1, # 跳转URL
|
||||
"title": "立即回复",
|
||||
"url": "https://itsupport.servyou.com.cn/h5/",
|
||||
},
|
||||
],
|
||||
|
||||
# 卡片点击区域
|
||||
card_action_url="https://itsupport.servyou.com.cn/h5/",
|
||||
)
|
||||
|
||||
if result.get("errcode") == 0:
|
||||
print(f"✅ 发送成功! msgid: {result.get('msgid')}")
|
||||
else:
|
||||
print(f"❌ 失败: {result}")
|
||||
|
||||
finally:
|
||||
await wecom.close()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(main())
|
||||
@@ -0,0 +1,38 @@
|
||||
#!/usr/bin/env python3
|
||||
"""将生成的卡片发送到企微"""
|
||||
import asyncio
|
||||
import sys
|
||||
|
||||
sys.path.insert(0, '/app')
|
||||
|
||||
from app.services.wecom_service import WecomService
|
||||
|
||||
|
||||
async def main():
|
||||
"""发送卡片图片"""
|
||||
wecom = WecomService()
|
||||
|
||||
try:
|
||||
# 上传图片
|
||||
print("📤 上传卡片图片...")
|
||||
with open('/tmp/it_reminder_card.png', 'rb') as f:
|
||||
image_data = f.read()
|
||||
|
||||
media_id = await wecom.upload_temp_media("image", image_data, "it_reminder_card.png")
|
||||
print(f" media_id: {media_id}")
|
||||
|
||||
# 发送图片
|
||||
print("📨 发送图片消息...")
|
||||
result = await wecom.send_image_message("sxn", media_id)
|
||||
|
||||
if result.get("errcode") == 0:
|
||||
print(f"✅ 发送成功! msgid: {result.get('msgid')}")
|
||||
else:
|
||||
print(f"❌ 发送失败: {result}")
|
||||
|
||||
finally:
|
||||
await wecom.close()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(main())
|
||||
@@ -0,0 +1,52 @@
|
||||
#!/usr/bin/env python3
|
||||
"""发送最终优化版模板卡片"""
|
||||
import asyncio
|
||||
import sys
|
||||
|
||||
sys.path.insert(0, '/app')
|
||||
|
||||
from app.services.wecom_service import WecomService
|
||||
|
||||
|
||||
async def main():
|
||||
wecom = WecomService()
|
||||
|
||||
try:
|
||||
print("📤 发送最终优化版模板卡片...")
|
||||
|
||||
result = await wecom.send_template_card_message(
|
||||
user_id="sxn",
|
||||
# 来源
|
||||
source_desc="智能IT服务平台",
|
||||
# 主标题
|
||||
main_title="您的IT咨询即将关闭",
|
||||
main_title_desc="请尽快回复",
|
||||
# 副标题
|
||||
sub_title_text="点击下方按钮直接跳转到咨询页面",
|
||||
# 高亮
|
||||
emphasis_title="2分钟",
|
||||
emphasis_desc="剩余处理时间",
|
||||
# 关键信息
|
||||
horizontal_content_list=[
|
||||
{"keyname": "咨询内容", "value": "IT问题咨询"},
|
||||
{"keyname": "坐席状态", "value": "已回复"},
|
||||
],
|
||||
# 按钮
|
||||
jump_list=[
|
||||
{"type": 1, "title": "立即回复", "url": "https://itsupport.servyou.com.cn/h5/"},
|
||||
],
|
||||
# 卡片点击
|
||||
card_action_url="https://itsupport.servyou.com.cn/h5/",
|
||||
)
|
||||
|
||||
if result.get("errcode") == 0:
|
||||
print(f"✅ 发送成功! msgid: {result.get('msgid')}")
|
||||
else:
|
||||
print(f"❌ 失败: {result}")
|
||||
|
||||
finally:
|
||||
await wecom.close()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(main())
|
||||
@@ -0,0 +1,45 @@
|
||||
#!/usr/bin/env python3
|
||||
"""直接发送模板卡片测试消息"""
|
||||
import asyncio
|
||||
import sys
|
||||
|
||||
sys.path.insert(0, '/app')
|
||||
|
||||
from app.services.wecom_service import WecomService
|
||||
|
||||
|
||||
async def main():
|
||||
"""发送测试模板卡片"""
|
||||
# 测试用的 UserID(宋献的企微账号)
|
||||
user_id = "sxn"
|
||||
|
||||
# 创建服务实例
|
||||
wecom = WecomService()
|
||||
|
||||
# 模板卡片内容
|
||||
main_title = "🧪 测试消息"
|
||||
main_title_desc = "这是一条测试用的模板卡片消息,用于验证功能是否正常。"
|
||||
sub_title_text = "点击下方按钮查看详情"
|
||||
card_action_url = "https://itsupport.servyou.com.cn"
|
||||
|
||||
print(f"📤 发送模板卡片到 UserID: {user_id}")
|
||||
print(f" 标题: {main_title}")
|
||||
print(f" 描述: {main_title_desc}")
|
||||
|
||||
try:
|
||||
result = await wecom.send_template_card_message(
|
||||
user_id=user_id,
|
||||
main_title=main_title,
|
||||
main_title_desc=main_title_desc,
|
||||
sub_title_text=sub_title_text,
|
||||
card_action_url=card_action_url
|
||||
)
|
||||
print(f"\n✅ 发送结果: {result}")
|
||||
except Exception as e:
|
||||
print(f"\n❌ 发送失败: {e}")
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(main())
|
||||
@@ -0,0 +1,37 @@
|
||||
#!/usr/bin/env python3
|
||||
"""发送卡片图片"""
|
||||
import asyncio
|
||||
import sys
|
||||
|
||||
sys.path.insert(0, '/app')
|
||||
|
||||
from app.services.wecom_service import WecomService
|
||||
|
||||
|
||||
async def main():
|
||||
wecom = WecomService()
|
||||
|
||||
try:
|
||||
# 读取图片
|
||||
with open('/tmp/it_reminder_card_v2.png', 'rb') as f:
|
||||
image_data = f.read()
|
||||
|
||||
# 上传
|
||||
print("📤 上传卡片...")
|
||||
media_id = await wecom.upload_temp_media("image", image_data, "card.png")
|
||||
print(f" media_id: {media_id}")
|
||||
|
||||
# 发送
|
||||
print("📨 发送消息...")
|
||||
result = await wecom.send_image_message("sxn", media_id)
|
||||
|
||||
if result.get("errcode") == 0:
|
||||
print(f"✅ 发送成功! msgid: {result.get('msgid')}")
|
||||
else:
|
||||
print(f"❌ 失败: {result}")
|
||||
finally:
|
||||
await wecom.close()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(main())
|
||||
@@ -0,0 +1,29 @@
|
||||
#!/usr/bin/env python3
|
||||
"""测试超时提醒模板卡片发送功能"""
|
||||
import asyncio
|
||||
import sys
|
||||
|
||||
# 添加项目路径
|
||||
sys.path.insert(0, '/opt/wecom-it-desk')
|
||||
|
||||
from app.services.reminder_service import send_reminder_message
|
||||
|
||||
|
||||
async def main():
|
||||
"""直接调用提醒服务发送测试消息"""
|
||||
# 使用一个测试用的 employee_id
|
||||
# 注意:需要替换为实际存在的用户 UserID
|
||||
test_employee_id = "sxn" # 测试用户
|
||||
|
||||
print(f"开始发送测试提醒到 employee_id: {test_employee_id}")
|
||||
try:
|
||||
result = await send_reminder_message(test_employee_id)
|
||||
print(f"发送结果: {result}")
|
||||
except Exception as e:
|
||||
print(f"发送失败: {e}")
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(main())
|
||||
@@ -0,0 +1,27 @@
|
||||
#!/usr/bin/env python3
|
||||
"""测试美化后的超时提醒模板卡片"""
|
||||
import asyncio
|
||||
import sys
|
||||
|
||||
sys.path.insert(0, '/app')
|
||||
|
||||
from app.services.reminder_service import send_reminder_message
|
||||
|
||||
|
||||
async def main():
|
||||
"""发送测试提醒"""
|
||||
user_id = "sxn" # 测试用户
|
||||
|
||||
print(f"📤 发送美化后的超时提醒到 UserID: {user_id}")
|
||||
|
||||
try:
|
||||
result = await send_reminder_message(user_id)
|
||||
print(f"\n✅ 发送结果: {result}")
|
||||
except Exception as e:
|
||||
print(f"\n❌ 发送失败: {e}")
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(main())
|
||||
@@ -0,0 +1,7 @@
|
||||
cat /tmp/h5-main-part1.bin /tmp/h5-main-part2.bin /tmp/h5-main-part3.bin /tmp/h5-main-part4.bin > /tmp/h5-main-merged.js
|
||||
wc -c < /tmp/h5-main-merged.js
|
||||
cp /opt/wecom-it-desk/frontend-h5/dist/assets/index-CFP5_C6V.js /opt/wecom-it-desk/frontend-h5/dist/assets/index-CFP5_C6V.js.bak
|
||||
cp /tmp/h5-main-merged.js /opt/wecom-it-desk/frontend-h5/dist/assets/index-Ad4OgjKG.js
|
||||
cp /opt/wecom-it-desk/frontend-h5/dist/index.html /opt/wecom-it-desk/frontend-h5/dist/index.html.bak
|
||||
cp /tmp/h5-index-v2.html /opt/wecom-it-desk/frontend-h5/dist/index.html
|
||||
ls -la /opt/wecom-it-desk/frontend-h5/dist/assets/index-Ad4OgjKG.js /opt/wecom-it-desk/frontend-h5/dist/index.html
|
||||
@@ -0,0 +1,8 @@
|
||||
cat /tmp/h5-full-part1.bin /tmp/h5-full-part2.bin > /tmp/h5-full.tar.gz
|
||||
wc -c < /tmp/h5-full.tar.gz
|
||||
cd /opt/wecom-it-desk/frontend-h5/dist && tar xzf /tmp/h5-full.tar.gz
|
||||
ls -la /opt/wecom-it-desk/frontend-h5/dist/assets/index-CgWukqlD.css
|
||||
ls -la /opt/wecom-it-desk/frontend-h5/dist/assets/index-Cfeo0axm.js
|
||||
ls -la /opt/wecom-it-desk/frontend-h5/dist/index.html
|
||||
grep -o 'index-[A-Za-z0-9_]*\.js' /opt/wecom-it-desk/frontend-h5/dist/index.html
|
||||
grep -o 'index-[A-Za-z0-9_]*\.css' /opt/wecom-it-desk/frontend-h5/dist/index.html
|
||||
@@ -0,0 +1,8 @@
|
||||
cat /tmp/h5-main-v2-part1.bin /tmp/h5-main-v2-part2.bin /tmp/h5-main-v2-part3.bin /tmp/h5-main-v2-part4.bin > /tmp/h5-main-v2-merged.js
|
||||
wc -c < /tmp/h5-main-v2-merged.js
|
||||
cp /opt/wecom-it-desk/frontend-h5/dist/assets/index-Ad4OgjKG.js /opt/wecom-it-desk/frontend-h5/dist/assets/index-Ad4OgjKG.js.bak.$(date +%Y%m%d-%H%M%S)
|
||||
cp /tmp/h5-main-v2-merged.js /opt/wecom-it-desk/frontend-h5/dist/assets/index-Cfeo0axm.js
|
||||
cp /opt/wecom-it-desk/frontend-h5/dist/index.html /opt/wecom-it-desk/frontend-h5/dist/index.html.bak.$(date +%Y%m%d-%H%M%S)
|
||||
cp /tmp/h5-index-v3.html /opt/wecom-it-desk/frontend-h5/dist/index.html
|
||||
ls -la /opt/wecom-it-desk/frontend-h5/dist/assets/index-Cfeo0axm.js /opt/wecom-it-desk/frontend-h5/dist/index.html
|
||||
grep -o 'index-[A-Za-z0-9_]*\.js' /opt/wecom-it-desk/frontend-h5/dist/index.html
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1 @@
|
||||
t(EE,[["__scopeId","data-v-f91237e0"]]);function xE(){return typeof navigator>"u"?!1:/wxwork/i.test(navigator.userAgent)}const CE=[{path:"/",name:"ChatView",component:aE,meta:{title:"IT智能服务台",requiresAuth:!0}},{path:"/login",name:"Login",component:()=>Hn(()=>import("./Login-B-38pybU.js"),__vite__mapDeps([4,5,6])),meta:{title:"登录",requiresAuth:!1}},{path:"/bind",name:"Bind",component:()=>Hn(()=>import("./Bind-DVCQqFbQ.js"),__vite__mapDeps([7,5,1,2,8,9])),meta:{title:"账号绑定",requiresAuth:!1}},{path:"/wework-only",name:"WeworkOnly",component:()=>Hn(()=>import("./WeworkOnly-t2Ct8LGE.js"),__vite__mapDeps([10,11])),meta:{title:"请在企业微信中打开",requiresAuth:!1}},{path:"/emergency",name:"EmergencyDispatcher",component:hE,meta:{title:"应急身份检测",requiresAuth:!1}},{path:"/h5-preview",name:"H5Preview",component:SE,meta:{title:"员工自助",requiresAuth:!1}},{path:"/automation/:id",name:"AutomationProgress",component:()=>Hn(()=>import("./AutomationProgress-BpfwCyBW.js"),__vite__mapDeps([12,3,1,13,9])),meta:{title:"自动化处置",requiresAuth:!0}},{path:"/:pathMatch(.*)*",redirect:"/"}],jf=X_({history:T_("/h5/"),routes:CE});jf.beforeEach(async(e,t,n)=>{if(e.name==="WeworkOnly"||e.name==="Login"||e.name==="Bind"||e.name==="EmergencyDispatcher"||e.name==="H5Preview"){n();return}const s=new URLSearchParams(window.location.search),o=e.query.token||s.get("token");if(o){localStorage.setItem("h5_token",o),s.delete("token");const c=s.toString(),u=c?`${window.location.pathname}?${c}`:window.location.pathname;window.history.replaceState({},"",u)}const{useEmployeeStore:r}=await Hn(async()=>{const{useEmployeeStore:c}=await Promise.resolve().then(()=>aw);return{useEmployeeStore:c}},void 0),i=r();if(o){i.$patch({token:o});try{await i.fetchEmployeeInfo()}catch(c){console.warn("[Router] Portal token 验证失败:",c)}}if(!(/^localhost(:\d+)?$/.test(window.location.hostname)||window.location.hostname==="127.0.0.1")&&!xE()){if(i.isAuthenticated){n();return}n({name:"Login"});return}const a=e.query.code||new URLSearchParams(window.location.search).get("code");if(a){try{await i.handleOAuthCallback(a);const c=new URLSearchParams(window.location.search);c.delete("code"),c.delete("state");const u=c.toString(),f=u?`${window.location.pathname}?${u}`:window.location.pathname;window.history.replaceState({},"",f),n()}catch(c){console.error("[Router] OAuth2 授权失败:",c),i.redirectToOAuth()}return}if(i.isAuthenticated){n();return}i.redirectToOAuth()});const zi=hu(Ug);zi.use(Fg());zi.use(jf);const AE=Date.now(),ja=500;zi.mount("#app");const Ua=Date.now()-AE;Ua>=ja?document.body.classList.add("app-loaded"):setTimeout(()=>{document.body.classList.add("app-loaded")},ja-Ua);export{mt as $,sm as A,am as B,Gm as C,Rg as D,vg as E,Fi as F,$e as G,B as H,Rt as I,M as J,Op as K,Go as L,Se as M,yt as N,Mm as O,Ws as P,A as Q,Ig as R,Re as S,Lt as T,Wl as U,kE as V,ut as W,ft as X,ff as Y,It as Z,Et as _,ql as a,Fn as a0,p as a1,dt as a2,Xe as a3,fe as a4,ie as a5,K as a6,df as a7,Bt as a8,bt as a9,Co as aa,Oe as ab,Xh as ac,De as ad,em as ae,TE as af,Dh as ag,Sh as ah,yu as ai,wu as aj,zs as ak,oe as al,Ko as am,Yh as an,On as ao,sn as ap,Ie as aq,kh as ar,Ke as as,RE as at,lt as au,_u as av,Ii as aw,Bi as ax,de as ay,Ft as az,Ns as b,hg as c,Hh as d,Om as e,tm as f,im as g,Am as h,Wm as i,dm as j,wg as k,gg as l,ng as m,vm as n,Sm as o,Nm as p,Vm as q,Og as r,ve as s,um as t,Ag as u,Cg as v,pg as w,OE as x,lg as y,cm as z};
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1 @@
|
||||
(),M("div",bE,[...i[6]||(i[6]=[p("p",null,"💡 电脑端访问可获得完整体验(右栏常驻显示)",-1),p("p",null,'移动端请点上方"右栏"按钮打开内容',-1)])])):fe("",!0)])}}}),SE=Et(EE,[["__scopeId","data-v-f91237e0"]]);function xE(){return typeof navigator>"u"?!1:/wxwork/i.test(navigator.userAgent)}const CE=[{path:"/",name:"ChatView",component:aE,meta:{title:"IT智能服务台",requiresAuth:!0}},{path:"/login",name:"Login",component:()=>qn(()=>import("./Login-B4ja_KpA.js"),__vite__mapDeps([4,5,6])),meta:{title:"登录",requiresAuth:!1}},{path:"/bind",name:"Bind",component:()=>qn(()=>import("./Bind-CR1wzN0t.js"),__vite__mapDeps([7,5,1,2,8,9])),meta:{title:"账号绑定",requiresAuth:!1}},{path:"/wework-only",name:"WeworkOnly",component:()=>qn(()=>import("./WeworkOnly-CSgFNSQF.js"),__vite__mapDeps([10,11])),meta:{title:"请在企业微信中打开",requiresAuth:!1}},{path:"/emergency",name:"EmergencyDispatcher",component:hE,meta:{title:"应急身份检测",requiresAuth:!1}},{path:"/h5-preview",name:"H5Preview",component:SE,meta:{title:"员工自助",requiresAuth:!1}},{path:"/automation/:id",name:"AutomationProgress",component:()=>qn(()=>import("./AutomationProgress-CGiOnei3.js"),__vite__mapDeps([12,3,1,13,9])),meta:{title:"自动化处置",requiresAuth:!0}},{path:"/:pathMatch(.*)*",redirect:"/"}],jf=X_({history:T_("/h5/"),routes:CE});jf.beforeEach(async(e,t,n)=>{if(e.name==="WeworkOnly"||e.name==="Login"||e.name==="Bind"||e.name==="EmergencyDispatcher"||e.name==="H5Preview"){n();return}const s=new URLSearchParams(window.location.search),o=e.query.token||s.get("token");if(o){localStorage.setItem("h5_token",o),s.delete("token");const c=s.toString(),u=c?`${window.location.pathname}?${c}`:window.location.pathname;window.history.replaceState({},"",u)}const{useEmployeeStore:r}=await qn(async()=>{const{useEmployeeStore:c}=await Promise.resolve().then(()=>aw);return{useEmployeeStore:c}},void 0),i=r();if(o){i.$patch({token:o});try{await i.fetchEmployeeInfo()}catch(c){console.warn("[Router] Portal token 验证失败:",c)}}if(!(/^localhost(:\d+)?$/.test(window.location.hostname)||window.location.hostname==="127.0.0.1")&&!xE()){if(i.isAuthenticated){n();return}n({name:"Login"});return}const a=e.query.code||new URLSearchParams(window.location.search).get("code");if(a){try{await i.handleOAuthCallback(a);const c=new URLSearchParams(window.location.search);c.delete("code"),c.delete("state");const u=c.toString(),f=u?`${window.location.pathname}?${u}`:window.location.pathname;window.history.replaceState({},"",f),n()}catch(c){console.error("[Router] OAuth2 授权失败:",c),i.redirectToOAuth()}return}if(i.isAuthenticated){n();return}i.redirectToOAuth()});const zi=hu(Ug);zi.use(Fg());zi.use(jf);const AE=Date.now(),ja=500;zi.mount("#app");const Ua=Date.now()-AE;Ua>=ja?document.body.classList.add("app-loaded"):setTimeout(()=>{document.body.classList.add("app-loaded")},ja-Ua);export{mt as $,sm as A,am as B,Gm as C,Rg as D,vg as E,Fi as F,$e as G,B as H,Rt as I,M as J,Op as K,Go as L,Se as M,yt as N,Mm as O,Ks as P,A as Q,Ig as R,Re as S,Lt as T,Wl as U,kE as V,ut as W,ft as X,ff as Y,It as Z,Et as _,ql as a,Bn as a0,p as a1,dt as a2,Xe as a3,fe as a4,ie as a5,K as a6,df as a7,Bt as a8,bt as a9,Co as aa,Oe as ab,Xh as ac,De as ad,em as ae,TE as af,Dh as ag,Sh as ah,yu as ai,wu as aj,Ws as ak,oe as al,Ko as am,Yh as an,Pn as ao,sn as ap,Ie as aq,kh as ar,Ke as as,RE as at,lt as au,_u as av,Ii as aw,Bi as ax,de as ay,Ft as az,Ls as b,hg as c,Hh as d,Om as e,tm as f,im as g,Am as h,Wm as i,dm as j,wg as k,gg as l,ng as m,vm as n,Sm as o,Nm as p,Vm as q,Og as r,ve as s,um as t,Ag as u,Cg as v,pg as w,OE as x,lg as y,cm as z};
|
||||
@@ -0,0 +1,3 @@
|
||||
curl -s -o /dev/null -w "%{http_code}" https://itsupport.servyou.com.cn/h5/
|
||||
grep -o "index-[A-Za-z0-9_]*\.js" /opt/wecom-it-desk/frontend-h5/dist/index.html
|
||||
curl -s -o /dev/null -w "%{http_code}" https://itsupport.servyou.com.cn/h5/assets/index-Ad4OgjKG.js
|
||||
@@ -0,0 +1,12 @@
|
||||
curl -s -o /dev/null -w '%{http_code}' http://localhost/h5/
|
||||
echo
|
||||
curl -s -o /dev/null -w '%{http_code}' http://localhost/h5/assets/index-Cfeo0axm.js
|
||||
echo
|
||||
curl -sI http://localhost/h5/assets/index-Cfeo0axm.js | grep -i content-length
|
||||
curl -s -o /dev/null -w '%{http_code}' http://localhost/h5/assets/index-CgWukqlD.css
|
||||
echo
|
||||
curl -sI http://localhost/h5/assets/index-CgWukqlD.css | grep -i content-length
|
||||
curl -s -o /dev/null -w '%{http_code}' http://localhost/h5/assets/Login-B4ja_KpA.js
|
||||
echo
|
||||
curl -s -o /dev/null -w '%{http_code}' http://localhost/h5/assets/auth-Bb_rTrmj.js
|
||||
echo
|
||||
Reference in New Issue
Block a user