|
@@ -349,56 +349,347 @@ export class AdminDashboard implements OnInit, AfterViewInit, OnDestroy {
|
|
|
objectId: this.company?.id || 'cDL6R1hgSi'
|
|
objectId: this.company?.id || 'cDL6R1hgSi'
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
- // 从Project表的data.pricing字段计算总收入
|
|
|
|
|
- const projectQuery = new Parse.Query('Project');
|
|
|
|
|
- projectQuery.equalTo('company', companyPointer);
|
|
|
|
|
- projectQuery.notEqualTo('isDeleted', true);
|
|
|
|
|
- projectQuery.limit(1000); // 限制查询数量
|
|
|
|
|
-
|
|
|
|
|
- const projects = await projectQuery.find();
|
|
|
|
|
-
|
|
|
|
|
|
|
+ // 🔥 修复:从ProjectPayment表获取已收到的尾款(真实收入)
|
|
|
|
|
+ // 而不是从Project.data.pricing获取报价金额
|
|
|
let totalRevenue = 0;
|
|
let totalRevenue = 0;
|
|
|
- projects.forEach(project => {
|
|
|
|
|
- const data = project.get('data') || {};
|
|
|
|
|
- const pricing = data.pricing || {};
|
|
|
|
|
|
|
+
|
|
|
|
|
+ try {
|
|
|
|
|
+ // 查询所有ProjectPayment记录(已收到的支付)
|
|
|
|
|
+ const paymentQuery = new Parse.Query('ProjectPayment');
|
|
|
|
|
+ paymentQuery.equalTo('company', companyPointer);
|
|
|
|
|
+ paymentQuery.notEqualTo('isDeleted', true);
|
|
|
|
|
+ paymentQuery.limit(1000);
|
|
|
|
|
|
|
|
- // 尝试多种可能的金额字段
|
|
|
|
|
- const totalAmount = pricing.totalAmount ||
|
|
|
|
|
- pricing.total ||
|
|
|
|
|
- pricing.finalPrice ||
|
|
|
|
|
- pricing.quotedPrice ||
|
|
|
|
|
- 0;
|
|
|
|
|
|
|
+ const payments = await paymentQuery.find();
|
|
|
|
|
|
|
|
- if (totalAmount > 0) {
|
|
|
|
|
- totalRevenue += totalAmount;
|
|
|
|
|
- console.log(` 项目 ${project.get('title')}: ¥${totalAmount.toLocaleString()}`);
|
|
|
|
|
|
|
+ console.log(`📊 找到 ${payments.length} 条支付记录`);
|
|
|
|
|
+
|
|
|
|
|
+ // 统计所有已收到的支付金额
|
|
|
|
|
+ payments.forEach(payment => {
|
|
|
|
|
+ const amount = payment.get('amount') || 0;
|
|
|
|
|
+ if (amount > 0) {
|
|
|
|
|
+ totalRevenue += amount;
|
|
|
|
|
+ const projectId = payment.get('project')?.id || '未知项目';
|
|
|
|
|
+ console.log(` 支付记录 ${projectId}: ¥${amount.toLocaleString()}`);
|
|
|
|
|
+ }
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ console.log(`✅ 收入统计: 已收到尾款 ¥${totalRevenue.toLocaleString()} (来自${payments.length}条支付记录)`);
|
|
|
|
|
+ } catch (paymentError) {
|
|
|
|
|
+ console.warn('⚠️ ProjectPayment查询失败,尝试从ProjectFile(payment_voucher)获取:', paymentError);
|
|
|
|
|
+
|
|
|
|
|
+ // 降级方案:从ProjectFile表的payment_voucher类型获取
|
|
|
|
|
+ try {
|
|
|
|
|
+ const fileQuery = new Parse.Query('ProjectFile');
|
|
|
|
|
+ fileQuery.equalTo('company', companyPointer);
|
|
|
|
|
+ fileQuery.equalTo('fileType', 'payment_voucher');
|
|
|
|
|
+ fileQuery.notEqualTo('isDeleted', true);
|
|
|
|
|
+ fileQuery.limit(1000);
|
|
|
|
|
+
|
|
|
|
|
+ const voucherFiles = await fileQuery.find();
|
|
|
|
|
+
|
|
|
|
|
+ voucherFiles.forEach(file => {
|
|
|
|
|
+ const data = file.get('data') || {};
|
|
|
|
|
+ const aiAnalysis = data.aiAnalysis || {};
|
|
|
|
|
+ const amount = aiAnalysis.amount || 0;
|
|
|
|
|
+
|
|
|
|
|
+ if (amount > 0) {
|
|
|
|
|
+ totalRevenue += amount;
|
|
|
|
|
+ }
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ console.log(`✅ 收入统计(降级): 已收到尾款 ¥${totalRevenue.toLocaleString()} (来自${voucherFiles.length}张凭证)`);
|
|
|
|
|
+ } catch (fallbackError) {
|
|
|
|
|
+ console.error('❌ 降级方案也失败:', fallbackError);
|
|
|
|
|
+ // 继续使用totalRevenue = 0
|
|
|
}
|
|
}
|
|
|
- });
|
|
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
this.stats.totalRevenue.set(totalRevenue);
|
|
this.stats.totalRevenue.set(totalRevenue);
|
|
|
- console.log(`✅ 收入统计: 总收入 ¥${totalRevenue.toLocaleString()} (来自${projects.length}个项目)`);
|
|
|
|
|
} catch (error) {
|
|
} catch (error) {
|
|
|
console.error('❌ 收入统计加载失败:', error);
|
|
console.error('❌ 收入统计加载失败:', error);
|
|
|
throw error;
|
|
throw error;
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- // 加载最近活动日志
|
|
|
|
|
|
|
+ // 加载最近活动日志 + 项目紧急事件 + 进展动态
|
|
|
private async loadRecentActivities(forceLimit?: number): Promise<void> {
|
|
private async loadRecentActivities(forceLimit?: number): Promise<void> {
|
|
|
try {
|
|
try {
|
|
|
this.loadingActivities.set(true);
|
|
this.loadingActivities.set(true);
|
|
|
const limit = forceLimit || (this.showAllActivities() ? 50 : 10);
|
|
const limit = forceLimit || (this.showAllActivities() ? 50 : 10);
|
|
|
|
|
+
|
|
|
|
|
+ // 1️⃣ 加载活动日志
|
|
|
const activities = await this.activityLogService.getRecentActivities(limit);
|
|
const activities = await this.activityLogService.getRecentActivities(limit);
|
|
|
- this.recentActivities.set(activities);
|
|
|
|
|
- console.log(`✅ 活动日志加载成功: ${activities.length}条`);
|
|
|
|
|
|
|
+
|
|
|
|
|
+ // 2️⃣ 加载项目紧急事件
|
|
|
|
|
+ const urgentEvents = await this.loadProjectUrgentEvents();
|
|
|
|
|
+
|
|
|
|
|
+ // 3️⃣ 加载项目进展动态
|
|
|
|
|
+ const progressUpdates = await this.loadProjectProgressUpdates();
|
|
|
|
|
+
|
|
|
|
|
+ // 合并所有活动,按时间排序
|
|
|
|
|
+ const allActivities = [
|
|
|
|
|
+ ...activities,
|
|
|
|
|
+ ...urgentEvents,
|
|
|
|
|
+ ...progressUpdates
|
|
|
|
|
+ ].sort((a, b) => {
|
|
|
|
|
+ const timeA = new Date(a.timestamp || a.createdAt || 0).getTime();
|
|
|
|
|
+ const timeB = new Date(b.timestamp || b.createdAt || 0).getTime();
|
|
|
|
|
+ return timeB - timeA; // 最新的在前
|
|
|
|
|
+ }).slice(0, limit);
|
|
|
|
|
+
|
|
|
|
|
+ this.recentActivities.set(allActivities);
|
|
|
|
|
+ console.log(`✅ 活动加载成功: ${activities.length}条日志 + ${urgentEvents.length}个紧急事件 + ${progressUpdates.length}个进展 = 共${allActivities.length}条`);
|
|
|
} catch (error) {
|
|
} catch (error) {
|
|
|
- console.error('❌ 活动日志加载失败:', error);
|
|
|
|
|
|
|
+ console.error('❌ 活动加载失败:', error);
|
|
|
this.recentActivities.set([]);
|
|
this.recentActivities.set([]);
|
|
|
} finally {
|
|
} finally {
|
|
|
this.loadingActivities.set(false);
|
|
this.loadingActivities.set(false);
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 加载项目紧急事件
|
|
|
|
|
+ */
|
|
|
|
|
+ private async loadProjectUrgentEvents(): Promise<any[]> {
|
|
|
|
|
+ try {
|
|
|
|
|
+ const companyPointer = {
|
|
|
|
|
+ __type: 'Pointer',
|
|
|
|
|
+ className: 'Company',
|
|
|
|
|
+ objectId: this.company?.id || 'cDL6R1hgSi'
|
|
|
|
|
+ };
|
|
|
|
|
+
|
|
|
|
|
+ // 查询所有进行中的项目
|
|
|
|
|
+ const projectQuery = new Parse.Query('Project');
|
|
|
|
|
+ projectQuery.equalTo('company', companyPointer);
|
|
|
|
|
+ projectQuery.notEqualTo('isDeleted', true);
|
|
|
|
|
+ projectQuery.notEqualTo('status', '已完成');
|
|
|
|
|
+ projectQuery.notEqualTo('status', '已取消');
|
|
|
|
|
+ projectQuery.limit(100);
|
|
|
|
|
+
|
|
|
|
|
+ const projects = await projectQuery.find();
|
|
|
|
|
+ console.log(`📊 [紧急事件] 查询到 ${projects.length} 个项目`);
|
|
|
|
|
+
|
|
|
|
|
+ const urgentEvents: any[] = [];
|
|
|
|
|
+
|
|
|
|
|
+ const now = new Date();
|
|
|
|
|
+ const oneDayMs = 24 * 60 * 60 * 1000;
|
|
|
|
|
+
|
|
|
|
|
+ for (const project of projects) {
|
|
|
|
|
+ const title = project.get('title') || '未命名项目';
|
|
|
|
|
+ const data = project.get('data') || {};
|
|
|
|
|
+ const currentStage = project.get('currentStage') || project.get('stage') || '订单分配';
|
|
|
|
|
+
|
|
|
|
|
+ console.log(`📋 检查项目 "${title}" 的截止时间:`, {
|
|
|
|
|
+ smallImageDeadline: data.smallImageDeadline || '无',
|
|
|
|
|
+ deliveryDeadline: data.deliveryDeadline || '无',
|
|
|
|
|
+ stageDeadline: data.stageDeadline || '无'
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ // 检查各类截止时间
|
|
|
|
|
+
|
|
|
|
|
+ // 1️⃣ 小图对图截止
|
|
|
|
|
+ if (data.smallImageDeadline) {
|
|
|
|
|
+ const deadline = new Date(data.smallImageDeadline);
|
|
|
|
|
+ const daysLeft = (deadline.getTime() - now.getTime()) / oneDayMs;
|
|
|
|
|
+
|
|
|
|
|
+ if (daysLeft < 1 && daysLeft >= 0) {
|
|
|
|
|
+ urgentEvents.push({
|
|
|
|
|
+ id: `urgent-${project.id}-smallimg`,
|
|
|
|
|
+ type: 'urgent_event',
|
|
|
|
|
+ module: 'project',
|
|
|
|
|
+ actionType: 'deadline_approaching',
|
|
|
|
|
+ entityName: title,
|
|
|
|
|
+ description: '小图对图截止在即',
|
|
|
|
|
+ severity: daysLeft < 0 ? 'critical' : 'high',
|
|
|
|
|
+ timestamp: new Date(),
|
|
|
|
|
+ createdAt: new Date(),
|
|
|
|
|
+ icon: '⚠️',
|
|
|
|
|
+ projectId: project.id,
|
|
|
|
|
+ deadline: deadline
|
|
|
|
|
+ });
|
|
|
|
|
+ } else if (daysLeft < 0) {
|
|
|
|
|
+ urgentEvents.push({
|
|
|
|
|
+ id: `urgent-${project.id}-smallimg-overdue`,
|
|
|
|
|
+ type: 'urgent_event',
|
|
|
|
|
+ module: 'project',
|
|
|
|
|
+ actionType: 'deadline_overdue',
|
|
|
|
|
+ entityName: title,
|
|
|
|
|
+ description: `小图对图已逾期 ${Math.abs(Math.floor(daysLeft))} 天`,
|
|
|
|
|
+ severity: 'critical',
|
|
|
|
|
+ timestamp: new Date(),
|
|
|
|
|
+ createdAt: new Date(),
|
|
|
|
|
+ icon: '🔴',
|
|
|
|
|
+ projectId: project.id,
|
|
|
|
|
+ deadline: deadline
|
|
|
|
|
+ });
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 2️⃣ 交付截止
|
|
|
|
|
+ if (data.deliveryDeadline) {
|
|
|
|
|
+ const deadline = new Date(data.deliveryDeadline);
|
|
|
|
|
+ const daysLeft = (deadline.getTime() - now.getTime()) / oneDayMs;
|
|
|
|
|
+
|
|
|
|
|
+ if (daysLeft < 1 && daysLeft >= 0) {
|
|
|
|
|
+ urgentEvents.push({
|
|
|
|
|
+ id: `urgent-${project.id}-delivery`,
|
|
|
|
|
+ type: 'urgent_event',
|
|
|
|
|
+ module: 'project',
|
|
|
|
|
+ actionType: 'deadline_approaching',
|
|
|
|
|
+ entityName: title,
|
|
|
|
|
+ description: '项目交付截止在即',
|
|
|
|
|
+ severity: daysLeft < 0 ? 'critical' : 'high',
|
|
|
|
|
+ timestamp: new Date(),
|
|
|
|
|
+ createdAt: new Date(),
|
|
|
|
|
+ icon: '📦',
|
|
|
|
|
+ projectId: project.id,
|
|
|
|
|
+ deadline: deadline
|
|
|
|
|
+ });
|
|
|
|
|
+ } else if (daysLeft < 0) {
|
|
|
|
|
+ urgentEvents.push({
|
|
|
|
|
+ id: `urgent-${project.id}-delivery-overdue`,
|
|
|
|
|
+ type: 'urgent_event',
|
|
|
|
|
+ module: 'project',
|
|
|
|
|
+ actionType: 'deadline_overdue',
|
|
|
|
|
+ entityName: title,
|
|
|
|
|
+ description: `项目交付已逾期 ${Math.abs(Math.floor(daysLeft))} 天`,
|
|
|
|
|
+ severity: 'critical',
|
|
|
|
|
+ timestamp: new Date(),
|
|
|
|
|
+ createdAt: new Date(),
|
|
|
|
|
+ icon: '🔴',
|
|
|
|
|
+ projectId: project.id,
|
|
|
|
|
+ deadline: deadline
|
|
|
|
|
+ });
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 3️⃣ 阶段截止
|
|
|
|
|
+ if (data.stageDeadline) {
|
|
|
|
|
+ const deadline = new Date(data.stageDeadline);
|
|
|
|
|
+ const daysLeft = (deadline.getTime() - now.getTime()) / oneDayMs;
|
|
|
|
|
+
|
|
|
|
|
+ if (daysLeft < 1 && daysLeft >= 0) {
|
|
|
|
|
+ urgentEvents.push({
|
|
|
|
|
+ id: `urgent-${project.id}-stage`,
|
|
|
|
|
+ type: 'urgent_event',
|
|
|
|
|
+ module: 'project',
|
|
|
|
|
+ actionType: 'deadline_approaching',
|
|
|
|
|
+ entityName: title,
|
|
|
|
|
+ description: `${currentStage}阶段截止在即`,
|
|
|
|
|
+ severity: daysLeft < 0 ? 'critical' : 'high',
|
|
|
|
|
+ timestamp: new Date(),
|
|
|
|
|
+ createdAt: new Date(),
|
|
|
|
|
+ icon: '⏰',
|
|
|
|
|
+ projectId: project.id,
|
|
|
|
|
+ deadline: deadline
|
|
|
|
|
+ });
|
|
|
|
|
+ } else if (daysLeft < 0) {
|
|
|
|
|
+ urgentEvents.push({
|
|
|
|
|
+ id: `urgent-${project.id}-stage-overdue`,
|
|
|
|
|
+ type: 'urgent_event',
|
|
|
|
|
+ module: 'project',
|
|
|
|
|
+ actionType: 'deadline_overdue',
|
|
|
|
|
+ entityName: title,
|
|
|
|
|
+ description: `${currentStage}阶段已逾期 ${Math.abs(Math.floor(daysLeft))} 天`,
|
|
|
|
|
+ severity: 'critical',
|
|
|
|
|
+ timestamp: new Date(),
|
|
|
|
|
+ createdAt: new Date(),
|
|
|
|
|
+ icon: '🔴',
|
|
|
|
|
+ projectId: project.id,
|
|
|
|
|
+ deadline: deadline
|
|
|
|
|
+ });
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ console.log(`📌 找到 ${urgentEvents.length} 个紧急事件`);
|
|
|
|
|
+ return urgentEvents;
|
|
|
|
|
+ } catch (error) {
|
|
|
|
|
+ console.error('❌ 加载紧急事件失败:', error);
|
|
|
|
|
+ return [];
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 加载项目进展动态
|
|
|
|
|
+ */
|
|
|
|
|
+ private async loadProjectProgressUpdates(): Promise<any[]> {
|
|
|
|
|
+ try {
|
|
|
|
|
+ const companyPointer = {
|
|
|
|
|
+ __type: 'Pointer',
|
|
|
|
|
+ className: 'Company',
|
|
|
|
|
+ objectId: this.company?.id || 'cDL6R1hgSi'
|
|
|
|
|
+ };
|
|
|
|
|
+
|
|
|
|
|
+ // 查询最近更新的项目
|
|
|
|
|
+ const projectQuery = new Parse.Query('Project');
|
|
|
|
|
+ projectQuery.equalTo('company', companyPointer);
|
|
|
|
|
+ projectQuery.notEqualTo('isDeleted', true);
|
|
|
|
|
+ projectQuery.descending('updatedAt');
|
|
|
|
|
+ projectQuery.limit(20);
|
|
|
|
|
+
|
|
|
|
|
+ const projects = await projectQuery.find();
|
|
|
|
|
+ const progressUpdates: any[] = [];
|
|
|
|
|
+
|
|
|
|
|
+ // 阶段映射
|
|
|
|
|
+ const stageLabels: Record<string, string> = {
|
|
|
|
|
+ '订单分配': '📋 订单分配',
|
|
|
|
|
+ '确认需求': '🎯 确认需求',
|
|
|
|
|
+ '交付执行': '🚀 交付执行',
|
|
|
|
|
+ '售后归档': '✅ 售后归档'
|
|
|
|
|
+ };
|
|
|
|
|
+
|
|
|
|
|
+ for (const project of projects) {
|
|
|
|
|
+ const title = project.get('title') || '未命名项目';
|
|
|
|
|
+ const currentStage = project.get('currentStage') || project.get('stage') || '订单分配';
|
|
|
|
|
+ const status = project.get('status') || '待分配';
|
|
|
|
|
+ const updatedAt = project.get('updatedAt');
|
|
|
|
|
+
|
|
|
|
|
+ // 计算距离现在的时间
|
|
|
|
|
+ const now = new Date();
|
|
|
|
|
+ const diffMs = now.getTime() - new Date(updatedAt).getTime();
|
|
|
|
|
+ const diffHours = Math.floor(diffMs / (60 * 60 * 1000));
|
|
|
|
|
+ const diffDays = Math.floor(diffMs / (24 * 60 * 60 * 1000));
|
|
|
|
|
+
|
|
|
|
|
+ let timeStr = '';
|
|
|
|
|
+ if (diffHours < 1) {
|
|
|
|
|
+ timeStr = '刚刚';
|
|
|
|
|
+ } else if (diffHours < 24) {
|
|
|
|
|
+ timeStr = `${diffHours}小时前`;
|
|
|
|
|
+ } else {
|
|
|
|
|
+ timeStr = `${diffDays}天前`;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 只显示最近24小时内的更新
|
|
|
|
|
+ if (diffHours <= 24) {
|
|
|
|
|
+ progressUpdates.push({
|
|
|
|
|
+ id: `progress-${project.id}`,
|
|
|
|
|
+ type: 'progress_update',
|
|
|
|
|
+ module: 'project',
|
|
|
|
|
+ actionType: 'stage_update',
|
|
|
|
|
+ entityName: title,
|
|
|
|
|
+ description: `进入${stageLabels[currentStage] || currentStage}阶段`,
|
|
|
|
|
+ severity: 'medium',
|
|
|
|
|
+ timestamp: updatedAt,
|
|
|
|
|
+ createdAt: updatedAt,
|
|
|
|
|
+ icon: stageLabels[currentStage]?.split(' ')[0] || '📊',
|
|
|
|
|
+ projectId: project.id,
|
|
|
|
|
+ stage: currentStage,
|
|
|
|
|
+ status: status,
|
|
|
|
|
+ timeStr: timeStr
|
|
|
|
|
+ });
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ console.log(`📈 找到 ${progressUpdates.length} 个进展动态`);
|
|
|
|
|
+ return progressUpdates;
|
|
|
|
|
+ } catch (error) {
|
|
|
|
|
+ console.error('❌ 加载进展动态失败:', error);
|
|
|
|
|
+ return [];
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
// 查看全部活动
|
|
// 查看全部活动
|
|
|
async viewAllActivities(): Promise<void> {
|
|
async viewAllActivities(): Promise<void> {
|
|
|
this.showAllActivities.set(true);
|
|
this.showAllActivities.set(true);
|
|
@@ -931,7 +1222,11 @@ export class AdminDashboard implements OnInit, AfterViewInit, OnDestroy {
|
|
|
'complete': 'complete',
|
|
'complete': 'complete',
|
|
|
'assign': 'assign',
|
|
'assign': 'assign',
|
|
|
'upload': 'upload',
|
|
'upload': 'upload',
|
|
|
- 'approve': 'approve'
|
|
|
|
|
|
|
+ 'approve': 'approve',
|
|
|
|
|
+ // 🔥 新增:紧急事件和进展动态
|
|
|
|
|
+ 'deadline_approaching': 'warning',
|
|
|
|
|
+ 'deadline_overdue': 'critical',
|
|
|
|
|
+ 'stage_update': 'info'
|
|
|
};
|
|
};
|
|
|
return actionMap[activity.actionType] || 'default';
|
|
return actionMap[activity.actionType] || 'default';
|
|
|
}
|
|
}
|
|
@@ -952,7 +1247,11 @@ export class AdminDashboard implements OnInit, AfterViewInit, OnDestroy {
|
|
|
'upload': '上传',
|
|
'upload': '上传',
|
|
|
'download': '下载',
|
|
'download': '下载',
|
|
|
'share': '分享',
|
|
'share': '分享',
|
|
|
- 'comment': '评论'
|
|
|
|
|
|
|
+ 'comment': '评论',
|
|
|
|
|
+ // 🔥 新增:紧急事件和进展动态
|
|
|
|
|
+ 'deadline_approaching': '截止在即',
|
|
|
|
|
+ 'deadline_overdue': '已逾期',
|
|
|
|
|
+ 'stage_update': '阶段更新'
|
|
|
};
|
|
};
|
|
|
return labelMap[actionType] || actionType;
|
|
return labelMap[actionType] || actionType;
|
|
|
}
|
|
}
|