当前位置:首页>java>利用DeepSeek大模型编程--编程设计网页版水质检测系统,借助AI大环境,这活以后工艺工程师也能参与

利用DeepSeek大模型编程--编程设计网页版水质检测系统,借助AI大环境,这活以后工艺工程师也能参与

  • 2026-08-23 11:37:51
利用DeepSeek大模型编程--编程设计网页版水质检测系统,借助AI大环境,这活以后工艺工程师也能参与
因部分同事、朋友提需求想如何入门AI编程,大家想利用deepseek如何帮忙编程,本文以开发水质展示平台为例,详细介绍过程,以下为详细步骤及思路,仅供参考
一、需求及准备开发环境
    1、需求:这里以开发一个可视化展示水质数据为需求,实时展示数据及指标趋势及多指标对比      
    2、开发环境:利用python语言开发、开发工具为pycharm具体下载参考之前发布的内容AI环境搭建软件集合
二、准备开发提示词
提示词如下:利用python开发一个水质数据展示的界面,功能要求1、水质展示包括流量、cod、氨氮、总磷、ss、ph,每个指标都需要有趋势图和实时展示2、需要利用python技术开发,数据可以模拟3、需要制作为网页的形式,请你提供完整的代码
三、查看大模型给的思考及制作程序过程    

我们将使用Flask作为Web框架,使用Chart.js来绘制图表,使用模拟数据来展示。由于要求实时展示,我们可以使用AJAX定期从后端获取数据更新前端图表。

步骤:

  1. 创建Flask应用。

  2. 设计一个路由用于渲染主页面。

  3. 设计一个路由用于提供模拟数据(JSON格式)。

  4. 前端页面使用HTML和JavaScript,利用Chart.js绘制多个图表,并定时更新。

注意:我们模拟的数据将包括流量、COD、氨氮、总磷、SS、pH这6个指标。我们假设每个指标的数据是一个时间序列,这里我们使用当前时间作为时间点,数据为随机值。

由于是模拟数据,我们将在后端生成随机数,并按照一定的时间间隔(比如每分钟)更新数据,但为了简单,我们每次请求都生成新的随机数(模拟实时变化)。

但是,考虑到趋势图需要历史数据,我们将在后端维护一个固定长度的历史数据队列,每次请求返回最新的数据以及历史数据。

由于有6个指标,我们可以为每个指标维护一个队列。

但是,为了简单起见,我们只模拟最近24小时的数据(每分钟一个点,共1440个点)。不过,我们也可以只返回最近一段时间的数据,比如最近100个点。

我们这里选择返回最近100个点,并且每次请求都会添加一个新的数据点(模拟实时数据)并移除最旧的数据点,以保持数据长度不变。

然而,如果我们希望前端每次请求都获取全部历史数据(比如最近100个点),那么我们就需要在后端存储这些数据。

由于我们要求是实时展示,所以我们每5秒更新一次图表。

我们采用以下结构:

后端:

  • 一个全局变量,存储6个指标各自最近100个点的数据(时间戳和值)。

  • 一个路由,返回JSON格式的数据,包含6个指标的最新数据(包括历史数据,即每个指标的时间序列)。

  • 另一个路由,用于渲染主页面。

前端:

  • 使用6个Chart.js图表,分别展示每个指标的趋势图。

  • 使用定时器,每5秒向后端请求一次数据,并更新图表。

由于我们使用模拟数据,我们将在后端初始化时生成一些历史数据。

我们开始编写代码。

四、大模型制作的程序测试

     下面是一个完整的水质数据展示网页应用,使用Python Flask框架开发,包含实时数据和趋势图展示功能,大家需要在pycharm开发工具中按如下布局进行

    项目结构

参考我构建的项目文件目录:
 1. 主应用文件 (app.py)  一键复制到开发环境
from flask import Flask, render_template, jsonify, requestimport randomimport timefrom datetime import datetime, timedeltaimport jsonfrom collections import dequeimport threadingapp = Flask(__name__)# 模拟水质数据存储water_quality_data = {    '流量': deque(maxlen=100),    'COD': deque(maxlen=100),    '氨氮': deque(maxlen=100),    '总磷': deque(maxlen=100),    'SS': deque(maxlen=100),    'pH': deque(maxlen=100)}# 时间戳存储timestamps = deque(maxlen=100)# 水质指标的正常范围quality_ranges = {    '流量': {'min': 10, 'max': 100, 'unit': 'm³/s'},    'COD': {'min': 10, 'max': 100, 'unit': 'mg/L'},    '氨氮': {'min': 0.1, 'max': 5, 'unit': 'mg/L'},    '总磷': {'min': 0.05, 'max': 2, 'unit': 'mg/L'},    'SS': {'min': 5, 'max': 100, 'unit': 'mg/L'},    'pH': {'min': 6.5, 'max': 8.5, 'unit': ''}}# 初始化一些模拟数据def initialize_data():    now = datetime.now()    for i in range(100):        time_point = now - timedelta(minutes=(100-i))        timestamps.append(time_point.strftime('%H:%M'))        # 生成模拟数据(添加一些随机变化)        water_quality_data['流量'].append(round(random.uniform(20, 80), 2))        water_quality_data['COD'].append(round(random.uniform(15, 85), 2))        water_quality_data['氨氮'].append(round(random.uniform(0.5, 4), 2))        water_quality_data['总磷'].append(round(random.uniform(0.1, 1.8), 2))        water_quality_data['SS'].append(round(random.uniform(10, 90), 2))        water_quality_data['pH'].append(round(random.uniform(6.8, 8.2), 2))# 更新数据(模拟实时数据)def update_data():    while True:        time.sleep(2)  # 每2秒更新一次数据        now = datetime.now()        # 更新时间戳        if len(timestamps) >= 100:            timestamps.popleft()        timestamps.append(now.strftime('%H:%M:%S'))        # 更新每个指标的数据(添加随机波动)        for key in water_quality_data.keys():            current_values = list(water_quality_data[key])            last_value = current_values[-1] if current_values else quality_ranges[key]['min']            # 生成新的数据点,基于前一个值添加随机变化            if key == 'pH':                # pH值变化较小                change = random.uniform(-0.05, 0.05)                new_value = last_value + change                # 确保pH在合理范围内                new_value = max(6.0, min(9.0, new_value))            elif key == '流量':                change = random.uniform(-3, 3)                new_value = last_value + change                new_value = max(5, min(95, new_value))            else:                change = random.uniform(-2, 2)                new_value = last_value + change                # 确保数据在合理范围内                new_value = max(quality_ranges[key]['min']*0.5,                               min(quality_ranges[key]['max']*1.5, new_value))            if len(water_quality_data[key]) >= 100:                water_quality_data[key].popleft()            water_quality_data[key].append(round(new_value, 2))@app.route('/')def index():    return render_template('index.html',                           indicators=list(water_quality_data.keys()),                          ranges=quality_ranges)@app.route('/api/current_data')def get_current_data():    """获取当前最新数据"""    current_data = {}    for key in water_quality_data.keys():        if water_quality_data[key]:            current_data[key] = water_quality_data[key][-1]        else:            current_data[key] = 0    return jsonify({        'data': current_data,        'timestamp': timestamps[-1] if timestamps else datetime.now().strftime('%H:%M:%S')    })@app.route('/api/historical_data')def get_historical_data():    """获取历史数据用于图表"""    return jsonify({        'timestamps': list(timestamps),        'data': {key: list(water_quality_data[key]) for key in water_quality_data.keys()}    })@app.route('/api/quality_status')def get_quality_status():    """获取水质状态(正常/警告/异常)"""    status = {}    current_data = {key: water_quality_data[key][-1] for key in water_quality_data.keys()}    for key, value in current_data.items():        min_val = quality_ranges[key]['min']        max_val = quality_ranges[key]['max']        if value < min_val * 0.9 or value > max_val * 1.1:            status[key] = 'danger'  # 异常        elif value < min_val or value > max_val:            status[key] = 'warning'  # 警告        else:            status[key] = 'normal'   # 正常    return jsonify(status)@app.route('/api/simulate_anomaly', methods=['POST'])def simulate_anomaly():    """模拟水质异常事件"""    data = request.json    indicator = data.get('indicator', 'COD')    if indicator in water_quality_data:        # 将当前值设置为异常值        current_values = list(water_quality_data[indicator])        if current_values:            # 设置一个超出正常范围的值            if indicator == 'pH':                anomaly_value = random.choice([5.5, 9.5])  # pH异常            else:                anomaly_value = quality_ranges[indicator]['max'] * 1.5            current_values[-1] = round(anomaly_value, 2)            water_quality_data[indicator].pop()            water_quality_data[indicator].append(current_values[-1])    return jsonify({'success': True, 'indicator': indicator})if __name__ == '__main__':    # 初始化数据    initialize_data()    # 启动后台数据更新线程    update_thread = threading.Thread(target=update_data, daemon=True)    update_thread.start()    # 启动Flask应用    app.run(debug=True, host='0.0.0.0', port=5000)

2. HTML模板文件 (templates/index.html) 一键复制到开发环境

<!DOCTYPE html><htmllang="zh-CN"><head>    <metacharset="UTF-8">    <metaname="viewport"content="width=device-width, initial-scale=1.0">    <title>水质数据监测系统</title>    <linkrel="stylesheet"href="{{ url_for('static', filename='css/style.css') }}">    <scriptsrc="https://cdn.jsdelivr.net/npm/chart.js"></script>    <linkrel="stylesheet"href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css"></head><body>    <divclass="container">        <headerclass="header">            <h1><iclass="fas fa-tint"></i> 水质数据监测系统</h1>            <divclass="time-display">                最后更新: <spanid="last-update">--:--:--</span>                <buttonid="refresh-btn"class="btn"><iclass="fas fa-sync-alt"></i> 刷新</button>            </div>        </header>        <divclass="dashboard">            <!-- 实时数据展示 -->            <divclass="section">                <h2><iclass="fas fa-chart-line"></i> 实时数据</h2>                <divclass="real-time-cards">                    {% for indicator in indicators %}                    <divclass="card"id="{{ indicator }}-card">                        <divclass="card-header">                            <h3>{{ indicator }}</h3>                            <spanclass="status-indicator"id="{{ indicator }}-status"></span>                        </div>                        <divclass="card-body">                            <divclass="value"id="{{ indicator }}-value">--</div>                            <divclass="unit">{{ ranges[indicator]['unit'] }}</div>                            <divclass="range">正常范围: {{ ranges[indicator]['min'] }} - {{ ranges[indicator]['max'] }}{{ ranges[indicator]['unit'] }}</div>                        </div>                        <divclass="card-footer">                            <buttonclass="btn-small anomaly-btn"data-indicator="{{ indicator }}">                                <iclass="fas fa-exclamation-triangle"></i> 模拟异常                            </button>                        </div>                    </div>                    {% endfor %}                </div>            </div>            <!-- 趋势图展示 -->            <divclass="section">                <h2><iclass="fas fa-chart-area"></i> 趋势图</h2>                <divclass="chart-controls">                    <labelfor="indicator-select">选择指标:</label>                    <selectid="indicator-select">                        {% for indicator in indicators %}                        <optionvalue="{{ indicator }}">{{ indicator }}</option>                        {% endfor %}                    </select>                    <labelfor="time-range">时间范围:</label>                    <selectid="time-range">                        <optionvalue="10">最近10分钟</option>                        <optionvalue="30"selected>最近30分钟</option>                        <optionvalue="60">最近60分钟</option>                        <optionvalue="all">全部数据</option>                    </select>                </div>                <divclass="chart-container">                    <canvasid="trend-chart"></canvas>                </div>            </div>            <!-- 多指标对比图 -->            <divclass="section">                <h2><iclass="fas fa-chart-bar"></i> 多指标对比</h2>                <divclass="chart-container">                    <canvasid="comparison-chart"></canvas>                </div>            </div>        </div>        <footerclass="footer">            <p>水质监测系统 | 模拟数据 | 更新时间: <spanid="current-time">--:--:--</span></p>            <p>数据每2秒自动更新 | 使用Python Flask + Chart.js开发</p>        </footer>    </div>    <scriptsrc="{{ url_for('static', filename='js/charts.js') }}"></script></body></html>

3. CSS样式文件 (static/css/style.css) 一键复制到开发环境

* {    margin: 0;    padding: 0;    box-sizing: border-box;    font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;}body {    background-color: #f5f7fa;    color: #333;    line-height: 1.6;}.container {    max-width: 1400px;    margin: 0 auto;    padding: 20px;}.header {    display: flex;    justify-content: space-between;    align-items: center;    background: linear-gradient(135deg, #1a6fc4 0%, #0d4d8c 100%);    color: white;    padding: 20px 30px;    border-radius: 12px;    margin-bottom: 25px;    box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);}.header h1 {    font-size: 28px;    font-weight: 600;}.header h1 i {    margin-right: 12px;}.time-display {    display: flex;    align-items: center;    gap: 15px;}#last-update {    font-weight: 600;    background: rgba(255, 255, 255, 0.2);    padding: 5px 12px;    border-radius: 20px;}.btn {    background-color: #2d9cdb;    color: white;    border: none;    padding: 10px 20px;    border-radius: 6px;    cursor: pointer;    font-weight: 600;    transition: all 0.3s ease;    display: flex;    align-items: center;    gap: 8px;}.btn:hover {    background-color: #1a8bc8;    transform: translateY(-2px);}.dashboard {    display: flex;    flex-direction: column;    gap: 30px;}.section {    background-color: white;    border-radius: 12px;    padding: 25px;    box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08);}.section h2 {    font-size: 22px;    color: #2c3e50;    margin-bottom: 20px;    display: flex;    align-items: center;    gap: 10px;}.real-time-cards {    display: grid;    grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));    gap: 20px;}.card {    background-color: #fff;    border-radius: 10px;    overflow: hidden;    box-shadow: 0 3px 10px rgba(0, 0, 0, 0.08);    transition: transform 0.3s ease, box-shadow 0.3s ease;    border: 1px solid #eaeaea;}.card:hover {    transform: translateY(-5px);    box-shadow: 0 6px 15px rgba(0, 0, 0, 0.1);}.card-header {    background-color: #f8f9fa;    padding: 15px 20px;    border-bottom: 1px solid #eaeaea;    display: flex;    justify-content: space-between;    align-items: center;}.card-header h3 {    font-size: 18px;    color: #2c3e50;    font-weight: 600;}.status-indicator {    width: 12px;    height: 12px;    border-radius: 50%;    background-color: #ccc;}.status-normal {    background-color: #27ae60 !important;}.status-warning {    background-color: #f39c12 !important;}.status-danger {    background-color: #e74c3c !important;}.card-body {    padding: 20px;    text-align: center;}.value {    font-size: 36px;    font-weight: 700;    color: #2c3e50;    margin-bottom: 5px;}.unit {    font-size: 16px;    color: #7f8c8d;    margin-bottom: 10px;}.range {    font-size: 14px;    color: #95a5a6;}.card-footer {    padding: 15px 20px;    background-color: #f8f9fa;    border-top: 1px solid #eaeaea;    text-align: center;}.btn-small {    background-color: #e74c3c;    color: white;    border: none;    padding: 8px 15px;    border-radius: 4px;    cursor: pointer;    font-size: 14px;    transition: all 0.3s ease;    display: inline-flex;    align-items: center;    gap: 5px;}.btn-small:hover {    background-color: #c0392b;}.chart-controls {    display: flex;    gap: 15px;    margin-bottom: 20px;    align-items: center;    flex-wrap: wrap;}.chart-controls label {    font-weight: 600;    color: #2c3e50;}.chart-controls select {    padding: 8px 15px;    border-radius: 6px;    border: 1px solid #ddd;    background-color: white;    color: #333;    font-size: 14px;}.chart-container {    position: relative;    height: 400px;    width: 100%;}.footer {    margin-top: 40px;    text-align: center;    color: #7f8c8d;    font-size: 14px;    padding-top: 20px;    border-top: 1px solid #eaeaea;}.footer p {    margin-bottom: 8px;}#current-time {    font-weight: 600;    color: #2c3e50;}@media (max-width: 768px) {    .header {        flex-direction: column;        gap: 15px;        text-align: center;    }    .real-time-cards {        grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));    }    .chart-controls {        flex-direction: column;        align-items: flex-start;    }}

4. JavaScript图表文件 (static/js/charts.js)

document.addEventListener('DOMContentLoaded', function() {    // 图表实例    let trendChart = null;    let comparisonChart = null;    // 获取DOM元素    const lastUpdateEl = document.getElementById('last-update');    const currentTimeEl = document.getElementById('current-time');    const refreshBtn = document.getElementById('refresh-btn');    const indicatorSelect = document.getElementById('indicator-select');    const timeRangeSelect = document.getElementById('time-range');    const anomalyButtons = document.querySelectorAll('.anomaly-btn');    // 初始化图表    initTrendChart();    initComparisonChart();    // 获取当前数据    functionfetchCurrentData() {        fetch('/api/current_data')            .then(response => response.json())            .then(data => {                updateCurrentData(data);                updateStatusIndicators();            })            .catch(error => console.error('获取当前数据失败:', error));    }    // 更新当前数据展示    functionupdateCurrentData(data) {        // 更新每个指标的值        for(const [indicator, value] of Object.entries(data.data)) {            const valueEl = document.getElementById(`${indicator}-value`);            if(valueEl) {                valueEl.textContent = value.toFixed(2);            }        }        // 更新时间戳        lastUpdateEl.textContent = data.timestamp;        // 更新当前时间        const now = new Date();        currentTimeEl.textContent = now.toLocaleTimeString();    }    // 更新状态指示器    functionupdateStatusIndicators() {        fetch('/api/quality_status')            .then(response => response.json())            .then(statusData => {                for(const [indicator, status] of Object.entries(statusData)) {                    const statusEl = document.getElementById(`${indicator}-status`);                    if(statusEl) {                        // 移除现有状态类                        statusEl.classList.remove('status-normal', 'status-warning', 'status-danger');                        // 添加新状态类                        statusEl.classList.add(`status-${status}`);                        // 根据状态更新卡片边框颜色                        const card = document.getElementById(`${indicator}-card`);                        if(card) {                            card.style.borderColor = getStatusColor(status);                        }                    }                }            })            .catch(error => console.error('获取状态数据失败:', error));    }    // 获取状态对应的颜色    functiongetStatusColor(status) {        switch(status) {            case 'normal': return '#27ae60';            case 'warning': return '#f39c12';            case 'danger': return '#e74c3c';            default: return '#eaeaea';        }    }    // 初始化趋势图    functioninitTrendChart() {        const ctx = document.getElementById('trend-chart').getContext('2d');        trendChart = new Chart(ctx, {            type: 'line',            data: {                labels: [],                datasets: [{                    label: '水质指标',                    data: [],                    borderColor: '#3498db',                    backgroundColor: 'rgba(52, 152, 219, 0.1)',                    borderWidth: 3,                    fill: true,                    tension: 0.3                }]            },            options: {                responsive: true,                maintainAspectRatio: false,                plugins: {                    legend: {                        display: true,                        position: 'top',                    },                    tooltip: {                        mode: 'index',                        intersect: false                    }                },                scales: {                    x: {                        title: {                            display: true,                            text: '时间'                        },                        grid: {                            display: true,                            color: 'rgba(0, 0, 0, 0.05)'                        }                    },                    y: {                        title: {                            display: true,                            text: '值'                        },                        grid: {                            display: true,                            color: 'rgba(0, 0, 0, 0.05)'                        },                        beginAtZero: false                    }                }            }        });        // 加载初始数据        updateTrendChart();    }    // 更新趋势图    functionupdateTrendChart() {        fetch('/api/historical_data')            .then(response => response.json())            .then(data => {                const indicator = indicatorSelect.value;                const timeRange = parseInt(timeRangeSelect.value);                let timestamps = data.timestamps;                let values = data.data[indicator];                // 如果选择了时间范围,则截取数据                if(timeRange !== 'all' && timestamps.length > timeRange) {                    timestamps = timestamps.slice(-timeRange);                    values = values.slice(-timeRange);                }                // 更新图表                trendChart.data.labels = timestamps;                trendChart.data.datasets[0].data = values;                trendChart.data.datasets[0].label = indicator;                trendChart.update();            })            .catch(error => console.error('获取历史数据失败:', error));    }    // 初始化对比图    functioninitComparisonChart() {        const ctx = document.getElementById('comparison-chart').getContext('2d');        comparisonChart = new Chart(ctx, {            type: 'bar',            data: {                labels: [],                datasets: [{                    label: '当前值',                    data: [],                    backgroundColor: [                        'rgba(52, 152, 219, 0.7)',                        'rgba(46, 204, 113, 0.7)',                        'rgba(155, 89, 182, 0.7)',                        'rgba(241, 196, 15, 0.7)',                        'rgba(230, 126, 34, 0.7)',                        'rgba(231, 76, 60, 0.7)'                    ],                    borderColor: [                        'rgb(52, 152, 219)',                        'rgb(46, 204, 113)',                        'rgb(155, 89, 182)',                        'rgb(241, 196, 15)',                        'rgb(230, 126, 34)',                        'rgb(231, 76, 60)'                    ],                    borderWidth: 1                }]            },            options: {                responsive: true,                maintainAspectRatio: false,                plugins: {                    legend: {                        display: true,                        position: 'top',                    }                },                scales: {                    x: {                        title: {                            display: true,                            text: '水质指标'                        }                    },                    y: {                        title: {                            display: true,                            text: '值'                        },                        beginAtZero: true                    }                }            }        });        // 加载初始数据        updateComparisonChart();    }    // 更新对比图    functionupdateComparisonChart() {        fetch('/api/current_data')            .then(response => response.json())            .then(data => {                const indicators = Object.keys(data.data);                const values = Object.values(data.data);                comparisonChart.data.labels = indicators;                comparisonChart.data.datasets[0].data = values;                comparisonChart.update();            })            .catch(error => console.error('获取对比数据失败:', error));    }    // 事件监听器    refreshBtn.addEventListener('click', function() {        fetchCurrentData();        updateTrendChart();        updateComparisonChart();    });    indicatorSelect.addEventListener('change', updateTrendChart);    timeRangeSelect.addEventListener('change', updateTrendChart);    // 模拟异常按钮    anomalyButtons.forEach(button => {        button.addEventListener('click', function() {            const indicator = this.getAttribute('data-indicator');            fetch('/api/simulate_anomaly', {                method: 'POST',                headers: {                    'Content-Type': 'application/json',                },                body: JSON.stringify({indicator: indicator})            })            .then(response => response.json())            .then(data => {                if(data.success) {                    alert(`已模拟${indicator}指标异常`);                    // 刷新数据                    fetchCurrentData();                    updateTrendChart();                    updateComparisonChart();                }            })            .catch(error => console.error('模拟异常失败:', error));        });    });    // 定时更新数据    setInterval(fetchCurrentData, 2000); // 每2秒更新一次当前数据    setInterval(updateTrendChart, 10000); // 每10秒更新一次趋势图    setInterval(updateComparisonChart, 10000); // 每10秒更新一次对比图    // 初始加载数据    fetchCurrentData();});

5. 项目依赖文件 (requirements.txt) ,需要安装以下库文件才能运行

Flask==2.3.3Werkzeug==2.3.7Jinja2==3.1.2
Flask==2.3.3Werkzeug==2.3.7Jinja2==3.1.2这三个库作用是啥,提供阿里云安装镜像地址把这段话给到deepseek,他会提供阿里云镜像安装地址,加快安装速度

deepseek思考过程

Flask==2.3.3:Flask是一个轻量级的Python Web框架,用于构建Web应用程序。它提供了路由、模板渲染、请求和响应处理等基本功能,是开发这个水质数据展示界面的核心框架。Werkzeug==2.3.7:Werkzeug是一个WSGI工具库,它提供了处理HTTP请求、响应、路由、调试等功能的底层支持。Flask框架就是基于Werkzeug构建的。Jinja2==3.1.2:Jinja2是一个模板引擎,用于在Python Web应用中生成动态HTML。Flask使用Jinja2来渲染模板,将Python变量和逻辑嵌入到HTML中,生成最终的网页内容。

各个库的作用说明

Flask==2.3.3

作用:Flask是Python的轻量级Web框架,用于快速开发Web应用程序。

  • 提供路由系统,处理URL到函数的映射

  • 处理HTTP请求和响应

  • 支持模板渲染(Jinja2集成)

  • 提供会话管理、错误处理等Web开发基础功能

  • 在这个项目中,Flask用于创建Web服务器和API接口

Werkzeug==2.3.7

作用:Werkzeug是WSGI工具包,是Flask的底层依赖。

  • 提供WSGI(Web Server Gateway Interface)实现

  • 处理HTTP请求解析和响应生成

  • 提供URL路由、调试工具、文件上传处理等

  • 包含开发服务器和调试器

  • 是Flask的基石,Flask是基于Werkzeug构建的

Jinja2==3.1.2

作用:Jinja2是Python的模板引擎。

  • 用于生成动态HTML页面

  • 支持模板继承、变量替换、控制结构等

  • 提供安全的HTML自动转义功能

  • Flask默认使用Jinja2作为模板引擎

  • 在这个项目中,用于渲染index.html模板

在pytharm安装环境,执行如下指令

# 单个包安装pip install Flask==2.3.3 -i https://mirrors.aliyun.com/pypi/simple/# 安装多个包pip install Flask==2.3.3 Werkzeug==2.3.7 Jinja2==3.1.2 -i https://mirrors.aliyun.com/pypi/simple/# 使用requirements.txt文件安装pip install -r requirements.txt -i https://mirrors.aliyun.com/pypi/simple/

6. 项目说明文件 (README.md)

# 水质数据监测系统一个基于Python Flask的水质数据展示网页应用,用于实时监测和展示水质指标。## 功能特点1. **实时数据展示**:显示流量、COD、氨氮、总磷、SS、pH等指标的实时值2. **趋势图展示**:每个指标都有对应的历史趋势图3. **多指标对比**:直观比较各指标当前值4. **状态指示**:根据预设范围显示正常/警告/异常状态5. **异常模拟**:可以手动触发模拟异常数据6. **自动更新**:数据每2秒自动更新## 安装和运行1. 确保已安装Python 3.7或更高版本2. 安装依赖包:pip install -r requirements.txt
3. 运行应用:python app.py
4. 在浏览器中访问:http://localhost:5000## 项目结构- `app.py` - Flask主应用,包含API接口和数据模拟逻辑- `templates/index.html` - 主页面HTML模板- `static/css/style.css` - 页面样式- `static/js/charts.js` - 图表交互和数据处理JavaScript- `requirements.txt` - Python依赖包列表## 数据模拟系统使用随机数生成模拟水质数据,具有以下特点:- 各指标在合理范围内随机波动- pH值变化幅度较小,其他指标变化幅度较大- 可以模拟异常数据以测试系统响应## 技术栈- 后端:Python Flask- 前端:HTML5, CSS3, JavaScript- 图表:Chart.js- 样式:Font Awesome图标库## 自定义配置可以修改`app.py`中的`quality_ranges`字典来调整各指标的正常范围。

运行说明

  1. 确保已安装Python 3.7+和pip

  2. 创建项目文件夹,将上述文件按结构放置

  3. 在项目根目录运行:pip install -r requirements.txt

  4. 运行:python app.py

  5. 打开浏览器访问:http://localhost:5000

功能说明

  1. 实时数据展示:顶部卡片显示各水质指标的实时数值和状态

  2. 趋势图展示:可以选择不同指标和时间范围查看历史趋势

  3. 多指标对比:使用柱状图对比各指标的当前值

  4. 状态指示:圆形指示灯显示水质状态(绿色=正常,黄色=警告,红色=异常)

  5. 模拟异常:点击"模拟异常"按钮可以测试系统对异常数据的响应

  6. 自动更新:数据每2秒自动更新,无需手动刷新

这个系统完全使用Python技术栈开发,包含完整的模拟数据生成和网页展示功能,可以直接运行使用

看下效果:
整个开发过程已经结束,如果你对上面代码不了解,看不懂也没关系,咱们先把代码复制到开发环境,先运行起来先
如果你对画面不满意,那你可以继续制作提示词,发给deepseek,让他再制作满意感高的页面,修改的提示词如下:
对上面html模板进行修改,修改为某公园景观关注的指标,比如空气、出水水质、流量指标,需要是可视化大屏的效果,请你修改html内容,其他代码不需要修改
deepseek思考过程如下:
我们要求将原本的水质指标改为公园景观关注的指标,如空气、出水水质、流量指标等。同时,要求大屏效果,因此可能需要调整布局和样式,使其更适合大屏展示。由于其他代码(如app.py)不需要修改,我们仅修改HTML模板部分。但是注意,原app.py中定义了六个指标,现在我们需要修改为公园景观关注的指标。由于原代码中使用了六个指标,且模拟数据部分和API都依赖于这些指标,我们不能随意减少指标数量,但可以改变指标的名称和正常范围。然而,根据问题,只修改HTML内容,但实际指标名称在app.py中定义,如果只改HTML不改app.py,那么指标名称对不上。所以我们需要协调一下:要么修改app.py中的指标名称,要么在HTML中使用相同的指标名称。由于问题要求只修改HTML,但为了匹配新的指标,我们假设app.py中的指标已经更改为公园景观相关的指标。但这里我们只能修改HTML,所以我们需要知道新的指标名称是什么?根据问题,新的指标可能是:空气(可能包含多个指标,但这里我们只能选择几个代表性的)、出水水质、流量指标。我们假设新的六个指标为:PM2.5(空气)温度(空气)湿度(空气)出水COD(出水水质)出水氨氮(出水水质)流量(流量指标)但是原代码中每个指标都有对应的卡片和图表,所以我们这里需要将HTML中的指标名称和单位等进行更改。另外,大屏效果通常意味着更大的字体、更紧凑的布局、更醒目的颜色等。我们将对CSS进行一些调整,使其更符合大屏展示。由于问题要求只修改HTML,但为了达到大屏效果,我们也会修改CSS部分(因为CSS是静态文件,属于HTML模板的一部分,所以我们可以在HTML中内嵌CSS,也可以修改外部CSS文件。这里我们选择修改外部CSS,但为了保持完整性,我们也会在HTML中引入一个内联的样式以作调整。不过,原项目结构中有单独的CSS文件,我们可以修改它。但这里为了简单,我们直接在HTML中添加一些内联样式,同时保留对外部CSS的引用。由于我们不知道app.py中具体改了哪些指标,所以我们假设app.py中的指标已经改为:water_quality_data = {'PM2.5': deque(maxlen=100),'温度': deque(maxlen=100),'湿度': deque(maxlen=100),'出水COD': deque(maxlen=100),'出水氨氮': deque(maxlen=100),'流量': deque(maxlen=100)}并且,quality_ranges也需要相应调整,但这里我们只修改HTML,所以假设这些已经调整。因此,我们修改HTML模板,将指标名称替换为上述六个,并调整页面标题和各个部分的描述。同时,为了达到大屏效果,我们将调整布局,可能使用更宽的布局,并调整字体大小。由于时间关系,我们只修改HTML文件,并对CSS进行一些调整。如果原CSS文件不够,我们将在HTML中增加一些内联样式。注意:原CSS文件是独立的,我们可以在HTML中覆盖一些样式,以达到大屏效果。由于我们无法知道原CSS文件的所有内容,因此我们将以内联样式的方式添加一些大屏样式。
以下是修改后的HTML模板,专门针对公园景观监测需求,调整为"空气、出水水质、流量指标"等关注指标,并优化为大屏可视化效果
<!DOCTYPE html><htmllang="zh-CN"><head>    <metacharset="UTF-8">    <metaname="viewport"content="width=device-width, initial-scale=1.0">    <title>公园景观环境监测大屏</title>    <linkrel="stylesheet"href="{{ url_for('static', filename='css/style.css') }}">    <scriptsrc="https://cdn.jsdelivr.net/npm/chart.js"></script>    <linkrel="stylesheet"href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">    <style>        /* 大屏专用样式 */        body {            background-color: #0a1a2d;            color: #ffffff;            font-family: 'Microsoft YaHei', 'Segoe UI', Arial, sans-serif;            overflow-x: hidden;        }        .container {            max-width: 100%;            margin: 0 auto;            padding: 15px;        }        .header {            background: linear-gradient(90deg, rgba(16, 36, 64, 0.9) 0%, rgba(22, 50, 92, 0.9) 100%);            border-radius: 15px;            padding: 20px 30px;            margin-bottom: 20px;            border: 1px solid rgba(64, 156, 255, 0.3);            box-shadow: 0 0 30px rgba(0, 150, 255, 0.1);            display: flex;            justify-content: space-between;            align-items: center;        }        .header h1 {            font-size: 32px;            font-weight: 700;            background: linear-gradient(90deg, #4facfe 0%, #00f2fe 100%);            -webkit-background-clip: text;            background-clip: text;            color: transparent;            margin: 0;        }        .header h1 i {            margin-right: 15px;            color: #00f2fe;        }        .park-info {            display: flex;            gap: 30px;            font-size: 16px;        }        .info-item {            text-align: center;        }        .info-label {            color: #8ba3c3;            font-size: 14px;            margin-bottom: 5px;        }        .info-value {            font-size: 22px;            font-weight: bold;            color: #4facfe;        }        .dashboard {            display: grid;            grid-template-columns: 1fr 1fr 1fr;            grid-template-rows: auto auto;            gap: 20px;            grid-template-areas:                 "air air water"                "flow stats stats";        }        .section {            background: rgba(16, 36, 64, 0.7);            border-radius: 15px;            padding: 20px;            border: 1px solid rgba(64, 156, 255, 0.2);            backdrop-filter: blur(10px);            box-shadow: 0 5px 15px rgba(0, 0, 0, 0.3);        }        .section-title {            font-size: 20px;            color: #4facfe;            margin-bottom: 15px;            padding-bottom: 10px;            border-bottom: 1px solid rgba(64, 156, 255, 0.3);            display: flex;            align-items: center;        }        .section-title i {            margin-right: 10px;        }        /* 空气质量模块 */        .air-quality-section {            grid-area: air;        }        .air-indicators {            display: grid;            grid-template-columns: repeat(3, 1fr);            gap: 15px;            margin-bottom: 20px;        }        .air-card {            background: rgba(22, 42, 75, 0.8);            border-radius: 12px;            padding: 15px;            text-align: center;            border: 1px solid rgba(64, 156, 255, 0.2);            transition: all 0.3s ease;        }        .air-card:hover {            transform: translateY(-5px);            box-shadow: 0 10px 20px rgba(0, 0, 0, 0.2);            border-color: rgba(64, 156, 255, 0.5);        }        .air-card h4 {            color: #8ba3c3;            font-size: 14px;            margin-bottom: 10px;        }        .air-value {            font-size: 28px;            font-weight: bold;            margin-bottom: 5px;        }        .air-unit {            color: #8ba3c3;            font-size: 14px;        }        .air-status {            display: inline-block;            padding: 3px 10px;            border-radius: 20px;            font-size: 12px;            margin-top: 8px;        }        .status-excellent { background-color: rgba(0, 200, 83, 0.2); color: #00c853; }        .status-good { background-color: rgba(76, 175, 80, 0.2); color: #4caf50; }        .status-moderate { background-color: rgba(255, 193, 7, 0.2); color: #ffc107; }        .status-poor { background-color: rgba(255, 87, 34, 0.2); color: #ff5722; }        /* 水质模块 */        .water-quality-section {            grid-area: water;        }        .water-indicators {            display: grid;            grid-template-columns: 1fr 1fr;            gap: 15px;        }        .water-card {            background: rgba(22, 42, 75, 0.8);            border-radius: 12px;            padding: 15px;            border: 1px solid rgba(64, 156, 255, 0.2);        }        .water-card h4 {            color: #8ba3c3;            font-size: 14px;            margin-bottom: 10px;        }        .water-value {            font-size: 24px;            font-weight: bold;            margin-bottom: 5px;        }        .water-unit {            color: #8ba3c3;            font-size: 14px;        }        .water-gauge {            height: 8px;            background: rgba(255, 255, 255, 0.1);            border-radius: 4px;            margin-top: 10px;            overflow: hidden;        }        .water-fill {            height: 100%;            border-radius: 4px;            transition: width 0.5s ease;        }        /* 流量模块 */        .flow-section {            grid-area: flow;        }        .flow-display {            text-align: center;            padding: 20px 0;        }        .flow-value {            font-size: 42px;            font-weight: bold;            background: linear-gradient(90deg, #4facfe 0%, #00f2fe 100%);            -webkit-background-clip: text;            background-clip: text;            color: transparent;            margin-bottom: 10px;        }        .flow-unit {            font-size: 18px;            color: #8ba3c3;        }        .flow-change {            font-size: 14px;            margin-top: 10px;        }        .positive { color: #00c853; }        .negative { color: #ff5722; }        /* 统计图表模块 */        .stats-section {            grid-area: stats;        }        .chart-container {            height: 300px;            margin-top: 15px;        }        .chart-header {            display: flex;            justify-content: space-between;            margin-bottom: 15px;        }        .chart-selector {            display: flex;            gap: 10px;        }        .chart-btn {            background: rgba(22, 42, 75, 0.8);            border: 1px solid rgba(64, 156, 255, 0.3);            color: #8ba3c3;            padding: 5px 15px;            border-radius: 20px;            cursor: pointer;            font-size: 14px;            transition: all 0.3s ease;        }        .chart-btn.active {            background: rgba(64, 156, 255, 0.2);            color: #4facfe;            border-color: #4facfe;        }        .chart-btn:hover {            background: rgba(64, 156, 255, 0.1);        }        /* 底部信息 */        .footer {            margin-top: 20px;            text-align: center;            color: #8ba3c3;            font-size: 14px;            padding: 15px;            border-top: 1px solid rgba(255, 255, 255, 0.1);        }        .data-refresh {            display: inline-flex;            align-items: center;            gap: 10px;            background: rgba(22, 42, 75, 0.8);            padding: 8px 20px;            border-radius: 20px;            margin-top: 10px;        }        .pulse {            display: inline-block;            width: 10px;            height: 10px;            border-radius: 50%;            background-color: #00c853;            margin-right: 5px;            animation: pulse 2s infinite;        }        @keyframes pulse {            0% { opacity: 1; }            50% { opacity: 0.5; }            100% { opacity: 1; }        }        /* 响应式调整 */        @media (max-width: 1200px) {            .dashboard {                grid-template-columns: 1fr 1fr;                grid-template-areas:                     "air water"                    "flow stats";            }        }        @media (max-width: 768px) {            .dashboard {                grid-template-columns: 1fr;                grid-template-areas:                     "air"                    "water"                    "flow"                    "stats";            }            .air-indicators {                grid-template-columns: 1fr;            }            .header {                flex-direction: column;                text-align: center;                gap: 15px;            }        }    </style></head><body>    <divclass="container">        <headerclass="header">            <h1><iclass="fas fa-tree"></i> 公园景观环境监测大屏</h1>            <divclass="park-info">                <divclass="info-item">                    <divclass="info-label">监测位置</div>                    <divclass="info-value">中央景观湖区</div>                </div>                <divclass="info-item">                    <divclass="info-label">监测时间</div>                    <divclass="info-value"id="current-date">--</div>                </div>                <divclass="info-item">                    <divclass="info-label">系统状态</div>                    <divclass="info-value"><spanclass="pulse"></span> 运行正常</div>                </div>            </div>        </header>        <divclass="dashboard">            <!-- 空气质量监测 -->            <divclass="section air-quality-section">                <divclass="section-title">                    <iclass="fas fa-wind"></i> 空气质量监测                </div>                <divclass="air-indicators">                    <divclass="air-card"id="pm25-card">                        <h4>PM2.5</h4>                        <divclass="air-value"id="pm25-value">--</div>                        <divclass="air-unit">μg/m³</div>                        <divclass="air-status status-excellent"id="pm25-status">优</div>                    </div>                    <divclass="air-card"id="temperature-card">                        <h4>温度</h4>                        <divclass="air-value"id="temperature-value">--</div>                        <divclass="air-unit">°C</div>                        <divclass="air-status status-good"id="temperature-status">舒适</div>                    </div>                    <divclass="air-card"id="humidity-card">                        <h4>湿度</h4>                        <divclass="air-value"id="humidity-value">--</div>                        <divclass="air-unit">%</div>                        <divclass="air-status status-good"id="humidity-status">适宜</div>                    </div>                </div>                <divclass="chart-container">                    <canvasid="air-trend-chart"></canvas>                </div>            </div>            <!-- 出水水质监测 -->            <divclass="section water-quality-section">                <divclass="section-title">                    <iclass="fas fa-tint"></i> 出水水质监测                </div>                <divclass="water-indicators">                    <divclass="water-card"id="ph-card">                        <h4>pH值</h4>                        <divclass="water-value"id="ph-value">--</div>                        <divclass="water-unit">pH</div>                        <divclass="water-gauge">                            <divclass="water-fill"id="ph-fill"style="width: 70%; background-color: #4caf50;"></div>                        </div>                    </div>                    <divclass="water-card"id="cod-card">                        <h4>COD</h4>                        <divclass="water-value"id="cod-value">--</div>                        <divclass="water-unit">mg/L</div>                        <divclass="water-gauge">                            <divclass="water-fill"id="cod-fill"style="width: 40%; background-color: #ff9800;"></div>                        </div>                    </div>                    <divclass="water-card"id="turbidity-card">                        <h4>浊度</h4>                        <divclass="water-value"id="turbidity-value">--</div>                        <divclass="water-unit">NTU</div>                        <divclass="water-gauge">                            <divclass="water-fill"id="turbidity-fill"style="width: 30%; background-color: #00bcd4;"></div>                        </div>                    </div>                    <divclass="water-card"id="do-card">                        <h4>溶解氧</h4>                        <divclass="water-value"id="do-value">--</div>                        <divclass="water-unit">mg/L</div>                        <divclass="water-gauge">                            <divclass="water-fill"id="do-fill"style="width: 85%; background-color: #4caf50;"></div>                        </div>                    </div>                </div>                <divclass="chart-container">                    <canvasid="water-trend-chart"></canvas>                </div>            </div>            <!-- 流量监测 -->            <divclass="section flow-section">                <divclass="section-title">                    <iclass="fas fa-water"></i> 景观水流监测                </div>                <divclass="flow-display">                    <divclass="flow-value"id="flow-value">0.00</div>                    <divclass="flow-unit">m³/s</div>                    <divclass="flow-change">                        日变化: <spanid="flow-change-value"class="positive">+2.5%</span>                    </div>                </div>                <divclass="chart-container">                    <canvasid="flow-trend-chart"></canvas>                </div>            </div>            <!-- 综合统计 -->            <divclass="section stats-section">                <divclass="section-title">                    <iclass="fas fa-chart-bar"></i> 综合数据统计                </div>                <divclass="chart-header">                    <divclass="chart-title">多指标对比分析</div>                    <divclass="chart-selector">                        <buttonclass="chart-btn active"data-chart="day">今日</button>                        <buttonclass="chart-btn"data-chart="week">本周</button>                        <buttonclass="chart-btn"data-chart="month">本月</button>                    </div>                </div>                <divclass="chart-container">                    <canvasid="comparison-chart"></canvas>                </div>            </div>        </div>        <footerclass="footer">            <p>© 2023 智慧公园景观监测系统 | 数据更新: <spanid="last-update">--:--:--</span></p>            <divclass="data-refresh">                <iclass="fas fa-sync-alt"></i>                <span>数据每2秒自动刷新 | 监测点: 公园东区 | 中央湖区 | 北侧林区</span>            </div>        </footer>    </div>    <scriptsrc="{{ url_for('static', filename='js/charts.js') }}"></script>    <script>        // 更新当前日期时间        function updateDateTime() {            const now = new Date();            const dateStr = now.toLocaleDateString('zh-CN', {                year: 'numeric',                month: '2-digit',                day: '2-digit'            });            const timeStr = now.toLocaleTimeString('zh-CN');            document.getElementById('current-date').textContent = dateStr + ' ' + timeStr;            document.getElementById('last-update').textContent = timeStr;            // 每秒钟更新一次时间            setTimeout(updateDateTime, 1000);        }        // 初始化时间显示        updateDateTime();        // 图表按钮切换        document.querySelectorAll('.chart-btn').forEach(btn => {            btn.addEventListener('click', function() {                document.querySelectorAll('.chart-btn').forEach(b => b.classList.remove('active'));                this.classList.add('active');                // 这里可以添加切换图表数据的逻辑                console.log('切换到:', this.dataset.chart, '数据');            });        });        // 模拟数据更新(实际应用中应由后端API提供)        function updateMockData() {            // 空气质量数据            const pm25 = Math.floor(Math.random() * 60) + 20;            const temperature = (Math.random() * 10 + 18).toFixed(1);            const humidity = Math.floor(Math.random() * 30) + 50;            document.getElementById('pm25-value').textContent = pm25;            document.getElementById('temperature-value').textContent = temperature;            document.getElementById('humidity-value').textContent = humidity;            // 更新PM2.5状态            const pm25Status = document.getElementById('pm25-status');            pm25Status.className = 'air-status ';            if (pm25 <= 35) {                pm25Status.classList.add('status-excellent');                pm25Status.textContent = '优';            } else if (pm25 <= 75) {                pm25Status.classList.add('status-good');                pm25Status.textContent = '良';            } else if (pm25 <= 115) {                pm25Status.classList.add('status-moderate');                pm25Status.textContent = '轻度';            } else {                pm25Status.classList.add('status-poor');                pm25Status.textContent = '中度';            }            // 水质数据            const ph = (Math.random() * 1.5 + 6.5).toFixed(1);            const cod = Math.floor(Math.random() * 30) + 10;            const turbidity = (Math.random() * 15 + 5).toFixed(1);            const doValue = (Math.random() * 4 + 5).toFixed(1);            document.getElementById('ph-value').textContent = ph;            document.getElementById('cod-value').textContent = cod;            document.getElementById('turbidity-value').textContent = turbidity;            document.getElementById('do-value').textContent = doValue;            // 更新仪表填充            document.getElementById('ph-fill').style.width = ((ph - 6.5) / 1.5 * 100) + '%';            document.getElementById('cod-fill').style.width = (cod / 40 * 100) + '%';            document.getElementById('turbidity-fill').style.width = (turbidity / 20 * 100) + '%';            document.getElementById('do-fill').style.width = ((doValue - 5) / 4 * 100) + '%';            // 流量数据            const flow = (Math.random() * 2.5 + 0.5).toFixed(2);            document.getElementById('flow-value').textContent = flow;            // 每2秒更新一次模拟数据            setTimeout(updateMockData, 2000);        }        // 启动模拟数据更新        updateMockData();    </script></body></html>
这里我把新的页面命名为default.html,到app.py程序修改模板名称
@app.route('/')def index():    return render_template('default.html',                            indicators=list(water_quality_data.keys()),                           ranges=quality_ranges)
重新运行app.py,效果如下:
介绍完毕,原来利用大模型编程那么容易,如果是新手,先把环境工具熟悉起来,后面就是把大模型当牛马用就行。

最新文章

随机文章