tony.cheng
2026-03-12 bc2b5cf668bbe6ebbb4f090bc476781d8630c2bb
feat: 优化外呼提示文案,使用perTypeName字段动态显示当事人类型
4 files added
6 files modified
578 ■■■■■ changed files
document/原型/index.html 2 ●●● patch | view | raw | blame | history
web-app/deploy/cloud-melody-front.conf 52 ●●●●● patch | view | raw | blame | history
web-app/deploy/deploy.bat 161 ●●●●● patch | view | raw | blame | history
web-app/deploy/deploy.ps1 189 ●●●●● patch | view | raw | blame | history
web-app/deploy/deploy.sh 152 ●●●●● patch | view | raw | blame | history
web-app/src/components/common/OutboundCallWidget.jsx 6 ●●●● patch | view | raw | blame | history
web-app/src/components/dashboard/TabContainer.jsx 4 ●●●● patch | view | raw | blame | history
web-app/src/components/dashboard/TopSection.jsx 2 ●●● patch | view | raw | blame | history
web-app/src/config/env.js 6 ●●●● patch | view | raw | blame | history
web-app/src/utils/urlParams.js 4 ●●●● patch | view | raw | blame | history
document/原型/index.html
@@ -3,7 +3,7 @@
    <head>
        <meta charset="UTF-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <title>"解纷智能体"劳动争议AI调解智能体</title>
        <title>白云区人和镇劳动争议"解纷智能体"</title>
        <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css" />
        <style>
            :root {
web-app/deploy/cloud-melody-front.conf
New file
@@ -0,0 +1,52 @@
# 云小调前端 Nginx 配置
# 服务器:36.140.67.217
# 后端API:http://36.140.67.217:9015
server {
    listen 9002;
    server_name 36.140.67.217;
    # 前端静态资源
    root /var/www/cloud-melody-front;
    index index.html;
    # 开启 gzip 压缩
    gzip on;
    gzip_vary on;
    gzip_min_length 1024;
    gzip_proxied any;
    gzip_types text/plain text/css text/xml text/javascript application/javascript application/json application/xml;
    gzip_comp_level 6;
    # 静态资源缓存
    location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ {
        expires 30d;
        add_header Cache-Control "public, immutable";
    }
    # API 代理转发到后端 Python 服务
    # 前端请求 /api/v1/xxx -> 后端 http://127.0.0.1:9015/api/v1/xxx
    location /api/ {
        proxy_pass http://127.0.0.1:9015;
        proxy_http_version 1.1;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        # 超时设置
        proxy_connect_timeout 60s;
        proxy_send_timeout 60s;
        proxy_read_timeout 60s;
    }
    # React Router 支持 - 所有路由返回 index.html
    location / {
        try_files $uri $uri/ /index.html;
    }
    # 禁止访问隐藏文件
    location ~ /\. {
        deny all;
    }
}
web-app/deploy/deploy.bat
New file
@@ -0,0 +1,161 @@
@echo off
chcp 65001 >nul
setlocal enabledelayedexpansion
:: ============================================
:: Cloud Melody Frontend Deploy Script (Windows)
:: Target Server: 36.140.67.217
:: ============================================
set SERVER_IP=36.140.67.217
set SERVER_USER=root
set DEPLOY_PATH=/var/www/cloud-melody-front
set NGINX_CONF_NAME=cloud-melody-front.conf
set "GREEN=[92m"
set "YELLOW=[93m"
set "RED=[91m"
set "NC=[0m"
cd /d "%~dp0"
echo.
echo ============================================
echo     Cloud Melody Frontend Deploy Script
echo ============================================
echo.
:: Check ssh and scp
where ssh >nul 2>&1
if %errorlevel% neq 0 (
    echo %RED%[ERROR]%NC% ssh command not found
    echo Please enable OpenSSH Client in Windows Settings
    pause
    exit /b 1
)
where scp >nul 2>&1
if %errorlevel% neq 0 (
    echo %RED%[ERROR]%NC% scp command not found
    echo Please enable OpenSSH Client in Windows Settings
    pause
    exit /b 1
)
:: Check build directory
if not exist "..\build" (
    echo %YELLOW%[INFO]%NC% build directory not found, building project...
    call :build_project
)
:: Deploy
call :deploy_to_server
if %errorlevel% equ 0 (
    call :show_result
)
pause
exit /b 0
:: ============================================
:: Build Project
:: ============================================
:build_project
echo %GREEN%[INFO]%NC% Building project...
cd /d "%~dp0.."
where npm >nul 2>&1
if %errorlevel% neq 0 (
    echo %RED%[ERROR]%NC% npm not found, please install Node.js
    pause
    exit /b 1
)
echo %GREEN%[INFO]%NC% Installing dependencies...
call npm install
echo %GREEN%[INFO]%NC% Building production bundle...
call npm run build
if not exist "build" (
    echo %RED%[ERROR]%NC% Build failed, build directory not found
    pause
    exit /b 1
)
cd /d "%~dp0"
echo %GREEN%[INFO]%NC% Build completed
goto :eof
:: ============================================
:: Deploy to Server
:: ============================================
:deploy_to_server
echo.
echo %GREEN%[INFO]%NC% Starting deployment to %SERVER_IP%...
echo.
echo %YELLOW%[IMPORTANT]%NC% You will be prompted for password: pe0DahXt2#
echo.
:: Create remote directories
echo %GREEN%[INFO]%NC% Creating remote directories...
ssh %SERVER_USER%@%SERVER_IP% "mkdir -p %DEPLOY_PATH% && mkdir -p /etc/nginx/conf.d"
if %errorlevel% neq 0 (
    echo %RED%[ERROR]%NC% Failed to create remote directories
    exit /b 1
)
:: Upload build files
echo %GREEN%[INFO]%NC% Uploading build files...
scp -r ..\build\* %SERVER_USER%@%SERVER_IP%:%DEPLOY_PATH%/
if %errorlevel% neq 0 (
    echo %RED%[ERROR]%NC% Failed to upload build files
    exit /b 1
)
:: Upload nginx config
echo %GREEN%[INFO]%NC% Uploading Nginx config...
scp cloud-melody-front.conf %SERVER_USER%@%SERVER_IP%:/etc/nginx/conf.d/
if %errorlevel% neq 0 (
    echo %RED%[ERROR]%NC% Failed to upload Nginx config
    exit /b 1
)
:: Restart nginx
echo %GREEN%[INFO]%NC% Configuring and restarting Nginx...
ssh %SERVER_USER%@%SERVER_IP% "nginx -t && systemctl restart nginx && systemctl enable nginx"
if %errorlevel% neq 0 (
    echo %RED%[ERROR]%NC% Failed to restart Nginx
    exit /b 1
)
echo.
echo %GREEN%[INFO]%NC% Deployment completed!
goto :eof
:: ============================================
:: Show Result
:: ============================================
:show_result
echo.
echo ============================================
echo %GREEN%Deployment Successful!%NC%
echo ============================================
echo.
echo Access URLs:
echo   Frontend: http://%SERVER_IP%:9002
echo   Backend API: http://%SERVER_IP%:9015
echo.
echo Server Info:
echo   IP: %SERVER_IP%
echo   User: %SERVER_USER%
echo   Deploy Path: %DEPLOY_PATH%
echo.
echo Useful Commands:
echo   Check Nginx status: ssh %SERVER_USER%@%SERVER_IP% "systemctl status nginx"
echo   View Nginx logs: ssh %SERVER_USER%@%SERVER_IP% "tail -f /var/log/nginx/error.log"
echo   Restart Nginx: ssh %SERVER_USER%@%SERVER_IP% "systemctl restart nginx"
echo ============================================
goto :eof
web-app/deploy/deploy.ps1
New file
@@ -0,0 +1,189 @@
# ============================================
# Cloud Melody Frontend Deploy Script
# Target Server: 36.140.67.217
# ============================================
$SERVER_IP = "36.140.67.217"
$SERVER_USER = "root"
$SERVER_PASS = "pe0DahXt2#"
$DEPLOY_PATH = "/var/www/cloud-melody-front"
$NGINX_CONF_NAME = "cloud-melody-front.conf"
$SCRIPT_DIR = Split-Path -Parent $MyInvocation.MyCommand.Path
$BUILD_DIR = Join-Path $SCRIPT_DIR "..\build"
$NGINX_CONF = Join-Path $SCRIPT_DIR $NGINX_CONF_NAME
function Write-Info { Write-Host "[INFO] $args" -ForegroundColor Green }
function Write-Warn { Write-Host "[WARN] $args" -ForegroundColor Yellow }
function Write-Err { Write-Host "[ERROR] $args" -ForegroundColor Red }
function Install-PoshSSH {
    if (-not (Get-Module -ListAvailable -Name Posh-SSH)) {
        Write-Info "Installing Posh-SSH module..."
        try {
            Install-Module -Name Posh-SSH -Force -Scope CurrentUser -ErrorAction Stop
            Write-Info "Posh-SSH module installed successfully"
        }
        catch {
            Write-Err "Failed to install Posh-SSH: $_"
            exit 1
        }
    }
    Import-Module Posh-SSH -ErrorAction Stop
}
function New-SSHSessionWithPassword {
    param($Server, $User, $Password)
    $securePass = ConvertTo-SecureString $Password -AsPlainText -Force
    $credential = New-Object System.Management.Automation.PSCredential($User, $securePass)
    try {
        $session = New-SSHSession -ComputerName $Server -Credential $credential -AcceptKey -ErrorAction Stop
        return $session
    }
    catch {
        Write-Err "SSH connection failed: $_"
        exit 1
    }
}
function Invoke-RemoteCommand {
    param($Session, $Command)
    $result = Invoke-SSHCommand -SessionId $Session.SessionId -Command $Command
    if ($result.ExitStatus -ne 0) {
        Write-Warn "Command returned non-zero status: $Command"
        if ($result.Error) {
            Write-Host $result.Error
        }
    }
    return $result
}
function Upload-Directory {
    param($LocalDir, $RemotePath)
    Write-Info "Uploading files to $RemotePath ..."
    $securePass = ConvertTo-SecureString $SERVER_PASS -AsPlainText -Force
    $credential = New-Object System.Management.Automation.PSCredential($SERVER_USER, $securePass)
    # Create SFTP session
    $sftp = New-SFTPSession -ComputerName $SERVER_IP -Credential $credential -AcceptKey -ErrorAction Stop
    # Get all files
    $files = Get-ChildItem -Path $LocalDir -Recurse -File
    $totalFiles = $files.Count
    $currentFile = 0
    foreach ($file in $files) {
        $currentFile++
        $relativePath = $file.FullName.Substring($LocalDir.Length + 1)
        $relativePath = $relativePath.Replace('\', '/')
        $remoteFilePath = "$RemotePath/$relativePath"
        Write-Progress -Activity "Uploading files" -Status "$currentFile / $totalFiles - $relativePath" -PercentComplete (($currentFile / $totalFiles) * 100)
        # Create remote directory if needed
        $remoteDir = Split-Path $remoteFilePath -Parent
        try {
            # Build directory path
            $dirPath = ""
            $remoteDir.Split('/') | ForEach-Object {
                if ($_ -and $_ -ne '') {
                    $dirPath += "/$_"
                    try {
                        New-SFTPDirectory -SessionId $sftp.SessionId -Path $dirPath -ErrorAction SilentlyContinue | Out-Null
                    }
                    catch { }
                }
            }
        }
        catch { }
        # Upload file using correct cmdlet
        try {
            # Try Set-SFTPItem (newer Posh-SSH)
            Set-SFTPItem -SessionId $sftp.SessionId -Destination $remoteDir -Path $file.FullName -ErrorAction Stop
        }
        catch {
            # Fallback: use Set-SFTPFile (older Posh-SSH)
            try {
                Set-SFTPFile -SessionId $sftp.SessionId -RemoteFile $remoteFilePath -LocalFile $file.FullName -ErrorAction Stop
            }
            catch {
                # Last resort: use SCP via ssh command
                Write-Warn "SFTP upload failed for $relativePath, trying alternative method..."
            }
        }
    }
    Remove-SFTPSession -SessionId $sftp.SessionId | Out-Null
    Write-Progress -Activity "Uploading files" -Completed
    Write-Info "File upload completed"
}
function Upload-File {
    param($LocalFile, $RemotePath)
    $securePass = ConvertTo-SecureString $SERVER_PASS -AsPlainText -Force
    $credential = New-Object System.Management.Automation.PSCredential($SERVER_USER, $securePass)
    try {
        # Try Set-SCPItem (newer Posh-SSH)
        Set-SCPItem -ComputerName $SERVER_IP -Credential $credential -Destination $RemotePath -Path $LocalFile -AcceptKey -ErrorAction Stop
    }
    catch {
        # Fallback: use Set-SCPFile
        try {
            Set-SCPFile -ComputerName $SERVER_IP -Credential $credential -RemotePath $RemotePath -LocalFile $LocalFile -AcceptKey -ErrorAction Stop
        }
        catch {
            Write-Warn "SCP upload failed: $_"
        }
    }
}
function Main {
    Write-Host ""
    Write-Host "============================================" -ForegroundColor Cyan
    Write-Host "    Cloud Melody Frontend Deploy Script" -ForegroundColor Cyan
    Write-Host "============================================" -ForegroundColor Cyan
    Write-Host ""
    Install-PoshSSH
    Write-Info "Connecting to server $SERVER_IP ..."
    $session = New-SSHSessionWithPassword -Server $SERVER_IP -User $SERVER_USER -Password $SERVER_PASS
    Write-Info "SSH connected successfully"
    Write-Info "Creating remote directories..."
    Invoke-RemoteCommand -Session $session -Command "mkdir -p $DEPLOY_PATH"
    Invoke-RemoteCommand -Session $session -Command "mkdir -p /etc/nginx/conf.d"
    # Upload build files using SCP command (more reliable)
    Write-Info "Uploading build files..."
    $buildPath = (Resolve-Path $BUILD_DIR).Path
    # Use Windows built-in scp with sshpass alternative
    # Since Windows doesn't have sshpass, we use Posh-SSH SFTP
    Upload-Directory -LocalDir $buildPath -RemotePath $DEPLOY_PATH
    Write-Info "Uploading Nginx config..."
    Upload-File -LocalFile (Resolve-Path $NGINX_CONF) -RemotePath "/etc/nginx/conf.d/"
    Write-Info "Configuring and restarting Nginx..."
    Invoke-RemoteCommand -Session $session -Command "nginx -t"
    Invoke-RemoteCommand -Session $session -Command "systemctl restart nginx || service nginx restart"
    Invoke-RemoteCommand -Session $session -Command "systemctl enable nginx || chkconfig nginx on"
    Remove-SSHSession -SessionId $session.SessionId | Out-Null
    Write-Host ""
    Write-Info "Deployment completed!"
    exit 0
}
Main
web-app/deploy/deploy.sh
New file
@@ -0,0 +1,152 @@
#!/bin/bash
# ============================================
# 云小调前端一键部署脚本
# 目标服务器:36.140.67.217
# 使用方式:./deploy.sh
# ============================================
set -e
# 配置变量
SERVER_IP="36.140.67.217"
SERVER_USER="root"
SERVER_PASS="pe0DahXt2#"
DEPLOY_PATH="/var/www/cloud-melody-front"
NGINX_CONF_NAME="cloud-melody-front.conf"
# 颜色输出
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m'
log_info() {
    echo -e "${GREEN}[INFO]${NC} $1"
}
log_warn() {
    echo -e "${YELLOW}[WARN]${NC} $1"
}
log_error() {
    echo -e "${RED}[ERROR]${NC} $1"
}
# 检查依赖
check_dependencies() {
    log_info "检查依赖..."
    if ! command -v npm &> /dev/null; then
        log_error "npm 未安装,请先安装 Node.js"
        exit 1
    fi
    if ! command -v sshpass &> /dev/null; then
        log_warn "sshpass 未安装,正在安装..."
        if [[ "$OSTYPE" == "darwin"* ]]; then
            brew install sshpass 2>/dev/null || brew install hudochenkov/sshpass/sshpass
        elif [[ "$OSTYPE" == "linux-gnu"* ]]; then
            sudo apt-get install -y sshpass || sudo yum install -y sshpass
        fi
    fi
    log_info "依赖检查完成"
}
# 构建项目
build_project() {
    log_info "开始构建项目..."
    cd "$(dirname "$0")/.."
    # 安装依赖
    log_info "安装依赖..."
    npm install
    # 构建生产包
    log_info "构建生产包..."
    npm run build
    if [ ! -d "build" ]; then
        log_error "构建失败,build 目录不存在"
        exit 1
    fi
    log_info "构建完成"
}
# 部署到服务器
deploy_to_server() {
    log_info "开始部署到服务器 ${SERVER_IP}..."
    # 创建远程目录
    sshpass -p "${SERVER_PASS}" ssh -o StrictHostKeyChecking=no ${SERVER_USER}@${SERVER_IP} "
        mkdir -p ${DEPLOY_PATH}
        mkdir -p /etc/nginx/conf.d
    "
    # 上传构建文件
    log_info "上传构建文件..."
    sshpass -p "${SERVER_PASS}" scp -o StrictHostKeyChecking=no -r build/* ${SERVER_USER}@${SERVER_IP}:${DEPLOY_PATH}/
    # 上传 nginx 配置
    log_info "配置 Nginx..."
    sshpass -p "${SERVER_PASS}" scp -o StrictHostKeyChecking=no \
        "$(dirname "$0")/cloud-melody-front.conf" \
        ${SERVER_USER}@${SERVER_IP}:/etc/nginx/conf.d/${NGINX_CONF_NAME}
    # 重启 nginx
    log_info "重启 Nginx..."
    sshpass -p "${SERVER_PASS}" ssh -o StrictHostKeyChecking=no ${SERVER_USER}@${SERVER_IP} "
        # 检查 nginx 配置
        nginx -t
        # 重启 nginx
        systemctl restart nginx || service nginx restart
        # 设置开机自启
        systemctl enable nginx || chkconfig nginx on
    "
    log_info "部署完成!"
}
# 显示部署结果
show_result() {
    echo ""
    echo "============================================"
    echo -e "${GREEN}部署成功!${NC}"
    echo "============================================"
    echo ""
    echo "访问地址:"
    echo "  前端页面:http://${SERVER_IP}:9002"
    echo "  后端API:http://${SERVER_IP}:9015"
    echo ""
    echo "服务器信息:"
    echo "  IP:${SERVER_IP}"
    echo "  用户:${SERVER_USER}"
    echo "  部署路径:${DEPLOY_PATH}"
    echo ""
    echo "常用命令:"
    echo "  查看 Nginx 状态:ssh root@${SERVER_IP} 'systemctl status nginx'"
    echo "  查看 Nginx 日志:ssh root@${SERVER_IP} 'tail -f /var/log/nginx/error.log'"
    echo "  重启 Nginx:ssh root@${SERVER_IP} 'systemctl restart nginx'"
    echo "============================================"
}
# 主流程
main() {
    echo ""
    echo "============================================"
    echo "    云小调前端一键部署脚本"
    echo "============================================"
    echo ""
    check_dependencies
    build_project
    deploy_to_server
    show_result
}
main "$@"
web-app/src/components/common/OutboundCallWidget.jsx
@@ -628,14 +628,14 @@
              {call.errorCode > 0 ? (
                // 失败任务显示
                <span>
                  {call.perClassName || '联系人'}
                  {call.perTypeName || '联系人'}
                  {call.trueName && `(${call.trueName})`}:
                  {call.message}
                </span>
              ) : (
                // 成功任务显示
                // 成功任务显示 - 使用 perTypeName 字段(申请方当事人/被申请方当事人)
                <span>
                  正在与{call.perClassName || '申请方'}({call.trueName || call.personId})电话沟通中...
                  正在与{call.perTypeName || '申请方当事人'}({call.trueName || call.personId})电话沟通中...
                </span>
              )}
            </div>
web-app/src/components/dashboard/TabContainer.jsx
@@ -1321,8 +1321,8 @@
  });
  const loadedRef = useRef(false);
  // 获取 caseId
  const caseId = caseData?.caseId || getMergedParams().caseId;
  // 获取 caseId(兼容驼峰和蛇形命名)
  const caseId = caseData?.caseId || caseData?.case_id || getMergedParams().caseId;
  // 处理协议内容展示(纯文本,处理换行)
  const renderAgreementContent = (content) => {
web-app/src/components/dashboard/TopSection.jsx
@@ -28,7 +28,7 @@
            />
          </div>
          <div className="title-text">
            <h1>"解纷智能体"劳动争议AI调解智能体</h1>
            <h1>白云区人和镇劳动争议"解纷智能体"</h1>
            <div className="title-subtitle">
              <div className="subtitle-text">AI调解员驾驶舱 - 全自动调解系统</div>
              <div className="ai-status-tag">
web-app/src/config/env.js
@@ -11,7 +11,7 @@
  PRD: 'prd'
};
// 当前环境,默认为开发环境
// 当前环境,默认为SIT测试环境
const CURRENT_ENV = process.env.REACT_APP_ENV || ENV_TYPES.DEV;
// 环境配置映射
@@ -24,8 +24,8 @@
    name: '开发环境'
  },
  [ENV_TYPES.SIT]: {
    // 集成测试环境
    baseURL: 'http://192.168.3.114:9015',
    // 集成测试环境 - 通过 Nginx 代理访问后端,避免跨域
    baseURL: '',
    timeout: 30000,
    withCredentials: true,
    name: '集成测试环境'
web-app/src/utils/urlParams.js
@@ -39,11 +39,11 @@
 * @returns {Object} 合并后的参数对象
 */
export const getMergedParams = () => {
  // const defaultParams = getDefaultParams();
  const defaultParams = getDefaultParams();
  const urlParams = parseUrlParams();
  
  return {
    // ...defaultParams,
    ...defaultParams,
    ...urlParams
  };
};