You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter登录应用:实现TextField接收并校验数据库名称的方法

Flutter登录应用数据库名称动态配置实现方案

我正在开发一款登录应用,登录界面设有三个TextField:工号、密码、公司代码(即数据库名称)。点击登录按钮时,需要通过输入的数据库名称连接对应数据库,完成账号密码的校验。目前代码可实现账号密码的校验,但无法处理数据库名称的接收与校验,我已尝试添加DBnameController,但未完成完整功能,现寻求具体实现方案。

现有代码

import 'package:flutter/material.dart';
import 'package:hdislogin/screen/menu.dart';
import 'package:postgres/postgres.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      home: LoginPage(),
    );
  }
}

class LoginPage extends StatefulWidget {
  const LoginPage({super.key});

  @override
  State<LoginPage> createState() => _LoginPageState();
}

class _LoginPageState extends State<LoginPage> {
  final TextEditingController DBnameController = TextEditingController();
  final TextEditingController _empl_noController = TextEditingController();
  final TextEditingController _passwdController = TextEditingController();

  Future<void> _login() async {
    //final String DBname = DBnameController.text;
    final String empl_no = _empl_noController.text;
    final String passwd = _passwdController.text;

    PostgreSQLConnection connection = PostgreSQLConnection(
      'ip',
      5432,
      'DBName',
      username: 'username',
      password: 'password',
    );

    try {
      await connection.open();

      final List<List<dynamic>> results = await connection.query(
        'SELECT * from table',
        substitutionValues: {
          'empl_no': empl_no,
          'passwd': passwd,
        },
      );

      if (results.isNotEmpty) {
        print('success');
        Navigator.push(
          context,
          MaterialPageRoute(builder: (_) => Menu()),
        );
      } else {
        print('fail');
      }
    } finally {
      await connection.close();
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: Colors.white,
      body: SingleChildScrollView(
        child: Padding(
          padding: const EdgeInsets.all(35),
          child: Center(
            child: Column(
              children: [
                Padding(
                  padding: const EdgeInsets.all(10),
                  child: Image.asset(
                    'assets/images/hdis.png',
                    height: 300,
                    width: 300,
                  ),
                ),
                 TextField(
                  maxLength: 4,
                  //controller: DBnameController = 'DBname',
                  decoration: InputDecoration(
                    labelText: 'CompanyCode',
                  ),
                ),
                 TextField(
                  maxLength: 6,
                  decoration: InputDecoration(
                    labelText: 'userID',
                  ),
                ),
                 TextField(
                  obscureText: true,
                  decoration: InputDecoration(
                    labelText: 'password',
                  ),
                ),
                Container(
                  margin: EdgeInsets.only(top: 0),
                  child: ElevatedButton(
                    style: OutlinedButton.styleFrom(
                      minimumSize: Size(70, 30),
                    ),
                    onPressed: () {
                      
                      Navigator.push(
                        context,
                        MaterialPageRoute(builder: (_) => Menu()),
                      );
                    },
                    child: Text(
                      "Login",
                      style: TextStyle(
                        color: Colors.black,
                      ),
                    ),
                  ),
                ),
              ],
            ),
          ),
        ),
      ),
    );
  }
}

我尝试过的修改

class _LoginPageState extends State<LoginPage>
  //added part
  final TextEditingController DBnameController = TextEditingController(); 

.
.
.

 TextField(
                  maxLength: 4,
     //added part //controller: DBnameController = 'DBname', 
                  decoration: InputDecoration(
                    labelText: 'CompanyCode',
                  ),
                ),

具体实现步骤

  1. 正确绑定控制器与TextField
    把CompanyCode对应的TextField的controller属性直接绑定到DBnameController,同时给另外两个TextField也绑定对应的控制器:

    TextField(
      maxLength: 4,
      controller: DBnameController,
      decoration: const InputDecoration(
        labelText: 'CompanyCode',
      ),
    ),
    TextField(
      maxLength: 6,
      controller: _empl_noController,
      decoration: const InputDecoration(
        labelText: 'userID',
      ),
    ),
    TextField(
      obscureText: true,
      controller: _passwdController,
      decoration: const InputDecoration(
        labelText: 'password',
      ),
    )
    
  2. 动态获取数据库名称并建立连接
    在_login方法中获取输入的数据库名称,替换固定的数据库名,同时添加输入校验和异常处理:

    Future<void> _login() async {
      final String DBname = DBnameController.text.trim();
      final String empl_no = _empl_noController.text.trim();
      final String passwd = _passwdController.text.trim();
    
      // 校验输入是否为空
      if (DBname.isEmpty || empl_no.isEmpty || passwd.isEmpty) {
        ScaffoldMessenger.of(context).showSnackBar(
          const SnackBar(content: Text('请填写完整信息')),
        );
        return;
      }
    
      PostgreSQLConnection connection = PostgreSQLConnection(
        'ip',
        5432,
        DBname, // 使用输入的数据库名称
        username: 'username',
        password: 'password',
      );
    
      try {
        await connection.open();
    
        // 参数化查询避免SQL注入
        final List<List<dynamic>> results = await connection.query(
          'SELECT * FROM your_table_name WHERE empl_no = @empl_no AND passwd = @passwd',
          substitutionValues: {
            'empl_no': empl_no,
            'passwd': passwd,
          },
        );
    
        if (results.isNotEmpty) {
          ScaffoldMessenger.of(context).showSnackBar(
            const SnackBar(content: Text('登录成功')),
          );
          Navigator.push(
            context,
            MaterialPageRoute(builder: (_) => Menu()),
          );
        } else {
          ScaffoldMessenger.of(context).showSnackBar(
            const SnackBar(content: Text('工号或密码错误')),
          );
        }
      } catch (e) {
        // 处理数据库连接异常
        ScaffoldMessenger.of(context).showSnackBar(
          SnackBar(content: Text('数据库连接失败:${e.toString()}')),
        );
      } finally {
        await connection.close();
      }
    }
    
  3. 修正登录按钮点击事件
    把登录按钮的onPressed改为调用_login方法,而非直接跳转:

    ElevatedButton(
      style: OutlinedButton.styleFrom(
        minimumSize: const Size(70, 30),
      ),
      onPressed: _login,
      child: const Text(
        "Login",
        style: TextStyle(
          color: Colors.black,
        ),
      ),
    )
    

修改后的完整代码

import 'package:flutter/material.dart';
import 'package:hdislogin/screen/menu.dart';
import 'package:postgres/postgres.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      home: LoginPage(),
    );
  }
}

class LoginPage extends StatefulWidget {
  const LoginPage({super.key});

  @override
  State<LoginPage> createState() => _LoginPageState();
}

class _LoginPageState extends State<LoginPage> {
  final TextEditingController DBnameController = TextEditingController();
  final TextEditingController _empl_noController = TextEditingController();
  final TextEditingController _passwdController = TextEditingController();

  Future<void> _login() async {
    final String DBname = DBnameController.text.trim();
    final String empl_no = _empl_noController.text.trim();
    final String passwd = _passwdController.text.trim();

    if (DBname.isEmpty || empl_no.isEmpty || passwd.isEmpty) {
      ScaffoldMessenger.of(context).showSnackBar(
        const SnackBar(content: Text('请填写完整信息')),
      );
      return;
    }

    PostgreSQLConnection connection = PostgreSQLConnection(
      'ip',
      5432,
      DBname,
      username: 'username',
      password: 'password',
    );

    try {
      await connection.open();

      final List<List<dynamic>> results = await connection.query(
        'SELECT * FROM your_table_name WHERE empl_no = @empl_no AND passwd = @passwd',
        substitutionValues: {
          'empl_no': empl_no,
          'passwd': passwd,
        },
      );

      if (results.isNotEmpty) {
        ScaffoldMessenger.of(context).showSnackBar(
          const SnackBar(content: Text('登录成功')),
        );
        Navigator.push(
          context,
          MaterialPageRoute(builder: (_) => Menu()),
        );
      } else {
        ScaffoldMessenger.of(context).showSnackBar(
          const SnackBar(content: Text('工号或密码错误')),
        );
      }
    } catch (e) {
      ScaffoldMessenger.of(context).showSnackBar(
        SnackBar(content: Text('数据库连接失败:${e.toString()}')),
      );
    } finally {
      await connection.close();
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: Colors.white,
      body: SingleChildScrollView(
        child: Padding(
          padding: const EdgeInsets.all(35),
          child: Center(
            child: Column(
              children: [
                Padding(
                  padding: const EdgeInsets.all(10),
                  child: Image.asset(
                    'assets/images/hdis.png',
                    height: 300,
                    width: 300,
                  ),
                ),
                TextField(
                  maxLength: 4,
                  controller: DBnameController,
                  decoration: const InputDecoration(
                    labelText: 'CompanyCode',
                  ),
                ),
                TextField(
                  maxLength: 6,
                  controller: _empl_noController,
                  decoration: const InputDecoration(
                    labelText: 'userID',
                  ),
                ),
                TextField(
                  obscureText: true,
                  controller: _passwdController,
                  decoration: const InputDecoration(
                    labelText: 'password',
                  ),
                ),
                Container(
                  margin: const EdgeInsets.only(top: 10),
                  child: ElevatedButton(
                    style: OutlinedButton.styleFrom(
                      minimumSize: const Size(70, 30),
                    ),
                    onPressed: _login,
                    child: const Text(
                      "Login",
                      style: TextStyle(
                        color: Colors.black,
                      ),
                    ),
                  ),
                ),
              ],
            ),
          ),
        ),
      ),
    );
  }
}

内容的提问来源于stack exchange,提问作者김민규

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.09 23:39:54