Explorar el Código

添加地图可视化模块,更新计算接口,修改部分文本问题

DIng hace 4 meses
padre
commit
b3ed59e27e
Se han modificado 42 ficheros con 1244 adiciones y 733 borrados
  1. 91 5
      api/README.md
  2. BIN
      api/SoilAcidification.db
  3. BIN
      api/__pycache__/api_db.cpython-38.pyc
  4. BIN
      api/__pycache__/run.cpython-38.pyc
  5. 1 1
      api/app/__init__.py
  6. 20 0
      api/app/celery_app.py
  7. 15 4
      api/app/config.py
  8. 26 20
      api/app/model.py
  9. 495 487
      api/app/routes.py
  10. 109 0
      api/app/tasks.py
  11. 12 7
      api/app/utils.py
  12. BIN
      api/environment.yml
  13. BIN
      api/model_optimize/data/Acidity_reduce_new.xlsx
  14. 149 106
      api/model_optimize/data_increase.py
  15. 149 73
      api/model_optimize/learning_rate.py
  16. BIN
      api/pkl/gbstr_model_0112_1235.pkl
  17. BIN
      api/pkl/rf_model_0111_1637.pkl
  18. BIN
      api/pkl/rf_model_0111_2110.pkl
  19. BIN
      api/pkl/rf_model_0111_2112.pkl
  20. BIN
      api/pkl/rf_model_0111_2145.pkl
  21. BIN
      api/pkl/rf_model_0119_0910.pkl
  22. BIN
      api/pkl/rf_model_0119_0920.pkl
  23. BIN
      api/pkl/rf_model_0119_0921.pkl
  24. 2 1
      api/run.py
  25. 1 1
      api/uploads/data/X_test_reflux.csv
  26. 5 2
      app.json
  27. BIN
      assets/taddar/marker.png
  28. 5 0
      pages/Home/Home.js
  29. 4 0
      pages/Home/Home.wxml
  30. 1 1
      pages/b/b.js
  31. 7 7
      shoping/AcidNeutralizationModel/AcidNeutralizationModel.wxml
  32. 2 2
      shoping/Calculation/Calculation.js
  33. 6 6
      shoping/Calculation/Calculation.wxml
  34. 1 2
      shoping/ResearchFindings/ResearchFindings.wxml
  35. 1 1
      shoping/Soil Acidification/Soil Acidification.wxml
  36. 6 3
      shoping/Soil Deacidification/Soil Deacidification.wxml
  37. 3 3
      shoping/SoilPro/SoilPro.wxml
  38. 1 1
      shoping/Unit Team Profile/Unit Team Profile.wxml
  39. 115 0
      shoping/mapView/mapView.js
  40. 6 0
      shoping/mapView/mapView.json
  41. 10 0
      shoping/mapView/mapView.wxml
  42. 1 0
      shoping/mapView/mapView.wxss

+ 91 - 5
api/README.md

@@ -1,6 +1,92 @@
-# 环境搭建
+# 项目名称
 
-根据`environment.yml`文件新建conda环境
-~~~ 
-conda env create -f environment.yml
-~~~
+## 简介
+本项目旨在通过Flask框架构建一个Web应用,支持数据的导入、导出以及机器学习模型的训练和预测。项目使用SQLAlchemy进行数据库操作,并集成了Celery用于异步任务处理。
+
+## 环境搭建
+
+### 创建Conda环境
+
+1. 确保已安装Anaconda。
+2. 根据`environment.yml`文件新建conda环境:
+   ```bash
+   conda env create -f environment.yml
+   ```
+3. 激活新创建的环境:
+   ```bash
+   conda activate your_env_name
+   ```
+
+## 项目结构
+
+- `app/`: 包含Flask应用的主要代码。
+  - `__init__.py`: 初始化Flask应用。
+  - `config.py`: 配置文件。
+  - `utils.py`: 工具函数。
+  - `model.py`: 机器学习模型相关操作。
+  - `tasks.py`: Celery任务定义。
+  - `celery_app.py`: Celery配置。
+- `model_optimize/`: 包含数据处理和模型优化的代码。
+- `uploads/`: 用于存储上传的文件。
+- `ssl/`: 存储SSL证书和密钥。
+
+## 主要功能
+
+### 数据导入与导出
+
+- 支持Excel和CSV格式的数据导入。
+- 根据表名导出数据为Excel或CSV格式。
+
+### 机器学习模型
+
+- 支持多种机器学习模型的训练和预测。
+- 提供模型评分功能。
+
+### 异步任务
+
+- 使用Celery处理异步任务。
+
+## 使用方法
+
+### 启动应用
+
+1. 激活conda环境:
+   ```bash
+   conda activate your_env_name
+   ```
+
+2. 启动Flask应用:
+   ```bash
+   python run.py
+   ```
+
+3. 启动Celery:
+   ```bash
+   celery -A app.celery_app.celery worker --loglevel=info
+   ```
+
+### API接口
+
+- `/download_template`: 下载数据模板。
+- `/import_data`: 导入数据。
+- `/export_data`: 导出数据。
+- `/add_item`: 添加记录。
+
+## 配置
+
+在`app/config.py`中可以修改数据库路径、上传文件夹路径等配置。
+
+## 依赖
+
+请确保已安装以下依赖:
+
+- Flask
+- SQLAlchemy
+- Celery
+- Pandas
+- Scikit-learn
+- XGBoost
+
+## 许可证
+
+本项目遵循MIT许可证。

BIN
api/SoilAcidification.db


BIN
api/__pycache__/api_db.cpython-38.pyc


BIN
api/__pycache__/run.cpython-38.pyc


+ 1 - 1
api/app/__init__.py

@@ -13,7 +13,7 @@ def create_app():
     app = Flask(__name__)
     CORS(app)
     # 进行初始配置,加载配置文件等
-    app.config.from_object(config.Configs)
+    app.config.from_object(config.Config)
     app.logger.setLevel(logging.DEBUG)
     # 初始化 SQLAlchemy
     db.init_app(app)

+ 20 - 0
api/app/celery_app.py

@@ -0,0 +1,20 @@
+"""
+Celery配置文件
+"""
+from celery import Celery
+from app.config import Config
+
+# 创建Celery实例
+celery = Celery('app',
+                broker=Config.CELERY_BROKER_URL,
+                backend=Config.CELERY_RESULT_BACKEND,
+                include=['app.tasks'])
+
+# Celery配置
+celery.conf.update(
+    task_serializer='json',
+    accept_content=['json'],
+    result_serializer='json',
+    timezone='Asia/Shanghai',
+    enable_utc=True,
+)

+ 15 - 4
api/app/config.py

@@ -1,9 +1,20 @@
+"""
+配置文件
+"""
 import os
 
-class Configs:
-    SECRET_KEY = 'your_secret_key'
+class Config:
     DEBUG = True
-    MODEL_PATH = 'model_optimize/pkl/RF_filt.pkl'
     DATABASE = os.path.join(os.path.dirname(os.path.dirname(__file__)), 'SoilAcidification.db')
     SQLALCHEMY_DATABASE_URI = f'sqlite:///{DATABASE}'
-    UPLOAD_FOLDER = 'uploads/datasets'
+    UPLOAD_FOLDER = 'uploads/datasets'  # 上传excel文件保存路径
+    MODEL_SAVE_PATH = 'pkl'             # 模型保存路径
+    # Celery配置
+    CELERY_BROKER_URL = 'redis://localhost:6379/0'
+    CELERY_RESULT_BACKEND = 'redis://localhost:6379/0'
+    
+    # 定义阈值配置
+    THRESHOLD = 20
+    
+    # 定义自动训练默认模型类型配置
+    DEFAULT_MODEL_TYPE = 'RandomForest'

+ 26 - 20
api/app/model.py

@@ -10,6 +10,7 @@ from sqlalchemy import text
 from xgboost import XGBRegressor
 
 from .database_models import Models, Datasets
+from .config import Config
 
 
 # 加载模型
@@ -129,7 +130,7 @@ def save_current_dataset(session, data_type, commit=True):
     new_table_name = f"dataset_{dataset_id}"
     session.execute(text(f"CREATE TABLE {new_table_name} AS SELECT * FROM {source_table};"))
 
-    session.execute(text(f"UPDATE datasets SET status='processed', row_count=(SELECT count(*) FROM {new_table_name}) WHERE dataset_id={dataset_id};"))
+    session.execute(text(f"UPDATE datasets SET status='Datasets upgraded success', row_count=(SELECT count(*) FROM {new_table_name}) WHERE dataset_id={dataset_id};"))
 
     if commit:
         session.commit()
@@ -248,41 +249,47 @@ def train_gradient_boosting(X_train, y_train):
 
     return best_model
 
-def save_model(session, model, model_name, model_type, model_description, dataset_id, data_type, custom_path='pkl', commit=False):
+def save_model(session, model, model_name, model_type, model_description, dataset_id, data_type, commit=False):
     """
-    保存模型到数据库,并将模型文件保存到磁盘,但不立即提交事务。
-
-    :param session: 数据库会话
-    :param model: 要保存的模型对象
-    :param model_name: 模型的名称
-    :param model_type: 模型的类型
-    :param model_description: 模型的描述信息
-    :param dataset_id: 数据集ID
-    :param custom_path: 保存模型的路径
-    :param commit: 是否提交事务
-    :return: 返回保存的模型文件路径
+    保存模型到数据库,并将模型文件保存到磁盘。
+    
+    Args:
+        session: 数据库会话
+        model: 要保存的模型对象
+        model_name: 模型的名称
+        model_type: 模型的类型
+        model_description: 模型的描述信息
+        dataset_id: 数据集ID
+        data_type: 数据类型
+        commit: 是否提交事务
+    
+    Returns:
+        int: 返回保存的模型ID
     """
     prefix_dict = {
         'RandomForest': 'rf_model_',
-        'XGBRegressor': 'xgbr_model_',
-        'GBSTRegressor': 'gbstr_model_'
+        'XGBR': 'xgbr_model_',
+        'GBSTR': 'gbstr_model_'
     }
     prefix = prefix_dict.get(model_type, 'default_model_')
 
     try:
+        # 从配置中获取保存路径
+        model_save_path = Config.MODEL_SAVE_PATH
+        
         # 确保路径存在
-        os.makedirs(custom_path, exist_ok=True)
+        os.makedirs(model_save_path, exist_ok=True)
 
         # 获取当前时间戳
         timestamp = datetime.datetime.now().strftime('%m%d_%H%M')
 
         # 拼接完整的文件名
-        file_name = os.path.join(custom_path, f'{prefix}{timestamp}.pkl')
+        file_name = os.path.join(model_save_path, f'{prefix}{timestamp}.pkl')
 
         # 保存模型到文件
         with open(file_name, 'wb') as f:
             pickle.dump(model, f)
-        print(f"模型已保存: {file_name}")
+        print(f"模型已保存: {file_name}")
 
         # 创建模型数据库记录
         new_model = Models(
@@ -299,11 +306,10 @@ def save_model(session, model, model_name, model_type, model_description, datase
         session.add(new_model)
         session.flush()
 
-        # 返回模型ID
         return new_model.ModelID
 
     except Exception as e:
-        print(f"Error saving model: {str(e)}")
+        print(f"保存模型时发生错误: {str(e)}")
         raise
 
 

La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 495 - 487
api/app/routes.py


+ 109 - 0
api/app/tasks.py

@@ -0,0 +1,109 @@
+"""
+Celery任务定义文件
+"""
+from celery import current_task
+
+from app.celery_app import celery
+import time
+
+from .database_models import Models, Datasets
+from .model import train_and_save_model, calculate_model_score
+import logging
+from . import create_app, db
+import os
+
+@celery.task(name='train_model_task')
+def train_model_task(model_type, model_name, model_description, data_type, dataset_id=None):
+    """
+    异步训练模型任务
+    
+    Args:
+        model_type: 模型类型
+        model_name: 模型名称
+        model_description: 模型描述
+        data_type: 数据类型
+        dataset_id: 数据集ID
+        
+    Returns:
+        dict: 训练结果
+    """
+    # 创建应用上下文
+    app = create_app()
+    session = None
+    
+    try:
+        with app.app_context():
+            # 确保数据库文件存在
+            if not os.path.exists(app.config['DATABASE']):
+                db.create_all()
+            
+            # 创建新的数据库引擎和会话
+            from sqlalchemy import create_engine
+            from sqlalchemy.orm import scoped_session, sessionmaker
+            
+            engine = create_engine(app.config['SQLALCHEMY_DATABASE_URI'])
+            session_factory = sessionmaker(bind=engine)
+            Session = scoped_session(session_factory)
+            session = Session()
+            
+            # 添加日志记录
+            logging.info(f"Starting auto-training for {data_type} dataset with {model_type} model")
+            
+            # 调用训练函数
+            model_name, model_id = train_and_save_model(
+                session, 
+                model_type, 
+                model_name, 
+                model_description, 
+                data_type, 
+                dataset_id
+            )
+
+            # 计算模型评分
+            if model_id:
+                model_info = session.query(Models).filter(Models.ModelID == model_id).first()
+                if model_info:
+                    score = calculate_model_score(model_info)
+                    # 更新模型评分
+                    model_info.Performance_score = score
+                    session.commit()
+
+            
+            logging.info(f"Auto-training completed successfully. Model ID: {model_id}")
+            
+            # 模拟训练过程
+            # 训练成功后更新状态
+            dataset = session.query(Datasets).filter_by(Dataset_ID=dataset_id).first()
+            if not dataset:
+                raise ValueError("Dataset not found")
+
+            # 如果训练成功
+            dataset.Status = 'training_success'
+            session.commit()
+
+            return {
+                'status': 'success',
+                'model_name': model_name,
+                'model_id': model_id,
+                'model_score': score,
+                'message': 'Model trained successfully'
+            }
+            
+    except Exception as e:
+        logging.error(f"Failed to train model: {str(e)}")
+        
+        # 更新任务状态为 FAILURE
+        current_task.update_state(state='FAILURE', meta={'error': str(e)})
+        
+        # 更新数据集状态为训练失败
+        if session:
+            dataset = session.query(Datasets).filter_by(Dataset_ID=dataset_id).first()
+            if dataset:
+                dataset.Status = 'training_failed'
+                session.commit()
+        
+        raise  # 重新抛出异常以确保 Celery 记录任务失败
+    finally:
+        if session:
+            session.close()
+            Session.remove()  # 清理scoped session 

+ 12 - 7
api/app/utils.py

@@ -114,12 +114,12 @@ def rename_columns_for_model_predict(dataframe, dataset_type):
         }
     elif dataset_type == 'reflux':
         rename_map = {
-            "organic_matter": "OM",
-            "chloride": "CL",
-            "cec": "CEC",
-            "h_concentration": "H_plus",
-            "n": "N",
-            "al_concentration": "Al3_plus"
+            "OM": "OM",
+            "CL": "CL",
+            "CEC": "CEC",
+            "H+": "H_plus",
+            "N": "N",
+            "Al3+": "Al3_plus"
         }
 
     # 使用 rename() 方法更新列名
@@ -185,6 +185,11 @@ def get_dataset_by_id(session, dataset_id):
 
 def predict_to_Q(predictions, init_ph, target_ph):
     # 将预测结果转换为Q
-    Q = predictions * (init_ph - target_ph)
+    Q = predictions * (target_ph - init_ph)
     return Q
 
+# 说明:Q指生石灰投加量,单位是%,例如1%代表100g土壤中施加1g生石灰。
+# 其中,土壤是指表层20cm土壤。# 如果Q的单位换算为吨/公顷,即t/ha,则需要乘以25。
+# ΔpH=目标pH-初始pH
+def Q_to_t_ha(Q):
+    return Q * 25

BIN
api/environment.yml


BIN
api/model_optimize/data/Acidity_reduce_new.xlsx


+ 149 - 106
api/model_optimize/data_increase.py

@@ -26,99 +26,141 @@ from sklearn.metrics import log_loss
 from sklearn.metrics import roc_auc_score
 
 import pickle
-import pandas as pd
-import numpy as np
-from sklearn.metrics import mean_squared_error
 from pathlib import Path
 
-# ## 土壤反酸筛选数据  64个样本 9个特征(包含delta_ph)  105_day_ph
-# data=pd.read_excel('model_optimize\data\data_filt.xlsx')   
-
-# x = data.iloc[:,1:10]
-# print(x)
-# y = data.iloc[:,-1]
-# print(y)
-
-# # 为 x 赋予列名
-# x.columns = [
-#     'organic_matter',        # OM g/kg
-#     'chloride',              # CL g/kg
-#     'cec',                   # CEC cmol/kg
-#     'h_concentration',       # H+ cmol/kg
-#     'hn',                    # HN mg/kg
-#     'al_concentration',      # Al3+ cmol/kg
-#     'free_alumina',          # Free alumina g/kg
-#     'free_iron',             # Free iron oxides g/kg
-#     'delta_ph'               # ΔpH
-# ]
-
-# y.name = 'target_ph'
-
-
-# ## 土壤反酸筛选数据   64个样本 8个特征 delta_ph
-# # data=pd.read_excel('model_optimize\data\data_filt.xlsx')    # 64个样本
-# data=pd.read_excel('model_optimize\data\data_filt - 副本.xlsx')   # 60个样本(去除异常点)
-
-# x = data.iloc[:,1:9]
-# print(x)
-
-# y = data.iloc[:,-2]
-# print(y)
-
-# # 为 x 赋予列名
-# x.columns = [
-#     'organic_matter',        # OM g/kg
-#     'chloride',              # CL g/kg
-#     'cec',                   # CEC cmol/kg
-#     'h_concentration',       # H+ cmol/kg
-#     'hn',                    # HN mg/kg
-#     'al_concentration',      # Al3+ cmol/kg
-#     'free_alumina',          # Free alumina g/kg
-#     'free_iron',             # Free iron oxides g/kg
-# ]
-
-# y.name = 'target_ph'
-
-
-
-## 土壤反酸筛选数据  最新数据:34个样本 6个特征 delta_ph
-data=pd.read_excel('model_optimize\data\data_reflux2.xlsx')   
-
-x = data.iloc[:,0:6]
+# 定义数据集配置
+DATASET_CONFIGS = {
+    'soil_acid_9features': {
+        'file_path': 'model_optimize/data/data_filt.xlsx',
+        'x_columns': range(1, 10),  # 9个特征(包含delta_ph)
+        'y_column': -1,  # 105_day_ph
+        'feature_names': [
+            'organic_matter',        # OM g/kg
+            'chloride',              # CL g/kg
+            'cec',                   # CEC cmol/kg
+            'h_concentration',       # H+ cmol/kg
+            'hn',                    # HN mg/kg
+            'al_concentration',      # Al3+ cmol/kg
+            'free_alumina',          # Free alumina g/kg
+            'free_iron',             # Free iron oxides g/kg
+            'delta_ph'               # ΔpH
+        ],
+        'target_name': 'target_ph'
+    },
+    'soil_acid_8features': {
+        'file_path': 'model_optimize/data/data_filt - 副本.xlsx',
+        'x_columns': range(1, 9),  # 8个特征
+        'y_column': -2,  # delta_ph
+        'feature_names': [
+            'organic_matter',        # OM g/kg
+            'chloride',              # CL g/kg
+            'cec',                   # CEC cmol/kg
+            'h_concentration',       # H+ cmol/kg
+            'hn',                    # HN mg/kg
+            'al_concentration',      # Al3+ cmol/kg
+            'free_alumina',          # Free alumina g/kg
+            'free_iron',             # Free iron oxides g/kg
+        ],
+        'target_name': 'target_ph'
+    },
+    'soil_acid_8features_original': {
+        'file_path': 'model_optimize/data/data_filt.xlsx',
+        'x_columns': range(1, 9),  # 8个特征
+        'y_column': -2,  # delta_ph
+        'feature_names': [
+            'organic_matter',        # OM g/kg
+            'chloride',              # CL g/kg
+            'cec',                   # CEC cmol/kg
+            'h_concentration',       # H+ cmol/kg
+            'hn',                    # HN mg/kg
+            'al_concentration',      # Al3+ cmol/kg
+            'free_alumina',          # Free alumina g/kg
+            'free_iron',             # Free iron oxides g/kg
+        ],
+        'target_name': 'target_ph'
+    },
+    'soil_acid_6features': {
+        'file_path': 'model_optimize/data/data_reflux2.xlsx',
+        'x_columns': range(0, 6),  # 6个特征
+        'y_column': -1,  # delta_ph
+        'feature_names': [
+            'organic_matter',        # OM g/kg
+            'chloride',              # CL g/kg
+            'cec',                   # CEC cmol/kg
+            'h_concentration',       # H+ cmol/kg
+            'hn',                    # HN mg/kg
+            'al_concentration',      # Al3+ cmol/kg
+        ],
+        'target_name': 'delta_ph'
+    },
+    'acidity_reduce': {
+        'file_path': 'model_optimize/data/Acidity_reduce.xlsx',
+        'x_columns': range(1, 6),  # 5个特征
+        'y_column': 0,  # 1/b
+        'feature_names': [
+            'pH',        
+            'OM',              
+            'CL', 
+            'H',
+            'Al'
+        ],
+        'target_name': 'target'
+    },
+    'acidity_reduce_new': {
+        'file_path': 'model_optimize/data/Acidity_reduce_new.xlsx',
+        'x_columns': range(1, 6),  # 5个特征
+        'y_column': 0,  # 1/b
+        'feature_names': [
+            'pH',        
+            'OM',              
+            'CL', 
+            'H',
+            'Al'
+        ],
+        'target_name': 'target'
+    }
+}
+
+def load_dataset(dataset_name):
+    """
+    加载指定的数据集
+    
+    Args:
+        dataset_name: 数据集配置名称
+        
+    Returns:
+        x: 特征数据
+        y: 目标数据
+    """
+    if dataset_name not in DATASET_CONFIGS:
+        raise ValueError(f"未知的数据集名称: {dataset_name}")
+    
+    config = DATASET_CONFIGS[dataset_name]
+    data = pd.read_excel(config['file_path'])
+    
+    x = data.iloc[:, config['x_columns']]
+    y = data.iloc[:, config['y_column']]
+    
+    # 设置列名
+    x.columns = config['feature_names']
+    y.name = config['target_name']
+    
+    return x, y
+
+# 选择要使用的数据集
+# dataset_name = 'soil_acid_9features'              # 土壤反酸数据:64个样本,9个特征(包含delta_ph),目标 105_day_ph
+# dataset_name = 'soil_acid_8features_original'     # 土壤反酸数据:64个样本,8个特征,目标 delta_ph
+dataset_name = 'soil_acid_8features'                # 土壤反酸数据:60个样本(去除异常点),8个特征,目标 delta_ph
+# dataset_name = 'soil_acid_6features'              # 土壤反酸数据:34个样本,6个特征,目标 delta_ph
+# dataset_name = 'acidity_reduce'                   # 精准降酸数据:54个样本,5个特征,目标是1/b
+# dataset_name = 'acidity_reduce_new'                   # 精准降酸数据(数据更新):54个样本,5个特征,目标是1/b
+x, y = load_dataset(dataset_name)
+
+print("特征数据:")
 print(x)
-y = data.iloc[:,-1]
-
+print("\n目标数据:")
 print(y)
 
-# 为 x 赋予列名
-x.columns = [
-    'organic_matter',        # OM g/kg
-    'chloride',              # CL g/kg
-    'cec',                   # CEC cmol/kg
-    'h_concentration',       # H+ cmol/kg
-    'hn',                    # HN mg/kg    ....
-    'al_concentration',      # Al3+ cmol/kg
-]
-
-y.name = 'delta_ph'
-
-
-# ## 精准降酸数据  54个样本 5个特征  1/b
-# data=pd.read_excel('model_optimize\data\Acidity_reduce.xlsx')
-
-# x = data.iloc[:,1:]
-# y = data.iloc[:,0]
-# # 为 x 赋予列名
-# x.columns = [
-#     'pH',        
-#     'OM',              
-#     'CL', 
-#     'H',
-#     'Al'
-# ]
-# y.name = 'target'
-
-
 ## 数据集划分
 Xtrain, Xtest, Ytrain, Ytest = train_test_split(x, y, test_size=0.2, random_state=42)
 
@@ -142,7 +184,7 @@ r2_scores_knn = []  # 用来记录KNN的r2_score
 
 
 # 对于每种训练集大小,训练模型并记录r2_score
-for size in train_sizes:
+for size in train_sizes[:10]:
     # 计算当前训练集的大小
     current_size = int(size * len(Xtrain))
     
@@ -197,11 +239,12 @@ plt.title('Model Performance with Incremental Data')
 plt.legend()
 plt.grid(True)
 plt.show()
-# # 打印JavaScript中需要的数据格式
-# print("X轴数据(训练数据大小):", [f"{int(size * 100)}%" for size in train_sizes])
-# print("Random Forest R2分数:", r2_scores_rfc)
-# print("XGBoost R2分数:", r2_scores_xgb)
-# print("Gradient Boosting R2分数:", r2_scores_gbst)
+
+# 打印JavaScript中需要的数据格式
+print("X轴数据(训练数据大小):", [f"{int(size * 100)}%" for size in train_sizes])
+print("Random Forest R2分数:", r2_scores_rfc)
+print("XGBoost R2分数:", r2_scores_xgb)
+print("Gradient Boosting R2分数:", r2_scores_gbst)
 
 
 
@@ -215,21 +258,21 @@ plt.ylabel('Predicted Values')
 plt.title('True vs Predicted Values')
 plt.grid(True)
 plt.show()
-# # 生成 scatterData
-# scatter_data = [[float(true), float(pred)] for true, pred in zip(Ytest, y_pred)]
-# # 打印 scatterData(可直接复制到 JavaScript 代码中)
-# print("scatterData = ", scatter_data)
+# 生成 scatterData
+scatter_data = [[float(true), float(pred)] for true, pred in zip(Ytest, y_pred)]
+# 打印 scatterData(可直接复制到 JavaScript 代码中)
+print("scatterData = ", scatter_data)
 
-# 保存 X_test 和 Y_test 为 CSV 文件
-X_test_df = pd.DataFrame(Xtest)
-Y_test_df = pd.DataFrame(Ytest)
+# # 保存 X_test 和 Y_test 为 CSV 文件
+# X_test_df = pd.DataFrame(Xtest)
+# Y_test_df = pd.DataFrame(Ytest)
 
-# 将 X_test 和 Y_test 保存为 CSV 文件,方便之后加载
-X_test_df.to_csv('X_test_reflux.csv', index=False)
-Y_test_df.to_csv('Y_test_reflux.csv', index=False)
+# # 将 X_test 和 Y_test 保存为 CSV 文件,方便之后加载
+# X_test_df.to_csv('X_test_reflux.csv', index=False)
+# Y_test_df.to_csv('Y_test_reflux.csv', index=False)
 
-# 输出提示信息
-print("X_test 和 Y_test 已保存为 'X_test_reduce.csv' 和 'Y_test_reduce.csv'")
+# # 输出提示信息
+# print("X_test 和 Y_test 已保存为 'X_test_reduce.csv' 和 'Y_test_reduce.csv'")
 
 
 

+ 149 - 73
api/model_optimize/learning_rate.py

@@ -2,86 +2,158 @@ from sklearn.model_selection import learning_curve
 import numpy as np
 import matplotlib.pyplot as plt
 from sklearn.ensemble import RandomForestRegressor
+from xgboost import XGBRegressor as XGBR
 import pandas as pd
 from sklearn.model_selection import train_test_split
 
-
-## 精准降酸数据  54个样本 5个特征  1/b
-data=pd.read_excel('model_optimize\data\Acidity_reduce.xlsx')
-
-x = data.iloc[:,1:]
-y = data.iloc[:,0]
-# 为 x 赋予列名
-x.columns = [
-    'pH',        
-    'OM',              
-    'CL', 
-    'H',
-    'Al'
-]
-y.name = 'target'
-
-# ## 土壤反酸筛选数据  64个样本 9个特征(包含delta_ph)  105_day_ph
-# data=pd.read_excel('model_optimize\data\data_filt.xlsx')   
-
-# x = data.iloc[:,1:10]
-# print(x)
-# y = data.iloc[:,-1]
-# print(y)
-
-# # 为 x 赋予列名
-# x.columns = [
-#     'organic_matter',        # OM g/kg
-#     'chloride',              # CL g/kg
-#     'cec',                   # CEC cmol/kg
-#     'h_concentration',       # H+ cmol/kg
-#     'hn',                    # HN mg/kg
-#     'al_concentration',      # Al3+ cmol/kg
-#     'free_alumina',          # Free alumina g/kg
-#     'free_iron',             # Free iron oxides g/kg
-#     'delta_ph'               # ΔpH
-# ]
-
-# y.name = 'target_ph'
-
-# ## 土壤反酸筛选数据   64个样本 8个特征 delta_ph
-# # data=pd.read_excel('model_optimize\data\data_filt.xlsx')    # 64个样本
-# data=pd.read_excel('model_optimize\data\data_filt - 副本.xlsx')   # 60个样本(去除异常点)
-
-# x = data.iloc[:,1:9]
-# print(x)
-
-# y = data.iloc[:,-2]
-# print(y)
-
-# # 为 x 赋予列名
-# x.columns = [
-#     'organic_matter',        # OM g/kg
-#     'chloride',              # CL g/kg
-#     'cec',                   # CEC cmol/kg
-#     'h_concentration',       # H+ cmol/kg
-#     'hn',                    # HN mg/kg
-#     'al_concentration',      # Al3+ cmol/kg
-#     'free_alumina',          # Free alumina g/kg
-#     'free_iron',             # Free iron oxides g/kg
-# ]
-
-# y.name = 'target_ph'
+# 定义数据集配置
+DATASET_CONFIGS = {
+    'soil_acid_9features': {
+        'file_path': 'model_optimize/data/data_filt.xlsx',
+        'x_columns': range(1, 10),  # 9个特征(包含delta_ph)
+        'y_column': -1,  # 105_day_ph
+        'feature_names': [
+            'organic_matter',        # OM g/kg
+            'chloride',              # CL g/kg
+            'cec',                   # CEC cmol/kg
+            'h_concentration',       # H+ cmol/kg
+            'hn',                    # HN mg/kg
+            'al_concentration',      # Al3+ cmol/kg
+            'free_alumina',          # Free alumina g/kg
+            'free_iron',             # Free iron oxides g/kg
+            'delta_ph'               # ΔpH
+        ],
+        'target_name': 'target_ph'
+    },
+    'soil_acid_8features': {
+        'file_path': 'model_optimize/data/data_filt - 副本.xlsx',
+        'x_columns': range(1, 9),  # 8个特征
+        'y_column': -2,  # delta_ph
+        'feature_names': [
+            'organic_matter',        # OM g/kg
+            'chloride',              # CL g/kg
+            'cec',                   # CEC cmol/kg
+            'h_concentration',       # H+ cmol/kg
+            'hn',                    # HN mg/kg
+            'al_concentration',      # Al3+ cmol/kg
+            'free_alumina',          # Free alumina g/kg
+            'free_iron',             # Free iron oxides g/kg
+        ],
+        'target_name': 'target_ph'
+    },
+    'soil_acid_8features_original': {
+        'file_path': 'model_optimize/data/data_filt.xlsx',
+        'x_columns': range(1, 9),  # 8个特征
+        'y_column': -2,  # delta_ph
+        'feature_names': [
+            'organic_matter',        # OM g/kg
+            'chloride',              # CL g/kg
+            'cec',                   # CEC cmol/kg
+            'h_concentration',       # H+ cmol/kg
+            'hn',                    # HN mg/kg
+            'al_concentration',      # Al3+ cmol/kg
+            'free_alumina',          # Free alumina g/kg
+            'free_iron',             # Free iron oxides g/kg
+        ],
+        'target_name': 'target_ph'
+    },
+    'soil_acid_6features': {
+        'file_path': 'model_optimize/data/data_reflux2.xlsx',
+        'x_columns': range(0, 6),  # 6个特征
+        'y_column': -1,  # delta_ph
+        'feature_names': [
+            'organic_matter',        # OM g/kg
+            'chloride',              # CL g/kg
+            'cec',                   # CEC cmol/kg
+            'h_concentration',       # H+ cmol/kg
+            'hn',                    # HN mg/kg
+            'al_concentration',      # Al3+ cmol/kg
+        ],
+        'target_name': 'delta_ph'
+    },
+    'acidity_reduce': {
+        'file_path': 'model_optimize/data/Acidity_reduce.xlsx',
+        'x_columns': range(1, 6),  # 5个特征
+        'y_column': 0,  # 1/b
+        'feature_names': [
+            'pH',        
+            'OM',              
+            'CL', 
+            'H',
+            'Al'
+        ],
+        'target_name': 'target'
+    },
+    'acidity_reduce_new': {
+        'file_path': 'model_optimize/data/Acidity_reduce_new.xlsx',
+        'x_columns': range(1, 6),  # 5个特征
+        'y_column': 0,  # 1/b
+        'feature_names': [
+            'pH',        
+            'OM',              
+            'CL', 
+            'H',
+            'Al'
+        ],
+        'target_name': 'target'
+    }
+}
+
+def load_dataset(dataset_name):
+    """
+    加载指定的数据集
+    
+    Args:
+        dataset_name: 数据集配置名称
+        
+    Returns:
+        x: 特征数据
+        y: 目标数据
+    """
+    if dataset_name not in DATASET_CONFIGS:
+        raise ValueError(f"未知的数据集名称: {dataset_name}")
+    
+    config = DATASET_CONFIGS[dataset_name]
+    data = pd.read_excel(config['file_path'])
+    
+    x = data.iloc[:, config['x_columns']]
+    y = data.iloc[:, config['y_column']]
+    
+    # 设置列名
+    x.columns = config['feature_names']
+    y.name = config['target_name']
+    
+    return x, y
+
+# 选择要使用的数据集
+# dataset_name = 'soil_acid_9features'              # 土壤反酸数据:64个样本,9个特征(包含delta_ph),目标 105_day_ph
+# dataset_name = 'soil_acid_8features_original'     # 土壤反酸数据:64个样本,8个特征,目标 delta_ph
+# dataset_name = 'soil_acid_8features'              # 土壤反酸数据:60个样本(去除异常点),8个特征,目标 delta_ph
+# dataset_name = 'soil_acid_6features'              # 土壤反酸数据:34个样本,6个特征,目标 delta_ph
+dataset_name = 'acidity_reduce'                   # 精准降酸数据:54个样本,5个特征,目标是1/b
+# dataset_name = 'acidity_reduce_new'                   # 精准降酸数据(数据更新):54个样本,5个特征,目标是1/b
+
+x, y = load_dataset(dataset_name)
+
+print("特征数据:")
+print(x)
+print("\n目标数据:")
+print(y)
 
 ## 数据集划分
 Xtrain, Xtest, Ytrain, Ytest = train_test_split(x, y, test_size=0.2, random_state=42)
 
-
 # 模型:使用 RandomForestRegressor 举例
 rfc = RandomForestRegressor(random_state=1)
+XGB = XGBR(random_state=1)
 
 # 计算学习曲线
 train_sizes, train_scores, test_scores = learning_curve(
-    rfc,                         # 使用的模型
-    Xtrain,                           # 训练特征
-    Ytrain,                           # 训练目标
-    cv=5,                         # 交叉验证折数
-    n_jobs=-1,                    # 使用所有可用的CPU核心进行并行计算
+    rfc,                            # 使用的模型
+    Xtrain,                         # 训练特征
+    Ytrain,                         # 训练目标
+    cv=5,                           # 交叉验证折数
+    n_jobs=-1,                      # 使用所有可用的CPU核心进行并行计算
     train_sizes=np.linspace(0.1, 1.0, 10)  # 训练集大小,从10%到100%,共10个点
 )
 
@@ -89,15 +161,15 @@ train_sizes, train_scores, test_scores = learning_curve(
 print("test_scores: \n", test_scores)
 print("train_scores: \n", train_scores)
 
-import matplotlib.pyplot as plt
-import numpy as np
-
 # 绘制学习曲线
 plt.figure(figsize=(8, 6))
 
+# 将训练样本数转换为百分比
+train_sizes_pct = train_sizes / len(Xtrain) * 100
+
 # 绘制训练误差和测试误差
-plt.plot(train_sizes, np.mean(train_scores, axis=1), label="Training score", color="r")
-plt.plot(train_sizes, np.mean(test_scores, axis=1), label="Cross-validation score", color="g")
+plt.plot(train_sizes_pct, np.mean(train_scores, axis=1), label="Training score", color="r")
+plt.plot(train_sizes_pct, np.mean(test_scores, axis=1), label="Cross-validation score", color="g")
 
 # 绘制图形的细节
 plt.title("Learning Curve (Random Forest Regressor)")
@@ -105,4 +177,8 @@ plt.xlabel("Training Size (%)")
 plt.ylabel("Score (R²)")
 plt.legend(loc="best")
 plt.grid(True)
+
+# 设置x轴刻度为10的整数倍
+plt.xticks(np.arange(0, 101, 10))
+
 plt.show()

BIN
api/pkl/gbstr_model_0112_1235.pkl


BIN
api/pkl/rf_model_0111_1637.pkl


BIN
api/pkl/rf_model_0111_2110.pkl


BIN
api/pkl/rf_model_0111_2112.pkl


BIN
api/pkl/rf_model_0111_2145.pkl


BIN
api/pkl/rf_model_0119_0910.pkl


BIN
api/pkl/rf_model_0119_0920.pkl


BIN
api/pkl/rf_model_0119_0921.pkl


+ 2 - 1
api/run.py

@@ -1,7 +1,7 @@
 from flask import request
 
 from app import create_app
-
+import os
 # 创建 Flask 应用
 app = create_app()
 context = ('ssl/cert.crt', 'ssl/cert.key')
@@ -16,3 +16,4 @@ def force_https():
 # 启动服务器
 if __name__ == '__main__':
     app.run(host="0.0.0.0", port=5000, debug=True, ssl_context=context)
+

+ 1 - 1
api/uploads/data/X_test_reflux.csv

@@ -1,4 +1,4 @@
-organic_matter,chloride,cec,h_concentration,hn,al_concentration
+OM,CL,CEC,H_plus,N,Al3_plus
 11.4,570.6,6.21,3.12,0.07897,0.733
 26.291,165.8,8.49278,0.98064,0.11042,2.51676
 18.77436,60.4,5.53292,0.82512,0.08111,2.82888

+ 5 - 2
app.json

@@ -13,6 +13,7 @@
     {
       "root": "shoping",
       "pages": [
+        "mapView/mapView",
         "thres/thres",
         "SoilPro/SoilPro",
         "ModelTrain/ModelTrain",
@@ -31,7 +32,9 @@
     },
     {
       "root": "pages/Result",
-      "pages": ["Result"]
+      "pages": [
+        "Result"
+      ]
     }
   ],
   "window": {
@@ -73,4 +76,4 @@
     ]
   },
   "sitemapLocation": "sitemap.json"
-}
+}

BIN
assets/taddar/marker.png


+ 5 - 0
pages/Home/Home.js

@@ -53,5 +53,10 @@ Page({
     wx.navigateTo({
       url: '/shoping/Unit Team Profile/Unit Team Profile'
     });
+  },
+  mapView() {
+    wx.navigateTo({
+      url: '/shoping/mapView/mapView'
+    });
   }
 });

+ 4 - 0
pages/Home/Home.wxml

@@ -15,6 +15,10 @@
     <image class="card-icon" src="/assets/taddar/团队介绍@1x.png" />
     <text class="card-title">团队信息</text>
   </view>
+  <view class="card" bindtap="mapView">
+    <image class="card-icon" src="/assets/taddar/团队介绍@1x.png" />
+    <text class="card-title">地图展示</text>
+  </view>
 </view>
 
 <!-- 底部导航栏 -->

+ 1 - 1
pages/b/b.js

@@ -40,7 +40,7 @@ Page({
     setTimeout(() => {
       // 发送请求到后端,进行用户注册
       wx.request({
-        url: 'https://127.0.0.1:5000/register', // 后端注册接口
+        url: 'https://soilgd.com:5000/register', // 后端注册接口
         method: 'POST',
         data: {
           name: name,        // 修改为 name

+ 7 - 7
shoping/AcidNeutralizationModel/AcidNeutralizationModel.wxml

@@ -17,7 +17,7 @@
       <view class="page-section-title">土壤目标 pH:</view>
       <input 
         class="input-field"  
-        placeholder="3~6" 
+        placeholder="5~7" 
         value="{{target_pH}}" 
         bindinput="onTargetPhChange" 
         inputmode="decimal"  
@@ -27,7 +27,7 @@
 
   <view class="white-box">
     <view class="input-row">
-      <view class="page-section-title">土壤有机质(g/kg) OM:</view>
+      <view class="page-section-title">土壤有机质(g/kg):</view>
       <input 
         class="input-field" 
         type="text" 
@@ -41,7 +41,7 @@
 
   <view class="white-box">
     <view class="input-row">
-      <view class="page-section-title">土壤粘粒(g/kg) CL:</view>
+      <view class="page-section-title">土壤粘粒(g/kg):</view>
       <input 
         class="input-field" 
         type="text" 
@@ -55,7 +55,7 @@
 
   <view class="white-box">
     <view class="input-row">
-      <view class="page-section-title">交换性氢(cmol/kg) H+:</view>
+      <view class="page-section-title">交换性氢(cmol/kg):</view>
       <input 
         class="input-field" 
         type="text" 
@@ -69,7 +69,7 @@
 
   <view class="white-box">
     <view class="input-row">
-      <view class="page-section-title">交换性铝(cmol/kg) Al3+:</view>
+      <view class="page-section-title">交换性铝(cmol/kg):</view>
       <input 
         class="input-field" 
         type="text" 
@@ -85,11 +85,11 @@
   <view wx:if="{{showModal}}" class="modal-overlay">
     <view class="modal">
       <view class="modal-header">
-        <text>100克土壤撒{{result}}克生石灰</text>
+        <text>每亩土壤(表层20cm)撒{{result}}吨生石灰</text>
         <button class="close-btn" bindtap="closeModal">×</button>
       </view>
       <view class="modal-body">
-        <text>{{result}}</text>
+        <text>{{result}}</text>
       </view>
     </view>
   </view>

+ 2 - 2
shoping/Calculation/Calculation.js

@@ -72,7 +72,7 @@ Page({
   calculate: function() {
     console.log('开始计算...');
     const data = {
-      model_id: 13,
+      model_id: 9,
       parameters: {
         organic_matter: this.data.OM,
         chloride: this.data.CL,
@@ -97,7 +97,7 @@ Page({
         if (res.data.result && Array.isArray(res.data.result)) {
           const result = res.data.result[0] ? res.data.result[0].toString() : '无结果';
           this.setData({
-            result: parseFloat(result).toFixed(5),
+            result: parseFloat(result).toFixed(2),
             showResultPopup: true, // 显示弹窗
           });
         } else {

+ 6 - 6
shoping/Calculation/Calculation.wxml

@@ -2,7 +2,7 @@
 <view class="page-body">
   <view class="white-box">
     <view class="input-row">
-      <view class="page-section-title">土壤有机质(g/kg) OM:</view>
+      <view class="page-section-title">土壤有机质(g/kg):</view>
       <input 
         class="input-field" 
         type="text" 
@@ -18,7 +18,7 @@
 <view class="page-body">
   <view class="white-box">
     <view class="input-row">
-      <view class="page-section-title">土壤粘粒(g/kg) CL:</view>
+      <view class="page-section-title">土壤粘粒(g/kg):</view>
       <input 
         class="input-field" 
         type="text" 
@@ -34,7 +34,7 @@
 <view class="page-body">
   <view class="white-box">
     <view class="input-row">
-      <view class="page-section-title">阳离子交换量(cmol/kg) CEC:</view>
+      <view class="page-section-title">阳离子交换量(cmol/kg):</view>
       <input 
         class="input-field" 
         type="text" 
@@ -50,7 +50,7 @@
 <view class="page-body">
   <view class="white-box">
     <view class="input-row">
-      <view class="page-section-title">交换性氢(cmol/kg) H+:</view>
+      <view class="page-section-title">交换性氢(cmol/kg):</view>
       <input 
         class="input-field" 
         type="text" 
@@ -66,7 +66,7 @@
 <view class="page-body">
   <view class="white-box">
     <view class="input-row">
-      <view class="page-section-title">水解氮(g/kg) N:</view>
+      <view class="page-section-title">水解氮(g/kg):</view>
       <input 
         class="input-field" 
         type="text" 
@@ -82,7 +82,7 @@
 <view class="page-body">
   <view class="white-box">
     <view class="input-row">
-      <view class="page-section-title">交换性铝(cmol/kg) Al3+:</view>
+      <view class="page-section-title">交换性铝(cmol/kg):</view>
       <input 
         class="input-field" 
         type="text" 

+ 1 - 2
shoping/ResearchFindings/ResearchFindings.wxml

@@ -3,9 +3,8 @@
 </view>
 <view class="container">
   <view class="section">
-    <text class="content">广东省典型区域土壤环境质量及农产品安全研究,在广东省典型区域率先系统地开展了土壤环境质量的探查研究,为新的国家土壤环境质量标准修订稿中有关有机污染物指标限值的确定提供了科广东省典型区域土壤环境质量及农产品安全研究,在广东省典型区域率先系统地开展了土壤环境质量的探查研究,为新的国土壤环境质量标准修订稿中有关有机污染物指标限值的确定提供了科学依据,并为全国开展土壤有机污染物调查提供了重要参考。相关成果获得2009年度⼴东省科学技术⼀等奖。</text>
+    <text class="content">广东省典型区域土壤环境质量及农产品安全研究,在广东省典型区域率先系统地开展了土壤环境质量的探查研究,为新的国家土壤环境质量标准修订稿中有关有机污染物指标限值的确定提供了科广东省典型区域土壤环境质量及农产品安全研究,在广东省典型区域率先系统地开展了土壤环境质量的探查研究,为新的国土壤环境质量标准修订稿中有关有机污染物指标限值的确定提供了科学依据,并为全国开展土壤有机污染物调查提供了重要参考。</text>
   </view>
 </view>
 
-<image class="navigat-arrow" src="/assets/taddar/12.png" />
 

+ 1 - 1
shoping/Soil Acidification/Soil Acidification.wxml

@@ -7,8 +7,8 @@
 <text class="sub-title">\n有机质含量(g/kg)</text>
 <text class="sub-title">\n阳离子交换量(cmol/kg)</text>
 <text class="sub-title">\n水解氮(g/kg)</text>
-<text class="sub-title">\n交换性铝(cmol/kg)</text>
 <text class="sub-title">\n交换性氢(cmol/kg)</text>
+<text class="sub-title">\n交换性铝(cmol/kg)</text>
 输入值必须在合理范围内,不应有异常数据,避免影响预测结果的准确性。
 <text class="sub-title">2. 模型进化能力</text>
 <text class="sub-title">\n模型迭代:</text>我们的模型将会随着用户数据量的增加和多样化,逐步迭代进化,提升预测的准确性和泛化能力。

+ 6 - 3
shoping/Soil Deacidification/Soil Deacidification.wxml

@@ -3,9 +3,12 @@
     该模型旨在帮助提升土壤 pH 值,通过输入土壤起始 pH 和目标 pH,精准计算石灰石的施用。为确保模型效果与使用体验,请注意以下事项:
 <text class="sub-title">1. 数据输入要求</text>
 <text class="sub-title"> \n必填参数:</text>
-<text class="sub-title">\n土壤起始 pH 值:</text>需通过实验室准确测定。
-<text class="sub-title">土壤目标 pH 值:</text>根据土壤改良目标设置。
-<text class="sub-title">关键理化指标:</text>包括离子含量、有机质含量等。
+<text class="sub-title">\n土壤起始 pH 值</text>
+<text class="sub-title">\n土壤目标 pH 值</text>
+<text class="sub-title">\n土壤粘粒含量(g/kg)</text>
+<text class="sub-title">\n有机质含量(g/kg)</text>
+<text class="sub-title">\n交换性氢(cmol/kg)</text>
+<text class="sub-title">\n交换性铝(cmol/kg)</text>
 输入数据必须符合实际测量值,避免因数据异常或错误导致计算结果偏差。
 <text class="sub-title">2. 模型进化能力</text>
 本模型将持续根据用户上传的真实数据优化和进化,提升预测精度和适用范围。

+ 3 - 3
shoping/SoilPro/SoilPro.wxml

@@ -4,7 +4,7 @@
 
 <view class="container">
   <view class="section">
-    <text class="sub-title">广东省生态环境与土壤研究所</text>
+    <text class="sub-title">广东省科学院生态环境与土壤研究所</text>
     <text class="content">开发了</text>
     <text class="sub-title">土壤酸化模型计算</text>
     <text class="content">软件。该软件集成了</text>
@@ -12,7 +12,7 @@
     <text class="sub-title">降酸模型,</text>
     <text class="content">以科学化、智能化的⽅式提供⼟壤酸性调控解决⽅案,同时通过模型迭代优化不断提升预测精度。以下为软件的综述性简介:</text>
     <text class="sub-title">\n1. 软件功能概述</text>
-    <text class="content"><text class="sub-title">\n反酸模型:</text>输入关键土壤理化指标(如土壤粘粒、交换性铝离子、有机质、游离氧化铝等),精准预测土壤反酸后的pH值变化。</text>
+    <text class="content"><text class="sub-title">\n反酸模型:</text>输入关键土壤理化指标(如土壤粘粒、交换性铝离子、有机质等),精准预测土壤反酸后的pH值变化。</text>
     <text class="content"><text class="sub-title">\n降酸模型:</text> 根据土壤起始pH和目标pH值,以及相关理化指标,计算生石灰的施用量。</text>
 
     <text class="sub-title">\n2. 核心技术特点</text>
@@ -31,5 +31,5 @@
   </view>
 </view>
 <view class="container">
-  <text class="title-e">广东省生态环境与土壤研究所期待与社会各界共同努力,为土壤科学技术进步和生态文明建设作出积极贡献!</text>
+  <text class="title-e">广东省科学院生态环境与土壤研究所期待与社会各界共同努力,为土壤科学技术进步和生态文明建设作出积极贡献!</text>
 </view>

+ 1 - 1
shoping/Unit Team Profile/Unit Team Profile.wxml

@@ -1,5 +1,5 @@
 <view class="green-box">
-  <text class="title-en">广东省⼟壤与⽣态环境研究所</text>
+  <text class="title-en">广东省科学院土壤与生态环境研究所</text>
 </view>
 <view class="container">
   <view class="section">

+ 115 - 0
shoping/mapView/mapView.js

@@ -0,0 +1,115 @@
+Page({
+  data: {
+    latitude: 25.040415, // 默认中心纬度
+    longitude: 110.273511, // 默认中心经度
+    scale: 5,
+    markers: [] // 初始化为空数组,后续动态填充
+  },
+
+  onLoad() {
+    // 假设已将 Excel 数据解析为以下数组
+    const excelData = [
+      { 土壤编号: "土1", 地点: "广西武鸣", dust_emissions: 5.34, longitude: 106.476143, latitude: 17.891756 },
+      { 土壤编号: "土2", 地点: "广西河池", dust_emissions: 3.96, longitude: 107.476143, latitude: 18.891756 },
+      { 土壤编号: "土3", 地点: "海南澄迈老城镇罗驿村委会罗驿洋", dust_emissions: 4.56, longitude: 108.476143, latitude: 19.891756 },
+      { 土壤编号: "土4", 地点: "广东江门新会", dust_emissions: 4.0, longitude: 109.476143, latitude: 20.891756 },
+      { 土壤编号: "土5", 地点: "广州增城Z6", dust_emissions: 4.77, longitude: 110.476143, latitude: 21.891756 },
+      { 土壤编号: "土6", 地点: "广州增城Z8", dust_emissions: 4.59, longitude: 111.476143, latitude: 22.891756 },
+      { 土壤编号: "土7", 地点: "湖南岳阳", dust_emissions: 5.14, longitude: 112.476143, latitude: 23.891756 },
+      { 土壤编号: "土8", 地点: "广东韶关武江", dust_emissions: 5.07, longitude: 113.476143, latitude: 24.891756 },
+      { 土壤编号: "土9", 地点: "海南临高头星村", dust_emissions: 4.12, longitude: 109.684993, latitude: 19.83774 },
+      { 土壤编号: "土10", 地点: "海南临高周礼村", dust_emissions: 5.0, longitude: 109.710703, latitude: 19.89222 },
+      { 土壤编号: "土11", 地点: "海南澄迈金江", dust_emissions: 4.6, longitude: 110.069537, latitude: 19.81189 },
+      { 土壤编号: "土12", 地点: "海南临高南贤村", dust_emissions: 4.2, longitude: 109.768714, latitude: 19.874323 },
+      { 土壤编号: "土13", 地点: "海南澄迈金江北让村", dust_emissions: 4.5, longitude: 110.096765, latitude: 19.814288 },
+      { 土壤编号: "土14", 地点: "广西扶绥", dust_emissions: 4.71, longitude: 107.7717789, latitude: 2.5166902 },
+      { 土壤编号: "土15", 地点: "广西江州", dust_emissions: 4.31, longitude: 107.56347787, latitude: 22.6022203 },
+      { 土壤编号: "土16", 地点: "广西龙州", dust_emissions: 5.15, longitude: 106.7870847, latitude: 22.3496497 },
+      { 土壤编号: "土17", 地点: "广西大新", dust_emissions: 4.71, longitude: 107.0230641, latitude: 22.5857946 },
+      { 土壤编号: "土18", 地点: "湖南岳阳荣家湾", dust_emissions: 5.04, longitude: 113.059629, latitude: 29.267061 },
+      { 土壤编号: "土19", 地点: "湖南长沙", dust_emissions: 5.08, longitude: 113.059629, latitude: 28.440613 },
+      { 土壤编号: "土20", 地点: "浙江", dust_emissions: 4.8, longitude: 111.45527, latitude: 24.395235 },
+      { 土壤编号: "土21", 地点: "云南陆良", dust_emissions: 4.67, longitude: 112.45527, latitude: 25.395235 },
+      { 土壤编号: "土22", 地点: "南昌横龙镇南园组", dust_emissions: 4.8, longitude: 113.45527, latitude: 26.395235 },
+      { 土壤编号: "土23", 地点: "南昌横龙枫塘南园", dust_emissions: 5.1, longitude: 114.45527, latitude: 27.395235 },
+      { 土壤编号: "土24", 地点: "南昌横龙镇院塘村", dust_emissions: 4.27, longitude: 109.852, latitude: 33.3147 },
+      { 土壤编号: "土25", 地点: "江西山庄乡秀水村黄田组", dust_emissions: 4.27, longitude: 110.852, latitude: 34.3147 },
+      { 土壤编号: "土26", 地点: "贵州双星村", dust_emissions: 4.7, longitude: 111.852, latitude: 35.3147 },
+      { 土壤编号: "土27", 地点: "湖南永州八宝镇唐家州", dust_emissions: 4.57, longitude: 112.852, latitude: 36.3147 },
+      { 土壤编号: "土28", 地点: "湖南永州金洞", dust_emissions: 5.3, longitude: 112.1564, latitude: 26.1685 },
+      { 土壤编号: "土29", 地点: "祁阳县中国农业科学院红壤实验室", dust_emissions: 4.75, longitude: 111.4, latitude: 22.24 },
+      { 土壤编号: "土30", 地点: "福建福州1", dust_emissions: 4.31, longitude: 112.4, latitude: 23.24 },
+      { 土壤编号: "土31", 地点: "福建福州2", dust_emissions: 4.38, longitude: 113.4, latitude: 24.24 },
+      { 土壤编号: "土32", 地点: "广东省韶关市南雄市下塅村", dust_emissions: 5.51, longitude: 114.4, latitude: 25.24 },
+      { 土壤编号: "土33", 地点: "广东省韶关市南雄市河塘西216米", dust_emissions: 6.44, longitude: 114.28, latitude: 25.14 },
+      { 土壤编号: "土34", 地点: "广东省韶关市南雄市上何屋西南500米", dust_emissions: 5.25, longitude: 114.15, latitude: 24.86 },
+      { 土壤编号: "土35", 地点: "广东省南雄市雄州街道林屋", dust_emissions: 4.62333333333333, longitude: 114.23, latitude: 25.4 },
+      { 土壤编号: "土36", 地点: "广东省台山都斛镇", dust_emissions: 3.0, longitude: 112.34, latitude: 27.31 },
+      { 土壤编号: "土52", 地点: "湖南省长沙市浏阳市永安镇千鹭湖", dust_emissions: 4.72333333333333, longitude: 113.34, latitude: 28.31 },
+      { 土壤编号: "土53", 地点: "湖南省长沙市浏阳市湖南农大实习基地", dust_emissions: 5.55333333333333, longitude: 113.83, latitude: 28.3 },
+      { 土壤编号: "土54", 地点: "湖南省邵阳市罗市镇1", dust_emissions: 4.64, longitude: 110.35, latitude: 25.47 },
+      { 土壤编号: "土55", 地点: "湖南省邵阳市罗市镇2", dust_emissions: 5.01333333333333, longitude: 111.35, latitude: 26.47 },
+      { 土壤编号: "土56", 地点: "湖南省邵阳市罗市镇3", dust_emissions: 5.18, longitude: 112.35, latitude: 27.47 },
+      { 土壤编号: "土57", 地点: "长沙县高桥镇的省农科院高桥科研基地1", dust_emissions: 5.1, longitude: 113.35, latitude: 28.47 },
+      { 土壤编号: "土58", 地点: "长沙县高桥镇的省农科院高桥科研基地2", dust_emissions: 4.92, longitude: 113.35, latitude: 28.47 },
+      { 土壤编号: "土59", 地点: "湖南省长沙市望城区桐林坳社区", dust_emissions: 3.0, longitude: 112.8, latitude: 28.37 },
+      { 土壤编号: "土60", 地点: "湖南省益阳市赫山区泥江口镇", dust_emissions: 3.0, longitude: 107.37, latitude: 21.92 },
+      { 土壤编号: "土70", 地点: "南宁市兴宁区柳杨路26号", dust_emissions: 3.0, longitude: 108.37, latitude: 22.92 },
+      { 土壤编号: "土71", 地点: "南宁市兴宁区柳杨路广西私享家家具用品", dust_emissions: 3.0, longitude: 108.37, latitude: 23.94 },
+      { 土壤编号: "土72", 地点: "南宁市兴宁区004乡道", dust_emissions: 6.24666666666667, longitude: 108.39, latitude: 24.92 },
+      { 土壤编号: "土73", 地点: "南宁市兴宁区G7201南宁绕城高速", dust_emissions: 3.0, longitude: 108.4, latitude: 25.94 },
+      { 土壤编号: "土74", 地点: "南宁市兴宁区012县道", dust_emissions: 3.0, longitude: 108.41, latitude: 26.92 },
+      { 土壤编号: "土75", 地点: "南宁市兴宁区那况路168号", dust_emissions: 3.0, longitude: 108.4, latitude: 27.9 },
+      { 土壤编号: "土76", 地点: "南宁市西乡塘区翊武路", dust_emissions: 5.37, longitude: 108.35, latitude: 28.96 },
+      { 土壤编号: "土77", 地点: "南宁市西乡塘区坛洛镇", dust_emissions: 3.0, longitude: 107.85, latitude: 29.92 },
+      { 土壤编号: "土81", 地点: "铜仁职业技术学院", dust_emissions: 4.0, longitude: 108.85, latitude: 27.34 },
+      { 土壤编号: "土87", 地点: "江西省红壤及种质资源研究所(进贤基地)1", dust_emissions: 4.55, longitude: 116.17, latitude: 28.34 },
+      { 土壤编号: "土88", 地点: "江西省红壤及种质资源研究所(进贤基地)2", dust_emissions: 4.99333333333333, longitude: 116.17, latitude: 28.34 }
+    ];
+
+    // 动态生成 markers 数据
+    const markers = excelData.map((item, index) => ({
+      id: index + 1, // 标记点 ID
+      latitude: item.latitude, // 纬度
+      longitude: item.longitude, // 经度
+      iconPath: "../../assets/taddar/marker.png", // 标记点图标路径
+      width: 34,
+      height: 34,
+      callout: {
+        content: `${item.地点} - pH值: ${parseFloat(item.dust_emissions).toFixed(2)}`, // 显示地名和污染物排放量
+        display: "BYCLICK", // 点击时显示气泡
+        fontSize: 14,
+        color: "#333",
+        bgColor: "#fff",
+        borderColor: "#ccc",
+        borderRadius: 5,
+        borderWidth: 1,
+        padding: 10,
+        textAlign: "center",
+        anchorX: 0.5,
+        anchorY: -5
+      }
+    }));
+
+    // 更新 markers 数据
+    this.setData({ markers });
+  },
+
+  onMarkerTap(e) {
+    console.log("Marker clicked:", e.detail.markerId);
+    const markerId = e.detail.markerId;
+    const markers = this.data.markers.map(marker => {
+      if (marker.id === markerId) {
+        marker.callout.display = "ALWAYS"; // 显示气泡
+      } else {
+        marker.callout.display = "NEVER"; // 隐藏其他气泡
+      }
+      return marker;
+    });
+    this.setData({ markers });
+  },
+
+  onCalloutTap(e) {
+    console.log("Callout clicked:", e.detail.markerId);
+  }
+});

+ 6 - 0
shoping/mapView/mapView.json

@@ -0,0 +1,6 @@
+{
+  "usingComponents": {},
+  "navigationBarTitleText": "地图展示",
+  "navigationBarBackgroundColor": "#dbdbdb",  
+  "navigationBarTextStyle": "black"  
+}

+ 10 - 0
shoping/mapView/mapView.wxml

@@ -0,0 +1,10 @@
+<map 
+  id="map" 
+  latitude="{{latitude}}" 
+  longitude="{{longitude}}" 
+  markers="{{markers}}" 
+  bindmarkertap="onMarkerTap" 
+  bindcallouttap="onCalloutTap"
+  scale="{{scale}}" 
+  style="width: 100%; height: 100vh;">
+</map>

+ 1 - 0
shoping/mapView/mapView.wxss

@@ -0,0 +1 @@
+/* shoping/mapView.wxss */

Algunos archivos no se mostraron porque demasiados archivos cambiaron en este cambio