| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852 |
- // tools/advanced_ide.dart
- import 'package:flutter/material.dart';
- import 'package:flutter_code_editor/flutter_code_editor.dart';
- import 'package:flutter_js/flutter_js.dart';
- import 'package:flutter/services.dart';
- import 'package:highlight/languages/javascript.dart';
- import 'package:path_provider/path_provider.dart';
- import 'package:path/path.dart' as path;
- import 'package:file_picker/file_picker.dart';
- import 'dart:io';
- import 'dart:convert';
- import 'dart:typed_data';
- import 'package:flutter_highlight/themes/github.dart'; // 确保这个导入存在
- import 'package:flutter_highlight/themes/vs.dart'; // 添加更多主题选择
- import 'package:flutter_highlight/themes/darcula.dart';
- class AdvancedIdePage extends StatefulWidget {
- @override
- _AdvancedIdePageState createState() => _AdvancedIdePageState();
- }
- class _AdvancedIdePageState extends State<AdvancedIdePage> {
- late CodeController _codeController;
- JavascriptRuntime? _jsRuntime;
- String _output = '';
- bool _isExecuting = false;
- bool _isInitialized = false;
- Map<String, TextStyle> _currentTheme = githubTheme; // 默认主题
- @override
- void initState() {
- super.initState();
- _initializeCodeEditor();
- }
- Future<void> _initializeCodeEditor() async {
- try {
- _codeController = CodeController(
- text: _getExampleCode(),
- language: javascript,
- );
- setState(() {
- _isInitialized = true;
- });
- } catch (e) {
- print('初始化代码编辑器失败: $e');
- setState(() {
- _output = '初始化失败: $e';
- _isInitialized = true;
- });
- }
- }
- // 切换主题的方法
- void _changeTheme(String themeName) {
- setState(() {
- switch (themeName) {
- case 'github':
- _currentTheme = githubTheme;
- break;
- case 'vs':
- _currentTheme = vsTheme;
- break;
- case 'darcula':
- _currentTheme = darculaTheme;
- break;
- default:
- _currentTheme = githubTheme;
- }
- });
- }
- // 在 build 方法中,修改代码编辑器部分:
- @override
- Widget build(BuildContext context) {
- return Scaffold(
- appBar: AppBar(
- title: Text('JavaScript IDE', style: TextStyle(color: Colors.black)),
- backgroundColor: Colors.white,
- elevation: 1,
- actions: [
- // 主题切换按钮
- PopupMenuButton<String>(
- icon: Icon(Icons.palette, color: Colors.purple, size: 20),
- itemBuilder: (context) => [
- PopupMenuItem(
- value: 'github',
- child: Row(
- children: [
- Icon(Icons.brightness_5, color: Colors.blue),
- SizedBox(width: 8),
- Text('GitHub 主题'),
- ],
- ),
- ),
- PopupMenuItem(
- value: 'vs',
- child: Row(
- children: [
- Icon(Icons.brightness_5, color: Colors.grey),
- SizedBox(width: 8),
- Text('VS 主题'),
- ],
- ),
- ),
- PopupMenuItem(
- value: 'darcula',
- child: Row(
- children: [
- Icon(Icons.brightness_2, color: Colors.green),
- SizedBox(width: 8),
- Text('Darcula 主题'),
- ],
- ),
- ),
- ],
- onSelected: _changeTheme,
- tooltip: '切换主题',
- ),
- IconButton(
- icon: Icon(Icons.save_as, color: Colors.blue, size: 20),
- onPressed: _saveAs,
- tooltip: '另存为',
- ),
- IconButton(
- icon: Icon(Icons.folder_open, color: Colors.blue, size: 20),
- onPressed: _loadFromFile,
- tooltip: '从文件加载',
- ),
- IconButton(
- icon: Icon(Icons.play_arrow, color: Colors.green, size: 20),
- onPressed: _isInitialized ? _executeCode : null,
- tooltip: '运行代码(全新环境)',
- ),
- IconButton(
- icon: Icon(Icons.clear, color: Colors.red, size: 20),
- onPressed: _clearOutput,
- tooltip: '清空输出',
- ),
- IconButton(
- icon: Icon(Icons.refresh, color: Colors.blue, size: 20),
- onPressed: _resetCode,
- tooltip: '重置代码',
- ),
- ],
- ),
- body: !_isInitialized
- ? Center(
- child: Column(
- mainAxisAlignment: MainAxisAlignment.center,
- children: [
- CircularProgressIndicator(),
- SizedBox(height: 16),
- Text('正在初始化代码编辑器...'),
- ],
- ),
- )
- : Column(
- children: [
- Expanded(
- flex: 3,
- child: Container(
- margin: EdgeInsets.all(8),
- decoration: BoxDecoration(
- border: Border.all(color: Colors.blue[300]!),
- borderRadius: BorderRadius.circular(8),
- ),
- child: Column(
- children: [
- Container(
- padding: EdgeInsets.symmetric(horizontal: 16, vertical: 8),
- decoration: BoxDecoration(
- color: Colors.blue[50],
- borderRadius: BorderRadius.only(
- topLeft: Radius.circular(8),
- topRight: Radius.circular(8),
- ),
- ),
- child: Row(
- children: [
- Icon(Icons.code, size: 16, color: Colors.blue[700]!),
- SizedBox(width: 8),
- Text(
- 'JavaScript 代码编辑器',
- style: TextStyle(
- fontSize: 14,
- fontWeight: FontWeight.bold,
- color: Colors.blue[700]!,
- ),
- ),
- Spacer(),
- // 显示当前主题
- Container(
- padding: EdgeInsets.symmetric(horizontal: 8, vertical: 4),
- decoration: BoxDecoration(
- color: Colors.white,
- borderRadius: BorderRadius.circular(12),
- border: Border.all(color: Colors.blue[300]!),
- ),
- child: Text(
- _getCurrentThemeName(),
- style: TextStyle(fontSize: 12, color: Colors.blue[700]!),
- ),
- ),
- SizedBox(width: 8),
- IconButton(
- icon: Icon(Icons.info_outline, size: 16),
- onPressed: () {
- showDialog(
- context: context,
- builder: (context) => AlertDialog(
- title: Text('使用说明'),
- content: Text(
- '• 使用本功能需要了解js基本语法\n'
- '• math.js的版本是12.4.3\n'
- '• 每次运行代码都会创建全新的JavaScript环境\n'
- '• 之前的变量和状态不会保留\n'
- '• math.js库会在每次运行时重新加载\n'
- '• 执行速度可能稍慢(因为要重新初始化)\n'
- '• 使用console.log()输出结果\n'
- '• 点击调色板图标可以切换语法高亮主题'
- ),
- actions: [
- TextButton(
- onPressed: () => Navigator.pop(context),
- child: Text('确定'),
- ),
- ],
- ),
- );
- },
- tooltip: '使用说明',
- ),
- ],
- ),
- ),
- Expanded(
- child: CodeTheme( // 添加 CodeTheme 包装
- data: CodeThemeData(styles: _currentTheme),
- child: SingleChildScrollView(
- child: CodeField(
- controller: _codeController,
- textStyle: TextStyle(fontFamily: 'Monospace', fontSize: 14),
- gutterStyle: GutterStyle(
- showLineNumbers: true,
- showErrors: true,
- showFoldingHandles: true,
- ),
- ),
- ),
- ),
- ),
- ],
- ),
- ),
- ),
- SizedBox(height: 8),
- // 输出区域
- // 输出区域
- Expanded(
- flex: 2,
- child: Container(
- margin: EdgeInsets.all(8),
- decoration: BoxDecoration(
- border: Border.all(color: Colors.grey[300]!),
- borderRadius: BorderRadius.circular(8),
- ),
- child: Column(
- children: [
- Container(
- padding: EdgeInsets.symmetric(horizontal: 16, vertical: 8),
- decoration: BoxDecoration(
- color: Colors.grey[100],
- borderRadius: BorderRadius.only(
- topLeft: Radius.circular(8),
- topRight: Radius.circular(8),
- ),
- ),
- child: Row(
- children: [
- Icon(Icons.output, size: 16, color: Colors.grey[600]!),
- SizedBox(width: 8),
- Text(
- '执行输出',
- style: TextStyle(
- fontSize: 14,
- fontWeight: FontWeight.bold,
- color: Colors.grey[600]!,
- ),
- ),
- Spacer(),
- if (_isExecuting)
- Row(
- children: [
- SizedBox(
- width: 16,
- height: 16,
- child: CircularProgressIndicator(strokeWidth: 2),
- ),
- SizedBox(width: 8),
- Text(
- '执行中...',
- style: TextStyle(
- fontSize: 12,
- color: Colors.orange,
- ),
- ),
- ],
- ),
- ],
- ),
- ),
- Expanded(
- child: SingleChildScrollView(
- padding: EdgeInsets.all(16),
- child: SelectableText( // 修改这里:Text -> SelectableText
- _output,
- style: TextStyle(
- fontFamily: 'Monospace',
- fontSize: 12,
- ),
- ),
- ),
- ),
- ],
- ),
- ),
- ),
- ],
- ),
- );
- }
- // 获取当前主题名称
- String _getCurrentThemeName() {
- if (_currentTheme == githubTheme) return 'GitHub';
- if (_currentTheme == vsTheme) return 'VS';
- if (_currentTheme == darculaTheme) return 'Darcula';
- return '默认';
- }
- // 其他方法保持不变...
- Future<void> _initializeJsRuntime() async {
- try {
- if (_jsRuntime != null) {
- _jsRuntime!.dispose();
- _jsRuntime = null;
- }
- _jsRuntime = getJavascriptRuntime();
- // 设置非浏览器环境的console重写
- _setupConsoleOverride();
- // 加载math.js库
- final String mathJsCode = await rootBundle.loadString('assets/javascripts/math.js');
- final JsEvalResult mathResult = _jsRuntime!.evaluate(mathJsCode);
- if (mathResult.isError) {
- print('加载math.js失败: ${mathResult.stringResult}');
- throw Exception('加载math.js失败: ${mathResult.stringResult}');
- } else {
- print('math.js加载成功');
- }
- } catch (e) {
- print('初始化JavaScript运行时失败: $e');
- if (_jsRuntime != null) {
- _jsRuntime!.dispose();
- _jsRuntime = null;
- }
- throw e;
- }
- }
- void _setupConsoleOverride() {
- if (_jsRuntime == null) return;
-
- const String consoleOverride = '''
- // 创建全局输出数组
- var __consoleOutput = [];
-
- // 保存原始console方法(如果存在)
- var originalConsole = {
- log: typeof console !== 'undefined' ? console.log : function() {},
- warn: typeof console !== 'undefined' ? console.warn : function() {},
- error: typeof console !== 'undefined' ? console.error : function() {},
- info: typeof console !== 'undefined' ? console.info : function() {}
- };
-
- // 重写console方法
- if (typeof console !== 'undefined') {
- console.log = function(...args) {
- originalConsole.log.apply(console, args);
- const message = args.map(arg =>
- typeof arg === 'object' ? JSON.stringify(arg, null, 2) : String(arg)
- ).join(' ');
- __consoleOutput.push('[LOG] ' + message);
- };
-
- console.warn = function(...args) {
- originalConsole.warn.apply(console, args);
- const message = args.map(arg =>
- typeof arg === 'object' ? JSON.stringify(arg, null, 2) : String(arg)
- ).join(' ');
- __consoleOutput.push('[WARN] ' + message);
- };
-
- console.error = function(...args) {
- originalConsole.error.apply(console, args);
- const message = args.map(arg =>
- typeof arg === 'object' ? JSON.stringify(arg, null, 2) : String(arg)
- ).join(' ');
- __consoleOutput.push('[ERROR] ' + message);
- };
-
- console.info = function(...args) {
- originalConsole.info.apply(console, args);
- const message = args.map(arg =>
- typeof arg === 'object' ? JSON.stringify(arg, null, 2) : String(arg)
- ).join(' ');
- __consoleOutput.push('[INFO] ' + message);
- };
- } else {
- // 如果console不存在,创建它
- var console = {
- log: function(...args) {
- const message = args.map(arg =>
- typeof arg === 'object' ? JSON.stringify(arg, null, 2) : String(arg)
- ).join(' ');
- __consoleOutput.push('[LOG] ' + message);
- },
- warn: function(...args) {
- const message = args.map(arg =>
- typeof arg === 'object' ? JSON.stringify(arg, null, 2) : String(arg)
- ).join(' ');
- __consoleOutput.push('[WARN] ' + message);
- },
- error: function(...args) {
- const message = args.map(arg =>
- typeof arg === 'object' ? JSON.stringify(arg, null, 2) : String(arg)
- ).join(' ');
- __consoleOutput.push('[ERROR] ' + message);
- },
- info: function(...args) {
- const message = args.map(arg =>
- typeof arg === 'object' ? JSON.stringify(arg, null, 2) : String(arg)
- ).join(' ');
- __consoleOutput.push('[INFO] ' + message);
- }
- };
- }
-
- // 清空输出数组的方法
- var __clearConsoleOutput = function() {
- __consoleOutput = [];
- };
-
- // 获取输出内容的方法(修复换行问题)
- var __getConsoleOutput = function() {
- return __consoleOutput.join('\\n'); // 关键修复:使用单个换行符
- };
- ''';
-
- _jsRuntime!.evaluate(consoleOverride);
- }
- @override
- void dispose() {
- _codeController.dispose();
- if (_jsRuntime != null) {
- _jsRuntime!.dispose();
- _jsRuntime = null;
- }
- super.dispose();
- }
- String _getExampleCode() {
- return '''// JavaScript IDE
- // math.js 库已自动加载,可以使用所有数学函数
- // 创建共享的作用域对象
- const scope = {};
- // 1. 基本算术运算
- console.log('1. 基本算术运算:');
- console.log('2 + 3 =', math.evaluate('2 + 3'));
- console.log('10 - 4 =', math.evaluate('10 - 4'));
- console.log('6 * 7 =', math.evaluate('6 * 7'));
- console.log('15 / 3 =', math.evaluate('15 / 3'));
- console.log('2^8 =', math.evaluate('2^8'));
- console.log('10 % 3 =', math.evaluate('10 % 3'));
- console.log('');
- // 2. 复杂表达式和运算符优先级
- console.log('2. 复杂表达式和运算符优先级:');
- console.log('2 + 3 * 4 =', math.evaluate('2 + 3 * 4'));
- console.log('(2 + 3) * 4 =', math.evaluate('(2 + 3) * 4'));
- console.log('3 + 4 * 2 / (1 - 5)^2 =', math.evaluate('3 + 4 * 2 / (1 - 5)^2'));
- console.log('');
- // 3. 数学常数
- console.log('3. 数学常数:');
- console.log('pi =', math.evaluate('pi'));
- console.log('e =', math.evaluate('e'));
- console.log('Infinity =', math.evaluate('Infinity'));
- console.log('');
- // 4. 内置函数
- console.log('4. 内置函数:');
- console.log('sqrt(25) =', math.evaluate('sqrt(25)'));
- console.log('sin(pi/2) =', math.evaluate('sin(pi/2)'));
- console.log('cos(pi) =', math.evaluate('cos(pi)'));
- console.log('tan(0) =', math.evaluate('tan(0)'));
- console.log('log(100) =', math.evaluate('log(100)'));
- console.log('log(100, 10) =', math.evaluate('log(100, 10)'));
- console.log('exp(2) =', math.evaluate('exp(2)'));
- console.log('abs(-5.5) =', math.evaluate('abs(-5.5)'));
- console.log('round(3.7) =', math.evaluate('round(3.7)'));
- console.log('floor(4.9) =', math.evaluate('floor(4.9)'));
- console.log('ceil(4.1) =', math.evaluate('ceil(4.1)'));
- console.log('max(1, 5, 3) =', math.evaluate('max(1, 5, 3)'));
- console.log('min(1, 5, 3) =', math.evaluate('min(1, 5, 3)'));
- console.log('');
- // 5. 变量和赋值
- console.log('5. 变量和赋值:');
- console.log('x = 5:', math.evaluate('x = 5', scope));
- console.log('y = x + 3:', math.evaluate('y = x + 3', scope));
- console.log('x * y =', math.evaluate('x * y', scope));
- console.log('');
- // 6. 矩阵和数组运算
- console.log('6. 矩阵和数组运算:');
- console.log('[1, 2, 3] =', math.evaluate('[1, 2, 3]'));
- console.log('[[1,2],[3,4]] =', math.evaluate('[[1,2],[3,4]]'));
- console.log('size([1,2,3,4]) =', math.evaluate('size([1,2,3,4])'));
- console.log('[1,2,3] + [4,5,6] =', math.evaluate('[1,2,3] + [4,5,6]'));
- console.log('2 * [1,2,3] =', math.evaluate('2 * [1,2,3]'));
- console.log('');
- // 7. 复数运算
- console.log('7. 复数运算:');
- console.log('2 + 3i =', math.evaluate('2 + 3i'));
- console.log('re(2+3i) =', math.evaluate('re(2+3i)'));
- console.log('im(2+3i) =', math.evaluate('im(2+3i)'));
- console.log('');
- // 8. 单位换算
- console.log('8. 单位换算:');
- console.log('5 inch to cm =', math.evaluate('5 inch to cm'));
- console.log('100 km/hour to m/s =', math.evaluate('100 km/hour to m/s'));
- console.log('');
- // 9. 布尔运算和比较
- console.log('9. 布尔运算和比较:');
- console.log('2 > 3 =', math.evaluate('2 > 3'));
- console.log('5 == 5 =', math.evaluate('5 == 5'));
- console.log('3 != 4 =', math.evaluate('3 != 4'));
- console.log('true and false =', math.evaluate('true and false'));
- console.log('true or false =', math.evaluate('true or false'));
- console.log('not true =', math.evaluate('not true'));
- console.log('');
- // 10. 条件表达式
- console.log('10. 条件表达式:');
- console.log('2 > 3 ? "yes" : "no" =', math.evaluate('2 > 3 ? "yes" : "no"'));
- console.log('x > 0 ? "positive" : "non-positive" =', math.evaluate('x > 0 ? "positive" : "non-positive"', scope));
- console.log('');
- // 11. 字符串操作
- console.log('11. 字符串操作:');
- console.log('concat("hello", " ", "world") =', math.evaluate('concat("hello", " ", "world")'));
- console.log('');
- // 12. 自定义函数
- console.log('12. 自定义函数:');
- math.evaluate('f(x) = x^2 + 2*x + 1', scope);
- console.log('f(3) =', math.evaluate('f(3)', scope));
- console.log('f(5) =', math.evaluate('f(5)', scope));
- console.log('');
- // 13. 统计函数
- console.log('13. 统计函数:');
- console.log('mean([1, 2, 3, 4, 5]) =', math.evaluate('mean([1, 2, 3, 4, 5])'));
- console.log('median([1, 2, 3, 4, 5]) =', math.evaluate('median([1, 2, 3, 4, 5])'));
- console.log('std([1, 2, 3, 4, 5]) =', math.evaluate('std([1, 2, 3, 4, 5])'));
- console.log('sum([1, 2, 3, 4, 5]) =', math.evaluate('sum([1, 2, 3, 4, 5])'));
- console.log('');
- // 14. 大数运算
- console.log('14. 大数运算:');
- console.log('123456789012345678901234567890 + 1 =', math.evaluate('123456789012345678901234567890 + 1'));
- console.log('2^100 =', math.evaluate('2^100'));
- console.log('');
- // 15. 链式操作示例
- console.log('15. 链式操作示例:');
- try {
- const result = math.chain(5)
- .add(3)
- .multiply(2)
- .divide(4)
- .done();
- console.log('(5 + 3) * 2 / 4 =', result);
- } catch (error) {
- console.log('链式操作出错:', error.message);
- }
- console.log('');
- // 16. 多表达式执行
- console.log('16. 多表达式执行:');
- const multiResult = math.evaluate(`
- a = 10;
- b = 20;
- c = a + b;
- c * 2
- `);
- console.log('多表达式结果:', multiResult);
- console.log('');
- // 17. 数值格式和精度
- console.log('17. 数值格式和精度:');
- console.log('format(1/3, 14) =', math.evaluate('format(1/3, 14)'));
- console.log('');
- // 18. 角度和弧度转换
- console.log('18. 角度和弧度转换:');
- console.log('sin(90 deg) =', math.evaluate('sin(90 deg)'));
- console.log('cos(180 deg) =', math.evaluate('cos(180 deg)'));
- console.log('');
- // 19. 随机数生成
- console.log('19. 随机数生成:');
- console.log('random() =', math.evaluate('random()'));
- console.log('random(10) =', math.evaluate('random(10)'));
- console.log('randomInt(10) =', math.evaluate('randomInt(10)'));
- console.log('random(5, 10) =', math.evaluate('random(5, 10)'));
- console.log('');
- // 20. 位运算
- console.log('20. 位运算:');
- console.log('5 & 3 =', math.evaluate('5 & 3'));
- console.log('5 | 3 =', math.evaluate('5 | 3'));
- console.log('');
- // 21. 阶乘和组合
- console.log('21. 阶乘和组合:');
- console.log('5! =', math.evaluate('5!'));
- console.log('combinations(5, 2) =', math.evaluate('combinations(5, 2)'));
- console.log('');
- // 22. 进制转换
- console.log('22. 进制转换:');
- console.log('0b1010 =', math.evaluate('0b1010'));
- console.log('0o777 =', math.evaluate('0o777'));
- console.log('0xFF =', math.evaluate('0xFF'));
- console.log('');
- // 23. 关系运算
- console.log('23. 关系运算:');
- console.log('2 < 3 =', math.evaluate('2 < 3'));
- console.log('2 <= 2 =', math.evaluate('2 <= 2'));
- console.log('3 >= 4 =', math.evaluate('3 >= 4'));
- console.log('');
- // 24. 分数运算
- console.log('24. 分数运算:');
- console.log("4/8 + 1 -1/3 = ", math.simplify('4/8 + 1 -1/3').toString());
- ''';
- }
- Future<void> _saveAs() async {
- try {
- final String codeText = _codeController.text;
- final Uint8List codeBytes = Uint8List.fromList(utf8.encode(codeText));
- String? outputPath = await FilePicker.platform.saveFile(
- dialogTitle: '另存为JavaScript文件',
- fileName: 'javascript_code.js',
- allowedExtensions: ['js'],
- bytes: codeBytes,
- );
-
- if (outputPath != null) {
- if (mounted) {
- ScaffoldMessenger.of(context).showSnackBar(
- SnackBar(
- content: Text('文件已保存'),
- backgroundColor: Colors.green,
- ),
- );
- }
- }
- } catch (e) {
- print('保存文件错误: $e');
- if (mounted) {
- ScaffoldMessenger.of(context).showSnackBar(
- SnackBar(
- content: Text('保存文件失败: $e'),
- backgroundColor: Colors.red,
- ),
- );
- }
- }
- }
- Future<void> _loadFromFile() async {
- try {
- FilePickerResult? result = await FilePicker.platform.pickFiles(
- type: FileType.custom,
- allowedExtensions: ['js'],
- dialogTitle: '选择JavaScript文件',
- );
-
- if (result != null && result.files.isNotEmpty) {
- final PlatformFile platformFile = result.files.single;
-
- if (platformFile.path == null && platformFile.bytes == null) {
- if (mounted) {
- ScaffoldMessenger.of(context).showSnackBar(
- SnackBar(
- content: Text('无法获取文件内容'),
- backgroundColor: Colors.red,
- ),
- );
- }
- return;
- }
-
- // 读取文件内容
- String contents;
- if (platformFile.bytes != null) {
- // 直接从字节数据读取
- contents = utf8.decode(platformFile.bytes!);
- } else {
- // 从文件路径读取
- final file = File(platformFile.path!);
- contents = await file.readAsString();
- }
-
- setState(() {
- _codeController.text = contents;
- _output = '文件已加载: ${platformFile.name}';
- });
- if (mounted) {
- ScaffoldMessenger.of(context).showSnackBar(
- SnackBar(
- content: Text('文件加载成功: ${platformFile.name}'),
- backgroundColor: Colors.green,
- ),
- );
- }
- }
- } catch (e) {
- print('加载文件错误: $e');
- if (mounted) {
- ScaffoldMessenger.of(context).showSnackBar(
- SnackBar(
- content: Text('加载文件失败: $e'),
- backgroundColor: Colors.red,
- ),
- );
- }
- }
- }
- Future<void> _executeCode() async {
- if (_isExecuting || !_isInitialized) return;
- setState(() {
- _isExecuting = true;
- _output = '正在初始化JavaScript环境...\\n';
- });
- try {
- await _initializeJsRuntime();
- final String code = _codeController.text;
- setState(() {
- _output += '执行代码中...\\n';
- });
- _jsRuntime!.evaluate('__clearConsoleOutput();');
- final JsEvalResult result = _jsRuntime!.evaluate(code);
- final JsEvalResult consoleOutputResult = _jsRuntime!.evaluate('__getConsoleOutput();');
- final String consoleOutput = consoleOutputResult.stringResult;
- setState(() {
- _output = '执行完成!\n';
-
- if (result.isError) {
- _output += '❌ 执行错误: ${result.stringResult}\n';
- } else {
- _output += '✅ 执行成功!\n';
- if (result.stringResult != 'null' && result.stringResult.isNotEmpty) {
- _output += '📊 返回值: ${result.stringResult}\n';
- } else {
- _output += '\n';
- }
- }
-
- if (consoleOutput.isNotEmpty) {
- _output += '--- 控制台输出 ---\n$consoleOutput';
- } else {
- _output += 'ℹ️ 没有控制台输出';
- }
- });
- } catch (e) {
- setState(() {
- _output = '执行出错: $e';
- });
- } finally {
- setState(() {
- _isExecuting = false;
- });
- }
- }
- void _clearOutput() {
- setState(() {
- _output = '';
- });
- }
- void _resetCode() {
- setState(() {
- _codeController.text = _getExampleCode();
- _output = '';
- });
- }
- void _injectMathJs() async {
- try {
- await _initializeJsRuntime();
-
- setState(() {
- _output = 'math.js重新加载成功! JavaScript环境已重置。';
- });
- } catch (e) {
- setState(() {
- _output = '重新加载math.js失败: $e';
- });
- }
- }
- }
|