elysia/lib/page/child/RobotProfilePage.dart
2025-11-04 09:53:47 +08:00

317 lines
11 KiB
Dart
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import 'dart:ui';
import 'package:elysia/page/FollowListPage.dart';
import 'package:elysia/page/child/ChatPage.dart';
import 'package:elysia/plugin/MarkdownSelectableText.dart';
import 'package:elysia/plugin/RouteAnimation.dart';
import 'package:flutter/material.dart';
import 'package:oktoast/oktoast.dart';
import '../../plugin/C.dart';
import '../../plugin/CacheAavatar.dart';
import '../../plugin/CacheBackgroundImage.dart';
import '../../plugin/HTTP.dart';
import '../../plugin/LoadingOverlay.dart';
import '../ChatRoomPage.dart';
class RobotProfilePage extends StatelessWidget {
final int robotId;
final String name;
final String avatar;
final String systemPrompt;
final String description;
final String creatorUsername;
final String template;
final bool followList;
const RobotProfilePage({
Key? key,
required this.robotId,
required this.name,
required this.avatar,
required this.systemPrompt,
required this.description,
required this.creatorUsername,
required this.template,
required this.followList,
}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("角色详情", style: const TextStyle(color: Colors.black)),
centerTitle: true,
backgroundColor: Colors.grey[200],
leading: IconButton(
icon: const Icon(Icons.arrow_back, color: Colors.black),
onPressed: () => Navigator.pop(context),
),
elevation: 0,
),
body: Stack(
children: [
SizedBox.expand(child: CacheBackgroundImage(url: avatar)),
Positioned.fill(
child: ClipRect(
child: BackdropFilter(
filter: ImageFilter.blur(sigmaX: 50, sigmaY: 50),
child: Container(color: Colors.black.withOpacity(0)),
),
),
),
Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
children: [
// 头像 + 名字 + 简介
Container(
decoration: BoxDecoration(
color: Colors.grey[100],
borderRadius: BorderRadius.circular(5),
),
child: Padding(
padding: EdgeInsets.all(10),
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
CacheAvatar(url: avatar),
SizedBox(width: 16),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
name,
style: TextStyle(
fontSize: 18,
fontWeight: FontWeight.bold,
),
),
SizedBox(height: 8),
Text(
description,
style: TextStyle(
fontSize: 14,
color: Colors.grey[700],
),
),
],
),
),
],
),
),
),
SizedBox(height: 15),
Container(
decoration: BoxDecoration(
color: Colors.grey[100],
borderRadius: BorderRadius.circular(5),
),
child: Padding(
padding: EdgeInsets.all(10),
child: SizedBox(
width: double.infinity,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
children: [
SizedBox(
width: 80,
child: Text(
"创 建 者 ",
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.bold,
),
),
),
Text(creatorUsername),
],
),
SizedBox(height: 8),
Row(
children: [
SizedBox(
width: 80,
child: Text(
"回复模板:",
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.bold,
),
),
),
Text(template),
],
),
],
),
),
),
),
SizedBox(height: 15),
// 多行不可编辑文本框
Container(
width: double.infinity,
// 宽度撑满
height: followList ? 520 : 570,
// 你可以根据需要调整高度例如200
padding: EdgeInsets.all(12),
decoration: BoxDecoration(
border: Border.all(color: Colors.white),
color: Colors.white,
borderRadius: BorderRadius.circular(8),
),
child: SingleChildScrollView(
child: MarkdownSelectableText(
systemPrompt,
style: TextStyle(fontSize: 16),
),
),
),
SizedBox(height: 24),
// 底部主题色按钮
if (followList)
Row(
children: [
Expanded(
flex: 8,
child: SizedBox(
height: 50,
child: ElevatedButton(
onPressed: () {
createChat(context, robotId, avatar, name);
},
style: ElevatedButton.styleFrom(
elevation: 0, // 去掉按钮阴影
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(12),
),
),
child: const Text(
'创建聊天',
style: TextStyle(
fontSize: 18,
color: Colors.white,
),
),
),
),
),
SizedBox(width: 5),
Expanded(
flex: 2,
child: SizedBox(
height: 50,
child: ElevatedButton(
onPressed: () async {
bool status = await unfollowRobot(
context,
robotId,
);
if (status) {
Navigator.pop(context);
}
},
style: ElevatedButton.styleFrom(
backgroundColor: Colors.amber,
elevation: 0, // 去掉按钮阴影
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(12),
),
),
child: Icon(
Icons.heart_broken,
color: Colors.white,
),
),
),
),
],
),
],
),
),
],
),
);
}
void createChat(
BuildContext context,
int robotId,
String avatar,
String name,
) {
showDialog(
context: context,
builder: (_) => ChatRoomDialog(
options: [
{'key': '对话引擎', 'value': 'deepseek-chat'},
{'key': '深度思考', 'value': 'deepseek-reasoner'},
],
onConfirm: (roomName, value) async {
LoadingOverlay.show(context: context, barrierColor: Colors.black54);
try {
dynamic result = await HTTP
.create("${C.BASE_URL}/chat/create")
.setHeader(C.TOKEN)
.setRequestType(RequestType.POST)
.setBody({
"engine": value,
"roomName": roomName,
"robotId": robotId,
})
.execute();
LoadingOverlay.hide();
if (result["code"] == 200) {
ChatRoomPage.flushData!(null);
Navigator.pop(context);
Navigator.push(
context,
RouteAnimation(
ChatPage(
roomId: result["data"],
robotAvatar: avatar,
robotName: roomName,
),
Offset(1, 0),
),
);
} else {
showToast(result["message"], position: ToastPosition.bottom);
}
} catch (e) {
LoadingOverlay.hide();
}
},
),
);
}
Future<bool> unfollowRobot(BuildContext context, int index) async {
LoadingOverlay.show(context: context, barrierColor: Colors.black54);
try {
dynamic result = await HTTP
.create("${C.BASE_URL}/robot/unfollow/$robotId")
.setHeader(C.TOKEN)
.setRequestType(RequestType.GET)
.execute();
LoadingOverlay.hide();
if (result["code"] == 200) {
FollowListPage.delete!(robotId);
return true;
} else {
showToast(result["message"]);
return false;
}
} catch (e) {
LoadingOverlay.hide();
return false;
}
}
}