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

如何实现AlertDialog打开时预填充OutlinedTextField并保留输入数据?

实现方案(Jetpack Compose + Node.js + Postgres)

一、Jetpack Compose 前端实现

1. 管理报告表单状态

用remember和mutableStateOf绑定表单数据,确保AlertDialog关闭/页面重组时数据不丢失:

data class ReportForm(
    val title: String = "",
    val description: String = "",
    val category: String = "",
    val severity: String = "",
    val lat: Double? = null,
    val lng: Double? = null
)

@Composable
fun ReportScreen() {
    var showDialog by remember { mutableStateOf(false) }
    var reportForm by remember { mutableStateOf(ReportForm()) }
    val navController = rememberNavController()

    // 监听地图页面返回的更新表单
    LaunchedEffect(navController) {
        navController.currentBackStackEntry?.savedStateHandle?.getLiveData<ReportForm>("updatedForm")?.observeForever {
            reportForm = it
            showDialog = true // 返回后保持Dialog打开
        }
    }

    // 打开Dialog的FAB
    FloatingActionButton(onClick = { showDialog = true }) {
        Icon(Icons.Default.Add, contentDescription = "新建报告")
    }

    if (showDialog) {
        AlertDialog(
            onDismissRequest = { showDialog = false },
            title = { Text("创建报告") },
            text = {
                Column(spacing = 16.dp) {
                    OutlinedTextField(
                        value = reportForm.title,
                        onValueChange = { reportForm = reportForm.copy(title = it) },
                        label = { Text("标题") }
                    )
                    OutlinedTextField(
                        value = reportForm.description,
                        onValueChange = { reportForm = reportForm.copy(description = it) },
                        label = { Text("描述") }
                    )
                    // 分类下拉选单、严重程度单选组可按需实现,逻辑类似
                }
            },
            confirmButton = {
                Button(onClick = {
                    // 跳转地图页,传递当前表单数据
                    navController.navigate("map_screen?form=${Gson().toJson(reportForm)}")
                }) {
                    Text("选择位置")
                }
            },
            dismissButton = {
                Button(onClick = { showDialog = false }) {
                    Text("取消")
                }
            },
            additionalButtons = {
                // 可选:添加最终提交按钮,需校验经纬度是否存在
                Button(
                    onClick = {
                        if (reportForm.lat != null && reportForm.lng != null) {
                            saveFullReport(reportForm)
                            showDialog = false
                            reportForm = ReportForm() // 重置表单
                        }
                    },
                    enabled = reportForm.title.isNotEmpty() && reportForm.lat != null
                ) {
                    Text("提交报告")
                }
            }
        )
    }
}

2. 地图页面(支持拖动标记选位)

集成Google Map组件,监听标记拖动事件获取经纬度,点击保存后返回原页面并更新表单:

@Composable
fun MapScreen(navController: NavHostController, formJson: String?) {
    val initialForm = remember {
        formJson?.let { Gson().fromJson(it, ReportForm::class.java) } ?: ReportForm()
    }
    var selectedLatLng by remember { mutableStateOf(LatLng(39.9042, 116.4074)) } // 默认坐标

    GoogleMap(
        modifier = Modifier.fillMaxSize(),
        cameraPositionState = rememberCameraPositionState {
            position = CameraPosition.fromLatLngZoom(selectedLatLng, 15f)
        }
    ) {
        Marker(
            position = selectedLatLng,
            draggable = true,
            onDragEnd = { newPos -> selectedLatLng = newPos }
        )
    }

    // 底部保存按钮
    Box(Modifier.fillMaxSize().padding(16.dp), contentAlignment = Alignment.BottomCenter) {
        Button(onClick = {
            val updatedForm = initialForm.copy(
                lat = selectedLatLng.latitude,
                lng = selectedLatLng.longitude
            )
            // 调用后端接口保存经纬度(可选:也可最后提交完整报告时再存)
            saveLocationToBackend(updatedForm)
            // 返回原页面并传递更新后的表单
            navController.previousBackStackEntry?.savedStateHandle?.set("updatedForm", updatedForm)
            navController.popBackStack()
        }) {
            Text("保存位置")
        }
    }
}

3. 网络请求工具类示例

封装简单的POST请求:

suspend fun saveLocationToBackend(form: ReportForm) {
    val client = OkHttpClient()
    val body = FormBody.Builder()
        .add("title", form.title)
        .add("lat", form.lat.toString())
        .add("lng", form.lng.toString())
        .build()
    val request = Request.Builder()
        .url("http://your-backend-url/api/reports/location")
        .post(body)
        .build()
    client.newCall(request).execute()
}

二、Node.js + Postgres 后端实现

1. 创建数据库表

CREATE TABLE reports (
    id SERIAL PRIMARY KEY,
    title VARCHAR(255) NOT NULL,
    description TEXT,
    category VARCHAR(100),
    severity VARCHAR(50),
    lat DOUBLE PRECISION NOT NULL,
    lng DOUBLE PRECISION NOT NULL,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

2. 编写API接口

用Express和pg库实现:

const express = require('express');
const { Pool } = require('pg');
const app = express();
app.use(express.json());

// 连接Postgres
const pool = new Pool({
    user: 'postgres',
    host: 'localhost',
    database: 'report_db',
    password: 'your-password',
    port: 5432,
});

// 分步保存位置(或完整报告)
app.post('/api/reports/location', async (req, res) => {
    const { title, lat, lng } = req.body;
    try {
        // 若先创建报告草稿,可先插入基础数据再更新;此处直接插入完整数据示例
        await pool.query(
            'INSERT INTO reports (title, lat, lng) VALUES ($1, $2, $3)',
            [title, lat, lng]
        );
        res.status(200).json({ message: "位置已保存" });
    } catch (err) {
        console.error(err);
        res.status(500).json({ error: "保存失败" });
    }
});

// 提交完整报告接口
app.post('/api/reports', async (req, res) => {
    const { title, description, category, severity, lat, lng } = req.body;
    try {
        const result = await pool.query(
            'INSERT INTO reports (title, description, category, severity, lat, lng) VALUES ($1, $2, $3, $4, $5, $6) RETURNING *',
            [title, description, category, severity, lat, lng]
        );
        res.status(201).json(result.rows[0]);
    } catch (err) {
        console.error(err);
        res.status(500).json({ error: "提交失败" });
    }
});

app.listen(3000, () => console.log('后端服务运行在3000端口'));

三、关键注意事项

  • 状态持久化:依赖Compose的remember和Navigation的savedStateHandle传递数据,避免使用全局变量导致状态混乱。
  • 地图权限:需在AndroidManifest.xml中添加位置权限和Google Maps API密钥。
  • 错误处理:前端需处理网络请求失败、权限拒绝等异常场景,给用户提示。
  • 分步/完整提交:可根据业务需求选择先保存位置再补全其他信息,或最后一次性提交完整报告。

内容的提问来源于stack exchange,提问作者alsabih

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.10 20:05:56