马良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,209 @@
import 'dart:convert';
import 'package:ainoval/utils/logger.dart';
import 'package:ainoval/utils/quill_helper.dart';
/// 字数统计信息
class WordCountStats {
const WordCountStats({
required this.charactersNoSpaces,
required this.charactersWithSpaces,
required this.words,
required this.paragraphs,
required this.readTimeMinutes,
});
final int charactersNoSpaces;
final int charactersWithSpaces;
final int words;
final int paragraphs;
final int readTimeMinutes;
}
/// 字数统计分析器
class WordCountAnalyzer {
static const String _tag = 'WordCountAnalyzer';
static const int _averageReadingWordsPerMinute = 200;
/// 统计字数的方法
///
/// @param content 可能是Delta格式或纯文本的内容
/// @return 内容的字数
static int countWords(String? content) {
if (content == null || content.isEmpty) {
return 0;
}
try {
// 使用QuillHelper工具类解析文本内容
final plainText = QuillHelper.deltaToText(content);
// 计算字数 - 使用Unicode字符计数
return _countUnicodeCharacters(plainText);
} catch (e) {
AppLogger.e(_tag, '解析内容失败,尝试直接计数', e);
// 如果解析失败,尝试直接计数
try {
return _countUnicodeCharacters(content);
} catch (e2) {
AppLogger.e(_tag, '字数统计失败返回0', e2);
return 0; // 完全失败时返回0
}
}
}
/// 统计基本字数信息
///
/// @param delta Quill Delta格式内容
/// @return 包含字数、行数、字符数统计结果的Map
static Map<String, int> getBasicStats(String? delta) {
if (delta == null || delta.isEmpty) {
return {'words': 0, 'lines': 0, 'chars': 0};
}
try {
// 使用QuillHelper工具类解析文本内容
final plainText = QuillHelper.deltaToText(delta);
// 计算字数、行数和字符数
final int wordCount = _countUnicodeCharacters(plainText);
final int lineCount = _countLines(plainText);
final int charCount = plainText.length;
return {
'words': wordCount,
'lines': lineCount,
'chars': charCount,
};
} catch (e) {
AppLogger.e(_tag, '解析内容失败,返回默认值', e);
try {
// 尝试直接对原始内容计数
final int wordCount = _countUnicodeCharacters(delta);
final int lineCount = _countLines(delta);
final int charCount = delta.length;
return {
'words': wordCount,
'lines': lineCount,
'chars': charCount,
};
} catch (e2) {
AppLogger.e(_tag, '基本统计失败,返回零值', e2);
return {'words': 0, 'lines': 0, 'chars': 0};
}
}
}
/// 分析文本并返回详细的字数统计信息
///
/// @param content 可能是Delta格式或纯文本的内容
/// @return 详细的字数统计信息
static WordCountStats analyze(String? content) {
if (content == null || content.isEmpty) {
return const WordCountStats(
charactersNoSpaces: 0,
charactersWithSpaces: 0,
words: 0,
paragraphs: 0,
readTimeMinutes: 0,
);
}
// 提取纯文本
String plainText;
try {
plainText = QuillHelper.deltaToText(content);
} catch (e) {
// 如果解析失败,假设是纯文本
plainText = content;
AppLogger.i(_tag, '内容格式解析失败,使用原始内容: ${e.toString()}');
}
try {
// 计算字符数(不含空格)
final charactersNoSpaces = plainText.replaceAll(RegExp(r'\s'), '').length;
// 计算字符数(含空格)
final charactersWithSpaces = plainText.length;
// 计算字数
final words = _countUnicodeCharacters(plainText);
// 计算段落数
final paragraphs = _countParagraphs(plainText);
// 估算阅读时间假设平均每分钟阅读200个字
final readTimeMinutes = _calculateReadingTime(words);
return WordCountStats(
charactersNoSpaces: charactersNoSpaces,
charactersWithSpaces: charactersWithSpaces,
words: words,
paragraphs: paragraphs,
readTimeMinutes: readTimeMinutes,
);
} catch (e) {
AppLogger.e(_tag, '字数分析失败,返回默认值', e);
return const WordCountStats(
charactersNoSpaces: 0,
charactersWithSpaces: 0,
words: 0,
paragraphs: 0,
readTimeMinutes: 0,
);
}
}
/// 统计Unicode字符数更适合中文等非英语字符
static int _countUnicodeCharacters(String text) {
if (text.isEmpty) return 0;
// 移除所有换行符和额外的空格
final String cleanText = text
.replaceAll('\n', '') // 移除换行符
.replaceAll(RegExp(r'\s+'), ' '); // 连续空格替换为单个空格
// 如果清理后为空返回0
if (cleanText.trim().isEmpty) return 0;
// 返回清理后的字符串长度
return cleanText.length;
}
/// 统计行数
static int _countLines(String text) {
if (text.isEmpty) return 0;
// 计算换行符数量
final lineCount = '\n'.allMatches(text).length;
// 如果文本不以换行符结尾加1
return text.endsWith('\n') ? lineCount : lineCount + 1;
}
/// 统计段落数
static int _countParagraphs(String text) {
if (text.isEmpty) return 0;
// 按连续的换行符分割文本,并计算非空段落数
return text.split(RegExp(r'\n+'))
.where((p) => p.trim().isNotEmpty)
.length;
}
/// 计算阅读时间(分钟)
///
/// 假设平均阅读速度为每分钟200个字
static int _calculateReadingTime(int wordCount) {
if (wordCount <= 0) return 0;
return (wordCount / _averageReadingWordsPerMinute).ceil();
}
/// 计算阅读时间(分钟)
///
/// @param content 内容文本
/// @return 估计的阅读时间(分钟)
static int estimateReadingTime(String content) {
final wordCount = countWords(content);
return _calculateReadingTime(wordCount);
}
}