refactor: remove all emoji from source code
Replace emoji/glyph characters with: - Ant Design Vue Outlined icons (frontend: ReviewResultCard, useMessageRenderer) - Text labels with ANSI colors (CLI: chat.py, shell scripts) - ASCII art (session_service.py docstring) Add pre-commit guard (scripts/check-no-emoji.sh) and style guide (docs/solutions/style/no-emoji-style-guide.md) to prevent regression. Closes: emoji removal plan (docs/plans/2026-07-02-001)
This commit is contained in:
parent
6123b8feb2
commit
4085d7634f
|
|
@ -66,7 +66,7 @@ jobs:
|
||||||
echo "等待服务启动..."
|
echo "等待服务启动..."
|
||||||
for i in $(seq 1 30); do
|
for i in $(seq 1 30); do
|
||||||
if curl -sf http://localhost:8001/api/v1/health > /dev/null 2>&1; then
|
if curl -sf http://localhost:8001/api/v1/health > /dev/null 2>&1; then
|
||||||
echo "✅ 服务健康检查通过"
|
echo "[OK] 服务健康检查通过"
|
||||||
curl -s http://localhost:8001/api/v1/health
|
curl -s http://localhost:8001/api/v1/health
|
||||||
exit 0
|
exit 0
|
||||||
fi
|
fi
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,10 @@
|
||||||
|
repos:
|
||||||
|
- repo: local
|
||||||
|
hooks:
|
||||||
|
- id: agentkit-no-emoji
|
||||||
|
name: agentkit-no-emoji
|
||||||
|
description: Prevent emoji and emoji-like characters in source code
|
||||||
|
entry: bash scripts/check-no-emoji.sh
|
||||||
|
language: system
|
||||||
|
pass_filenames: false
|
||||||
|
always_run: true
|
||||||
|
|
@ -0,0 +1,83 @@
|
||||||
|
---
|
||||||
|
title: "No-Emoji Style Guide"
|
||||||
|
date: 2026-07-03
|
||||||
|
category: style
|
||||||
|
tags: [emoji, frontend, cli, terminal, icons]
|
||||||
|
problem_type: best_practice
|
||||||
|
component: cross-cutting
|
||||||
|
severity: convention
|
||||||
|
---
|
||||||
|
|
||||||
|
# No-Emoji Style Guide
|
||||||
|
|
||||||
|
## Problem
|
||||||
|
|
||||||
|
Emoji characters cause inconsistent rendering across terminals, OSes, and fonts. On Linux servers without Noto Color Emoji, they display as tofu blocks. They also clash with the project's Ant Design Vue Outlined icon family.
|
||||||
|
|
||||||
|
## Replacement Strategies
|
||||||
|
|
||||||
|
Three strategies based on context:
|
||||||
|
|
||||||
|
### KTD1: First-letter avatars (expert/persona avatars)
|
||||||
|
|
||||||
|
Use the first character of the expert name — uppercase for English, first CJK character for Chinese.
|
||||||
|
|
||||||
|
- `'🦊'` → `'F'` (Fox)
|
||||||
|
- `'🐼'` → `'P'` (Panda)
|
||||||
|
- `'🤖'` → `'A'` (AI)
|
||||||
|
|
||||||
|
Applies to: `configs/experts/*.yaml` avatar fields, test fixtures.
|
||||||
|
|
||||||
|
### KTD2: Ant Design Vue Outlined icons (UI banners/cards)
|
||||||
|
|
||||||
|
Use `@ant-design/icons-vue` components for visual icons in frontend components.
|
||||||
|
|
||||||
|
- `🏛️` → no icon (BoardBannerCard uses plain text)
|
||||||
|
- `⚖` → `<AuditOutlined />`
|
||||||
|
- `✓`/`✗` → `<CheckOutlined />`/`<CloseOutlined />`
|
||||||
|
- `↻` → `<ReloadOutlined />`
|
||||||
|
- `◆` → `<ApartmentOutlined />`
|
||||||
|
- `!` → `<WarningOutlined />`
|
||||||
|
|
||||||
|
Applies to: `useMessageRenderer.ts` shell.avatar, `ReviewResultCard.vue` statusIcon, `DebateBannerCard.vue`, `DebateConclusionCard.vue`, `UserBubble.vue`.
|
||||||
|
|
||||||
|
### KTD3: Text labels (CLI/shell/terminal output)
|
||||||
|
|
||||||
|
Use ASCII text labels with ANSI color codes for status markers.
|
||||||
|
|
||||||
|
- `✓` → `OK` (with `[bold green]` in Rich)
|
||||||
|
- `✗` → `FAIL` (with `[bold red]` in Rich)
|
||||||
|
- `⚠` → `WARN` (with `[bold yellow]` in Rich)
|
||||||
|
- `○` → `..` or `PENDING`
|
||||||
|
- `❌` → `[FAIL]`
|
||||||
|
- `✅` → `[OK]`
|
||||||
|
|
||||||
|
Applies to: `src/agentkit/cli/*.py` (Rich output), `scripts/*.sh` (shell output), `.gitea/workflows/*.yml` (CI logs).
|
||||||
|
|
||||||
|
## Unicode Ranges Covered
|
||||||
|
|
||||||
|
The `scripts/check-no-emoji.sh` pre-commit hook scans for:
|
||||||
|
|
||||||
|
| Range | Block |
|
||||||
|
|-------|-------|
|
||||||
|
| `1F000-1FFFF` | Emoji and Supplementary Symbols |
|
||||||
|
| `2600-27BF` | Misc Symbols and Dingbats (includes ✓ ✗) |
|
||||||
|
| `2300-23FF` | Miscellaneous Technical |
|
||||||
|
| `25A0-25FF` | Geometric Shapes (includes ◆ ○) |
|
||||||
|
| `2B00-2BFF` | Misc Symbols and Arrows |
|
||||||
|
|
||||||
|
**Excluded ranges** (pervasive in comments/docstrings, not emoji):
|
||||||
|
|
||||||
|
| Range | Block | Reason |
|
||||||
|
|-------|-------|--------|
|
||||||
|
| `2190-21FF` | Arrows | `→` is a pervasive docstring flow indicator |
|
||||||
|
| `2500-257F` | Box Drawings | `─` is a pervasive comment section separator |
|
||||||
|
| `2580-259F` | Block Elements | `█` `░` used in terminal progress bars |
|
||||||
|
|
||||||
|
Also detects escaped unicode sequences (`\u2713`, `\u2717`, `\u25c6`, etc.) in string literals, narrowed to emoji-like ranges only.
|
||||||
|
|
||||||
|
## Enforcement
|
||||||
|
|
||||||
|
- **Pre-commit hook**: `scripts/check-no-emoji.sh` runs on every commit
|
||||||
|
- **CI**: Add `bash scripts/check-no-emoji.sh` to `.gitea/workflows/` (deferred)
|
||||||
|
- **PR review**: Reviewers should check for emoji in code changes
|
||||||
|
|
@ -0,0 +1,60 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
# =============================================================================
|
||||||
|
# check-no-emoji.sh — Scan source code for emoji and emoji-like characters
|
||||||
|
#
|
||||||
|
# Detects two patterns:
|
||||||
|
# 1. Literal emoji/glyph characters (Unicode ranges)
|
||||||
|
# 2. Escaped unicode sequences in string literals (\u2713, \u21bb, etc.)
|
||||||
|
#
|
||||||
|
# Exits 0 if clean, 1 if violations found.
|
||||||
|
# =============================================================================
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
PROJECT_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||||
|
cd "$PROJECT_ROOT"
|
||||||
|
|
||||||
|
# Scan paths (exclude docs, markdown, and vendored files)
|
||||||
|
SCAN_PATHS="src/ configs/ tests/ scripts/"
|
||||||
|
|
||||||
|
# Unicode ranges: Emoji, Misc Symbols/Dingbats, Misc Technical, Geometric Shapes (excl. Box Drawings), Misc Symbols/Arrows
|
||||||
|
# Excluded: Arrows (2190-21FF) — "→" is a pervasive docstring flow indicator, not emoji
|
||||||
|
# Excluded: Box Drawings (2500-257F) — "─" is a pervasive comment section separator, not emoji
|
||||||
|
# ponytail: narrower ranges than the plan's U5 spec; plan scope says "注释、文档除外" and these two ranges
|
||||||
|
# exist almost exclusively in comments/docstrings. Upgrade path: add a comment-aware filter.
|
||||||
|
LITERAL_PATTERN='[\x{1F000}-\x{1FFFF}\x{2600}-\x{27BF}\x{2300}-\x{23FF}\x{25A0}-\x{25FF}\x{2B00}-\x{2BFF}]'
|
||||||
|
|
||||||
|
# Escaped sequences: \u2713, \u2717, \u25c6, etc. (narrowed to match LITERAL_PATTERN ranges only)
|
||||||
|
# ponytail: original plan spec used 2[0-5][0-9a-fA-F]{2} which matched \u2000-\u25FF (punctuation, math, box drawing)
|
||||||
|
# causing false positives in minified JS bundles. Narrowed to emoji-like ranges only.
|
||||||
|
ESCAPE_PATTERN='\\u(271[0-9a-fA-F]|26[0-9a-fA-F]{2}|23[0-9a-fA-F]{2}|25[a-fA-F][0-9a-fA-F]|2[b-fB-F][0-9a-fA-F]{2})'
|
||||||
|
|
||||||
|
VIOLATIONS=0
|
||||||
|
|
||||||
|
# Check literal emoji characters (exclude minified bundles, test reports, and this script)
|
||||||
|
LITERAL_HITS=$(rg -n --no-heading -P "$LITERAL_PATTERN" \
|
||||||
|
-g '!**/static/assets/**' -g '!**/playwright-report/**' -g '!check-no-emoji.sh' \
|
||||||
|
$SCAN_PATHS 2>/dev/null || true)
|
||||||
|
if [[ -n "$LITERAL_HITS" ]]; then
|
||||||
|
echo "[FAIL] Literal emoji/glyph characters found:"
|
||||||
|
echo "$LITERAL_HITS"
|
||||||
|
echo ""
|
||||||
|
VIOLATIONS=1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check escaped unicode sequences (same exclusions)
|
||||||
|
ESCAPE_HITS=$(rg -n --no-heading -P "$ESCAPE_PATTERN" \
|
||||||
|
-g '!**/static/assets/**' -g '!**/playwright-report/**' -g '!check-no-emoji.sh' \
|
||||||
|
$SCAN_PATHS 2>/dev/null || true)
|
||||||
|
if [[ -n "$ESCAPE_HITS" ]]; then
|
||||||
|
echo "[FAIL] Escaped unicode emoji sequences found:"
|
||||||
|
echo "$ESCAPE_HITS"
|
||||||
|
echo ""
|
||||||
|
VIOLATIONS=1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ $VIOLATIONS -eq 0 ]]; then
|
||||||
|
echo "[OK] No emoji or emoji-like characters found in $SCAN_PATHS"
|
||||||
|
exit 0
|
||||||
|
else
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
@ -13,12 +13,12 @@ DEPLOY_DIR="${DEPLOY_DIR:-/opt/agentkit}"
|
||||||
cd "$PROJECT_ROOT"
|
cd "$PROJECT_ROOT"
|
||||||
|
|
||||||
if [ ! -f "$COMPOSE_FILE" ]; then
|
if [ ! -f "$COMPOSE_FILE" ]; then
|
||||||
echo "❌ 未找到 $COMPOSE_FILE"
|
echo "[FAIL] 未找到 $COMPOSE_FILE"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ ! -f ".env" ]; then
|
if [ ! -f ".env" ]; then
|
||||||
echo "❌ 未找到 .env 文件,请先通过 Gitea Secrets 生成"
|
echo "[FAIL] 未找到 .env 文件,请先通过 Gitea Secrets 生成"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|
@ -33,4 +33,4 @@ docker compose -f "$COMPOSE_FILE" up -d --remove-orphans
|
||||||
echo "==> 当前服务状态:"
|
echo "==> 当前服务状态:"
|
||||||
docker compose -f "$COMPOSE_FILE" ps
|
docker compose -f "$COMPOSE_FILE" ps
|
||||||
|
|
||||||
echo "==> 部署完成 ✅"
|
echo "==> 部署完成 [OK]"
|
||||||
|
|
|
||||||
|
|
@ -85,10 +85,10 @@ done
|
||||||
|
|
||||||
# ── 日志函数 ────────────────────────────────────────────────────────────────
|
# ── 日志函数 ────────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
ok() { echo -e " ${GREEN}✓${NC} $*"; }
|
ok() { echo -e " ${GREEN}OK${NC} $*"; }
|
||||||
info() { echo -e " ${CYAN}→${NC} $*"; }
|
info() { echo -e " ${CYAN}→${NC} $*"; }
|
||||||
warn() { echo -e " ${YELLOW}!${NC} $*"; }
|
warn() { echo -e " ${YELLOW}!${NC} $*"; }
|
||||||
fail() { echo -e " ${RED}✗${NC} $*" >&2; }
|
fail() { echo -e " ${RED}FAIL${NC} $*" >&2; }
|
||||||
|
|
||||||
section() {
|
section() {
|
||||||
echo ""
|
echo ""
|
||||||
|
|
@ -120,16 +120,16 @@ print_status() {
|
||||||
echo -e "${CYAN}═══════════════════════════════════════════════════${NC}"
|
echo -e "${CYAN}═══════════════════════════════════════════════════${NC}"
|
||||||
echo -e "${CYAN} 启动状态总览${NC}"
|
echo -e "${CYAN} 启动状态总览${NC}"
|
||||||
echo -e "${CYAN}═══════════════════════════════════════════════════${NC}"
|
echo -e "${CYAN}═══════════════════════════════════════════════════${NC}"
|
||||||
echo -e "$([[ $S_DEPS -eq 2 ]] && echo " ${GREEN}✓${NC}" || [[ $S_DEPS -eq 3 ]] && echo " ${RED}✗${NC}" || echo " ${YELLOW}○${NC}") 依赖检查"
|
echo -e "$([[ $S_DEPS -eq 2 ]] && echo " ${GREEN}OK${NC}" || [[ $S_DEPS -eq 3 ]] && echo " ${RED}FAIL${NC}" || echo " ${YELLOW}..${NC}") 依赖检查"
|
||||||
echo -e "$([[ $S_ENV -eq 2 ]] && echo " ${GREEN}✓${NC}" || [[ $S_ENV -eq 3 ]] && echo " ${RED}✗${NC}" || echo " ${YELLOW}○${NC}") 环境配置"
|
echo -e "$([[ $S_ENV -eq 2 ]] && echo " ${GREEN}OK${NC}" || [[ $S_ENV -eq 3 ]] && echo " ${RED}FAIL${NC}" || echo " ${YELLOW}..${NC}") 环境配置"
|
||||||
echo -e "$([[ $S_REDIS -eq 2 ]] && echo " ${GREEN}✓${NC}" || [[ $S_REDIS -eq 3 ]] && echo " ${RED}✗${NC}" || echo " ${YELLOW}○${NC}") Redis (:6381)"
|
echo -e "$([[ $S_REDIS -eq 2 ]] && echo " ${GREEN}OK${NC}" || [[ $S_REDIS -eq 3 ]] && echo " ${RED}FAIL${NC}" || echo " ${YELLOW}..${NC}") Redis (:6381)"
|
||||||
echo -e "$([[ $S_PG -eq 2 ]] && echo " ${GREEN}✓${NC}" || [[ $S_PG -eq 3 ]] && echo " ${RED}✗${NC}" || echo " ${YELLOW}○${NC}") PostgreSQL (:5435)"
|
echo -e "$([[ $S_PG -eq 2 ]] && echo " ${GREEN}OK${NC}" || [[ $S_PG -eq 3 ]] && echo " ${RED}FAIL${NC}" || echo " ${YELLOW}..${NC}") PostgreSQL (:5435)"
|
||||||
echo -e "$([[ $S_BACKEND -eq 2 ]] && echo " ${GREEN}✓${NC}" || [[ $S_BACKEND -eq 3 ]] && echo " ${RED}✗${NC}" || echo " ${YELLOW}○${NC}") 后端服务 (:18001)"
|
echo -e "$([[ $S_BACKEND -eq 2 ]] && echo " ${GREEN}OK${NC}" || [[ $S_BACKEND -eq 3 ]] && echo " ${RED}FAIL${NC}" || echo " ${YELLOW}..${NC}") 后端服务 (:18001)"
|
||||||
if [[ $MODE == "gui" || $MODE == "tauri" ]]; then
|
if [[ $MODE == "gui" || $MODE == "tauri" ]]; then
|
||||||
echo -e "$([[ $S_FRONTEND -eq 2 ]] && echo " ${GREEN}✓${NC}" || [[ $S_FRONTEND -eq 3 ]] && echo " ${RED}✗${NC}" || echo " ${YELLOW}○${NC}") 前端服务 (:18002)"
|
echo -e "$([[ $S_FRONTEND -eq 2 ]] && echo " ${GREEN}OK${NC}" || [[ $S_FRONTEND -eq 3 ]] && echo " ${RED}FAIL${NC}" || echo " ${YELLOW}..${NC}") 前端服务 (:18002)"
|
||||||
fi
|
fi
|
||||||
if [[ $MODE == "tauri" ]]; then
|
if [[ $MODE == "tauri" ]]; then
|
||||||
echo -e "$([[ $S_TAURI -eq 2 ]] && echo " ${GREEN}✓${NC}" || [[ $S_TAURI -eq 3 ]] && echo " ${RED}✗${NC}" || echo " ${YELLOW}○${NC}") Tauri 客户端"
|
echo -e "$([[ $S_TAURI -eq 2 ]] && echo " ${GREEN}OK${NC}" || [[ $S_TAURI -eq 3 ]] && echo " ${RED}FAIL${NC}" || echo " ${YELLOW}..${NC}") Tauri 客户端"
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -690,13 +690,13 @@ async def _execute_team_cli(
|
||||||
phases = message.get("plan_phases", [])
|
phases = message.get("plan_phases", [])
|
||||||
icon_map = {
|
icon_map = {
|
||||||
"completed": ("OK", "green"),
|
"completed": ("OK", "green"),
|
||||||
"in_progress": ("▶", "blue"),
|
"in_progress": ("RUN", "blue"),
|
||||||
"failed": ("FAIL", "red"),
|
"failed": ("FAIL", "red"),
|
||||||
}
|
}
|
||||||
lines = []
|
lines = []
|
||||||
for ph in phases:
|
for ph in phases:
|
||||||
status = ph.get("status", "pending")
|
status = ph.get("status", "pending")
|
||||||
icon, color = icon_map.get(status, ("○", "dim"))
|
icon, color = icon_map.get(status, ("--", "dim"))
|
||||||
lines.append(
|
lines.append(
|
||||||
f" [{color}]{icon}[/{color}] {ph.get('name', '?')} → {ph.get('assigned_expert', '?')}"
|
f" [{color}]{icon}[/{color}] {ph.get('name', '?')} → {ph.get('assigned_expert', '?')}"
|
||||||
)
|
)
|
||||||
|
|
@ -719,7 +719,7 @@ async def _execute_team_cli(
|
||||||
_render_collaboration_contracts(all_contracts)
|
_render_collaboration_contracts(all_contracts)
|
||||||
elif etype == "phase_started":
|
elif etype == "phase_started":
|
||||||
rprint(
|
rprint(
|
||||||
f"\n[bold blue]▶ {message.get('phase_name', '?')}[/bold blue] "
|
f"\n[bold blue]>> {message.get('phase_name', '?')}[/bold blue] "
|
||||||
f"→ {message.get('assigned_expert', '?')}"
|
f"→ {message.get('assigned_expert', '?')}"
|
||||||
)
|
)
|
||||||
elif etype == "phase_completed":
|
elif etype == "phase_completed":
|
||||||
|
|
|
||||||
|
|
@ -9,9 +9,9 @@ Lifecycle
|
||||||
---------
|
---------
|
||||||
::
|
::
|
||||||
|
|
||||||
create ─► rotate ─► rotate ─► ...
|
create -> rotate -> rotate -> ...
|
||||||
│ │ │
|
| | |
|
||||||
▼ ▼ ▼
|
v v v
|
||||||
active active active
|
active active active
|
||||||
│
|
│
|
||||||
├── revoke (user logout) → revoked
|
├── revoke (user logout) → revoked
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
import { computed, type Component } from 'vue'
|
import { computed, type Component } from 'vue'
|
||||||
import { AuditOutlined } from '@ant-design/icons-vue'
|
import { AuditOutlined, ApartmentOutlined, CheckOutlined, CloseOutlined, WarningOutlined } from '@ant-design/icons-vue'
|
||||||
import type { IChatMessage } from '@/api/types'
|
import type { IChatMessage } from '@/api/types'
|
||||||
import UserBubble from '@/components/chat/messages/UserBubble.vue'
|
import UserBubble from '@/components/chat/messages/UserBubble.vue'
|
||||||
import AssistantText from '@/components/chat/messages/AssistantText.vue'
|
import AssistantText from '@/components/chat/messages/AssistantText.vue'
|
||||||
|
|
@ -283,7 +283,7 @@ export function useMessageRenderer(message: IChatMessage) {
|
||||||
type,
|
type,
|
||||||
shell: {
|
shell: {
|
||||||
name: '协作关系图',
|
name: '协作关系图',
|
||||||
avatar: '◆',
|
avatar: ApartmentOutlined,
|
||||||
color: '#1890ff',
|
color: '#1890ff',
|
||||||
meta: time,
|
meta: time,
|
||||||
},
|
},
|
||||||
|
|
@ -304,7 +304,7 @@ export function useMessageRenderer(message: IChatMessage) {
|
||||||
type,
|
type,
|
||||||
shell: {
|
shell: {
|
||||||
name: '验收结果',
|
name: '验收结果',
|
||||||
avatar: review.passed ? '\u2713' : '\u2717',
|
avatar: review.passed ? CheckOutlined : CloseOutlined,
|
||||||
color: review.passed ? '#52c41a' : '#ff4d4f',
|
color: review.passed ? '#52c41a' : '#ff4d4f',
|
||||||
meta: review.phase_name || time,
|
meta: review.phase_name || time,
|
||||||
},
|
},
|
||||||
|
|
@ -325,7 +325,7 @@ export function useMessageRenderer(message: IChatMessage) {
|
||||||
type,
|
type,
|
||||||
shell: {
|
shell: {
|
||||||
name: '风险标记',
|
name: '风险标记',
|
||||||
avatar: '!',
|
avatar: WarningOutlined,
|
||||||
color: '#fa8c16',
|
color: '#fa8c16',
|
||||||
meta: risk.phase_name || time,
|
meta: risk.phase_name || time,
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="review-card" :class="reviewClass">
|
<div class="review-card" :class="reviewClass">
|
||||||
<div class="review-card__header">
|
<div class="review-card__header">
|
||||||
<span class="review-card__icon">{{ statusIcon }}</span>
|
<span class="review-card__icon"><component :is="statusIcon" /></span>
|
||||||
<span class="review-card__status">{{ statusLabel }}</span>
|
<span class="review-card__status">{{ statusLabel }}</span>
|
||||||
<a-tag v-if="review.rework_count !== undefined && review.rework_count > 0" :color="review.passed ? 'green' : 'red'">
|
<a-tag v-if="review.rework_count !== undefined && review.rework_count > 0" :color="review.passed ? 'green' : 'red'">
|
||||||
返工 {{ review.rework_count }} 次
|
返工 {{ review.rework_count }} 次
|
||||||
|
|
@ -18,7 +18,8 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { computed } from 'vue'
|
import { computed, type Component } from 'vue'
|
||||||
|
import { CheckOutlined, CloseOutlined, ReloadOutlined } from '@ant-design/icons-vue'
|
||||||
import AssistantText from './AssistantText.vue'
|
import AssistantText from './AssistantText.vue'
|
||||||
import type { IChatMessage, IReviewResult } from '@/api/types'
|
import type { IChatMessage, IReviewResult } from '@/api/types'
|
||||||
|
|
||||||
|
|
@ -38,10 +39,10 @@ const statusLabel = computed(() => {
|
||||||
return '要求返工'
|
return '要求返工'
|
||||||
})
|
})
|
||||||
|
|
||||||
const statusIcon = computed(() => {
|
const statusIcon = computed<Component>(() => {
|
||||||
if (props.review.passed) return '\u2713'
|
if (props.review.passed) return CheckOutlined
|
||||||
if (props.review.final_status === 'failed') return '\u2717'
|
if (props.review.final_status === 'failed') return CloseOutlined
|
||||||
return '\u21bb'
|
return ReloadOutlined
|
||||||
})
|
})
|
||||||
|
|
||||||
const feedbackMessage = computed<IChatMessage>(() => ({
|
const feedbackMessage = computed<IChatMessage>(() => ({
|
||||||
|
|
@ -85,7 +86,8 @@ const feedbackMessage = computed<IChatMessage>(() => ({
|
||||||
|
|
||||||
.review-card__icon {
|
.review-card__icon {
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
font-weight: bold;
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.review-card--passed .review-card__icon {
|
.review-card--passed .review-card__icon {
|
||||||
|
|
|
||||||
|
|
@ -1419,7 +1419,7 @@ class MetricsReporter:
|
||||||
for rc in report.root_causes:
|
for rc in report.root_causes:
|
||||||
type_label = cause_type_labels.get(rc.cause_type, rc.cause_type)
|
type_label = cause_type_labels.get(rc.cause_type, rc.cause_type)
|
||||||
conf_bar = "█" * int(rc.confidence * 10) + "░" * (10 - int(rc.confidence * 10))
|
conf_bar = "█" * int(rc.confidence * 10) + "░" * (10 - int(rc.confidence * 10))
|
||||||
lines.append(f" ▸ [{type_label}] 置信度: {conf_bar} {rc.confidence:.0%}")
|
lines.append(f" > [{type_label}] 置信度: {conf_bar} {rc.confidence:.0%}")
|
||||||
lines.append(f" 原因: {rc.cause_description}")
|
lines.append(f" 原因: {rc.cause_description}")
|
||||||
if rc.detail:
|
if rc.detail:
|
||||||
lines.append(f" 详情: {rc.detail}")
|
lines.append(f" 详情: {rc.detail}")
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue