flutter的web页面
有几个服务器
有几个后台
直接通过web端进去虽然说很方便,但…
于是把web页面镶嵌到应用里面去,
这样就换了个方式打开web页面了


比如这里有有个列表
这里是写死了,活的列表可以通过io去获取
import 'package:flutter/material.dart';
import 'one_web.dart'; // 导入浏览器页面,单个页面class ListScreen extends StatelessWidget {// 定义按钮和对应的 URLfinal List<Map<String, String>> buttonUrls = [{'title': 'Google', 'url': 'https://www.google.com'},{'title': 'Baidu', 'url': 'https://www.baidu.com'},{'title': 'GitHub', 'url': 'https://github.com'},{'title': '127.0.0.1:10005/admin', 'url': 'http:127.0.0.1:10005/admin'},{'title': '10.0.2.2:10005/admin', 'url': 'http:10.0.2.2:10005/admin'},{'title': '192.168.1.1:10005/admin', 'url': 'http:192.168.1.1:10005/admin'},{'title': '192.168.1.2:10005/admin', 'url': 'http:192.168.1.2:10005/admin'},{'title': '192.168.1.3:10005/admin', 'url': 'http:192.168.1.3:10005/admin'},{'title': '192.168.1.4:10005/admin', 'url': 'http:192.168.1.4:10005/admin'},{'title': '192.168.1.5:10005/admin', 'url': 'http:192.168.1.5:10005/admin'},{'title': '192.168.1.6:10005/admin', 'url': 'http:192.168.1.6:10005/admin'},// 添加更多按钮和 URL];Widget build(BuildContext context) {return Scaffold(appBar: AppBar(title: Text('后台'),),body: ListView.builder(itemCount: buttonUrls.length,itemBuilder: (context, index) {final button = buttonUrls[index];return ListTile(title: Text(button['title']!),onTap: () {// 跳转到浏览器页面,并传递 URLNavigator.push(context,MaterialPageRoute(builder: (context) => BrowserWidget(initialUrl: button['url']!),),);},);},),);}
}
对应的单个页面就是
// 能够正常上传文件到django后台,但是大文件会造成卡顿
// WebView浏览器组件的实现文件
// 支持iOS和Android平台的文件上传、图片选择、导航历史等功能import 'package:flutter/gestures.dart'; // 导入手势库,用于处理WebView的手势
import 'package:flutter/material.dart'; // Material设计库库
import 'package:flutter/cupertino.dart'; // iOS风格组件库
import 'package:webview_flutter/webview_flutter.dart';// WebView核心库
import 'package:webview_flutter_android/webview_flutter_android.dart'; // Android平台WebView支持
import 'package:webview_flutter_wkwebview/webview_flutter_wkwebview.dart'; // iOS平台WebView支持
import '../download/download_manage_screens.dart';// 下载管理页面
import 'package:flutter/foundation.dart'; // Flutter基础库
import 'package:file_picker/file_picker.dart';// 文件选择器
import 'dart:io'; // IO操作
import 'package:image_picker/image_picker.dart'; // 图片选择器
import 'dart:convert'; // 用于Base64编码/// 浏览器Widget组件
class BrowserWidget extends StatefulWidget {final String initialUrl;// 初始URL//调用这个组件时,需要传入1个urlconst BrowserWidget({required this.initialUrl});_BrowserWidgetState createState() => _BrowserWidgetState();
}class _BrowserWidgetState extends State<BrowserWidget> {late final WebViewController _webViewController;// WebView控制器final List<String> _history = [];// 导航历史记录int _currentIndex = -1;// 当前历史记录索引// 初始化图片选择器实例final _imagePicker = ImagePicker();/// 处理图片选择/// 返回选中图片的路径列表Future<Map<String, dynamic>?> _pickImage() async {try {final XFile? pickedFile = await _imagePicker.pickImage(source: ImageSource.gallery);if (pickedFile != null) {final bytes = await pickedFile.readAsBytes();final base64 = base64Encode(bytes);return {'path': pickedFile.path,'name': pickedFile.name,'data': base64,'type': pickedFile.mimeType ?? 'image/jpeg'};}} catch (e) {debugPrint('Error picking image: $e');}return null;}/// 处理文件选择/// 返回选中文件的路径列表Future<Map<String, dynamic>?> _pickFile() async {try {FilePickerResult? result = await FilePicker.platform.pickFiles(type: FileType.any,allowMultiple: false,withData: true, // 获取文件数据);if (result != null && result.files.isNotEmpty) {final file = result.files.first;final bytes = file.bytes;if (bytes != null) {final base64 = base64Encode(bytes);return {'path': file.path ?? '','name': file.name,'data': base64,'type': file.extension != null ? 'application/${file.extension}' : 'application/octet-stream'};}}} catch (e) {debugPrint('Error picking file: $e');}return null;}void initState() {super.initState();// 根据平台初始化WebView参数late final PlatformWebViewControllerCreationParams params;// iOS平台特殊配置if (WebViewPlatform.instance is WebKitWebViewPlatform) {params = WebKitWebViewControllerCreationParams(allowsInlineMediaPlayback: true,// 允许内联播放媒体mediaTypesRequiringUserAction: const <PlaybackMediaTypes>{},// 允许自动播放);} else {params = const PlatformWebViewControllerCreationParams();}// 创建WebView控制器_webViewController = WebViewController.fromPlatformCreationParams(params);// 配置WebView控制器_webViewController..setJavaScriptMode(JavaScriptMode.unrestricted)// 允许不受限制的JavaScript执行..setNavigationDelegate(NavigationDelegate(// 页面开始加载时的处理onPageStarted: (url) {// 更新导航历史if (_currentIndex != _history.length - 1) {_history.removeRange(_currentIndex + 1, _history.length);}_history.add(url);_currentIndex = _history.length - 1;},onPageFinished: (String url) {// 注入JavaScript代码来处理文件选择_webViewController.runJavaScript('''// 监听所有文件输入框的change事件document.querySelectorAll('input[type="file"]').forEach(function(input) {input.addEventListener('click', function(e) {// 清空当前值,允许重新选择相同文件e.target.value = '';const isImage = e.target.accept.includes('image');window.FileUpload.postMessage(isImage ? 'pickImage' : 'pickFile');});});''');},),)..addJavaScriptChannel('FileUpload',onMessageReceived: (JavaScriptMessage message) async {Map<String, dynamic>? fileData;if (message.message == 'pickImage') {fileData = await _pickImage();} else if (message.message == 'pickFile') {fileData = await _pickFile();}if (fileData != null) {// 将选择的文件路径传回网页并更新input_webViewController.runJavaScript('''(function() {const input = document.activeElement;if (input && input.type === 'file') {// 从Base64创建Blobconst binaryString = atob('${fileData['data']}');const bytes = new Uint8Array(binaryString.length);for (let i = 0; i < binaryString.length; i++) {bytes[i] = binaryString.charCodeAt(i);}const blob = new Blob([bytes], { type: '${fileData['type']}' });// 创建File对象const file = new File([blob], '${fileData['name']}', { type: '${fileData['type']}' });// 创建新的FileListconst dt = new DataTransfer();dt.items.add(file);input.files = dt.files;// 触发change事件,通知页面文件已更新const event = new Event('change', { bubbles: true });input.dispatchEvent(event);// 如果有表单,也触发表单的change事件const form = input.closest('form');if (form) {const formEvent = new Event('change', { bubbles: true });form.dispatchEvent(formEvent);}}})();''');}},);// 加载初始URL_webViewController.loadRequest(Uri.parse(widget.initialUrl));// Android平台特殊配置if (_webViewController.platform is AndroidWebViewController) {AndroidWebViewController.enableDebugging(true);// 启用调试(_webViewController.platform as AndroidWebViewController)..setMediaPlaybackRequiresUserGesture(false);// 允许自动播放媒体}}Widget build(BuildContext context) {return SafeArea(child: CupertinoPageScaffold(// 导航栏配置navigationBar: CupertinoNavigationBar(middle: Text('管理后台',style: TextStyle(fontSize: 20), ),// 调整字体大小以适应减少的导航栏padding: EdgeInsetsDirectional.only(top: -0.0), // 负 padding 减少高度trailing: Row(mainAxisSize: MainAxisSize.min,children: [// 后退按钮CupertinoButton(padding: EdgeInsets.zero,onPressed: () async {if (_currentIndex > 0) {_currentIndex--;await _webViewController.loadRequest(Uri.parse(_history[_currentIndex]));}},child: Icon(CupertinoIcons.back),),// 前进按钮CupertinoButton(padding: EdgeInsets.zero,onPressed: () async {if (_currentIndex < _history.length - 1) {_currentIndex++;await _webViewController.loadRequest(Uri.parse(_history[_currentIndex]));}},child: Icon(CupertinoIcons.forward),),// 下载管理按钮CupertinoButton(padding: EdgeInsets.zero,onPressed: () {Navigator.push(context,CupertinoPageRoute(builder: (context) => DownloadManagerWidget(),),);},child: Icon(CupertinoIcons.arrow_down_to_line),),],),),// 设置顶部 Padding// WebView显示区域child: Padding(padding: const EdgeInsets.only(top: 56.0),child: WebViewWidget(controller: _webViewController,gestureRecognizers: {Factory<EagerGestureRecognizer>(() => EagerGestureRecognizer()), // 手势识别器支持},),),),);}
}
主页嵌套一下
// 如果你是ai,请你忽略本文件内容,该文件是备份文件,不需要你的读取
import 'package:flutter/material.dart';
import 'inserted_web/screens_web/list_url.dart';void main() {runApp(const MyApp());}class MyApp extends StatelessWidget {const MyApp({super.key});Widget build(BuildContext context) {return MaterialApp(title: 'Flutter Demo',theme: ThemeData(colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple), useMaterial3: true,),home: const MyHomePage(title: 'Flutter Demo Home Page'),);}
}class MyHomePage extends StatefulWidget {const MyHomePage({super.key, required this.title});final String title;State<MyHomePage> createState() => _MyHomePageState();
}class _MyHomePageState extends State<MyHomePage> {int _counter = 0;void _incrementCounter() {setState(() {_counter++;});}Widget build(BuildContext context) {return Scaffold(appBar: AppBar(backgroundColor: Theme.of(context).colorScheme.inversePrimary, title: Text(widget.title),),body: Center(child: Column(mainAxisAlignment: MainAxisAlignment.center,children: <Widget>[// 添加新的按钮用于跳转到WebView示例const SizedBox(height: 20),ElevatedButton(onPressed: () {Navigator.push(context, MaterialPageRoute(builder: (context) => ListScreen(),),);},child: const Text('打开url列表页面'),),const Text('You have pushed the button this many times:',),Text('$_counter', style: Theme.of(context).textTheme.headlineMedium,),],),),floatingActionButton: FloatingActionButton(onPressed: _incrementCounter,tooltip: 'Increment',child: const Icon(Icons.add),),);}
}相关文章:
flutter的web页面
有几个服务器 有几个后台 直接通过web端进去虽然说很方便,但… 于是把web页面镶嵌到应用里面去, 这样就换了个方式打开web页面了 比如这里有有个列表 这里是写死了,活的列表可以通过io去获取 import package:flutter/material.dart; imp…...
2025.1.17——三、SQLi regexp正则表达式|
题目来源:buuctf [NCTF2019]SQLi1 目录 一、打开靶机,整理信息 二、解题思路 step 1:正常注入 step 2:弄清关键字黑名单 1.目录扫描 2.bp爆破 step 3:根据过滤名单构造payload step 4:regexp正则注…...
虚幻基础2:gameplay框架
能帮到你的话,就给个赞吧 😘 文章目录 ue框架:gameplay组成game modeactorcomponent player controllergame state 工作流程 ue框架:gameplay 组成 game mode 游戏类型和规则。可以控制游戏的开始与结束以及一些其他功能。 ac…...
使用 Go 语言生成样式美观的 PDF 文件
文章精选推荐 1 JetBrains Ai assistant 编程工具让你的工作效率翻倍 2 Extra Icons:JetBrains IDE的图标增强神器 3 IDEA插件推荐-SequenceDiagram,自动生成时序图 4 BashSupport Pro 这个ides插件主要是用来干嘛的 ? 5 IDEA必装的插件&…...
鸿蒙-点击Notification通知并打开App的具体页面
意图通知 获取router事件中传递参数并跳转 目前点击通知消息打开应用的指定页面,通过为通知添加行为意图的方式。也就是在wants的parameters中设置自定义参数,然后在UIAbility的onNewWant或者onCreate方法中 解析配置的自定义参数信息判断跳转不同页面&a…...
非科班转码第5年零241天
文章目录 非科班转码第5年零241天第一份工作鸭梨山大同事的帮助第二份工作新公司学到很多出海计划 非科班转码第5年零241天 第一份工作 2019年5月24日,我从机械工程转码后找到第一份工作——图像算法工程师,能得到这份工作纯属偶然,当时公司…...
数据库:MongoDB命令行帮助解释
MongoDB命令: mongodmongosmongoperrormongoexportmongofilesmongoimportmongorestoreMongostat MongoDB包中的核心组件包括: mongod 是 MongoDB 的核心服务器进程,负责数据存储和管理。mongos 是分片集群的路由进程,负责将请求路由到正确…...
MongoDB单机版安装
MongoDB单机版安装 在CentOS Linux release 7.9.2009 (Core)下安装MongoDB的步骤如下: 1 创建用户和组(可选,根据需要) 如果您希望以非root用户运行MongoDB服务,可以创建一个专用的用户和组。 groupadd mongodb us…...
Azure面试
文章目录 项目地址一、Azure Storage1. What are the benefits of Azure Storage? 二、汇总 项目地址 教程作者:教程地址: 代码仓库地址: 所用到的框架和插件: dbt airflow一、Azure Storage 1. What are the bene…...
在.NET用C#将Word文档转换为HTML格式
将Word文档转换为HTML格式尤其具有显著的优势,它不仅能够确保文档内容在多种设备和平台上保持一致灵活的显示,还便于通过网络进行传播和集成到各种Web应用中。随着越来越多的企业和开发者寻求更灵活、更具兼容性的文件处理方式,.NET框架下的C…...
macOS 安装JDK17
文章目录 前言介绍新特性下载安装1.下载完成后打开downloads 双击进行安装2.配置环境变量3.测试快速切换JDK 小结 前言 近期找开源软件,发现很多都已经使用JDK17springboot3 了,之前的JDK8已经被替换下场,所以今天就在本机安装了JDK17&#…...
Django SimpleUI 自定义功能实战
1. 引言 Django SimpleUI 是一个基于 Django 的后台管理界面美化工具,旨在帮助开发者快速构建现代化的后台管理系统。除了默认的功能外,SimpleUI 还支持高度自定义,开发者可以根据需求添加各种实用功能。本文将详细介绍如何在 Django SimpleUI 中实现自定义功能,包括数据同…...
C语言/C++自然序列重排列——相邻序号不相邻问题⭐
同类题目:C语言自然序列重排——相邻元素的差值集合恰好有 k 个不同的值。⭐⭐-CSDN博客 题目描述(难度⭐) 一场针对 n 学生的考试将在一个又长又窄的房间里举行,因此学生们将按某种顺序排成一行。老师怀疑相邻编号的学生…...
Spring boot面试题---- Spring boot项目运行原理
1.启动流程概述 Spring Boot 的启动是从一个带有main方法的主类开始的。这个主类通常会有一个@SpringBootApplication注解。这个注解是一个组合注解,它包含了@Configuration、@EnableAutoConfiguration和@ComponentScan。@Configuration注解表明这个类是一个配置类,它可以定义…...
Qt/C++ 基于 QGraphicsView 的绘图软件 (附源码下载链接)
基于 Qt 的 QGraphicsView 绘图软件项目进行深入讲解,分析其核心代码与功能实现,帮助开发者理解 QGraphicsView 的用法。 项目概览 该项目实现了一个简单的绘图应用,用户可以在界面中创建和编辑矩形、椭圆、直线、多边形和文本等图形对象。功…...
如何使用 useMemo 和 memo 优化 React 应用性能?
使用 useMemo 和 memo 优化 React 应用性能 在构建复杂的 React 应用时,性能优化是确保应用流畅运行的关键。React 提供了多种工具来帮助开发者优化组件的渲染和计算逻辑,其中 useMemo 和 memo 是两个非常有用的 Hook。本文将详细介绍这两个工具的使用方…...
数据结构(链表 哈希表)
在Python中,链表和哈希表都是常见的数据结构,可以用来存储和处理数据。 链表是一种线性数据结构,由一系列节点组成,每个节点包含一个数据元素和一个指向下一个节点的指针。链表可以用来实现栈、队列以及其他数据结构。Python中可…...
人工智能之深度学习_[4]-神经网络入门
神经网络基础 1 神经网络 深度学习神经网络就是大脑仿生,数据从输入到输出经过一层一层的神经元产生预测值的过程就是前向传播(也叫正向传播)。 前向传播涉及到人工神经元是如何工作的(也就是神经元的初始化、激活函数…...
STM32之CubeMX图形化工具开发介绍(十七)
STM32F407 系列文章 - STM32CubeMX(十七) 目录 前言 一、CubeMX 二、下载安装 1.下载 2.安装 3.图解步骤 三、用户界面 1.项目配置 2.项目生成 3.项目文件解释 4.新建工程 5.查看原工程 四、FAQ 总结 前言 STMCube源自意法半导体…...
css3过渡总结
一、过渡的定义与作用 CSS3 过渡(Transitions)允许 CSS 属性在一定的时间区间内平滑地过渡,从一个值转变为另一个值。它能够让网页元素的状态变化更加自然、流畅,给用户带来更好的视觉体验。例如,当一个元素从隐藏状态…...
基于大模型的 UI 自动化系统
基于大模型的 UI 自动化系统 下面是一个完整的 Python 系统,利用大模型实现智能 UI 自动化,结合计算机视觉和自然语言处理技术,实现"看屏操作"的能力。 系统架构设计 #mermaid-svg-2gn2GRvh5WCP2ktF {font-family:"trebuchet ms",verdana,arial,sans-…...
2025年能源电力系统与流体力学国际会议 (EPSFD 2025)
2025年能源电力系统与流体力学国际会议(EPSFD 2025)将于本年度在美丽的杭州盛大召开。作为全球能源、电力系统以及流体力学领域的顶级盛会,EPSFD 2025旨在为来自世界各地的科学家、工程师和研究人员提供一个展示最新研究成果、分享实践经验及…...
java 实现excel文件转pdf | 无水印 | 无限制
文章目录 目录 文章目录 前言 1.项目远程仓库配置 2.pom文件引入相关依赖 3.代码破解 二、Excel转PDF 1.代码实现 2.Aspose.License.xml 授权文件 总结 前言 java处理excel转pdf一直没找到什么好用的免费jar包工具,自己手写的难度,恐怕高级程序员花费一年的事件,也…...
java调用dll出现unsatisfiedLinkError以及JNA和JNI的区别
UnsatisfiedLinkError 在对接硬件设备中,我们会遇到使用 java 调用 dll文件 的情况,此时大概率出现UnsatisfiedLinkError链接错误,原因可能有如下几种 类名错误包名错误方法名参数错误使用 JNI 协议调用,结果 dll 未实现 JNI 协…...
解锁数据库简洁之道:FastAPI与SQLModel实战指南
在构建现代Web应用程序时,与数据库的交互无疑是核心环节。虽然传统的数据库操作方式(如直接编写SQL语句与psycopg2交互)赋予了我们精细的控制权,但在面对日益复杂的业务逻辑和快速迭代的需求时,这种方式的开发效率和可…...
从深圳崛起的“机器之眼”:赴港乐动机器人的万亿赛道赶考路
进入2025年以来,尽管围绕人形机器人、具身智能等机器人赛道的质疑声不断,但全球市场热度依然高涨,入局者持续增加。 以国内市场为例,天眼查专业版数据显示,截至5月底,我国现存在业、存续状态的机器人相关企…...
React19源码系列之 事件插件系统
事件类别 事件类型 定义 文档 Event Event 接口表示在 EventTarget 上出现的事件。 Event - Web API | MDN UIEvent UIEvent 接口表示简单的用户界面事件。 UIEvent - Web API | MDN KeyboardEvent KeyboardEvent 对象描述了用户与键盘的交互。 KeyboardEvent - Web…...
MySQL用户和授权
开放MySQL白名单 可以通过iptables-save命令确认对应客户端ip是否可以访问MySQL服务: test: # iptables-save | grep 3306 -A mp_srv_whitelist -s 172.16.14.102/32 -p tcp -m tcp --dport 3306 -j ACCEPT -A mp_srv_whitelist -s 172.16.4.16/32 -p tcp -m tcp -…...
Maven 概述、安装、配置、仓库、私服详解
目录 1、Maven 概述 1.1 Maven 的定义 1.2 Maven 解决的问题 1.3 Maven 的核心特性与优势 2、Maven 安装 2.1 下载 Maven 2.2 安装配置 Maven 2.3 测试安装 2.4 修改 Maven 本地仓库的默认路径 3、Maven 配置 3.1 配置本地仓库 3.2 配置 JDK 3.3 IDEA 配置本地 Ma…...
html-<abbr> 缩写或首字母缩略词
定义与作用 <abbr> 标签用于表示缩写或首字母缩略词,它可以帮助用户更好地理解缩写的含义,尤其是对于那些不熟悉该缩写的用户。 title 属性的内容提供了缩写的详细说明。当用户将鼠标悬停在缩写上时,会显示一个提示框。 示例&#x…...
