perf: 优化预览消息

This commit is contained in:
kuaifan 2024-11-02 08:21:29 +08:00
parent 312acdab51
commit bd15915648
8 changed files with 114 additions and 116 deletions

View File

@ -368,7 +368,7 @@ class ProjectTask extends AbstractModel
}
}, $matches[0]);
}, $content);
return Base::cutStr(strip_tags($content), 100, 0, "...");
return Base::cutStr(strip_tags($content), 100);
}
/**

View File

@ -251,13 +251,12 @@ class WebSocketDialog extends AbstractModel
}
// 最后消息处理
if ($data['last_msg']) {
foreach ($data['last_msg']['emoji'] as &$value) {
unset($value['userids']);
}
if ($data['last_msg']['type'] === 'text') {
$data['last_msg']['msg']['text'] = WebSocketDialogMsg::previewTextMsg($data['last_msg']['msg']);
}
if ($data['last_msg'] && $data['last_msg']['type'] != 'preview') {
$msgData = $data['last_msg'];
$msgData['emoji'] = Base::array_only_recursive($msgData['emoji'], ['symbol']);
$msgData['msg'] = ['preview' => WebSocketDialogMsg::previewMsg($msgData)];
$msgData['type'] = 'preview';
$data['last_msg'] = array_intersect_key($msgData, array_flip(['id', 'type', 'msg', 'userid', 'percentage', 'emoji', 'created_at']));
}
// 对方信息

View File

@ -575,7 +575,7 @@ class WebSocketDialogMsg extends AbstractModel
case 'meeting':
$action = Doo::translate("会议");
return "[{$action}] ${$data['msg']['name']}";
return "[{$action}] " . Base::cutStr($data['msg']['name'], 30);
case 'file':
return self::previewFileMsg($data['msg']);
@ -593,17 +593,45 @@ class WebSocketDialogMsg extends AbstractModel
return "[{$action}] " . self::previewMsg($data['msg']['data']);
case 'notice':
return Doo::translate($data['msg']['notice']);
return Base::cutStr(Doo::translate($data['msg']['notice']), 30);
case 'template':
return self::previewTemplateMsg($data['msg']);
case 'preview':
return $data['msg']['preview'];
default:
$action = Doo::translate("未知的消息");
return "[{$action}]";
}
}
/**
* 返回文本预览消息
* @param array $msgData
* @param bool $preserveHtml 保留html格式
* @return string|string[]|null
*/
private static function previewTextMsg($msgData, $preserveHtml = false)
{
$text = $msgData['text'] ?? '';
if (!$text) return '';
if ($msgData['type'] === 'md') {
$text = Base::markdown2html($text);
}
$text = preg_replace("/<img\s+class=\"emoticon\"[^>]*?alt=\"(\S+)\"[^>]*?>/", "[$1]", $text);
$text = preg_replace("/<img\s+class=\"emoticon\"[^>]*?>/", "[动画表情]", $text);
$text = preg_replace("/<img\s+class=\"browse\"[^>]*?>/", "[图片]", $text);
if (!$preserveHtml) {
$text = strip_tags($text);
$text = str_replace(["&nbsp;", "&amp;", "&lt;", "&gt;"], [" ", "&", "<", ">"], $text);
$text = preg_replace("/\s+/", " ", $text);
$text = Base::cutStr($text, 30);
}
return $text;
}
/**
* 预览文件消息
* @param $msg
@ -619,7 +647,7 @@ class WebSocketDialogMsg extends AbstractModel
return "[{$action}]";
}
$action = Doo::translate("文件");
return "[{$action}] {$msg['name']}";
return "[{$action}] " . Base::cutStr($msg['name'], 30);
}
/**
@ -633,16 +661,15 @@ class WebSocketDialogMsg extends AbstractModel
return $msg['title_raw'];
}
if ($msg['type'] === 'task_list' && count($msg['list']) === 1) {
return Doo::translate($msg['title']) . ": " . $msg['list'][0]['name'];
return Doo::translate($msg['title']) . ": " . Base::cutStr($msg['list'][0]['name'], 30);
}
if (!empty($msg['title'])) {
return Doo::translate($msg['title']);
}
if ($msg['type'] === 'content' && is_string($msg['content']) && $msg['content'] !== '') {
return Doo::translate($msg['content']);
return Base::cutStr(Doo::translate($msg['content']), 30);
}
return Doo::translate('未知的消息');
}
/**
@ -698,33 +725,6 @@ class WebSocketDialogMsg extends AbstractModel
return $msg;
}
/**
* 返回文本预览消息
* @param array $msgData
* @param bool $preserveHtml 保留html格式
* @return string|string[]|null
*/
public static function previewTextMsg($msgData, $preserveHtml = false)
{
$text = $msgData['text'] ?? '';
if (!$text) return '';
if ($msgData['type'] === 'md') {
$text = Base::markdown2html($text);
}
$text = preg_replace("/<img\s+class=\"emoticon\"[^>]*?alt=\"(\S+)\"[^>]*?>/", "[$1]", $text);
$text = preg_replace("/<img\s+class=\"emoticon\"[^>]*?>/", "[动画表情]", $text);
$text = preg_replace("/<img\s+class=\"browse\"[^>]*?>/", "[图片]", $text);
if (!$preserveHtml) {
$text = strip_tags($text);
$text = str_replace(["&nbsp;", "&amp;", "&lt;", "&gt;"], [" ", "&", "<", ">"], $text);
$text = preg_replace("/\s+/", " ", $text);
if (mb_strlen($text) > 30) {
$text = mb_substr($text, 0, 30) . "...";
}
}
return $text;
}
/**
* 处理文本消息内容,用于发送前
* @param $text

View File

@ -375,79 +375,33 @@ class Base
/**
*
* 截取字符串
* @param string $string 字符串
* @param string $str 字符串
* @param int $length 截取长度
* @param int $start 何处开始
* @param string $dot 超出尾部添加
* @param string $charset 默认编码
* @param string $suffix 后缀(超出长度显示,默认:...
* @return string
*/
public static function cutStr($string, $length, $start = 0, $dot = '', $charset = 'utf-8')
public static function cutStr(string $str, int $length, int $start = 0, string $suffix = '...')
{
if (strtolower($charset) == 'utf-8') {
if (Base::getStrlen($string) <= $length) return $string;
$strcut = Base::utf8Substr($string, $length, $start);
return $strcut . $dot;
} else {
$length = $length * 2;
if (strlen($string) <= $length) return $string;
$strcut = '';
for ($i = 0; $i < $length; $i++) {
$strcut .= ord($string[$i]) > 127 ? $string[$i] . $string[++$i] : $string[$i];
}
$strLen = mb_strlen($str);
// 处理负数长度
if ($length < 0) {
$length = max($strLen + $length, 0);
}
return $strcut . $dot;
}
/**
* PHP获取字符串中英文混合长度
* @param string $str 字符串
* @param string $charset 编码
* @return float 返回长度1中文=12英文=1
*/
public static function getStrlen($str, $charset = 'utf-8')
{
if (strtolower($charset) == 'utf-8') {
$str = iconv('utf-8', 'GBK//IGNORE', $str);
// 处理负数起始位置
if ($start < 0) {
$start = max($strLen + $start, 0);
}
$num = strlen($str);
$cnNum = 0;
for ($i = 0; $i < $num; $i++) {
if (ord(substr($str, $i + 1, 1)) > 127) {
$cnNum++;
$i++;
}
// 处理边界情况
if ($length === 0 || $start >= $strLen) {
return '';
}
$enNum = $num - ($cnNum * 2);
$number = ($enNum / 2) + $cnNum;
return ceil($number);
}
/**
* PHP截取UTF-8字符串,解决半字符问题。
* @param string $str 源字符串
* @param int $len 左边的子串的长度
* @param int $start 何处开始
* @return string 取出的字符串, $len小于等于0时, 会返回整个字符串
*/
public static function utf8Substr($str, $len, $start = 0)
{
$len = $len * 2;
$new_str = [];
for ($i = 0; $i < $len; $i++) {
$temp_str = substr($str, 0, 1);
if (ord($temp_str) > 127) {
$i++;
if ($i < $len) {
$new_str[] = substr($str, 0, 3);
$str = substr($str, 3);
}
} else {
$new_str[] = substr($str, 0, 1);
$str = substr($str, 1);
}
$result = mb_substr($str, $start, $length);
// 只有当实际截取的长度小于原字符串长度时才添加后缀
if ($start + $length < $strLen) {
return $result . $suffix;
}
return join(array_slice($new_str, $start));
return $result;
}
/**
@ -2025,6 +1979,20 @@ class Base
return $array;
}
/**
* 多维数组只保留指定键值
* @param $array
* @param $keys
* @return array
*/
public static function array_only_recursive($array, $keys) {
return array_map(function ($item) use ($keys) {
return is_array($item)
? array_intersect_key($item, array_flip($keys))
: $item;
}, $array);
}
/**
* 是否微信
* @return bool

View File

@ -86,7 +86,6 @@ const timezone = require("dayjs/plugin/timezone");
return str;
},
/**
* 字符串是否包含
* @param string
@ -1226,6 +1225,36 @@ const timezone = require("dayjs/plugin/timezone");
extractImageParameterAll(html) {
const imgTags = html.match(/<img\s+[^>]*?>/g) || [];
return imgTags.map(imgTag => this.extractImageParameter(imgTag));
},
/**
* 增强版的字符串截取
* @param str
* @param length
* @param start
* @param suffix
* @returns {string}
*/
cutString(str, length, start = 0, suffix = '...') {
const chars = [...str];
// 如果长度为负数,则从末尾开始计数
if (length < 0) {
length = Math.max(chars.length + length, 0);
}
// 如果起始位置为负数,则从末尾开始计数
if (start < 0) {
start = Math.max(chars.length + start, 0);
}
// 如果截取长度为0或起始位置超出字符串长度返回空字符串
if (length === 0 || start >= chars.length) {
return '';
}
const sliced = chars.slice(start, start + length);
// 只有当实际截取的长度小于原字符串长度时才添加后缀
if (start + length < chars.length) {
return sliced.join('') + suffix;
}
return sliced.join('');
}
});

View File

@ -281,10 +281,7 @@ import {MarkdownPreview} from "../store/markdown";
text = text.replace(/\[image:(.*?)\]/g, `<img class="${imgClassName}" src="$1">`)
text = text.replace(/\{\{RemoteURL\}\}/g, this.apiUrl('../'))
} else {
const tmpText = text.substring(0, 30)
if (tmpText.length < text.length) {
text = tmpText + '...'
}
text = $A.cutString(text, 30)
}
return text
},
@ -409,7 +406,7 @@ import {MarkdownPreview} from "../store/markdown";
case 'record':
return `[${$A.L('语音')}]`
case 'meeting':
return `[${$A.L('会议')}] ${data.msg.name}`
return `[${$A.L('会议')}] ${$A.cutString(data.msg.name, 30)}`
case 'file':
return $A.fileMsgSimpleDesc(data.msg, imgClassName)
case 'tag':
@ -419,9 +416,11 @@ import {MarkdownPreview} from "../store/markdown";
case 'todo':
return `[${$A.L(data.msg.action === 'remove' ? '取消待办' : (data.msg.action === 'done' ? '完成' : '设待办'))}] ${$A.getMsgSimpleDesc(data.msg.data)}`
case 'notice':
return $A.L(data.msg.notice)
return $A.cutString($A.L(data.msg.notice), 30)
case 'template':
return $A.templateMsgSimpleDesc(data.msg)
case 'preview':
return data.msg.preview
default:
return `[${$A.L('未知的消息')}]`
}
@ -450,7 +449,7 @@ import {MarkdownPreview} from "../store/markdown";
} else if (msg.ext == 'mp4') {
return `[${$A.L('视频')}]`
}
return `[${$A.L('文件')}] ${msg.name}`
return `[${$A.L('文件')}] ${$A.cutString(msg.name, 30)}`
},
/**
@ -463,13 +462,13 @@ import {MarkdownPreview} from "../store/markdown";
return msg.title_raw
}
if (msg.type === 'task_list' && $A.arrayLength(msg.list) === 1) {
return $A.L(msg.title) + ": " + msg.list[0].name
return $A.L(msg.title) + ": " + $A.cutString(msg.list[0].name, 30)
}
if (msg.title) {
return $A.L(msg.title)
}
if (msg.type === 'content' && typeof msg.content === 'string' && msg.content !== '') {
return $A.L(msg.content)
return $A.cutString($A.L(msg.content), 30)
}
return $A.L('未知的消息')
},

View File

@ -412,6 +412,9 @@ export default {
case 'file':
searchString += ` ${last_msg.msg.name}`
break
case 'preview':
searchString += ` ${last_msg.msg.preview}`
break
}
}
if (!$A.strExists(searchString, dialogSearchKey)) {

View File

@ -3634,8 +3634,8 @@ export default {
// 更新最后消息
const newData = {
id: dialog_id,
last_at: data.last_msg && data.last_msg.created_at,
last_msg: data.last_msg,
last_at: data.last_msg ? data.last_msg.created_at : $A.daytz().format("YYYY-MM-DD HH:mm:ss"),
}
if (data.update_read) {
// 更新未读数量