Twilioapp-project/index.html

1335 lines
43 KiB
HTML
Raw Normal View History

2025-06-29 21:45:58 +08:00
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>翻译服务应用</title>
<link rel="manifest" href="manifest.json">
<meta name="theme-color" content="#4285f4">
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
min-height: 100vh;
color: #333;
}
.app-container {
max-width: 414px;
margin: 0 auto;
background: white;
min-height: 100vh;
position: relative;
box-shadow: 0 0 20px rgba(0,0,0,0.1);
}
.header {
background: linear-gradient(135deg, #4285f4, #34a853);
color: white;
text-align: center;
padding: 20px;
position: relative;
}
.header h1 {
font-size: 20px;
font-weight: 600;
}
.content {
padding: 20px;
padding-bottom: 100px;
min-height: calc(100vh - 140px);
}
.tab-content {
display: none;
}
.tab-content.active {
display: block;
}
/* 通话页面样式 */
.call-page {
text-align: center;
}
.call-options {
display: flex;
flex-direction: column;
gap: 20px;
margin-top: 40px;
}
.call-btn {
padding: 20px;
border: none;
border-radius: 15px;
font-size: 18px;
font-weight: 600;
cursor: pointer;
transition: all 0.3s ease;
box-shadow: 0 4px 15px rgba(0,0,0,0.1);
}
.voice-call {
background: linear-gradient(135deg, #4CAF50, #45a049);
color: white;
}
.video-call {
background: linear-gradient(135deg, #2196F3, #1976D2);
color: white;
}
.call-btn:hover {
transform: translateY(-2px);
box-shadow: 0 6px 20px rgba(0,0,0,0.15);
}
.call-interface {
display: none;
text-align: center;
margin-top: 40px;
}
.call-timer {
font-size: 48px;
font-weight: bold;
color: #4285f4;
margin: 40px 0;
}
.call-type-display {
font-size: 18px;
color: #666;
margin-bottom: 20px;
}
.end-call-btn {
display: none;
background: #f44336;
color: white;
padding: 15px 30px;
border: none;
border-radius: 50px;
font-size: 18px;
cursor: pointer;
margin-top: 20px;
transition: all 0.3s ease;
}
.end-call-btn:hover {
background: #d32f2f;
}
/* 费率弹窗样式 */
.modal {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(0,0,0,0.5);
display: flex;
justify-content: center;
align-items: center;
z-index: 1000;
}
.modal.hidden {
display: none;
}
.modal-content {
background: white;
padding: 30px;
border-radius: 20px;
width: 90%;
max-width: 400px;
text-align: center;
}
.modal h3 {
font-size: 20px;
margin-bottom: 20px;
color: #333;
}
.rate-info {
background: #f5f5f5;
padding: 20px;
border-radius: 15px;
margin: 20px 0;
}
.rate-item {
display: flex;
justify-content: space-between;
margin: 10px 0;
font-size: 16px;
}
.translator-option {
margin: 20px 0;
text-align: left;
}
.translator-option label {
display: flex;
align-items: center;
cursor: pointer;
}
.translator-option input[type="checkbox"] {
margin-right: 10px;
}
.modal-buttons {
display: flex;
gap: 15px;
margin-top: 25px;
}
.modal-btn {
flex: 1;
padding: 12px;
border: none;
border-radius: 10px;
font-size: 16px;
cursor: pointer;
transition: all 0.3s ease;
}
.cancel-btn {
background: #f0f0f0;
color: #666;
}
.confirm-btn {
background: #4285f4;
color: white;
}
.modal-btn:hover {
transform: translateY(-1px);
}
/* 账单弹窗样式 */
.bill-modal .modal-content {
max-width: 350px;
}
.bill-details {
text-align: left;
margin: 20px 0;
}
.bill-row {
display: flex;
justify-content: space-between;
margin: 10px 0;
padding: 5px 0;
}
.bill-row.total {
border-top: 2px solid #eee;
padding-top: 10px;
margin-top: 15px;
font-weight: bold;
font-size: 18px;
}
/* 日历组件样式 */
.calendar-container {
background: white;
border-radius: 15px;
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
overflow: hidden;
margin-bottom: 20px;
}
.calendar-header {
background: linear-gradient(135deg, #4285f4, #34a853);
color: white;
padding: 20px;
text-align: center;
display: flex;
justify-content: space-between;
align-items: center;
}
.calendar-nav-btn {
background: none;
border: none;
color: white;
font-size: 20px;
cursor: pointer;
padding: 5px 10px;
border-radius: 5px;
transition: background 0.3s ease;
}
.calendar-nav-btn:hover {
background: rgba(255,255,255,0.2);
}
.calendar-month {
font-size: 18px;
font-weight: 600;
}
.calendar-grid {
display: grid;
grid-template-columns: repeat(7, 1fr);
}
.calendar-day-header {
padding: 15px 5px;
text-align: center;
font-weight: 600;
color: #666;
font-size: 14px;
background: #f8f9fa;
}
.calendar-day {
padding: 15px 5px;
text-align: center;
cursor: pointer;
transition: all 0.3s ease;
position: relative;
min-height: 50px;
display: flex;
align-items: center;
justify-content: center;
border: 1px solid #f0f0f0;
}
.calendar-day:hover {
background: #f0f8ff;
}
.calendar-day.other-month {
color: #ccc;
}
.calendar-day.today {
background: #4285f4;
color: white;
font-weight: bold;
}
.calendar-day.has-appointment {
background: #e8f5e8;
color: #2e7d32;
font-weight: 600;
}
.calendar-day.has-appointment::after {
content: '•';
position: absolute;
bottom: 5px;
left: 50%;
transform: translateX(-50%);
color: #4CAF50;
font-size: 20px;
}
.appointment-details {
margin-top: 20px;
}
.appointment-item {
background: white;
padding: 15px;
border-radius: 10px;
box-shadow: 0 2px 5px rgba(0,0,0,0.1);
margin-bottom: 10px;
border-left: 4px solid #4285f4;
}
.appointment-time {
font-weight: 600;
color: #4285f4;
margin-bottom: 5px;
}
.appointment-desc {
color: #666;
font-size: 14px;
}
/* 文档页面样式 */
.document-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 20px;
}
.document-title {
font-size: 20px;
font-weight: 600;
color: #333;
}
.import-btn {
background: linear-gradient(135deg, #4285f4, #34a853);
color: white;
border: none;
padding: 10px 20px;
border-radius: 25px;
font-size: 14px;
cursor: pointer;
transition: all 0.3s ease;
box-shadow: 0 2px 10px rgba(66, 133, 244, 0.3);
}
.import-btn:hover {
transform: translateY(-2px);
box-shadow: 0 4px 15px rgba(66, 133, 244, 0.4);
}
.file-input {
display: none;
}
.document-stats {
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 15px;
margin-bottom: 30px;
}
.stat-card {
background: white;
padding: 20px;
border-radius: 15px;
text-align: center;
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
}
.stat-number {
font-size: 24px;
font-weight: bold;
color: #4285f4;
margin-bottom: 5px;
}
.stat-label {
color: #666;
font-size: 14px;
}
.document-list {
display: flex;
flex-direction: column;
gap: 15px;
}
.document-item {
background: white;
padding: 20px;
border-radius: 15px;
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
}
.document-item-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 10px;
}
.document-name {
font-weight: 600;
color: #333;
}
.document-progress {
font-size: 12px;
padding: 4px 8px;
border-radius: 12px;
}
.progress-completed {
background: #e8f5e8;
color: #2e7d32;
}
.progress-processing {
background: #fff3e0;
color: #f57c00;
}
.document-info {
color: #666;
font-size: 14px;
}
/* 个人中心样式 */
.profile-header {
text-align: center;
margin-bottom: 30px;
}
.profile-avatar {
width: 80px;
height: 80px;
border-radius: 50%;
background: linear-gradient(135deg, #4285f4, #34a853);
display: flex;
align-items: center;
justify-content: center;
margin: 0 auto 15px;
font-size: 32px;
color: white;
font-weight: bold;
}
.profile-name {
font-size: 20px;
font-weight: 600;
margin-bottom: 5px;
}
.profile-id {
color: #666;
font-size: 14px;
}
.profile-menu {
display: flex;
flex-direction: column;
gap: 1px;
background: #f0f0f0;
border-radius: 15px;
overflow: hidden;
}
.menu-item {
background: white;
padding: 20px;
display: flex;
justify-content: space-between;
align-items: center;
cursor: pointer;
transition: background 0.3s ease;
}
.menu-item:hover {
background: #f8f9fa;
}
.menu-item-left {
display: flex;
align-items: center;
gap: 15px;
}
.menu-icon {
width: 24px;
height: 24px;
display: flex;
align-items: center;
justify-content: center;
font-size: 18px;
}
.menu-text {
font-size: 16px;
color: #333;
}
.menu-arrow {
color: #ccc;
font-size: 14px;
}
/* 底部导航样式 */
.bottom-nav {
position: fixed;
bottom: 0;
left: 50%;
transform: translateX(-50%);
width: 100%;
max-width: 414px;
background: white;
border-top: 1px solid #eee;
display: flex;
justify-content: space-around;
padding: 10px 0;
z-index: 100;
}
.nav-item {
display: flex;
flex-direction: column;
align-items: center;
padding: 5px;
cursor: pointer;
transition: color 0.3s ease;
color: #999;
text-decoration: none;
}
.nav-item.active {
color: #4285f4;
}
.nav-icon {
font-size: 20px;
margin-bottom: 4px;
}
.nav-text {
font-size: 12px;
}
/* 响应式设计 */
@media (max-width: 480px) {
.app-container {
max-width: 100%;
}
.content {
padding: 15px;
}
}
/* 账单历史样式 */
.bill-list {
display: flex;
flex-direction: column;
gap: 10px;
margin-top: 20px;
}
.bill-item {
display: flex;
justify-content: space-between;
align-items: center;
padding: 15px;
background: white;
border-radius: 10px;
box-shadow: 0 2px 5px rgba(0,0,0,0.1);
}
.bill-info {
flex: 1;
}
.bill-date {
font-size: 14px;
color: #666;
}
.bill-type {
font-weight: 600;
margin-top: 2px;
}
.bill-amount {
font-size: 16px;
font-weight: bold;
color: #4285f4;
margin: 0 15px;
}
.bill-status {
padding: 4px 8px;
border-radius: 12px;
font-size: 12px;
font-weight: 500;
}
.bill-status.paid {
background: #e8f5e8;
color: #2e7d32;
}
.bill-status.unpaid {
background: #ffebee;
color: #c62828;
}
</style>
</head>
<body>
<div class="app-container">
<div class="header">
<h1>翻译服务应用</h1>
</div>
<div class="content">
<!-- 通话页面 -->
<div id="call" class="tab-content active">
<div class="call-page">
<div class="call-options">
<button class="call-btn voice-call" onclick="selectCallType('voice')">
📞 语音通话
</button>
<button class="call-btn video-call" onclick="selectCallType('video')">
📹 视频通话
</button>
</div>
<div class="call-interface">
<div class="call-type-display">通话中...</div>
<div class="call-timer">00:00</div>
</div>
<button class="end-call-btn" onclick="endCall()">
结束通话
</button>
</div>
</div>
<!-- 预约页面 - 日历组件 -->
<div id="appointment" class="tab-content">
<div class="calendar-container">
<div class="calendar-header">
<button class="calendar-nav-btn" onclick="previousMonth()"></button>
<div class="calendar-month" id="currentMonth">2024年1月</div>
<button class="calendar-nav-btn" onclick="nextMonth()"></button>
</div>
<div class="calendar-grid" id="calendarGrid">
<!-- 日历将通过JavaScript生成 -->
</div>
</div>
<div class="appointment-details" id="appointmentDetails">
<div class="appointment-item">
<div class="appointment-time">今天 14:30</div>
<div class="appointment-desc">商务会议翻译 - 英语 | 翻译员:张译文</div>
</div>
</div>
</div>
<!-- 文档页面 -->
<div id="document" class="tab-content">
<div class="document-header">
<div class="document-title">文档管理</div>
<button class="import-btn" onclick="document.getElementById('fileInput').click()">
📁 导入文档
</button>
<input type="file" id="fileInput" class="file-input" multiple accept=".pdf,.doc,.docx,.txt" onchange="handleFileImport(event)">
</div>
<div class="document-stats">
<div class="stat-card">
<div class="stat-number" id="totalDocs">24</div>
<div class="stat-label">总文档数</div>
</div>
<div class="stat-card">
<div class="stat-number">18</div>
<div class="stat-label">已完成</div>
</div>
<div class="stat-card">
<div class="stat-number">4</div>
<div class="stat-label">进行中</div>
</div>
<div class="stat-card">
<div class="stat-number">2</div>
<div class="stat-label">待开始</div>
</div>
</div>
<div class="document-list" id="documentList">
<div class="document-item">
<div class="document-item-header">
<div class="document-name">产品说明书.pdf</div>
<div class="document-progress progress-completed">已完成</div>
</div>
<div class="document-info">
中文 → 英文 | 5页 | 完成时间2024-01-15
</div>
</div>
<div class="document-item">
<div class="document-item-header">
<div class="document-name">合同文件.docx</div>
<div class="document-progress progress-processing">翻译中</div>
</div>
<div class="document-info">
英文 → 中文 | 12页 | 进度60%
</div>
</div>
<div class="document-item">
<div class="document-item-header">
<div class="document-name">技术手册.pdf</div>
<div class="document-progress progress-processing">审核中</div>
</div>
<div class="document-info">
日文 → 中文 | 8页 | 预计完成:明天
</div>
</div>
</div>
</div>
<!-- 个人中心页面 -->
<div id="profile" class="tab-content">
<div class="profile-header">
<div class="profile-avatar"></div>
<div class="profile-name">用户名</div>
<div class="profile-id">ID: 123456789</div>
</div>
<div class="profile-menu">
<div class="menu-item">
<div class="menu-item-left">
<div class="menu-icon">📋</div>
<div class="menu-text">账单历史</div>
</div>
<div class="menu-arrow"></div>
</div>
<div class="menu-item">
<div class="menu-item-left">
<div class="menu-icon">⚙️</div>
<div class="menu-text">设置</div>
</div>
<div class="menu-arrow"></div>
</div>
<div class="menu-item">
<div class="menu-item-left">
<div class="menu-icon"></div>
<div class="menu-text">帮助与支持</div>
</div>
<div class="menu-arrow"></div>
</div>
<div class="menu-item">
<div class="menu-item-left">
<div class="menu-icon"></div>
<div class="menu-text">关于我们</div>
</div>
<div class="menu-arrow"></div>
</div>
</div>
<div class="bill-list">
<!-- 账单历史将通过JavaScript动态加载 -->
</div>
</div>
</div>
<!-- 底部导航 -->
<div class="bottom-nav">
<div class="nav-item active" onclick="switchTab('call')">
<div class="nav-icon">📞</div>
<div class="nav-text">通话</div>
</div>
<div class="nav-item" onclick="switchTab('appointment')">
<div class="nav-icon">📅</div>
<div class="nav-text">预约</div>
</div>
<div class="nav-item" onclick="switchTab('document')">
<div class="nav-icon">📄</div>
<div class="nav-text">文档</div>
</div>
<div class="nav-item" onclick="switchTab('profile')">
<div class="nav-icon">👤</div>
<div class="nav-text">我的</div>
</div>
</div>
</div>
<!-- 费率确认弹窗 -->
<div id="rate-modal" class="modal hidden">
<div class="modal-content">
<h3>通话费率确认</h3>
<div class="rate-info">
<div class="rate-item">
<span>通话类型:</span>
<span id="modal-call-type">语音通话</span>
</div>
<div class="rate-item">
<span>基础费率:</span>
<span id="modal-base-rate">¥80/小时</span>
</div>
<div class="translator-option">
<label>
<input type="checkbox" id="translator-checkbox" onchange="updateModalRate()">
添加翻译员服务 (+¥50/小时)
</label>
</div>
<div class="rate-item" style="font-weight: bold; border-top: 1px solid #eee; padding-top: 10px;">
<span>总费率:</span>
<span id="modal-total-rate">¥80/小时</span>
</div>
</div>
<div style="font-size: 14px; color: #666; margin: 15px 0;">
* 按分钟计费最低1分钟
</div>
<div class="modal-buttons">
<button class="modal-btn cancel-btn" onclick="closeRateModal()">取消</button>
<button class="modal-btn confirm-btn" onclick="confirmAndStartCall()">开始通话</button>
</div>
</div>
</div>
<!-- 账单弹窗 -->
<div class="bill-modal modal hidden">
<div class="modal-content">
<h3>通话账单</h3>
<div class="bill-details">
<div class="bill-row">
<span>通话类型:</span>
<span id="bill-call-type">语音通话</span>
</div>
<div class="bill-row">
<span>通话时长:</span>
<span id="bill-duration">2分30秒</span>
</div>
<div class="bill-row">
<span>基础费用:</span>
<span id="bill-base-rate">¥6.67</span>
</div>
<div class="bill-row" id="translator-fee-item" style="display: none;">
<span>翻译员费用:</span>
<span id="bill-translator-fee">¥4.17</span>
</div>
<div class="bill-row total">
<span>总计:</span>
<span id="bill-total-amount">¥6.67</span>
</div>
</div>
<div class="modal-buttons">
<button class="modal-btn cancel-btn" onclick="closeBill()">稍后支付</button>
<button class="modal-btn confirm-btn" onclick="payBill()">立即支付</button>
</div>
</div>
</div>
<script>
// 全局变量
let currentTab = 'call';
let isCallActive = false;
let callStartTime = null;
let callTimer = null;
let currentCallType = null;
let hasTranslator = false;
let currentBill = null;
// 日历相关变量
let currentDate = new Date();
let selectedDate = null;
// 通话费率配置
const callRates = {
voice: 80, // 语音通话 ¥80/小时
video: 120, // 视频通话 ¥120/小时
translator: 50 // 翻译员服务 ¥50/小时
};
// 账单历史数据
let billHistory = [
{
date: '2024-01-15 14:30',
type: '视频通话',
duration: 15,
amount: 32.50,
paid: true,
hasTranslator: true
},
{
date: '2024-01-14 10:15',
type: '语音通话',
duration: 8,
amount: 10.67,
paid: true,
hasTranslator: false
},
{
date: '2024-01-13 16:45',
type: '视频通话',
duration: 25,
amount: 50.00,
paid: false,
hasTranslator: false
}
];
// 预约数据
const appointments = {
'2024-01-15': [
{ time: '14:30', desc: '商务会议翻译 - 英语 | 翻译员:张译文' }
],
'2024-01-16': [
{ time: '10:00', desc: '技术文档翻译 - 日语 | 翻译员:待分配' }
],
'2024-01-14': [
{ time: '16:00', desc: '法律咨询翻译 - 法语 | 翻译员:李法兰' }
]
};
// 文档数据
let documentCount = 24;
// 标签页切换功能
function switchTab(tabName) {
// 隐藏所有标签页内容
document.querySelectorAll('.tab-content').forEach(tab => {
tab.classList.remove('active');
});
// 显示选中的标签页
document.getElementById(tabName).classList.add('active');
// 更新导航状态
document.querySelectorAll('.nav-item').forEach(nav => {
nav.classList.remove('active');
});
event.target.closest('.nav-item').classList.add('active');
currentTab = tabName;
// 如果切换到个人中心,更新账单历史
if (tabName === 'profile') {
updateBillHistory();
} else if (tabName === 'appointment') {
generateCalendar();
}
}
// 日历功能
function generateCalendar() {
const grid = document.getElementById('calendarGrid');
const monthDisplay = document.getElementById('currentMonth');
const year = currentDate.getFullYear();
const month = currentDate.getMonth();
monthDisplay.textContent = `${year}年${month + 1}月`;
const firstDay = new Date(year, month, 1);
const lastDay = new Date(year, month + 1, 0);
const startDate = new Date(firstDay);
startDate.setDate(startDate.getDate() - firstDay.getDay());
grid.innerHTML = '';
// 添加星期标题
const weekdays = ['日', '一', '二', '三', '四', '五', '六'];
weekdays.forEach(day => {
const dayHeader = document.createElement('div');
dayHeader.className = 'calendar-day-header';
dayHeader.textContent = day;
grid.appendChild(dayHeader);
});
// 生成日历天数
for (let i = 0; i < 42; i++) {
const date = new Date(startDate);
date.setDate(startDate.getDate() + i);
const dayElement = document.createElement('div');
dayElement.className = 'calendar-day';
dayElement.textContent = date.getDate();
const dateStr = date.toISOString().split('T')[0];
if (date.getMonth() !== month) {
dayElement.classList.add('other-month');
}
if (date.toDateString() === new Date().toDateString()) {
dayElement.classList.add('today');
}
if (appointments[dateStr]) {
dayElement.classList.add('has-appointment');
}
dayElement.onclick = () => selectDate(dateStr);
grid.appendChild(dayElement);
}
}
function previousMonth() {
currentDate.setMonth(currentDate.getMonth() - 1);
generateCalendar();
}
function nextMonth() {
currentDate.setMonth(currentDate.getMonth() + 1);
generateCalendar();
}
function selectDate(dateStr) {
selectedDate = dateStr;
const appointmentDetails = document.getElementById('appointmentDetails');
if (appointments[dateStr]) {
appointmentDetails.innerHTML = '';
appointments[dateStr].forEach(appointment => {
const item = document.createElement('div');
item.className = 'appointment-item';
item.innerHTML = `
<div class="appointment-time">${appointment.time}</div>
<div class="appointment-desc">${appointment.desc}</div>
`;
appointmentDetails.appendChild(item);
});
} else {
appointmentDetails.innerHTML = '<div style="text-align: center; color: #666; padding: 20px;">该日期暂无预约</div>';
}
}
// 文档导入功能
function handleFileImport(event) {
const files = event.target.files;
if (files.length === 0) return;
for (let file of files) {
addDocumentToList(file);
documentCount++;
}
// 更新文档统计
document.getElementById('totalDocs').textContent = documentCount;
// 显示成功提示
alert(`成功导入 ${files.length} 个文档!`);
// 清空文件输入
event.target.value = '';
}
function addDocumentToList(file) {
const documentList = document.getElementById('documentList');
const documentItem = document.createElement('div');
documentItem.className = 'document-item';
documentItem.innerHTML = `
<div class="document-item-header">
<div class="document-name">${file.name}</div>
<div class="document-progress progress-processing">待处理</div>
</div>
<div class="document-info">
文件大小:${(file.size / 1024).toFixed(1)} KB | 上传时间:${new Date().toLocaleString('zh-CN')}
</div>
`;
// 插入到列表开头
documentList.insertBefore(documentItem, documentList.firstChild);
}
// 通话相关功能
function selectCallType(type) {
currentCallType = type;
// 更新弹窗内容
const modalCallType = document.getElementById('modal-call-type');
const modalBaseRate = document.getElementById('modal-base-rate');
const modalTotalRate = document.getElementById('modal-total-rate');
const translatorCheckbox = document.getElementById('translator-checkbox');
modalCallType.textContent = type === 'voice' ? '语音通话' : '视频通话';
modalBaseRate.textContent = `¥${callRates[type]}/小时`;
// 重置翻译员选项
translatorCheckbox.checked = false;
hasTranslator = false;
modalTotalRate.textContent = `¥${callRates[type]}/小时`;
// 显示费率弹窗
document.getElementById('rate-modal').classList.remove('hidden');
}
function updateModalRate() {
const translatorCheckbox = document.getElementById('translator-checkbox');
const modalTotalRate = document.getElementById('modal-total-rate');
hasTranslator = translatorCheckbox.checked;
const baseRate = callRates[currentCallType];
const totalRate = baseRate + (hasTranslator ? callRates.translator : 0);
modalTotalRate.textContent = `¥${totalRate}/小时`;
}
function closeRateModal() {
document.getElementById('rate-modal').classList.add('hidden');
currentCallType = null;
hasTranslator = false;
}
function confirmAndStartCall() {
if (!currentCallType) return;
// 关闭弹窗
closeRateModal();
// 开始通话
startCall();
}
function startCall() {
if (!currentCallType) return;
isCallActive = true;
callStartTime = new Date();
// 隐藏选择面板,显示通话界面
document.querySelector('.call-options').style.display = 'none';
document.querySelector('.call-interface').style.display = 'block';
document.querySelector('.end-call-btn').style.display = 'block';
// 更新通话界面信息
const callTypeDisplay = document.querySelector('.call-type-display');
callTypeDisplay.textContent = currentCallType === 'voice' ? '语音通话中' : '视频通话中';
// 开始计时器
startCallTimer();
}
function startCallTimer() {
callTimer = setInterval(() => {
if (callStartTime) {
const elapsed = Math.floor((new Date() - callStartTime) / 1000);
const minutes = Math.floor(elapsed / 60);
const seconds = elapsed % 60;
document.querySelector('.call-timer').textContent =
`${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}`;
}
}, 1000);
}
function endCall() {
if (!isCallActive) return;
isCallActive = false;
const callEndTime = new Date();
const callDuration = Math.ceil((callEndTime - callStartTime) / 1000 / 60); // 分钟,向上取整
// 停止计时器
if (callTimer) {
clearInterval(callTimer);
callTimer = null;
}
// 计算费用
const baseRate = callRates[currentCallType];
const translatorRate = hasTranslator ? callRates.translator : 0;
const totalRate = baseRate + translatorRate;
const amount = Math.max(callDuration * totalRate / 60, totalRate / 60); // 最低1分钟计费
// 创建账单
currentBill = {
date: new Date().toLocaleString('zh-CN'),
type: currentCallType === 'voice' ? '语音通话' : '视频通话',
duration: callDuration,
amount: parseFloat(amount.toFixed(2)),
paid: false,
hasTranslator: hasTranslator
};
// 显示账单
showBillModal();
// 重置通话界面
document.querySelector('.call-interface').style.display = 'none';
document.querySelector('.end-call-btn').style.display = 'none';
document.querySelector('.call-options').style.display = 'flex';
document.querySelector('.call-timer').textContent = '00:00';
// 重置状态
callStartTime = null;
currentCallType = null;
hasTranslator = false;
}
function showBillModal() {
if (!currentBill) return;
const modal = document.querySelector('.bill-modal');
const callTypeSpan = document.getElementById('bill-call-type');
const durationSpan = document.getElementById('bill-duration');
const baseRateSpan = document.getElementById('bill-base-rate');
const translatorFeeItem = document.getElementById('translator-fee-item');
const translatorFeeSpan = document.getElementById('bill-translator-fee');
const totalAmountSpan = document.getElementById('bill-total-amount');
// 更新账单信息
callTypeSpan.textContent = currentBill.type;
const minutes = Math.floor(currentBill.duration);
const seconds = (currentBill.duration % 1) * 60;
durationSpan.textContent = `${minutes}分${Math.round(seconds)}秒`;
const baseRate = callRates[currentCallType === 'voice' ? 'voice' : 'video'];
const baseAmount = (baseRate * currentBill.duration / 60).toFixed(2);
baseRateSpan.textContent = `¥${baseAmount}`;
if (currentBill.hasTranslator) {
translatorFeeItem.style.display = 'block';
const translatorAmount = (callRates.translator * currentBill.duration / 60).toFixed(2);
translatorFeeSpan.textContent = `¥${translatorAmount}`;
} else {
translatorFeeItem.style.display = 'none';
}
totalAmountSpan.textContent = `¥${currentBill.amount}`;
// 显示模态框
modal.classList.remove('hidden');
}
function closeBill() {
document.querySelector('.bill-modal').classList.add('hidden');
if (currentBill) {
billHistory.unshift(currentBill);
updateBillHistory();
}
currentBill = null;
}
function payBill() {
if (currentBill) {
currentBill.paid = true;
billHistory.unshift(currentBill);
updateBillHistory();
alert('支付成功!');
}
document.querySelector('.bill-modal').classList.add('hidden');
currentBill = null;
}
function updateBillHistory() {
const billList = document.querySelector('.bill-list');
billList.innerHTML = '';
billHistory.forEach(bill => {
const billItem = document.createElement('div');
billItem.className = 'bill-item';
billItem.innerHTML = `
<div class="bill-info">
<div class="bill-date">${bill.date}</div>
<div class="bill-type">${bill.type}${bill.hasTranslator ? ' + 翻译员' : ''}</div>
</div>
<div class="bill-amount">¥${bill.amount}</div>
<div class="bill-status ${bill.paid ? 'paid' : 'unpaid'}">
${bill.paid ? '已支付' : '待支付'}
</div>
`;
billList.appendChild(billItem);
});
}
// 页面加载完成后初始化
document.addEventListener('DOMContentLoaded', function() {
updateBillHistory();
generateCalendar();
});
</script>
</body>
</html>