马良AI写作初始化仓库

This commit is contained in:
邓滨杰
2025-09-10 00:07:52 +08:00
parent 3c06bb1a03
commit 39c0f8840f
1309 changed files with 318528 additions and 0 deletions

View File

@@ -0,0 +1,307 @@
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:ainoval/utils/web_theme.dart';
import 'package:ainoval/models/prompt_models.dart';
import 'package:ainoval/blocs/prompt_new/prompt_new_bloc.dart';
import 'package:ainoval/blocs/prompt_new/prompt_new_event.dart';
class PromptQuickEditDialog extends StatefulWidget {
const PromptQuickEditDialog({
super.key,
required this.templateId,
required this.aiFeatureType,
this.onTemporaryPromptsSaved,
});
final String templateId;
final String aiFeatureType;
final void Function(String systemPrompt, String userPrompt)? onTemporaryPromptsSaved;
@override
State<PromptQuickEditDialog> createState() => _PromptQuickEditDialogState();
}
class _PromptQuickEditDialogState extends State<PromptQuickEditDialog> with TickerProviderStateMixin {
late TabController _tabController;
late TextEditingController _systemController;
late TextEditingController _userController;
bool _isEdited = false;
@override
void initState() {
super.initState();
_tabController = TabController(length: 2, vsync: this);
_systemController = TextEditingController();
_userController = TextEditingController();
WidgetsBinding.instance.addPostFrameCallback((_) {
final state = context.read<PromptNewBloc>().state;
final feature = AIFeatureTypeHelper.fromApiString(widget.aiFeatureType.toUpperCase());
final pkg = state.promptPackages[feature];
if (pkg != null) {
UserPromptInfo? selected;
if (widget.templateId.startsWith('system_default_')) {
if (pkg.systemPrompt.defaultSystemPrompt.isNotEmpty) {
selected = UserPromptInfo(
id: widget.templateId,
name: '系统默认模板',
featureType: feature,
systemPrompt: pkg.systemPrompt.effectivePrompt,
userPrompt: pkg.systemPrompt.defaultUserPrompt,
createdAt: pkg.lastUpdated,
updatedAt: pkg.lastUpdated,
);
}
} else if (widget.templateId.startsWith('public_')) {
final pid = widget.templateId.substring('public_'.length);
final pub = pkg.publicPrompts.firstWhere(
(e) => e.id == pid,
orElse: () => PublicPromptInfo(
id: '', name: '', featureType: feature, systemPrompt: '', userPrompt: '', createdAt: DateTime.now(), updatedAt: DateTime.now(),
),
);
if (pub.id.isNotEmpty) {
selected = UserPromptInfo(
id: widget.templateId,
name: pub.name,
featureType: feature,
systemPrompt: pub.systemPrompt,
userPrompt: pub.userPrompt,
createdAt: pub.createdAt,
updatedAt: pub.updatedAt,
isPublic: true,
isVerified: pub.isVerified,
);
}
} else {
selected = pkg.userPrompts.firstWhere(
(e) => e.id == widget.templateId,
orElse: () => UserPromptInfo(
id: '', name: '', featureType: AIFeatureType.textExpansion, userPrompt: '', createdAt: DateTime.now(), updatedAt: DateTime.now(),
),
);
}
if (selected != null && selected.id.isNotEmpty) {
_systemController.text = selected.systemPrompt ?? '';
_userController.text = selected.userPrompt;
setState(() {});
}
}
});
}
@override
void dispose() {
_tabController.dispose();
_systemController.dispose();
_userController.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Dialog(
insetPadding: const EdgeInsets.all(24),
backgroundColor: WebTheme.getSurfaceColor(context),
child: SizedBox(
width: 900,
height: 640,
child: Column(
children: [
_buildHeader(),
_buildTabBar(),
Expanded(
child: TabBarView(
controller: _tabController,
children: [
_buildContentEditor(),
_buildPropertiesPlaceholder(),
],
),
),
_buildBottomActions(),
],
),
),
);
}
Widget _buildHeader() {
return Container(
padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 12),
decoration: BoxDecoration(
color: WebTheme.getSurfaceColor(context),
border: Border(
bottom: BorderSide(color: WebTheme.getBorderColor(context), width: 1),
),
),
child: Row(
children: [
Text(
'编辑提示词',
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.w600,
color: WebTheme.getTextColor(context),
),
),
const Spacer(),
IconButton(
icon: const Icon(Icons.close),
color: WebTheme.getTextColor(context),
onPressed: () => Navigator.of(context).pop(),
tooltip: '关闭',
),
],
),
);
}
Widget _buildTabBar() {
return Container(
decoration: BoxDecoration(
color: WebTheme.getSurfaceColor(context),
border: Border(
bottom: BorderSide(color: WebTheme.getBorderColor(context), width: 1),
),
),
child: TabBar(
controller: _tabController,
labelColor: WebTheme.getTextColor(context),
unselectedLabelColor: WebTheme.getSecondaryTextColor(context),
indicatorColor: WebTheme.getTextColor(context),
dividerColor: Colors.transparent,
tabs: const [
Tab(text: '内容编辑', icon: Icon(Icons.edit_outlined, size: 16)),
Tab(text: '属性设置', icon: Icon(Icons.settings_outlined, size: 16)),
],
),
);
}
Widget _buildContentEditor() {
final isDark = WebTheme.isDarkMode(context);
return Padding(
padding: const EdgeInsets.all(16),
child: Row(
children: [
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text('系统提示词 (System Prompt)', style: TextStyle(fontSize: 14, fontWeight: FontWeight.w600, color: WebTheme.getTextColor(context))),
const SizedBox(height: 8),
Expanded(
child: Container(
decoration: BoxDecoration(
border: Border.all(color: isDark ? WebTheme.darkGrey300 : WebTheme.grey300),
borderRadius: BorderRadius.circular(8),
color: WebTheme.getSurfaceColor(context),
),
child: TextField(
controller: _systemController,
maxLines: null,
expands: true,
textAlignVertical: TextAlignVertical.top,
decoration: const InputDecoration(border: InputBorder.none, contentPadding: EdgeInsets.all(12), hintText: '输入系统提示词...'),
onChanged: (_) => setState(() => _isEdited = true),
),
),
),
],
),
),
Container(width: 1, margin: const EdgeInsets.symmetric(horizontal: 12), color: WebTheme.getBorderColor(context)),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text('用户提示词 (User Prompt)', style: TextStyle(fontSize: 14, fontWeight: FontWeight.w600, color: WebTheme.getTextColor(context))),
const SizedBox(height: 8),
Expanded(
child: Container(
decoration: BoxDecoration(
border: Border.all(color: isDark ? WebTheme.darkGrey300 : WebTheme.grey300),
borderRadius: BorderRadius.circular(8),
color: WebTheme.getSurfaceColor(context),
),
child: TextField(
controller: _userController,
maxLines: null,
expands: true,
textAlignVertical: TextAlignVertical.top,
decoration: const InputDecoration(border: InputBorder.none, contentPadding: EdgeInsets.all(12), hintText: '输入用户提示词...'),
onChanged: (_) => setState(() => _isEdited = true),
),
),
),
],
),
),
],
),
);
}
Widget _buildPropertiesPlaceholder() {
return Center(
child: Text(
'属性设置可在完整提示词页面中编辑',
style: Theme.of(context).textTheme.bodyMedium,
),
);
}
Widget _buildBottomActions() {
return Container(
padding: const EdgeInsets.all(16),
decoration: BoxDecoration(
border: Border(top: BorderSide(color: WebTheme.getBorderColor(context))),
),
child: Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
TextButton(
onPressed: () {
widget.onTemporaryPromptsSaved?.call(
_systemController.text.trim(),
_userController.text.trim(),
);
Navigator.of(context).pop();
ScaffoldMessenger.of(context).showSnackBar(const SnackBar(content: Text('已临时保存当前编辑的提示词')));
},
child: const Text('临时保存'),
),
const SizedBox(width: 12),
ElevatedButton.icon(
onPressed: _isEdited ? _saveToServer : null,
icon: const Icon(Icons.save, size: 16),
label: const Text('保存'),
),
],
),
);
}
void _saveToServer() {
if (widget.templateId.startsWith('system_default_') || widget.templateId.startsWith('public_')) {
ScaffoldMessenger.of(context).showSnackBar(const SnackBar(content: Text('系统/公共模板不可直接修改,请先复制为私有模板')));
return;
}
context.read<PromptNewBloc>().add(UpdatePromptDetails(
promptId: widget.templateId,
request: UpdatePromptTemplateRequest(
systemPrompt: _systemController.text.trim(),
userPrompt: _userController.text.trim(),
),
));
setState(() => _isEdited = false);
Navigator.of(context).pop();
ScaffoldMessenger.of(context).showSnackBar(const SnackBar(content: Text('模板已保存')));
}
}