317 lines
11 KiB
Dart
317 lines
11 KiB
Dart
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;
|
||
}
|
||
}
|
||
}
|