用OpenHarmony KMP发现最佳旅游目的地 | 景点评分系统
本文介绍了基于Kotlin Multiplatform (KMP)框架和OpenHarmony的旅游景点评分系统。该系统通过景观质量、设施完善度、服务质量、价格合理性等多维度评估景点,采用加权平均计算综合评分,并提供个性化推荐。核心功能包括景点评分、对比分析、旅游建议等,支持跨平台运行。系统采用0-100分制,根据分数划分1-5星等级,并结合游客数量、季节因素等生成优化建议。文章详细阐述了评估方法

目录
概述
旅游已成为现代生活中不可或缺的一部分。无论是周末短途旅行还是长期假期规划,选择合适的旅游景点对于获得最佳旅游体验至关重要。然而,面对众多景点和大量的游客评价,旅游者往往难以做出最优选择。旅游景点评分系统是帮助旅游者了解景点特色、评估景点质量、制定最优旅游计划的重要工具。本文档介绍如何在 Kotlin Multiplatform (KMP) 框架下,结合 OpenHarmony 鸿蒙操作系统,实现一个功能完整的旅游景点评分系统。
旅游景点评分系统是一个综合性的旅游信息平台,它不仅能够对景点进行多维度评分,还能够进行景点对比、生成旅游建议、提供个性化的景点推荐。通过KMP框架的跨端能力,这个工具可以在Android、iOS、Web和OpenHarmony等多个平台上运行,为旅游者提供了一个强大的旅游决策辅助工具。
旅游景点评分的重要性
旅游景点评分在现代旅游中的重要性日益凸显:
- 信息参考:科学的评分能够帮助旅游者了解景点的真实情况。
- 时间优化:通过评分可以优化旅游时间分配,避免浪费时间在不值得的景点。
- 成本控制:合理的景点选择能够控制旅游成本。
- 体验提升:选择高评分景点能够显著提升旅游体验。
- 决策支持:评分系统为旅游决策提供了科学的支持。
工具的核心价值
旅游景点评分系统提供以下价值:
- 多维度评分:从景观、设施、服务、价格等多个维度进行评分
- 综合对比:支持多个景点的对比分析
- 个性化推荐:根据用户偏好提供个性化的景点推荐
- 详细信息:提供景点的详细信息和游客评价
- 旅游建议:根据评分结果提供旅游建议
- 跨平台支持:一份代码可在多个平台运行,提高开发效率
旅游评分基础
核心概念
景点评分(Attraction Rating):对旅游景点的综合评价,通常用0-100的分数表示。
景观质量(Scenery Quality):景点的自然或人文景观质量。
设施完善度(Facility Completeness):景点的基础设施和便利设施的完善程度。
服务质量(Service Quality):景点提供的服务质量,包括导游、餐饮等。
游客满意度(Tourist Satisfaction):游客对景点的整体满意程度。
性价比(Value for Money):景点的价格与价值的比例。
常见的景点评估维度
自然景观:山水、植被、气候等自然特征。
人文景观:历史、文化、建筑等人文特征。
基础设施:停车场、卫生间、餐饮设施等。
交通便利性:到达景点的便利程度。
游客服务:导游、讲解、安全等服务。
价格合理性:门票价格与景点价值的匹配度。
影响景点评分的关键因素
景观独特性:景点的独特之处是吸引游客的重要因素。
基础设施:完善的基础设施能够提升游客体验。
服务质量:优质的服务能够显著提升游客满意度。
游客数量:适度的游客数量能够提升体验质量。
季节因素:不同季节景点的特色不同。
核心评估方法
1. 景观评估
评估景点的自然和人文景观质量。
2. 设施评估
评估景点的基础设施和便利设施。
3. 服务评估
评估景点提供的各项服务质量。
4. 价格评估
评估景点的价格合理性。
5. 综合评分
综合考虑多个维度,计算总体评分。
6. 个性化推荐
根据用户偏好提供个性化的景点推荐。
Kotlin 源代码
// TouristAttractionRatingSystem.kt
import java.time.LocalDateTime
import kotlin.math.pow
data class Attraction(
val id: String,
val name: String,
val location: String,
val category: String,
val ticketPrice: Double,
val openingHours: String
)
data class AttractionRating(
val attractionId: String,
val attractionName: String,
val sceneryScore: Double,
val facilityScore: Double,
val serviceScore: Double,
val priceScore: Double,
val overallScore: Double,
val ratingLevel: String,
val visitorCount: Int,
val visitorsPerDay: Double,
val recommendations: List<String>,
val timestamp: String
)
data class RatingMetrics(
val totalAttractions: Long,
val averageScore: Double,
val highestRatedAttraction: String,
val lowestRatedAttraction: String,
val averageVisitorCount: Double,
val mostPopularCategory: String
)
data class AttractionComparison(
val attractions: List<AttractionRating>,
val bestScenery: String,
val bestFacility: String,
val bestService: String,
val bestValue: String,
val recommendation: String
)
class TouristAttractionRatingSystem {
private val attractions = mutableListOf<Attraction>()
private val ratings = mutableListOf<AttractionRating>()
private var attractionIdCounter = 0
// 添加景点
fun addAttraction(
name: String,
location: String,
category: String,
ticketPrice: Double,
openingHours: String
): Attraction {
val id = "ATTR${++attractionIdCounter}"
val attraction = Attraction(id, name, location, category, ticketPrice, openingHours)
attractions.add(attraction)
return attraction
}
// 评分景点
fun rateAttraction(
attractionId: String,
sceneryScore: Double,
facilityScore: Double,
serviceScore: Double,
priceScore: Double,
visitorCount: Int
): AttractionRating {
val attraction = attractions.find { it.id == attractionId }
?: return AttractionRating("", "", 0.0, 0.0, 0.0, 0.0, 0.0, "", 0, 0.0, emptyList(), "")
// 确保分数在0-100范围内
val scenery = minOf(maxOf(sceneryScore, 0.0), 100.0)
val facility = minOf(maxOf(facilityScore, 0.0), 100.0)
val service = minOf(maxOf(serviceScore, 0.0), 100.0)
val price = minOf(maxOf(priceScore, 0.0), 100.0)
// 计算综合评分(加权平均)
val overallScore = scenery * 0.35 + facility * 0.25 + service * 0.25 + price * 0.15
// 判断评分等级
val ratingLevel = when {
overallScore >= 90 -> "5星"
overallScore >= 80 -> "4星"
overallScore >= 70 -> "3星"
overallScore >= 60 -> "2星"
else -> "1星"
}
// 计算日均游客数
val visitorsPerDay = visitorCount / 365.0
// 生成建议
val recommendations = generateRecommendations(
scenery, facility, service, price, visitorCount, attraction.category
)
val rating = AttractionRating(
attractionId, attraction.name, scenery, facility, service, price,
overallScore, ratingLevel, visitorCount, visitorsPerDay,
recommendations, LocalDateTime.now().toString()
)
ratings.add(rating)
return rating
}
// 生成建议
private fun generateRecommendations(
scenery: Double,
facility: Double,
service: Double,
price: Double,
visitorCount: Int,
category: String
): List<String> {
val recommendations = mutableListOf<String>()
if (scenery >= 85) {
recommendations.add("🏞️ 景观优美,强烈推荐游览")
} else if (scenery < 60) {
recommendations.add("🏞️ 景观一般,可作为备选景点")
}
if (facility >= 80) {
recommendations.add("🏢 设施完善,游客体验佳")
} else if (facility < 60) {
recommendations.add("🏢 设施不完善,建议提前做好准备")
}
if (service >= 80) {
recommendations.add("👥 服务质量高,值得体验")
} else if (service < 60) {
recommendations.add("👥 服务有待改进,可能影响体验")
}
if (price >= 75) {
recommendations.add("💰 性价比高,物有所值")
} else if (price < 50) {
recommendations.add("💰 价格较高,需谨慎考虑")
}
if (visitorCount > 1000000) {
recommendations.add("👫 游客众多,建议错峰游览")
} else if (visitorCount < 100000) {
recommendations.add("👫 游客较少,可能冷门景点")
}
if (category == "自然景观" && scenery >= 80) {
recommendations.add("🌿 自然风光秀美,适合摄影爱好者")
} else if (category == "人文景观" && service >= 80) {
recommendations.add("🏛️ 文化底蕴深厚,值得深入了解")
}
return recommendations
}
// 获取评分指标
fun getRatingMetrics(): RatingMetrics {
if (ratings.isEmpty()) {
return RatingMetrics(0, 0.0, "", "", 0.0, "")
}
val totalAttractions = attractions.size.toLong()
val averageScore = ratings.map { it.overallScore }.average()
val highestRated = ratings.maxByOrNull { it.overallScore }?.attractionName ?: ""
val lowestRated = ratings.minByOrNull { it.overallScore }?.attractionName ?: ""
val averageVisitors = ratings.map { it.visitorCount }.average()
val mostPopularCategory = attractions.groupBy { it.category }
.maxByOrNull { it.value.size }?.key ?: ""
return RatingMetrics(
totalAttractions, averageScore, highestRated, lowestRated,
averageVisitors, mostPopularCategory
)
}
// 获取所有评分
fun getAllRatings(): List<AttractionRating> {
return ratings.toList()
}
// 景点对比
fun compareAttractions(attractionIds: List<String>): AttractionComparison {
val comparisonRatings = ratings.filter { it.attractionId in attractionIds }
val bestScenery = comparisonRatings.maxByOrNull { it.sceneryScore }?.attractionName ?: ""
val bestFacility = comparisonRatings.maxByOrNull { it.facilityScore }?.attractionName ?: ""
val bestService = comparisonRatings.maxByOrNull { it.serviceScore }?.attractionName ?: ""
val bestValue = comparisonRatings.maxByOrNull { it.priceScore }?.attractionName ?: ""
val avgScore = comparisonRatings.map { it.overallScore }.average()
val recommendation = when {
avgScore >= 85 -> "这些景点整体评分很高,都值得游览"
avgScore >= 75 -> "这些景点评分良好,可根据偏好选择"
else -> "这些景点评分一般,建议选择评分最高的"
}
return AttractionComparison(
comparisonRatings, bestScenery, bestFacility, bestService, bestValue, recommendation
)
}
// 生成旅游报告
fun generateTouristReport(): Map<String, Any> {
val metrics = getRatingMetrics()
return mapOf(
"timestamp" to LocalDateTime.now().toString(),
"metrics" to metrics,
"ratings" to ratings.toList(),
"topAttractions" to ratings.sortedByDescending { it.overallScore }.take(5),
"recommendations" to generateGeneralRecommendations(metrics)
)
}
// 生成通用建议
private fun generateGeneralRecommendations(metrics: RatingMetrics): List<String> {
val recommendations = mutableListOf<String>()
if (metrics.averageScore >= 80) {
recommendations.add("📊 整体景点质量高,旅游选择丰富")
} else if (metrics.averageScore < 70) {
recommendations.add("📊 整体景点质量一般,建议选择高评分景点")
}
if (metrics.averageVisitorCount > 500000) {
recommendations.add("👫 热门景点众多,建议提前规划行程")
}
recommendations.add("✅ 根据个人偏好选择景点,制定最优旅游计划")
return recommendations
}
// 清空数据
fun clearData() {
attractions.clear()
ratings.clear()
}
}
fun main() {
val system = TouristAttractionRatingSystem()
// 添加景点
system.addAttraction("黄山", "安徽省", "自然景观", 190.0, "06:00-18:00")
system.addAttraction("故宫", "北京市", "人文景观", 60.0, "08:30-17:00")
system.addAttraction("西湖", "浙江省", "自然景观", 0.0, "全天开放")
// 评分景点
val rating1 = system.rateAttraction("ATTR1", 95.0, 85.0, 90.0, 80.0, 2000000)
val rating2 = system.rateAttraction("ATTR2", 90.0, 88.0, 85.0, 85.0, 3000000)
val rating3 = system.rateAttraction("ATTR3", 92.0, 80.0, 88.0, 90.0, 2500000)
println("景点评分结果:")
println("${rating1.attractionName}: ${String.format("%.2f", rating1.overallScore)} (${rating1.ratingLevel})")
println("${rating2.attractionName}: ${String.format("%.2f", rating2.overallScore)} (${rating2.ratingLevel})")
println("${rating3.attractionName}: ${String.format("%.2f", rating3.overallScore)} (${rating3.ratingLevel})")
// 生成报告
val report = system.generateTouristReport()
println("\n旅游报告已生成")
}
Kotlin代码说明:这个Kotlin实现提供了完整的旅游景点评分功能。TouristAttractionRatingSystem 类能够管理景点信息、进行景点评分、进行景点对比、生成旅游报告。通过使用数据类和科学的计算方法,代码既简洁又准确。系统支持多维度的景点分析,从单个景点的详细评分到整个景点库的趋势分析,为旅游者提供了全面的旅游决策支持。
JavaScript 编译代码
// TouristAttractionRatingSystem.js
class Attraction {
constructor(id, name, location, category, ticketPrice, openingHours) {
this.id = id;
this.name = name;
this.location = location;
this.category = category;
this.ticketPrice = ticketPrice;
this.openingHours = openingHours;
}
}
class AttractionRating {
constructor(attractionId, attractionName, sceneryScore, facilityScore, serviceScore, priceScore, overallScore, ratingLevel, visitorCount, visitorsPerDay, recommendations, timestamp) {
this.attractionId = attractionId;
this.attractionName = attractionName;
this.sceneryScore = sceneryScore;
this.facilityScore = facilityScore;
this.serviceScore = serviceScore;
this.priceScore = priceScore;
this.overallScore = overallScore;
this.ratingLevel = ratingLevel;
this.visitorCount = visitorCount;
this.visitorsPerDay = visitorsPerDay;
this.recommendations = recommendations;
this.timestamp = timestamp;
}
}
class RatingMetrics {
constructor(totalAttractions, averageScore, highestRatedAttraction, lowestRatedAttraction, averageVisitorCount, mostPopularCategory) {
this.totalAttractions = totalAttractions;
this.averageScore = averageScore;
this.highestRatedAttraction = highestRatedAttraction;
this.lowestRatedAttraction = lowestRatedAttraction;
this.averageVisitorCount = averageVisitorCount;
this.mostPopularCategory = mostPopularCategory;
}
}
class TouristAttractionRatingSystem {
constructor() {
this.attractions = [];
this.ratings = [];
this.attractionIdCounter = 0;
}
addAttraction(name, location, category, ticketPrice, openingHours) {
const id = `ATTR${++this.attractionIdCounter}`;
const attraction = new Attraction(id, name, location, category, ticketPrice, openingHours);
this.attractions.push(attraction);
return attraction;
}
rateAttraction(attractionId, sceneryScore, facilityScore, serviceScore, priceScore, visitorCount) {
const attraction = this.attractions.find(a => a.id === attractionId);
if (!attraction) return null;
const scenery = Math.min(Math.max(sceneryScore, 0), 100);
const facility = Math.min(Math.max(facilityScore, 0), 100);
const service = Math.min(Math.max(serviceScore, 0), 100);
const price = Math.min(Math.max(priceScore, 0), 100);
const overallScore = scenery * 0.35 + facility * 0.25 + service * 0.25 + price * 0.15;
let ratingLevel;
if (overallScore >= 90) ratingLevel = "5星";
else if (overallScore >= 80) ratingLevel = "4星";
else if (overallScore >= 70) ratingLevel = "3星";
else if (overallScore >= 60) ratingLevel = "2星";
else ratingLevel = "1星";
const visitorsPerDay = visitorCount / 365;
const recommendations = this.generateRecommendations(scenery, facility, service, price, visitorCount, attraction.category);
const rating = new AttractionRating(attractionId, attraction.name, scenery, facility, service, price, overallScore, ratingLevel, visitorCount, visitorsPerDay, recommendations, new Date().toISOString());
this.ratings.push(rating);
return rating;
}
generateRecommendations(scenery, facility, service, price, visitorCount, category) {
const recommendations = [];
if (scenery >= 85) {
recommendations.push("🏞️ 景观优美,强烈推荐游览");
} else if (scenery < 60) {
recommendations.push("🏞️ 景观一般,可作为备选景点");
}
if (facility >= 80) {
recommendations.push("🏢 设施完善,游客体验佳");
} else if (facility < 60) {
recommendations.push("🏢 设施不完善,建议提前做好准备");
}
if (service >= 80) {
recommendations.push("👥 服务质量高,值得体验");
} else if (service < 60) {
recommendations.push("👥 服务有待改进,可能影响体验");
}
if (price >= 75) {
recommendations.push("💰 性价比高,物有所值");
} else if (price < 50) {
recommendations.push("💰 价格较高,需谨慎考虑");
}
if (visitorCount > 1000000) {
recommendations.push("👫 游客众多,建议错峰游览");
} else if (visitorCount < 100000) {
recommendations.push("👫 游客较少,可能冷门景点");
}
if (category === "自然景观" && scenery >= 80) {
recommendations.push("🌿 自然风光秀美,适合摄影爱好者");
} else if (category === "人文景观" && service >= 80) {
recommendations.push("🏛️ 文化底蕴深厚,值得深入了解");
}
return recommendations;
}
getRatingMetrics() {
if (this.ratings.length === 0) {
return new RatingMetrics(0, 0, "", "", 0, "");
}
const totalAttractions = this.attractions.length;
const averageScore = this.ratings.reduce((sum, r) => sum + r.overallScore, 0) / this.ratings.length;
const highestRated = this.ratings.reduce((max, r) => r.overallScore > max.overallScore ? r : max).attractionName;
const lowestRated = this.ratings.reduce((min, r) => r.overallScore < min.overallScore ? r : min).attractionName;
const averageVisitors = this.ratings.reduce((sum, r) => sum + r.visitorCount, 0) / this.ratings.length;
const categoryCount = {};
for (const attraction of this.attractions) {
categoryCount[attraction.category] = (categoryCount[attraction.category] || 0) + 1;
}
const mostPopularCategory = Object.keys(categoryCount).reduce((a, b) => categoryCount[a] > categoryCount[b] ? a : b, "");
return new RatingMetrics(totalAttractions, averageScore, highestRated, lowestRated, averageVisitors, mostPopularCategory);
}
getAllRatings() {
return this.ratings;
}
compareAttractions(attractionIds) {
const comparisonRatings = this.ratings.filter(r => attractionIds.includes(r.attractionId));
const bestScenery = comparisonRatings.reduce((max, r) => r.sceneryScore > max.sceneryScore ? r : max).attractionName;
const bestFacility = comparisonRatings.reduce((max, r) => r.facilityScore > max.facilityScore ? r : max).attractionName;
const bestService = comparisonRatings.reduce((max, r) => r.serviceScore > max.serviceScore ? r : max).attractionName;
const bestValue = comparisonRatings.reduce((max, r) => r.priceScore > max.priceScore ? r : max).attractionName;
const avgScore = comparisonRatings.reduce((sum, r) => sum + r.overallScore, 0) / comparisonRatings.length;
let recommendation;
if (avgScore >= 85) recommendation = "这些景点整体评分很高,都值得游览";
else if (avgScore >= 75) recommendation = "这些景点评分良好,可根据偏好选择";
else recommendation = "这些景点评分一般,建议选择评分最高的";
return {
attractions: comparisonRatings,
bestScenery: bestScenery,
bestFacility: bestFacility,
bestService: bestService,
bestValue: bestValue,
recommendation: recommendation
};
}
generateTouristReport() {
const metrics = this.getRatingMetrics();
return {
timestamp: new Date().toISOString(),
metrics: metrics,
ratings: this.ratings,
topAttractions: this.ratings.sort((a, b) => b.overallScore - a.overallScore).slice(0, 5),
recommendations: this.generateGeneralRecommendations(metrics)
};
}
generateGeneralRecommendations(metrics) {
const recommendations = [];
if (metrics.averageScore >= 80) {
recommendations.push("📊 整体景点质量高,旅游选择丰富");
} else if (metrics.averageScore < 70) {
recommendations.push("📊 整体景点质量一般,建议选择高评分景点");
}
if (metrics.averageVisitorCount > 500000) {
recommendations.push("👫 热门景点众多,建议提前规划行程");
}
recommendations.push("✅ 根据个人偏好选择景点,制定最优旅游计划");
return recommendations;
}
clearData() {
this.attractions = [];
this.ratings = [];
}
}
// 使用示例
const system = new TouristAttractionRatingSystem();
system.addAttraction("黄山", "安徽省", "自然景观", 190, "06:00-18:00");
system.addAttraction("故宫", "北京市", "人文景观", 60, "08:30-17:00");
system.addAttraction("西湖", "浙江省", "自然景观", 0, "全天开放");
const rating1 = system.rateAttraction("ATTR1", 95, 85, 90, 80, 2000000);
const rating2 = system.rateAttraction("ATTR2", 90, 88, 85, 85, 3000000);
const rating3 = system.rateAttraction("ATTR3", 92, 80, 88, 90, 2500000);
console.log("景点评分结果:");
console.log(`${rating1.attractionName}: ${rating1.overallScore.toFixed(2)} (${rating1.ratingLevel})`);
console.log(`${rating2.attractionName}: ${rating2.overallScore.toFixed(2)} (${rating2.ratingLevel})`);
console.log(`${rating3.attractionName}: ${rating3.overallScore.toFixed(2)} (${rating3.ratingLevel})`);
const report = system.generateTouristReport();
console.log("\n旅游报告已生成");
JavaScript代码说明:JavaScript版本是Kotlin代码的直接转译。我们使用ES6的class语法定义各个类,使用数学函数进行计算。整体逻辑和算法与Kotlin版本保持一致,确保跨平台的一致性。JavaScript的灵活性使得代码更加简洁,同时保持了清晰的结构和完整的功能。
ArkTS 调用代码
// TouristAttractionPage.ets
import { TouristAttractionRatingSystem } from './TouristAttractionRatingSystem';
@Entry
@Component
struct TouristAttractionPage {
@State attractionName: string = '黄山';
@State location: string = '安徽省';
@State category: string = '自然景观';
@State ticketPrice: number = 190;
@State sceneryScore: number = 95;
@State facilityScore: number = 85;
@State serviceScore: number = 90;
@State priceScore: number = 80;
@State visitorCount: number = 2000000;
@State selectedTab: number = 0;
@State ratings: Array<any> = [];
@State metrics: any = null;
@State isLoading: boolean = false;
@State errorMessage: string = '';
@State report: any = null;
private system: TouristAttractionRatingSystem = new TouristAttractionRatingSystem();
private categories = ['自然景观', '人文景观', '主题公园', '宗教景点', '城市景观'];
addAndRateAttraction() {
if (!this.attractionName.trim() || !this.location.trim()) {
this.errorMessage = '请输入景点名称和位置';
return;
}
this.isLoading = true;
this.errorMessage = '';
try {
this.system.addAttraction(
this.attractionName,
this.location,
this.category,
this.ticketPrice,
"全天开放"
);
const attractionId = `ATTR${this.ratings.length + 1}`;
this.system.rateAttraction(
attractionId,
this.sceneryScore,
this.facilityScore,
this.serviceScore,
this.priceScore,
this.visitorCount
);
this.ratings = this.system.getAllRatings();
this.metrics = this.system.getRatingMetrics();
AlertDialog.show({ message: '景点已添加并评分' });
// 重置表单
this.attractionName = '';
this.location = '';
this.sceneryScore = 80;
this.facilityScore = 80;
this.serviceScore = 80;
this.priceScore = 80;
} catch (error) {
this.errorMessage = '操作失败: ' + error.message;
} finally {
this.isLoading = false;
}
}
generateReport() {
this.isLoading = true;
try {
this.report = this.system.generateTouristReport();
} catch (error) {
this.errorMessage = '生成报告失败: ' + error.message;
} finally {
this.isLoading = false;
}
}
getRatingLevelColor(level: string): string {
switch (level) {
case '5星': return '#FFD700';
case '4星': return '#4CAF50';
case '3星': return '#FF9800';
case '2星': return '#F44336';
case '1星': return '#D32F2F';
default: return '#999999';
}
}
build() {
Column() {
Text('旅游景点评分系统')
.fontSize(24)
.fontWeight(FontWeight.Bold)
.margin({ top: 20, bottom: 20 })
Tabs({ barPosition: BarPosition.Start }) {
TabContent() {
Column() {
Text('添加景点').fontSize(14).fontWeight(FontWeight.Bold).margin({ bottom: 15 })
Text('景点名称:').fontSize(12).margin({ bottom: 5 })
TextInput({ placeholder: '黄山' })
.value(this.attractionName)
.onChange((value: string) => { this.attractionName = value; })
.height(40).padding(10).border({ width: 1, color: '#cccccc' }).margin({ bottom: 15 })
Row() {
Column() {
Text('位置:').fontSize(12).margin({ bottom: 5 })
TextInput({ placeholder: '安徽省' })
.value(this.location)
.onChange((value: string) => { this.location = value; })
.height(40).padding(10).border({ width: 1, color: '#cccccc' })
}
.flex(1)
Column() {
Text('门票价格:').fontSize(12).margin({ bottom: 5 })
TextInput({ placeholder: '190' })
.type(InputType.Number)
.value(this.ticketPrice.toString())
.onChange((value: string) => { this.ticketPrice = parseFloat(value) || 0; })
.height(40).padding(10).border({ width: 1, color: '#cccccc' })
}
.flex(1)
.margin({ left: 10 })
}
.margin({ bottom: 15 })
Text('景点类别:').fontSize(12).margin({ bottom: 5 })
Select(this.categories.map(c => ({ value: c })))
.value(this.category)
.onSelect((index: number, value?: string) => {
this.category = value || '自然景观';
})
.margin({ bottom: 15 })
Text('景观评分:').fontSize(12).margin({ bottom: 5 })
Slider({ value: this.sceneryScore, min: 0, max: 100, step: 5 })
.onChange((value: number) => { this.sceneryScore = value; })
.margin({ bottom: 15 })
Row() {
Column() {
Text('设施评分:').fontSize(12).margin({ bottom: 5 })
Slider({ value: this.facilityScore, min: 0, max: 100, step: 5 })
.onChange((value: number) => { this.facilityScore = value; })
}
.flex(1)
Column() {
Text('服务评分:').fontSize(12).margin({ bottom: 5 })
Slider({ value: this.serviceScore, min: 0, max: 100, step: 5 })
.onChange((value: number) => { this.serviceScore = value; })
}
.flex(1)
.margin({ left: 10 })
}
.margin({ bottom: 15 })
Text('价格评分:').fontSize(12).margin({ bottom: 5 })
Slider({ value: this.priceScore, min: 0, max: 100, step: 5 })
.onChange((value: number) => { this.priceScore = value; })
.margin({ bottom: 15 })
Text('年游客数:').fontSize(12).margin({ bottom: 5 })
TextInput({ placeholder: '2000000' })
.type(InputType.Number)
.value(this.visitorCount.toString())
.onChange((value: string) => { this.visitorCount = parseInt(value) || 0; })
.height(40).padding(10).border({ width: 1, color: '#cccccc' }).margin({ bottom: 15 })
Button('添加并评分').width('100%').height(40).margin({ bottom: 15 })
.onClick(() => { this.addAndRateAttraction(); }).enabled(!this.isLoading)
if (this.errorMessage) {
Text(this.errorMessage).fontSize(12).fontColor('#F44336').margin({ bottom: 15 })
}
}
.padding(15)
}
.tabBar('➕ 添加景点')
TabContent() {
Column() {
if (this.ratings.length > 0) {
Text('景点评分').fontSize(16).fontWeight(FontWeight.Bold).margin({ bottom: 15 })
List() {
ForEach(this.ratings, (rating: any) => {
ListItem() {
Column() {
Row() {
Text(rating.attractionName).fontSize(14).fontWeight(FontWeight.Bold).flex(1)
Text(rating.ratingLevel).fontSize(12).fontColor(this.getRatingLevelColor(rating.ratingLevel))
.fontWeight(FontWeight.Bold)
}
.margin({ bottom: 10 })
Row() {
Text('综合评分:').fontSize(11)
Text(rating.overallScore.toFixed(1)).fontSize(11).fontWeight(FontWeight.Bold)
.fontColor('#2196F3')
}
.margin({ bottom: 5 })
Row() {
Column() {
Text('景观:').fontSize(10).fontColor('#999999')
Text(rating.sceneryScore.toFixed(0)).fontSize(10).fontWeight(FontWeight.Bold)
}
.flex(1)
Column() {
Text('设施:').fontSize(10).fontColor('#999999')
Text(rating.facilityScore.toFixed(0)).fontSize(10).fontWeight(FontWeight.Bold)
}
.flex(1)
Column() {
Text('服务:').fontSize(10).fontColor('#999999')
Text(rating.serviceScore.toFixed(0)).fontSize(10).fontWeight(FontWeight.Bold)
}
.flex(1)
Column() {
Text('价格:').fontSize(10).fontColor('#999999')
Text(rating.priceScore.toFixed(0)).fontSize(10).fontWeight(FontWeight.Bold)
}
.flex(1)
}
}
.padding(10).border({ width: 1, color: '#eeeeee' }).borderRadius(5)
}
}, (rating: any) => rating.attractionId)
}
} else {
Text('请先添加景点').fontSize(12).fontColor('#999999')
}
}
.padding(15)
}
.tabBar('⭐ 评分列表')
TabContent() {
Column() {
if (this.metrics) {
Text('评分指标').fontSize(16).fontWeight(FontWeight.Bold).margin({ bottom: 15 })
Row() {
Column() {
Text('平均评分').fontSize(11).fontColor('#999999')
Text(this.metrics.averageScore.toFixed(1)).fontSize(18)
.fontWeight(FontWeight.Bold).fontColor('#2196F3').margin({ top: 5 })
}
.flex(1).alignItems(HorizontalAlign.Center).padding(15).backgroundColor('#F5F5F5').borderRadius(5)
Column() {
Text('景点总数').fontSize(11).fontColor('#999999')
Text(this.metrics.totalAttractions.toString()).fontSize(18)
.fontWeight(FontWeight.Bold).fontColor('#4CAF50').margin({ top: 5 })
}
.flex(1).alignItems(HorizontalAlign.Center).padding(15).backgroundColor('#F5F5F5').borderRadius(5)
.margin({ left: 10 })
}
.margin({ bottom: 15 })
Column() {
Row() {
Text('最高评分:').fontSize(12)
Text(this.metrics.highestRatedAttraction).fontSize(12).fontWeight(FontWeight.Bold)
}
.margin({ bottom: 10 })
Row() {
Text('最低评分:').fontSize(12)
Text(this.metrics.lowestRatedAttraction).fontSize(12).fontWeight(FontWeight.Bold)
}
.margin({ bottom: 10 })
Row() {
Text('热门类别:').fontSize(12)
Text(this.metrics.mostPopularCategory).fontSize(12).fontWeight(FontWeight.Bold)
}
}
.padding(10).backgroundColor('#F5F5F5').borderRadius(5)
} else {
Text('请先添加景点').fontSize(12).fontColor('#999999')
}
}
.padding(15)
}
.tabBar('📊 指标')
TabContent() {
Column() {
Button('生成报告').width('100%').height(40).margin({ bottom: 15 })
.onClick(() => { this.generateReport(); })
if (this.report) {
Text('旅游报告').fontSize(16).fontWeight(FontWeight.Bold).margin({ bottom: 15 })
if (this.report.recommendations && this.report.recommendations.length > 0) {
Text('建议:').fontSize(14).fontWeight(FontWeight.Bold).margin({ bottom: 10 })
Column() {
ForEach(this.report.recommendations, (rec: string, index: number) => {
Row() {
Text('•').fontSize(14).fontWeight(FontWeight.Bold).margin({ right: 10 })
Text(rec).fontSize(11).flex(1)
}
.padding(10).margin({ bottom: 8 }).backgroundColor('#E3F2FD').borderRadius(5)
}, (rec: string, index: number) => index.toString())
}
}
}
}
.padding(15)
}
.tabBar('📈 报告')
}
.width('100%')
.flex(1)
}
.padding(10)
.width('100%')
.height('100%')
}
}
ArkTS代码说明:这个ArkTS实现展示了如何在OpenHarmony应用中集成旅游景点评分系统。通过使用标签页组件,用户可以在添加景点、查看评分列表、查看评分指标和生成报告之间切换。UI设计直观,提供了良好的用户体验。每个标签页都有不同的功能,用户可以全面地进行景点评分和旅游规划。
评分指标详解
景点评分维度
景观评分:景点的自然或人文景观质量,范围0-100。
设施评分:景点的基础设施和便利设施完善程度,范围0-100。
服务评分:景点提供的服务质量,范围0-100。
价格评分:景点价格的合理性,范围0-100。
综合评分:四个维度的加权平均,权重分别为35%、25%、25%、15%。
评分等级
5星:综合评分90-100分,景点质量优秀。
4星:综合评分80-89分,景点质量良好。
3星:综合评分70-79分,景点质量一般。
2星:综合评分60-69分,景点质量较差。
1星:综合评分0-59分,景点质量很差。
实战应用
应用场景1:旅游规划
旅游者可以使用这个系统评估不同景点,制定最优的旅游计划。
应用场景2:景点管理
景点管理部门可以使用这个系统了解游客评价,改进景点管理。
应用场景3:旅游推荐
旅游平台可以集成这个系统,为用户提供个性化的景点推荐。
应用场景4:旅游研究
旅游研究机构可以使用这个系统进行景点评估和旅游市场分析。
总结
旅游景点评分系统是现代旅游中的重要工具。通过KMP框架和OpenHarmony操作系统的结合,我们可以实现一个功能完整、高效可靠的景点评分系统。
这个工具不仅能够对景点进行多维度评分,还能够进行景点对比、生成旅游建议、提供个性化的景点推荐。通过本文介绍的Kotlin实现、JavaScript编译和ArkTS调用,旅游者可以快速构建自己的旅游决策系统。
在实际应用中,景点评分的价值远不止于此。从提升旅游体验到优化旅游资源配置,从支持旅游决策到促进旅游产业发展,景点评分都发挥着重要的作用。通过持续改进和优化,可以构建更加科学和高效的旅游评估体系。
掌握好景点评分的方法和工具,对于提升旅游体验和实现旅游目标都有重要的帮助。通过这个系统的学习和使用,希望能够帮助旅游者更好地了解景点特色,制定科学的旅游计划,享受美好的旅游体验。欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.csdn.net
更多推荐



所有评论(0)