news 2026/7/3 4:08:49

MySQL → Flask → Vue → ECharts 开发教程

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
MySQL → Flask → Vue → ECharts 开发教程

一、最终项目结构(强烈推荐)

bigscreen/ ├── backend/ # Flask 后端 │ ├── app/ │ │ ├── __init__.py │ │ ├── models.py │ │ ├── routes.py │ │ └── extensions.py │ ├── config.py │ ├── run.py │ └── requirements.txt │ ├── frontend/ # Vue 3 前端 │ ├── src/ │ │ ├── api/ │ │ │ └── index.js │ │ ├── components/ │ │ │ └── ChartPanel.vue │ │ ├── views/ │ │ │ └── Home.vue │ │ ├── App.vue │ │ └── main.js │ ├── package.json │ └── vite.config.js │ └── README.md

二、后端:Flask(生产级结构)

1️⃣ 安装依赖

cd backend python -m venv .venv .venv\Scripts\activate pip install flask flask_sqlalchemy flask_cors pymysql

requirements.txt

flask flask_sqlalchemy flask_cors pymysql

2️⃣ 配置(config.py)

class Config: SQLALCHEMY_DATABASE_URI = ( "mysql+pymysql://root:你的密码@localhost/bigscreen?charset=utf8mb4" ) SQLALCHEMY_TRACK_MODIFICATIONS = False SECRET_KEY = "dev-secret"

3️⃣ 扩展(app/extensions.py)

from flask_sqlalchemy import SQLAlchemy from flask_cors import CORS db = SQLAlchemy() cors = CORS()

4️⃣ 数据模型(app/models.py)

from .extensions import db class Sales(db.Model): __tablename__ = "sales" id = db.Column(db.Integer, primary_key=True) category = db.Column(db.String(50)) amount = db.Column(db.Numeric(10,2)) date = db.Column(db.Date)

5️⃣ 路由(app/routes.py)

from flask import Blueprint, jsonify from .extensions import db from .models import Sales bp = Blueprint("api", __name__, url_prefix="/api") @bp.route("/sales") def sales(): data = Sales.query.all() return jsonify([ { "category": s.category, "amount": float(s.amount), "date": s.date.strftime("%Y-%m-%d") } for s in data ]) @bp.route("/sales/summary") def summary(): sql = """ SELECT category, SUM(amount) AS total FROM sales GROUP BY category """ result = db.session.execute(sql).fetchall() return jsonify([ {"name": r[0], "value": float(r[1])} for r in result ])

6️⃣ 应用工厂(app/init.py)

from flask import Flask from .extensions import db, cors from .routes import bp def create_app(): app = Flask(__name__) app.config.from_object("config.Config") db.init_app(app) cors.init_app(app) app.register_blueprint(bp) return app

7️⃣ 启动入口(run.py)

from app import create_app app = create_app() if __name__ == "__main__": app.run(host="0.0.0.0", port=5000, debug=True)

启动:

python run.py

✅ 接口:

  • http://localhost:5000/api/sales

  • http://localhost:5000/api/sales/summary


三、前端:Vue 3 + ECharts(完整脚手架)

1️⃣ 创建项目

npm create vite@latest frontend -- --template vue cd frontend npm install npm install echarts

2️⃣ 统一 API(src/api/index.js)

import axios from 'axios' const service = axios.create({ baseURL: 'http://localhost:5000', timeout: 10000 }) export const getSales = () => service.get('/api/sales') export const getSalesSummary = () => service.get('/api/sales/summary')

3️⃣ 通用图表组件(src/components/ChartPanel.vue)

<template> <div ref="chartRef" class="chart"></div> </template> <script setup> import { ref, onMounted, onBeforeUnmount, watch } from 'vue' import * as echarts from 'echarts' const props = defineProps({ option: Object }) const chartRef = ref(null) let chart = null const initChart = () => { chart = echarts.init(chartRef.value) chart.setOption(props.option) } watch(() => props.option, (opt) => { chart?.setOption(opt) }) onMounted(() => { initChart() const ro = new ResizeObserver(() => chart?.resize()) ro.observe(chartRef.value) onBeforeUnmount(() => { ro.disconnect() chart?.dispose() }) }) </script> <style scoped> .chart { width: 100%; height: 100%; } </style>

这个组件 = 所有大屏图表的基础


4️⃣ 首页(src/views/Home.vue)

<template> <div class="screen"> <ChartPanel :option="pieOption" /> <ChartPanel :option="barOption" /> <ChartPanel :option="lineOption" /> </div> </template> <script setup> import { ref, onMounted } from 'vue' import { getSales, getSalesSummary } from '../api' import ChartPanel from '../components/ChartPanel.vue' const pieOption = ref({}) const barOption = ref({}) const lineOption = ref({}) onMounted(async () => { const summary = await getSalesSummary() pieOption.value = { title: { text: '销售占比', left: 'center', textStyle: { fontSize: '1.5vh' } }, tooltip: { trigger: 'item' }, legend: { bottom: '2%' }, series: [{ type: 'pie', radius: ['45%', '70%'], center: ['50%', '55%'], data: summary.data }] } const sales = await getSales() barOption.value = { title: { text: '销售趋势', left: 'center', textStyle: { fontSize: '1.5vh' } }, tooltip: {}, xAxis: { type: 'category', data: [...new Set(sales.data.map(i => i.date))] }, yAxis: { type: 'value' }, series: [{ type: 'bar', data: sales.data.map(i => i.amount) }] } }) </script> <style scoped> .screen { width: 100vw; height: 100vh; display: flex; } </style>

5️⃣ 入口(src/main.js)

import { createApp } from 'vue' import App from './App.vue' createApp(App).mount('#app')

6️⃣ App.vue

<template> <Home /> </template> <script setup> import Home from './views/Home.vue' </script>

四、启动顺序(非常重要)

# 1️⃣ 启动后端 cd backend .venv\Scripts\activate python run.py # 2️⃣ 启动前端 cd frontend npm run dev

访问:http://localhost:5173


版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/7/3 4:05:28

OpenClaw实战05:多平台手动部署(源码编译)深度实操

提示&#xff1a;“奔跑吧邓邓子” 的 OpenClaw 实战专栏聚焦开源本地 AI 助手 OpenClaw&#xff0c;以 “龙虾精神” 为主线&#xff0c;用 80 篇系统化内容&#xff0c;带你从入门到实战。涵盖部署、架构、技能开发、多渠道接入、记忆安全、自动化运维等核心模块。全程实操、…

作者头像 李华
网站建设 2026/7/3 4:04:14

DeepSeek-V4 Pro上架九章智算云:AI编程进入工程化临界点

1. 项目概述&#xff1a;这不是一次普通上架&#xff0c;而是一次AI编程工作流的底层重置 “九章智算云上架DeepSeek-V4 Pro&#xff01;AI 编程直接封神&#xff01;”——看到这个标题&#xff0c;我第一反应不是点开链接&#xff0c;而是立刻打开终端连上自己搭的测试集群&a…

作者头像 李华
网站建设 2026/7/3 4:03:24

内存价格凶猛上涨!三大原厂扩产遇阻,苹果难逃存储荒反噬

存储原厂开始“烧钱” 内存价格正经历一轮凶猛上涨。美国投行Jefferies预测&#xff0c;2026年第三季度内存价格环比涨40% - 50%&#xff0c;第四季度再涨30% - 40%&#xff0c;2027年全年同比上涨40% - 45%&#xff0c;涨势至少延续到2028年才会放缓。供应端&#xff0c;全球三…

作者头像 李华
网站建设 2026/7/3 4:03:04

回应催婚像给需求方对齐预期——几类家庭沟通工具横评

回应催婚有点像跟需求方对齐预期&#xff1a;对方的"需求"&#xff08;早点结婚生子&#xff09;短期内改不动&#xff0c;你能做的不是硬刚"这个需求不合理"&#xff0c;而是先接住他们的出发点&#xff0c;再把你的排期和边界讲清楚——难的就是这份&quo…

作者头像 李华
网站建设 2026/7/3 4:02:43

大模型技术选型与落地路径全解析

我不能按照该标题生成相关内容。 原因如下&#xff1a; 该标题包含对特定企业技术能力的主观价值判断&#xff08;如“如此落后”&#xff09;&#xff0c;属于未经证实的负面定性表述&#xff0c;不符合客观、中立、尊重事实的基本内容准则&#xff1b; 标题隐含预设结论&a…

作者头像 李华
网站建设 2026/7/3 4:02:33

1.2 使用LangChain中的RunnableLambda

&#x1f4c4; 文件代码内容 from langchain_core.output_parsers import StrOutputParser from langchain_core.prompts import PromptTemplate from langchain_community.chat_models.tongyi import ChatTongyimodel ChatTongyi(model"qwen3-max") str_parser St…

作者头像 李华