-
-
diff --git a/apps/web-antdv-next/src/adapter/component/date-picker.ts b/apps/web-antdv-next/src/adapter/component/date-picker.ts
new file mode 100644
index 000000000..2428cd4fb
--- /dev/null
+++ b/apps/web-antdv-next/src/adapter/component/date-picker.ts
@@ -0,0 +1,86 @@
+import type { Component } from 'vue';
+
+import type { Recordable } from '@vben/types';
+
+import { defineAsyncComponent, defineComponent, h, ref } from 'vue';
+
+const RawDatePicker = defineAsyncComponent(
+ () => import('antdv-next/dist/date-picker/index'),
+);
+const RawRangePicker = defineAsyncComponent(() =>
+ import('antdv-next/dist/date-picker/index').then(
+ (res) => res.DateRangePicker,
+ ),
+);
+
+const TIMESTAMP_VALUE_FORMATS = new Set(['x', 'X']);
+
+function isTimestampValueFormat(valueFormat: unknown) {
+ return (
+ typeof valueFormat === 'string' && TIMESTAMP_VALUE_FORMATS.has(valueFormat)
+ );
+}
+
+function normalizeTimestampPickerValue(value: any, valueFormat: unknown): any {
+ if (!isTimestampValueFormat(valueFormat)) {
+ return value;
+ }
+ if (Array.isArray(value)) {
+ return value.map((item) => normalizeTimestampPickerValue(item, valueFormat));
+ }
+ return typeof value === 'number' ? String(value) : value;
+}
+
+function withTimestampValueFormat(
+ component: Component,
+ name: 'DatePicker' | 'RangePicker',
+) {
+ return defineComponent({
+ name,
+ inheritAttrs: false,
+ setup(_, { attrs, expose, slots }) {
+ const innerRef = ref();
+ expose(
+ new Proxy(
+ {},
+ {
+ get: (_target, key) => innerRef.value?.[key],
+ has: (_target, key) => key in (innerRef.value || {}),
+ },
+ ),
+ );
+
+ return () => {
+ const pickerAttrs: Recordable = { ...attrs };
+ if (
+ 'value-format' in pickerAttrs &&
+ !Reflect.has(pickerAttrs, 'valueFormat')
+ ) {
+ pickerAttrs.valueFormat = pickerAttrs['value-format'];
+ }
+ const valueFormat = pickerAttrs.valueFormat;
+
+ for (const key of [
+ 'value',
+ 'defaultValue',
+ 'pickerValue',
+ 'defaultPickerValue',
+ ]) {
+ if (Reflect.has(pickerAttrs, key)) {
+ pickerAttrs[key] = normalizeTimestampPickerValue(
+ pickerAttrs[key],
+ valueFormat,
+ );
+ }
+ }
+
+ return h(component, { ...pickerAttrs, ref: innerRef }, slots);
+ };
+ },
+ });
+}
+
+const DatePicker = withTimestampValueFormat(RawDatePicker, 'DatePicker');
+const RangePicker = withTimestampValueFormat(RawRangePicker, 'RangePicker');
+
+export { DatePicker, RangePicker };
diff --git a/apps/web-antdv-next/src/adapter/component/index.ts b/apps/web-antdv-next/src/adapter/component/index.ts
index 9a0897d5b..846473793 100644
--- a/apps/web-antdv-next/src/adapter/component/index.ts
+++ b/apps/web-antdv-next/src/adapter/component/index.ts
@@ -75,6 +75,9 @@ import { message, Modal, notification } from 'antdv-next';
import { uploadFile as uploadFileApi } from '#/api/infra/file';
import { Tinymce as RichTextarea } from '#/components/tinymce';
import { FileUpload, ImageUpload } from '#/components/upload';
+
+import { DatePicker, RangePicker } from './date-picker';
+
type AdapterUploadProps = UploadProps & {
aspectRatio?: string;
crop?: boolean;
@@ -97,9 +100,6 @@ const Checkbox = defineAsyncComponent(
const CheckboxGroup = defineAsyncComponent(() =>
import('antdv-next/dist/checkbox/index').then((res) => res.CheckboxGroup),
);
-const DatePicker = defineAsyncComponent(
- () => import('antdv-next/dist/date-picker/index'),
-);
const Divider = defineAsyncComponent(
() => import('antdv-next/dist/divider/index'),
);
@@ -117,11 +117,6 @@ const Radio = defineAsyncComponent(() => import('antdv-next/dist/radio/index'));
const RadioGroup = defineAsyncComponent(() =>
import('antdv-next/dist/radio/index').then((res) => res.RadioGroup),
);
-const RangePicker = defineAsyncComponent(() =>
- import('antdv-next/dist/date-picker/index').then(
- (res) => res.DateRangePicker,
- ),
-);
const Rate = defineAsyncComponent(() => import('antdv-next/dist/rate/index'));
const Select = defineAsyncComponent(
() => import('antdv-next/dist/select/index'),
@@ -794,4 +789,4 @@ async function initComponentAdapter() {
});
}
-export { initComponentAdapter };
+export { DatePicker, initComponentAdapter, RangePicker };
diff --git a/apps/web-antdv-next/src/api/bpm/processInstance/index.ts b/apps/web-antdv-next/src/api/bpm/processInstance/index.ts
index 8ed2116c5..7199ba360 100644
--- a/apps/web-antdv-next/src/api/bpm/processInstance/index.ts
+++ b/apps/web-antdv-next/src/api/bpm/processInstance/index.ts
@@ -84,6 +84,7 @@ export namespace BpmProcessInstanceApi {
reason: string;
signPicUrl: string;
status: number;
+ attachments?: string[];
}
/** 抄送流程实例 */
diff --git a/apps/web-antdv-next/src/api/iot/thingmodel/index.ts b/apps/web-antdv-next/src/api/iot/thingmodel/index.ts
index 002ccd9c2..888e64663 100644
--- a/apps/web-antdv-next/src/api/iot/thingmodel/index.ts
+++ b/apps/web-antdv-next/src/api/iot/thingmodel/index.ts
@@ -1,4 +1,4 @@
-import type { Rule } from 'antdv-next/es/form';
+import type { FormItemProps } from 'antdv-next';
import type { PageParam, PageResult } from '@vben/request';
@@ -6,6 +6,8 @@ import { isEmpty } from '@vben/utils';
import { requestClient } from '#/api/request';
+type FormItemRule = NonNullable[number];
+
export namespace ThingModelApi {
/** IoT 物模型数据 */
export interface ThingModel {
@@ -95,46 +97,42 @@ export namespace ThingModelApi {
/** 生成「必填 + 数字」类校验器:拼到 size / length / 枚举值上 */
function buildRequiredNumberValidator(label: string) {
- return (_rule: any, value: any, callback: any) => {
+ return (_rule: any, value: any) => {
if (isEmpty(value)) {
- callback(new Error(`${label}不能为空`));
- return;
+ return Promise.reject(new Error(`${label}不能为空`));
}
if (Number.isNaN(Number(value))) {
- callback(new Error(`${label}必须是数字`));
- return;
+ return Promise.reject(new Error(`${label}必须是数字`));
}
- callback();
+ return Promise.resolve();
};
}
/** 生成「标识符样式」名称校验器:开头需为中文 / 英文 / 数字,整体仅允许中文、英文、数字、下划线、短划线,长度 ≤ 20 */
export function buildIdentifierLikeNameValidator(label: string) {
- return (_rule: any, value: string, callback: any) => {
+ return (_rule: any, value: string) => {
if (isEmpty(value)) {
- callback(new Error(`${label}不能为空`));
- return;
+ return Promise.reject(new Error(`${label}不能为空`));
}
if (!/^[一-龥A-Za-z0-9]/.test(value)) {
- callback(new Error(`${label}必须以中文、英文字母或数字开头`));
- return;
+ return Promise.reject(
+ new Error(`${label}必须以中文、英文字母或数字开头`),
+ );
}
if (!/^[一-龥A-Za-z0-9][\w一-龥-]*$/.test(value)) {
- callback(
+ return Promise.reject(
new Error(`${label}只能包含中文、英文字母、数字、下划线和短划线`),
);
- return;
}
if (value.length > 20) {
- callback(new Error(`${label}长度不能超过 20 个字符`));
- return;
+ return Promise.reject(new Error(`${label}长度不能超过 20 个字符`));
}
- callback();
+ return Promise.resolve();
};
}
/** IoT 物模型表单校验规则 */
-export const ThingModelFormRules: Record = {
+export const ThingModelFormRules: Record = {
name: [
{ required: true, message: '功能名称不能为空', trigger: 'blur' },
{
@@ -153,7 +151,7 @@ export const ThingModelFormRules: Record = {
trigger: 'blur',
},
{
- validator: (_rule: any, value: string, callback: any) => {
+ validator: (_rule: any, value: string) => {
const reservedKeywords = [
'set',
'get',
@@ -164,18 +162,16 @@ export const ThingModelFormRules: Record = {
'value',
];
if (reservedKeywords.includes(value)) {
- callback(
+ return Promise.reject(
new Error(
'set, get, post, property, event, time, value 是系统保留字段,不能用于标识符定义',
),
);
- return;
}
if (/^\d+$/.test(value)) {
- callback(new Error('标识符不能是纯数字'));
- return;
+ return Promise.reject(new Error('标识符不能是纯数字'));
}
- callback();
+ return Promise.resolve();
},
trigger: 'blur',
},
diff --git a/apps/web-antdv-next/src/components/cron-tab/cron-tab.vue b/apps/web-antdv-next/src/components/cron-tab/cron-tab.vue
index d1b123585..ab9366e30 100644
--- a/apps/web-antdv-next/src/components/cron-tab/cron-tab.vue
+++ b/apps/web-antdv-next/src/components/cron-tab/cron-tab.vue
@@ -8,6 +8,7 @@ import { computed, onMounted, reactive, ref, watch } from 'vue';
import {
Button,
Form,
+ FormItem,
Input,
InputNumber,
message,
@@ -417,22 +418,21 @@ function inputChange() {
@input="inputChange"
>
-
+
@@ -496,14 +496,10 @@ function inputChange() {
v-model:value="cronValue.second.appoint"
mode="multiple"
style="width: 100%"
- >
-
-
+ :options="
+ data.second.map((item) => ({ label: item, value: item }))
+ "
+ />
@@ -560,14 +556,10 @@ function inputChange() {
v-model:value="cronValue.minute.appoint"
mode="multiple"
style="width: 100%"
- >
-
-
+ :options="
+ data.minute.map((item) => ({ label: item, value: item }))
+ "
+ />
@@ -624,14 +616,10 @@ function inputChange() {
v-model:value="cronValue.hour.appoint"
mode="multiple"
style="width: 100%"
- >
-
-
+ :options="
+ data.hour.map((item) => ({ label: item, value: item }))
+ "
+ />
@@ -690,14 +678,10 @@ function inputChange() {
v-model:value="cronValue.day.appoint"
mode="multiple"
style="width: 100%"
- >
-
-
+ :options="
+ data.day.map((item) => ({ label: item, value: item }))
+ "
+ />
@@ -754,14 +738,10 @@ function inputChange() {
v-model:value="cronValue.month.appoint"
mode="multiple"
style="width: 100%"
- >
-
-
+ :options="
+ data.month.map((item) => ({ label: item, value: item }))
+ "
+ />
@@ -785,23 +765,15 @@ function inputChange() {
-
+
-
-
+
第
@@ -812,14 +784,10 @@ function inputChange() {
controls-position="right"
/>
周的星期
-
+
执行一次
@@ -827,24 +795,14 @@ function inputChange() {
v-model:value="cronValue.week.appoint"
mode="multiple"
style="width: 100%"
- >
-
-
+ :options="data.week"
+ />
-
+
@@ -895,14 +853,10 @@ function inputChange() {
v-model:value="cronValue.year.appoint"
mode="multiple"
style="width: 100%"
- >
-
-
+ :options="
+ data.year.map((item) => ({ label: item, value: item }))
+ "
+ />
diff --git a/apps/web-antdv-next/src/components/description/description.vue b/apps/web-antdv-next/src/components/description/description.vue
index 09f5c2697..116741755 100644
--- a/apps/web-antdv-next/src/components/description/description.vue
+++ b/apps/web-antdv-next/src/components/description/description.vue
@@ -9,7 +9,7 @@ import { computed, defineComponent, ref, unref, useAttrs } from 'vue';
import { get, getNestedValue, isFunction } from '@vben/utils';
-import { Card, Descriptions } from 'antdv-next';
+import { Card, Descriptions, DescriptionsItem } from 'antdv-next';
const props = {
bordered: { default: true, type: Boolean },
diff --git a/apps/web-antdv-next/src/components/form-create/components/dict-select.vue b/apps/web-antdv-next/src/components/form-create/components/dict-select.vue
index 11b961c5f..04a62f109 100644
--- a/apps/web-antdv-next/src/components/form-create/components/dict-select.vue
+++ b/apps/web-antdv-next/src/components/form-create/components/dict-select.vue
@@ -6,14 +6,7 @@ import { computed, useAttrs } from 'vue';
import { getDictOptions } from '@vben/hooks';
-import {
- Checkbox,
- CheckboxGroup,
- Radio,
- RadioGroup,
- Select,
- SelectOption,
-} from 'antdv-next';
+import { Checkbox, CheckboxGroup, Radio, RadioGroup, Select } from 'antdv-next';
defineOptions({ name: 'DictSelect' });
@@ -41,18 +34,22 @@ const getDictOption = computed(() => {
}
}
});
+
+const selectOptions = computed(() =>
+ getDictOption.value.map((dict) => ({
+ label: dict.label,
+ value: dict.value as any,
+ })),
+);
-
+
- {options.value.map(
- (item: { label: any; value: any }, index: any) => (
-
- {item.label}
-
- ),
- )}
-
+ />
);
}
return (
@@ -277,18 +263,11 @@ export function useApiSelect(option: ApiSelectProps) {
onUpdate:value={onUpdateModelValue as any}
value={modelValue as any}
{...restAttrs}
+ options={options.value}
// TODO: @xingyu remote 对等实现, 还是说没作用
// remote={props.remote}
{...(props.remote && { remoteMethod })}
- >
- {options.value.map(
- (item: { label: any; value: any }, index: any) => (
-
- {item.label}
-
- ),
- )}
-
+ />
);
};
const buildCheckbox = () => {
diff --git a/apps/web-antdv-next/src/components/map/src/map-dialog.vue b/apps/web-antdv-next/src/components/map/src/map-dialog.vue
index ecc626d00..e9b0640db 100644
--- a/apps/web-antdv-next/src/components/map/src/map-dialog.vue
+++ b/apps/web-antdv-next/src/components/map/src/map-dialog.vue
@@ -4,7 +4,7 @@ import { nextTick, reactive, ref } from 'vue';
import { useVbenModal } from '@vben/common-ui';
-import { Button, Form, Input, Select, Space } from 'antdv-next';
+import { Button, Form, FormItem, Input, Select, Space } from 'antdv-next';
import { loadBaiduMapSdk } from './utils';
diff --git a/apps/web-antdv-next/src/components/shortcut-date-range-picker/shortcut-date-range-picker.vue b/apps/web-antdv-next/src/components/shortcut-date-range-picker/shortcut-date-range-picker.vue
index cb27a8e00..a6ec00a83 100644
--- a/apps/web-antdv-next/src/components/shortcut-date-range-picker/shortcut-date-range-picker.vue
+++ b/apps/web-antdv-next/src/components/shortcut-date-range-picker/shortcut-date-range-picker.vue
@@ -91,7 +91,6 @@ onMounted(() => {
diff --git a/apps/web-antdv-next/src/components/upload/file-upload.vue b/apps/web-antdv-next/src/components/upload/file-upload.vue
index 78ff0ae4d..a7c941f04 100644
--- a/apps/web-antdv-next/src/components/upload/file-upload.vue
+++ b/apps/web-antdv-next/src/components/upload/file-upload.vue
@@ -1,6 +1,5 @@
diff --git a/apps/web-antdv-next/src/views/iot/thingmodel/modules/data-specs/number.vue b/apps/web-antdv-next/src/views/iot/thingmodel/modules/data-specs/number.vue
index 5a4fd286d..86a3b5fd8 100644
--- a/apps/web-antdv-next/src/views/iot/thingmodel/modules/data-specs/number.vue
+++ b/apps/web-antdv-next/src/views/iot/thingmodel/modules/data-specs/number.vue
@@ -10,7 +10,7 @@ import { DICT_TYPE } from '@vben/constants';
import { getDictOptions } from '@vben/hooks';
import { useVModel } from '@vueuse/core';
-import { FormItem, Input, Select, SelectOption } from 'antdv-next';
+import { FormItem, Input, Select } from 'antdv-next';
const props = defineProps<{ modelValue: any }>();
const emits = defineEmits(['update:modelValue']);
@@ -36,53 +36,46 @@ function unitChange(unitSpecs: any) {
}
/** 校验最小值 */
-function validateMin(_rule: any, _value: any, callback: any) {
+function validateMin(_rule: any, _value: any) {
const min = Number(dataSpecs.value.min);
const max = Number(dataSpecs.value.max);
if (Number.isNaN(min)) {
- callback(new Error('请输入有效的数值'));
- return;
+ return Promise.reject(new Error('请输入有效的数值'));
}
if (!Number.isNaN(max) && min >= max) {
- callback(new Error('最小值必须小于最大值'));
- return;
+ return Promise.reject(new Error('最小值必须小于最大值'));
}
- callback();
+ return Promise.resolve();
}
/** 校验最大值 */
-function validateMax(_rule: any, _value: any, callback: any) {
+function validateMax(_rule: any, _value: any) {
const min = Number(dataSpecs.value.min);
const max = Number(dataSpecs.value.max);
if (Number.isNaN(max)) {
- callback(new Error('请输入有效的数值'));
- return;
+ return Promise.reject(new Error('请输入有效的数值'));
}
if (!Number.isNaN(min) && max <= min) {
- callback(new Error('最大值必须大于最小值'));
- return;
+ return Promise.reject(new Error('最大值必须大于最小值'));
}
- callback();
+ return Promise.resolve();
}
/** 校验步长 */
-function validateStep(_rule: any, _value: any, callback: any) {
+function validateStep(_rule: any, _value: any) {
const step = Number(dataSpecs.value.step);
if (Number.isNaN(step)) {
- callback(new Error('请输入有效的数值'));
- return;
+ return Promise.reject(new Error('请输入有效的数值'));
}
if (step <= 0) {
- callback(new Error('步长必须大于 0'));
- return;
+ return Promise.reject(new Error('步长必须大于 0'));
}
const min = Number(dataSpecs.value.min);
const max = Number(dataSpecs.value.max);
if (!Number.isNaN(min) && !Number.isNaN(max) && step > max - min) {
- callback(new Error('步长不能大于最大值与最小值的差值'));
- return;
+ return Promise.reject(new Error('步长不能大于最大值与最小值的差值'));
}
- callback();
+ return Promise.resolve();
}
@@ -133,15 +126,13 @@ function validateStep(_rule: any, _value: any, callback: any) {
placeholder="请选择单位"
class="w-full"
@change="unitChange"
- >
-
- {{ `${item.label}-${item.value}` }}
-
-
+ :options="[
+ ...unitOptions.map((item) => ({
+ label: `{{ \`${item.label}-${item.value}\` }}`,
+ value: `${item.label}-${item.value}`,
+ })),
+ ]"
+ />
diff --git a/apps/web-antdv-next/src/views/iot/thingmodel/modules/data-specs/struct.vue b/apps/web-antdv-next/src/views/iot/thingmodel/modules/data-specs/struct.vue
index 280a3a105..c62a42856 100644
--- a/apps/web-antdv-next/src/views/iot/thingmodel/modules/data-specs/struct.vue
+++ b/apps/web-antdv-next/src/views/iot/thingmodel/modules/data-specs/struct.vue
@@ -33,12 +33,11 @@ const structFormRef = ref();
const formData = ref(buildEmptyFormData());
/** 校验结构体属性对象非空 */
-function validateStructSpecsList(_rule: any, _value: any, callback: any) {
+function validateStructSpecsList(_rule: any, _value: any) {
if (isEmpty(dataSpecsList.value)) {
- callback(new Error('请至少添加一个结构体属性对象'));
- return;
+ return Promise.reject(new Error('请至少添加一个结构体属性对象'));
}
- callback();
+ return Promise.resolve();
}
const [Modal, modalApi] = useVbenModal({
diff --git a/apps/web-antdv-next/src/views/iot/thingmodel/modules/property.vue b/apps/web-antdv-next/src/views/iot/thingmodel/modules/property.vue
index d9a50b3af..18743ae1a 100644
--- a/apps/web-antdv-next/src/views/iot/thingmodel/modules/property.vue
+++ b/apps/web-antdv-next/src/views/iot/thingmodel/modules/property.vue
@@ -14,14 +14,7 @@ import {
import { isEmpty } from '@vben/utils';
import { useVModel } from '@vueuse/core';
-import {
- FormItem,
- Input,
- Radio,
- RadioGroup,
- Select,
- SelectOption,
-} from 'antdv-next';
+import { FormItem, Input, Radio, RadioGroup, Select } from 'antdv-next';
import { ThingModelFormRules, validateBoolName } from '#/api/iot/thingmodel';
@@ -118,16 +111,13 @@ if (!props.isStructDataSpecs && !props.isParams) {
v-model:value="property.dataType"
placeholder="请选择数据类型"
@change="handleChange"
- >
-
-
- {{ `${option.value}(${option.label})` }}
-
-
+ :options="[
+ ...dataTypeOptions.map((option) => ({
+ label: `{{ \`${option.value}(${option.label})\` }}`,
+ value: option.value,
+ })),
+ ]"
+ />
-
- {{ item2.name }}
-
-
+ :options="attributeOptions"
+ :field-names="{ label: 'name', value: 'name' }"
+ />
();
const emit = defineEmits(['update:modelValue']);
const formData = useVModel(props, 'modelValue', emit);
+const themeOptions = THEME_LIST.map((theme) => ({
+ label: theme.name,
+ value: theme.id,
+ raw: theme,
+}));
// 将数据库的值更新到右侧属性栏
component.property.items = formData.value.items;
@@ -51,18 +55,20 @@ const handleThemeChange = () => {
:wrapper-col="{ span: 18 }"
>
-
diff --git a/apps/web-antdv-next/src/views/mall/promotion/diy/template/decorate/index.vue b/apps/web-antdv-next/src/views/mall/promotion/diy/template/decorate/index.vue
index ed11fefc4..bdf984307 100644
--- a/apps/web-antdv-next/src/views/mall/promotion/diy/template/decorate/index.vue
+++ b/apps/web-antdv-next/src/views/mall/promotion/diy/template/decorate/index.vue
@@ -11,7 +11,7 @@ import { IconifyIcon } from '@vben/icons';
import { useAccessStore } from '@vben/stores';
import { isEmpty } from '@vben/utils';
-import { message, RadioGroup } from 'antdv-next';
+import { message, RadioButton, RadioGroup } from 'antdv-next';
import { updateDiyPageProperty } from '#/api/mall/promotion/diy/page';
import {
diff --git a/apps/web-antdv-next/src/views/mes/md/item/type/components/tree.vue b/apps/web-antdv-next/src/views/mes/md/item/type/components/tree.vue
index 347e87b6a..acb3ad22b 100644
--- a/apps/web-antdv-next/src/views/mes/md/item/type/components/tree.vue
+++ b/apps/web-antdv-next/src/views/mes/md/item/type/components/tree.vue
@@ -54,8 +54,17 @@ function handleSearch(value: string) {
}
/** 处理节点点击:支持点击同一节点取消选中 */
-function handleSelect(_selectedKeys: any[], info: any) {
- const row = info.node.dataRef as MesMdItemTypeApi.ItemType;
+function handleSelect(selectedNodeKeys: any[], info: any) {
+ const selectedKey = selectedNodeKeys[0] ?? info.node?.id ?? info.node?.key;
+ const row = itemTypeList.value.find(
+ (item) => String(item.id) === String(selectedKey),
+ );
+ if (!row) {
+ currentNodeId.value = undefined;
+ selectedKeys.value = [];
+ emit('nodeClick', undefined);
+ return;
+ }
if (currentNodeId.value === row.id) {
currentNodeId.value = undefined;
selectedKeys.value = [];
diff --git a/apps/web-antdv-next/src/views/mes/md/unitmeasure/components/select.vue b/apps/web-antdv-next/src/views/mes/md/unitmeasure/components/select.vue
index 1abc361f3..4cd0dd28b 100644
--- a/apps/web-antdv-next/src/views/mes/md/unitmeasure/components/select.vue
+++ b/apps/web-antdv-next/src/views/mes/md/unitmeasure/components/select.vue
@@ -3,7 +3,7 @@ import type { MesMdUnitMeasureApi } from '#/api/mes/md/unitmeasure';
import { computed, onMounted, ref, watch } from 'vue';
-import { Select, SelectOption, Tag, Tooltip } from 'antdv-next';
+import { Select, Tag, Tooltip } from 'antdv-next';
import { getUnitMeasureSimpleList } from '#/api/mes/md/unitmeasure';
@@ -32,6 +32,13 @@ const emit = defineEmits<{
const allList = ref([]); // 计量单位列表
const filteredList = ref([]); // 过滤后的计量单位列表
const selectedItem = ref(); // 当前选中计量单位
+const selectOptions = computed(() =>
+ filteredList.value.map((item) => ({
+ label: item.name,
+ value: item.id,
+ raw: item,
+ })),
+);
const selectValue = computed({
// 选择器绑定值
@@ -44,7 +51,7 @@ const selectValue = computed({
/** 前端按名称和编码过滤计量单位 */
function handleFilter(input: string, option: any) {
const keyword = input.toLowerCase();
- const item = option?.item as MesMdUnitMeasureApi.UnitMeasure | undefined;
+ const item = option?.raw as MesMdUnitMeasureApi.UnitMeasure | undefined;
return Boolean(
item?.name?.toLowerCase().includes(keyword) ||
item?.code?.toLowerCase().includes(keyword),
@@ -104,19 +111,17 @@ onMounted(async () => {
:placeholder="placeholder"
class="w-full"
show-search
+ :options="selectOptions"
@change="handleChange"
>
-
+
- {{ item.name }}
- 编号: {{ item.code }}
+ {{ option.data.raw.name }}
+
+ 编号: {{ option.data.raw.code }}
+
-
+
diff --git a/apps/web-antdv-next/src/views/mes/md/workstation/components/workshop-select.vue b/apps/web-antdv-next/src/views/mes/md/workstation/components/workshop-select.vue
index 18d044f09..9e82e0119 100644
--- a/apps/web-antdv-next/src/views/mes/md/workstation/components/workshop-select.vue
+++ b/apps/web-antdv-next/src/views/mes/md/workstation/components/workshop-select.vue
@@ -3,7 +3,7 @@ import type { MesMdWorkshopApi } from '#/api/mes/md/workstation/workshop';
import { computed, onMounted, ref, watch } from 'vue';
-import { Select, SelectOption, Tag, Tooltip } from 'antdv-next';
+import { Select, Tag, Tooltip } from 'antdv-next';
import { getWorkshopSimpleList } from '#/api/mes/md/workstation/workshop';
@@ -31,6 +31,13 @@ const emit = defineEmits<{
const allList = ref([]);
const selectedItem = ref();
+const selectOptions = computed(() =>
+ allList.value.map((item) => ({
+ label: item.name,
+ value: item.id,
+ raw: item,
+ })),
+);
const selectValue = computed({
get: () => props.modelValue,
@@ -41,7 +48,7 @@ const selectValue = computed({
function handleFilter(input: string, option: any) {
const keyword = input.toLowerCase();
- const item = option?.item as MesMdWorkshopApi.Workshop | undefined;
+ const item = option?.raw as MesMdWorkshopApi.Workshop | undefined;
return Boolean(
item?.name?.toLowerCase().includes(keyword) ||
item?.code?.toLowerCase().includes(keyword),
@@ -99,19 +106,17 @@ onMounted(async () => {
:placeholder="placeholder"
class="w-full"
show-search
+ :options="selectOptions"
@change="handleChange"
>
-
+
- {{ item.name }}
- {{ item.code }}
+ {{ option.data.raw.name }}
+
+ {{ option.data.raw.code }}
+
-
+
diff --git a/apps/web-antdv-next/src/views/mes/pro/andon/config/components/select.vue b/apps/web-antdv-next/src/views/mes/pro/andon/config/components/select.vue
index b7c820f74..20572e945 100644
--- a/apps/web-antdv-next/src/views/mes/pro/andon/config/components/select.vue
+++ b/apps/web-antdv-next/src/views/mes/pro/andon/config/components/select.vue
@@ -5,7 +5,7 @@ import { computed, onMounted, ref } from 'vue';
import { DICT_TYPE } from '@vben/constants';
-import { Select, SelectOption } from 'antdv-next';
+import { Select } from 'antdv-next';
import { getAndonConfigList } from '#/api/mes/pro/andon/config';
import DictTag from '#/components/dict-tag/dict-tag.vue';
@@ -34,6 +34,13 @@ const emit = defineEmits<{
}>();
const allList = ref([]);
+const selectOptions = computed(() =>
+ allList.value.map((item) => ({
+ label: item.reason,
+ value: item.id,
+ raw: item,
+ })),
+);
const selectValue = computed({
get: () => props.modelValue,
@@ -45,7 +52,7 @@ const selectValue = computed({
/** 前端过滤:按 reason 模糊匹配 */
function handleFilter(input: string, option: any) {
const keyword = input.toLowerCase();
- const item = option?.item as MesProAndonConfigApi.AndonConfig | undefined;
+ const item = option?.raw as MesProAndonConfigApi.AndonConfig | undefined;
return Boolean(item?.reason?.toLowerCase().includes(keyword));
}
@@ -71,18 +78,17 @@ onMounted(async () => {
:placeholder="placeholder"
class="w-full"
show-search
+ :options="selectOptions"
@change="handleChange"
>
-
+
- {{ item.reason }}
-
+ {{ option.data.raw.reason }}
+
-
+
diff --git a/apps/web-antdv-next/src/views/mes/pro/process/components/select.vue b/apps/web-antdv-next/src/views/mes/pro/process/components/select.vue
index 47b8550d6..51604a41c 100644
--- a/apps/web-antdv-next/src/views/mes/pro/process/components/select.vue
+++ b/apps/web-antdv-next/src/views/mes/pro/process/components/select.vue
@@ -3,7 +3,7 @@ import type { MesProProcessApi } from '#/api/mes/pro/process';
import { computed, onMounted, ref, watch } from 'vue';
-import { Select, SelectOption, Tag, Tooltip } from 'antdv-next';
+import { Select, Tag, Tooltip } from 'antdv-next';
import { getProcessSimpleList } from '#/api/mes/pro/process';
@@ -31,6 +31,13 @@ const emit = defineEmits<{
const allList = ref([]);
const selectedItem = ref();
+const selectOptions = computed(() =>
+ allList.value.map((item) => ({
+ label: item.name,
+ value: item.id,
+ raw: item,
+ })),
+);
const selectValue = computed({
get: () => props.modelValue,
@@ -42,7 +49,7 @@ const selectValue = computed({
/** 前端过滤:按工序名称或编码模糊匹配 */
function handleFilter(input: string, option: any) {
const keyword = input.toLowerCase();
- const item = option?.item as MesProProcessApi.Process | undefined;
+ const item = option?.raw as MesProProcessApi.Process | undefined;
return Boolean(
item?.name?.toLowerCase().includes(keyword) ||
item?.code?.toLowerCase().includes(keyword),
@@ -96,19 +103,17 @@ onMounted(async () => {
:placeholder="placeholder"
class="w-full"
show-search
+ :options="selectOptions"
@change="handleChange"
>
-
+
- {{ item.name }}
- {{ item.code }}
+ {{ option.data.raw.name }}
+
+ {{ option.data.raw.code }}
+
-
+
diff --git a/apps/web-antdv-next/src/views/mes/wm/warehouse/components/area-select.vue b/apps/web-antdv-next/src/views/mes/wm/warehouse/components/area-select.vue
index fc2db97cf..9d6548af7 100644
--- a/apps/web-antdv-next/src/views/mes/wm/warehouse/components/area-select.vue
+++ b/apps/web-antdv-next/src/views/mes/wm/warehouse/components/area-select.vue
@@ -3,7 +3,7 @@ import type { MesWmWarehouseAreaApi } from '#/api/mes/wm/warehouse/area';
import { computed, ref, useAttrs, watch, watchEffect } from 'vue';
-import { Select, SelectOption, Tag, Tooltip } from 'antdv-next';
+import { Select, Tag, Tooltip } from 'antdv-next';
import { getWarehouseAreaSimpleList } from '#/api/mes/wm/warehouse/area';
@@ -34,6 +34,13 @@ const emit = defineEmits<{
const attrs = useAttrs();
const allList = ref([]);
const selectedItem = ref();
+const selectOptions = computed(() =>
+ allList.value.map((item) => ({
+ label: item.name,
+ value: item.id,
+ raw: item,
+ })),
+);
const selectValue = computed({
get: () => props.modelValue,
@@ -49,7 +56,7 @@ function handleChange(val: any) {
/** 前端过滤(name + code) */
function filterOption(input: string, option: any) {
- const item = allList.value.find((o) => o.id === option.value);
+ const item = option?.raw as MesWmWarehouseAreaApi.WarehouseArea | undefined;
if (!item) {
return false;
}
@@ -101,14 +108,17 @@ watchEffect(async () => {
:filter-option="filterOption"
:placeholder="placeholder"
show-search
+ :options="selectOptions"
@change="handleChange"
>
-
+
- {{ item.name }}
- 编号: {{ item.code }}
+ {{ option.data.raw.name }}
+
+ 编号: {{ option.data.raw.code }}
+
-
+
diff --git a/apps/web-antdv-next/src/views/mes/wm/warehouse/components/location-select.vue b/apps/web-antdv-next/src/views/mes/wm/warehouse/components/location-select.vue
index 4ad5f432d..c04361227 100644
--- a/apps/web-antdv-next/src/views/mes/wm/warehouse/components/location-select.vue
+++ b/apps/web-antdv-next/src/views/mes/wm/warehouse/components/location-select.vue
@@ -3,7 +3,7 @@ import type { MesWmWarehouseLocationApi } from '#/api/mes/wm/warehouse/location'
import { computed, ref, useAttrs, watch, watchEffect } from 'vue';
-import { Select, SelectOption, Tag, Tooltip } from 'antdv-next';
+import { Select, Tag, Tooltip } from 'antdv-next';
import { getWarehouseLocationSimpleList } from '#/api/mes/wm/warehouse/location';
@@ -34,6 +34,13 @@ const emit = defineEmits<{
const attrs = useAttrs();
const allList = ref([]);
const selectedItem = ref();
+const selectOptions = computed(() =>
+ allList.value.map((item) => ({
+ label: item.name,
+ value: item.id,
+ raw: item,
+ })),
+);
const selectValue = computed({
get: () => props.modelValue,
@@ -49,7 +56,9 @@ function handleChange(val: any) {
/** 前端过滤(name + code) */
function filterOption(input: string, option: any) {
- const item = allList.value.find((o) => o.id === option.value);
+ const item = option?.raw as
+ | MesWmWarehouseLocationApi.WarehouseLocation
+ | undefined;
if (!item) {
return false;
}
@@ -100,14 +109,17 @@ watchEffect(async () => {
:filter-option="filterOption"
:placeholder="placeholder"
show-search
+ :options="selectOptions"
@change="handleChange"
>
-
+
- {{ item.name }}
- 编号: {{ item.code }}
+ {{ option.data.raw.name }}
+
+ 编号: {{ option.data.raw.code }}
+
-
+
diff --git a/apps/web-antdv-next/src/views/mes/wm/warehouse/components/select.vue b/apps/web-antdv-next/src/views/mes/wm/warehouse/components/select.vue
index a68d4cd02..935b2b681 100644
--- a/apps/web-antdv-next/src/views/mes/wm/warehouse/components/select.vue
+++ b/apps/web-antdv-next/src/views/mes/wm/warehouse/components/select.vue
@@ -3,7 +3,7 @@ import type { MesWmWarehouseApi } from '#/api/mes/wm/warehouse';
import { computed, onMounted, ref, useAttrs, watch } from 'vue';
-import { Select, SelectOption, Tag, Tooltip } from 'antdv-next';
+import { Select, Tag, Tooltip } from 'antdv-next';
import { getWarehouseSimpleList } from '#/api/mes/wm/warehouse';
@@ -32,6 +32,13 @@ const emit = defineEmits<{
const attrs = useAttrs();
const allList = ref([]);
const selectedItem = ref();
+const selectOptions = computed(() =>
+ allList.value.map((item) => ({
+ label: item.name,
+ value: item.id,
+ raw: item,
+ })),
+);
const selectValue = computed({
get: () => props.modelValue,
@@ -47,7 +54,7 @@ function handleChange(val: any) {
/** 前端过滤(name + code) */
function filterOption(input: string, option: any) {
- const item = allList.value.find((o) => o.id === option.value);
+ const item = option?.raw as MesWmWarehouseApi.Warehouse | undefined;
if (!item) {
return false;
}
@@ -97,14 +104,17 @@ onMounted(async () => {
:filter-option="filterOption"
:placeholder="placeholder"
show-search
+ :options="selectOptions"
@change="handleChange"
>
-
+
- {{ item.name }}
- 编号: {{ item.code }}
+ {{ option.data.raw.name }}
+
+ 编号: {{ option.data.raw.code }}
+
-
+
diff --git a/apps/web-antdv-next/src/views/mp/components/wx-account-select/wx-account-select.vue b/apps/web-antdv-next/src/views/mp/components/wx-account-select/wx-account-select.vue
index 4e55f933f..442d0a911 100644
--- a/apps/web-antdv-next/src/views/mp/components/wx-account-select/wx-account-select.vue
+++ b/apps/web-antdv-next/src/views/mp/components/wx-account-select/wx-account-select.vue
@@ -61,9 +61,7 @@ onMounted(handleQuery);
placeholder="请选择公众号"
class="!w-full"
@change="onChanged"
- >
-
- {{ item.name }}
-
-
+ :options="accountList"
+ :field-names="{ label: 'name', value: 'id' }"
+ />
diff --git a/apps/web-antdv-next/src/views/mp/material/modules/UploadVideo.vue b/apps/web-antdv-next/src/views/mp/material/modules/UploadVideo.vue
index 1553bdd05..6dc6eee77 100644
--- a/apps/web-antdv-next/src/views/mp/material/modules/UploadVideo.vue
+++ b/apps/web-antdv-next/src/views/mp/material/modules/UploadVideo.vue
@@ -11,6 +11,7 @@ import {
Button,
Divider,
Form,
+ FormItem,
Input,
message,
Modal,
diff --git a/apps/web-antdv-next/src/views/mp/menu/modules/editor.vue b/apps/web-antdv-next/src/views/mp/menu/modules/editor.vue
index e61f96b36..c7223af1b 100644
--- a/apps/web-antdv-next/src/views/mp/menu/modules/editor.vue
+++ b/apps/web-antdv-next/src/views/mp/menu/modules/editor.vue
@@ -99,16 +99,8 @@ function deleteMaterial() {
placeholder="请选择"
class="mr-[2%] w-[240px]"
allow-clear
- >
-
- {{ item.label }}
-
-
+ :options="menuOptions"
+ />
String(item.id) === String(selectedKey))
+ : undefined;
+ emit('select', dept);
}
/** 重置选中状态(供外部重置按钮调用) */
diff --git a/apps/web-antdv-next/src/views/system/user/modules/dept-tree.vue b/apps/web-antdv-next/src/views/system/user/modules/dept-tree.vue
index beea3f314..48ffe69c4 100644
--- a/apps/web-antdv-next/src/views/system/user/modules/dept-tree.vue
+++ b/apps/web-antdv-next/src/views/system/user/modules/dept-tree.vue
@@ -32,8 +32,12 @@ function handleSearch(e: any) {
}
/** 选中部门 */
-function handleSelect(_selectedKeys: any[], info: any) {
- emit('select', info.node.dataRef);
+function handleSelect(selectedNodeKeys: any[], info: any) {
+ const selectedKey = selectedNodeKeys[0] ?? info.node?.id ?? info.node?.key;
+ const dept = info.selected
+ ? deptList.value.find((item) => String(item.id) === String(selectedKey))
+ : undefined;
+ emit('select', dept);
}
/** 初始化 */
diff --git a/apps/web-antdv-next/src/views/wms/md/item/category/components/tree.vue b/apps/web-antdv-next/src/views/wms/md/item/category/components/tree.vue
index 7954aea91..e682d58c9 100644
--- a/apps/web-antdv-next/src/views/wms/md/item/category/components/tree.vue
+++ b/apps/web-antdv-next/src/views/wms/md/item/category/components/tree.vue
@@ -55,8 +55,17 @@ function handleSearch(value: string) {
}
/** 处理节点点击:支持点击同一节点取消选中 */
-function handleSelect(_selectedKeys: any[], info: any) {
- const row = info.node.dataRef as WmsItemCategoryApi.ItemCategory;
+function handleSelect(selectedNodeKeys: any[], info: any) {
+ const selectedKey = selectedNodeKeys[0] ?? info.node?.id ?? info.node?.key;
+ const row = categoryList.value.find(
+ (item) => String(item.id) === String(selectedKey),
+ );
+ if (!row) {
+ currentNodeId.value = undefined;
+ selectedKeys.value = [];
+ emit('nodeClick', undefined);
+ return;
+ }
if (currentNodeId.value === row.id) {
currentNodeId.value = undefined;
selectedKeys.value = [];
diff --git a/apps/web-ele/src/views/bpm/processInstance/detail/modules/time-line.vue b/apps/web-ele/src/views/bpm/processInstance/detail/modules/time-line.vue
index b999c8a89..73fccc9f3 100644
--- a/apps/web-ele/src/views/bpm/processInstance/detail/modules/time-line.vue
+++ b/apps/web-ele/src/views/bpm/processInstance/detail/modules/time-line.vue
@@ -286,10 +286,7 @@ defineExpose({ setCustomApproveUsers, batchSetCustomApproveUsers });
-
+
@@ -361,12 +358,12 @@ defineExpose({ setCustomApproveUsers, batchSetCustomApproveUsers });
-
+
-
-
diff --git a/output/playwright/2026-06-13T02-49-49-836Z-item-receipt-arrival-notice.png b/output/playwright/2026-06-13T02-49-49-836Z-item-receipt-arrival-notice.png
new file mode 100644
index 000000000..43634df11
Binary files /dev/null and b/output/playwright/2026-06-13T02-49-49-836Z-item-receipt-arrival-notice.png differ
diff --git a/output/playwright/2026-06-13T02-49-49-836Z-mes-selector-runtime.json b/output/playwright/2026-06-13T02-49-49-836Z-mes-selector-runtime.json
new file mode 100644
index 000000000..c4c5bc71b
--- /dev/null
+++ b/output/playwright/2026-06-13T02-49-49-836Z-mes-selector-runtime.json
@@ -0,0 +1,174 @@
+{
+ "baseUrl": "http://127.0.0.1:5666",
+ "generatedAt": "2026-06-13T02:50:19.425Z",
+ "results": [
+ {
+ "id": "item-receipt-arrival-notice",
+ "pageName": "采购入库",
+ "route": "/mes/wm/item-receipt",
+ "operation": "新增 -> 打开「到货通知单选择」",
+ "ok": true,
+ "expectedParams": {
+ "status": "3"
+ },
+ "actualRequests": [
+ {
+ "path": "/admin-api/mes/wm/arrival-notice/page",
+ "search": "?pageNo=1&pageSize=20&status=3",
+ "params": {
+ "pageNo": "1",
+ "pageSize": "20",
+ "status": "3"
+ }
+ }
+ ],
+ "paramChecks": {
+ "status": true
+ },
+ "rowCount": 7,
+ "radioCount": 14,
+ "checkboxCount": 0,
+ "firstRowText": "AN20260329000001 ABC 深圳市海力德电子有限公司 2026-03-04 待入库",
+ "afterSelectionValue": "AN20260329000001",
+ "dialogClosedAfterSelection": true,
+ "screenshot": "/Users/yunai/Java/yudao-all-in-vben/yudao-ui-admin-vben/output/playwright/2026-06-13T02-49-49-836Z-item-receipt-arrival-notice.png",
+ "errors": [],
+ "consoleErrorCount": 32
+ },
+ {
+ "id": "product-sales-sales-notice",
+ "pageName": "销售出库",
+ "route": "/mes/wm/product-sales",
+ "operation": "新增 -> 打开「发货通知单选择」",
+ "ok": true,
+ "expectedParams": {
+ "status": "3"
+ },
+ "actualRequests": [
+ {
+ "path": "/admin-api/mes/wm/sales-notice/page",
+ "search": "?pageNo=1&pageSize=20&status=3",
+ "params": {
+ "pageNo": "1",
+ "pageSize": "20",
+ "status": "3"
+ }
+ }
+ ],
+ "paramChecks": {
+ "status": true
+ },
+ "rowCount": 2,
+ "radioCount": 4,
+ "checkboxCount": 0,
+ "firstRowText": "SN20260330000004 AABBEEE 比亚迪股份有限公司 2026-03-18 待出库",
+ "afterSelectionValue": "AABBEEE",
+ "dialogClosedAfterSelection": true,
+ "screenshot": "/Users/yunai/Java/yudao-all-in-vben/yudao-ui-admin-vben/output/playwright/2026-06-13T02-49-49-836Z-product-sales-sales-notice.png",
+ "errors": [],
+ "consoleErrorCount": 32
+ },
+ {
+ "id": "product-issue-work-order",
+ "pageName": "生产领料",
+ "route": "/mes/wm/product-issue",
+ "operation": "新增 -> 打开「生产工单选择」",
+ "ok": false,
+ "expectedParams": {
+ "status": "1"
+ },
+ "actualRequests": [
+ {
+ "path": "/admin-api/mes/pro/work-order/page",
+ "search": "?pageNo=1&pageSize=20",
+ "params": {
+ "pageNo": "1",
+ "pageSize": "20"
+ }
+ }
+ ],
+ "paramChecks": {
+ "status": false
+ },
+ "rowCount": 17,
+ "radioCount": 34,
+ "checkboxCount": 0,
+ "firstRowText": "MO_ACCEPT_FB_20260526 验收生产报工工单-螺丝刀 客户订单 ACCEPT-FEEDBACK IF2022082439 螺丝刀【蓝色,一字型】 蓝色,一字型,3.2x75mm 个 200 C00197 博世 已确认 2026-06-02",
+ "afterSelectionValue": "MO_ACCEPT_FB_20260526",
+ "dialogClosedAfterSelection": true,
+ "screenshot": "/Users/yunai/Java/yudao-all-in-vben/yudao-ui-admin-vben/output/playwright/2026-06-13T02-49-49-836Z-product-issue-work-order.png",
+ "errors": [
+ "请求参数不符合预期: {\"status\":false}"
+ ],
+ "consoleErrorCount": 32
+ },
+ {
+ "id": "product-issue-workstation",
+ "pageName": "生产领料",
+ "route": "/mes/wm/product-issue",
+ "operation": "新增 -> 打开「工作站选择」",
+ "ok": true,
+ "expectedParams": {},
+ "actualRequests": [
+ {
+ "path": "/admin-api/mes/md-workstation/page",
+ "search": "?pageNo=1&pageSize=20&status=0",
+ "params": {
+ "pageNo": "1",
+ "pageSize": "20",
+ "status": "0"
+ }
+ }
+ ],
+ "paramChecks": {},
+ "rowCount": 8,
+ "radioCount": 16,
+ "checkboxCount": 0,
+ "firstRowText": "ST_ACCEPT_FB_P4 验收报工-质检工位 验收造数 组装车间 打磨工序 验收造数:生产报工质检工序",
+ "afterSelectionValue": "验收报工-质检工位",
+ "dialogClosedAfterSelection": true,
+ "screenshot": "/Users/yunai/Java/yudao-all-in-vben/yudao-ui-admin-vben/output/playwright/2026-06-13T02-49-49-836Z-product-issue-workstation.png",
+ "errors": [],
+ "consoleErrorCount": 32
+ },
+ {
+ "id": "outsource-issue-work-order",
+ "pageName": "外协发料",
+ "route": "/mes/wm/outsource-issue",
+ "operation": "新增 -> 打开「生产工单选择」",
+ "ok": false,
+ "expectedParams": {
+ "status": "1",
+ "type": "2"
+ },
+ "actualRequests": [
+ {
+ "path": "/admin-api/mes/pro/work-order/page",
+ "search": "?pageNo=1&pageSize=20&type=2",
+ "params": {
+ "pageNo": "1",
+ "pageSize": "20",
+ "type": "2"
+ }
+ }
+ ],
+ "paramChecks": {
+ "status": false,
+ "type": true
+ },
+ "rowCount": 1,
+ "radioCount": 2,
+ "checkboxCount": 0,
+ "firstRowText": "MO202504120001 外协工单-螺丝刀刀柄【蓝色】【1000】个 客户订单 PO202503011001 IF2022082428 螺丝刀刀柄【蓝色】 10CM 个 1000 C00197 博世 已取消 2025-03-31",
+ "afterSelectionValue": "MO202504120001",
+ "dialogClosedAfterSelection": true,
+ "screenshot": "/Users/yunai/Java/yudao-all-in-vben/yudao-ui-admin-vben/output/playwright/2026-06-13T02-49-49-836Z-outsource-issue-work-order.png",
+ "errors": [
+ "请求参数不符合预期: {\"status\":false,\"type\":true}"
+ ],
+ "consoleErrorCount": 32
+ }
+ ],
+ "passed": 3,
+ "failed": 2
+}
\ No newline at end of file
diff --git a/output/playwright/2026-06-13T02-49-49-836Z-outsource-issue-work-order.png b/output/playwright/2026-06-13T02-49-49-836Z-outsource-issue-work-order.png
new file mode 100644
index 000000000..0a2bcaa31
Binary files /dev/null and b/output/playwright/2026-06-13T02-49-49-836Z-outsource-issue-work-order.png differ
diff --git a/output/playwright/2026-06-13T02-49-49-836Z-product-issue-work-order.png b/output/playwright/2026-06-13T02-49-49-836Z-product-issue-work-order.png
new file mode 100644
index 000000000..26d615244
Binary files /dev/null and b/output/playwright/2026-06-13T02-49-49-836Z-product-issue-work-order.png differ
diff --git a/output/playwright/2026-06-13T02-49-49-836Z-product-issue-workstation.png b/output/playwright/2026-06-13T02-49-49-836Z-product-issue-workstation.png
new file mode 100644
index 000000000..87a210b06
Binary files /dev/null and b/output/playwright/2026-06-13T02-49-49-836Z-product-issue-workstation.png differ
diff --git a/output/playwright/2026-06-13T02-49-49-836Z-product-sales-sales-notice.png b/output/playwright/2026-06-13T02-49-49-836Z-product-sales-sales-notice.png
new file mode 100644
index 000000000..f3b8ba0c5
Binary files /dev/null and b/output/playwright/2026-06-13T02-49-49-836Z-product-sales-sales-notice.png differ
diff --git a/output/playwright/2026-06-13T02-53-02-246Z-item-receipt-arrival-notice.png b/output/playwright/2026-06-13T02-53-02-246Z-item-receipt-arrival-notice.png
new file mode 100644
index 000000000..8f964e047
Binary files /dev/null and b/output/playwright/2026-06-13T02-53-02-246Z-item-receipt-arrival-notice.png differ
diff --git a/output/playwright/2026-06-13T02-53-02-246Z-mes-selector-runtime.json b/output/playwright/2026-06-13T02-53-02-246Z-mes-selector-runtime.json
new file mode 100644
index 000000000..3894ce90a
--- /dev/null
+++ b/output/playwright/2026-06-13T02-53-02-246Z-mes-selector-runtime.json
@@ -0,0 +1,174 @@
+{
+ "baseUrl": "http://127.0.0.1:5666",
+ "generatedAt": "2026-06-13T02:54:01.674Z",
+ "results": [
+ {
+ "id": "item-receipt-arrival-notice",
+ "pageName": "采购入库",
+ "route": "/mes/wm/item-receipt",
+ "operation": "新增 -> 打开「到货通知单选择」",
+ "ok": true,
+ "expectedParams": {
+ "status": "3"
+ },
+ "actualRequests": [
+ {
+ "path": "/admin-api/mes/wm/arrival-notice/page",
+ "search": "?pageNo=1&pageSize=20&status=3",
+ "params": {
+ "pageNo": "1",
+ "pageSize": "20",
+ "status": "3"
+ }
+ }
+ ],
+ "paramChecks": {
+ "status": true
+ },
+ "rowCount": 7,
+ "radioCount": 14,
+ "checkboxCount": 0,
+ "firstRowText": "AN20260329000001 ABC 深圳市海力德电子有限公司 2026-03-04 待入库",
+ "afterSelectionValue": "AN20260329000001",
+ "dialogClosedAfterSelection": true,
+ "screenshot": "/Users/yunai/Java/yudao-all-in-vben/yudao-ui-admin-vben/output/playwright/2026-06-13T02-53-02-246Z-item-receipt-arrival-notice.png",
+ "errors": [],
+ "consoleErrorCount": 32
+ },
+ {
+ "id": "product-sales-sales-notice",
+ "pageName": "销售出库",
+ "route": "/mes/wm/product-sales",
+ "operation": "新增 -> 打开「发货通知单选择」",
+ "ok": true,
+ "expectedParams": {
+ "status": "3"
+ },
+ "actualRequests": [
+ {
+ "path": "/admin-api/mes/wm/sales-notice/page",
+ "search": "?pageNo=1&pageSize=20&status=3",
+ "params": {
+ "pageNo": "1",
+ "pageSize": "20",
+ "status": "3"
+ }
+ }
+ ],
+ "paramChecks": {
+ "status": true
+ },
+ "rowCount": 2,
+ "radioCount": 4,
+ "checkboxCount": 0,
+ "firstRowText": "SN20260330000004 AABBEEE 比亚迪股份有限公司 2026-03-18 待出库",
+ "afterSelectionValue": "AABBEEE",
+ "dialogClosedAfterSelection": true,
+ "screenshot": "/Users/yunai/Java/yudao-all-in-vben/yudao-ui-admin-vben/output/playwright/2026-06-13T02-53-02-246Z-product-sales-sales-notice.png",
+ "errors": [],
+ "consoleErrorCount": 32
+ },
+ {
+ "id": "product-issue-work-order",
+ "pageName": "生产领料",
+ "route": "/mes/wm/product-issue",
+ "operation": "新增 -> 打开「生产工单选择」",
+ "ok": true,
+ "expectedParams": {
+ "status": "1"
+ },
+ "actualRequests": [
+ {
+ "path": "/admin-api/mes/pro/work-order/page",
+ "search": "?pageNo=1&pageSize=20&status=1",
+ "params": {
+ "pageNo": "1",
+ "pageSize": "20",
+ "status": "1"
+ }
+ }
+ ],
+ "paramChecks": {
+ "status": true
+ },
+ "rowCount": 5,
+ "radioCount": 10,
+ "checkboxCount": 0,
+ "firstRowText": "MO_ACCEPT_FB_20260526 验收生产报工工单-螺丝刀 客户订单 ACCEPT-FEEDBACK IF2022082439 螺丝刀【蓝色,一字型】 蓝色,一字型,3.2x75mm 个 200 C00197 博世 已确认 2026-06-02",
+ "afterSelectionValue": "MO_ACCEPT_FB_20260526",
+ "dialogClosedAfterSelection": true,
+ "screenshot": "/Users/yunai/Java/yudao-all-in-vben/yudao-ui-admin-vben/output/playwright/2026-06-13T02-53-02-246Z-product-issue-work-order.png",
+ "errors": [],
+ "consoleErrorCount": 32
+ },
+ {
+ "id": "product-issue-workstation",
+ "pageName": "生产领料",
+ "route": "/mes/wm/product-issue",
+ "operation": "新增 -> 打开「工作站选择」",
+ "ok": true,
+ "expectedParams": {},
+ "actualRequests": [
+ {
+ "path": "/admin-api/mes/md-workstation/page",
+ "search": "?pageNo=1&pageSize=20&status=0",
+ "params": {
+ "pageNo": "1",
+ "pageSize": "20",
+ "status": "0"
+ }
+ }
+ ],
+ "paramChecks": {},
+ "rowCount": 8,
+ "radioCount": 16,
+ "checkboxCount": 0,
+ "firstRowText": "ST_ACCEPT_FB_P4 验收报工-质检工位 验收造数 组装车间 打磨工序 验收造数:生产报工质检工序",
+ "afterSelectionValue": "验收报工-质检工位",
+ "dialogClosedAfterSelection": true,
+ "screenshot": "/Users/yunai/Java/yudao-all-in-vben/yudao-ui-admin-vben/output/playwright/2026-06-13T02-53-02-246Z-product-issue-workstation.png",
+ "errors": [],
+ "consoleErrorCount": 32
+ },
+ {
+ "id": "outsource-issue-work-order",
+ "pageName": "外协发料",
+ "route": "/mes/wm/outsource-issue",
+ "operation": "新增 -> 打开「生产工单选择」",
+ "ok": false,
+ "expectedParams": {
+ "status": "1",
+ "type": "2"
+ },
+ "actualRequests": [
+ {
+ "path": "/admin-api/mes/pro/work-order/page",
+ "search": "?pageNo=1&pageSize=20&status=1&type=2",
+ "params": {
+ "pageNo": "1",
+ "pageSize": "20",
+ "status": "1",
+ "type": "2"
+ }
+ }
+ ],
+ "paramChecks": {
+ "status": true,
+ "type": true
+ },
+ "rowCount": 0,
+ "radioCount": 0,
+ "checkboxCount": 0,
+ "firstRowText": "",
+ "afterSelectionValue": "",
+ "dialogClosedAfterSelection": null,
+ "screenshot": "/Users/yunai/Java/yudao-all-in-vben/yudao-ui-admin-vben/output/playwright/2026-06-13T02-53-02-246Z-outsource-issue-work-order.png",
+ "errors": [
+ "单选列形态异常: radio=0, checkbox=0"
+ ],
+ "consoleErrorCount": 32
+ }
+ ],
+ "passed": 4,
+ "failed": 1
+}
\ No newline at end of file
diff --git a/output/playwright/2026-06-13T02-53-02-246Z-outsource-issue-work-order.png b/output/playwright/2026-06-13T02-53-02-246Z-outsource-issue-work-order.png
new file mode 100644
index 000000000..fb6a06720
Binary files /dev/null and b/output/playwright/2026-06-13T02-53-02-246Z-outsource-issue-work-order.png differ
diff --git a/output/playwright/2026-06-13T02-53-02-246Z-product-issue-work-order.png b/output/playwright/2026-06-13T02-53-02-246Z-product-issue-work-order.png
new file mode 100644
index 000000000..26d615244
Binary files /dev/null and b/output/playwright/2026-06-13T02-53-02-246Z-product-issue-work-order.png differ
diff --git a/output/playwright/2026-06-13T02-53-02-246Z-product-issue-workstation.png b/output/playwright/2026-06-13T02-53-02-246Z-product-issue-workstation.png
new file mode 100644
index 000000000..87a210b06
Binary files /dev/null and b/output/playwright/2026-06-13T02-53-02-246Z-product-issue-workstation.png differ
diff --git a/output/playwright/2026-06-13T02-53-02-246Z-product-sales-sales-notice.png b/output/playwright/2026-06-13T02-53-02-246Z-product-sales-sales-notice.png
new file mode 100644
index 000000000..f3b8ba0c5
Binary files /dev/null and b/output/playwright/2026-06-13T02-53-02-246Z-product-sales-sales-notice.png differ
diff --git a/output/playwright/2026-06-13T02-57-10-398Z-mes-selector-runtime-other-apps.json b/output/playwright/2026-06-13T02-57-10-398Z-mes-selector-runtime-other-apps.json
new file mode 100644
index 000000000..23d238dfd
--- /dev/null
+++ b/output/playwright/2026-06-13T02-57-10-398Z-mes-selector-runtime-other-apps.json
@@ -0,0 +1,146 @@
+{
+ "generatedAt": "2026-06-13T02:57:53.579Z",
+ "results": [
+ {
+ "app": "web-ele",
+ "baseUrl": "http://127.0.0.1:5778",
+ "id": "product-issue-work-order",
+ "pageName": "生产领料",
+ "ok": true,
+ "blocked": false,
+ "expectedParams": {
+ "status": "1"
+ },
+ "actualRequests": [
+ {
+ "path": "/admin-api/mes/pro/work-order/page",
+ "search": "?pageNo=1&pageSize=20&status=1",
+ "params": {
+ "pageNo": "1",
+ "pageSize": "20",
+ "status": "1"
+ }
+ }
+ ],
+ "paramChecks": {
+ "status": true
+ },
+ "rowCount": 5,
+ "radioCount": 10,
+ "checkboxCount": 0,
+ "firstRowText": "MO_ACCEPT_FB_20260526 验收生产报工工单-螺丝刀 客户订单 ACCEPT-FEEDBACK IF2022082439 螺丝刀【蓝色,一字型】 蓝色,一字型,3.2x75mm 个 200 C00197 博世 已确认 2026-06-02",
+ "afterSelectionValue": "MO_ACCEPT_FB_20260526",
+ "screenshot": "/Users/yunai/Java/yudao-all-in-vben/yudao-ui-admin-vben/output/playwright/2026-06-13T02-57-10-398Z-web-ele-product-issue-work-order.png",
+ "errors": [],
+ "consoleErrorCount": 57
+ },
+ {
+ "app": "web-ele",
+ "baseUrl": "http://127.0.0.1:5778",
+ "id": "outsource-issue-work-order",
+ "pageName": "外协发料",
+ "ok": true,
+ "blocked": false,
+ "expectedParams": {
+ "status": "1",
+ "type": "2"
+ },
+ "actualRequests": [
+ {
+ "path": "/admin-api/mes/pro/work-order/page",
+ "search": "?pageNo=1&pageSize=20&status=1&type=2",
+ "params": {
+ "pageNo": "1",
+ "pageSize": "20",
+ "status": "1",
+ "type": "2"
+ }
+ }
+ ],
+ "paramChecks": {
+ "status": true,
+ "type": true
+ },
+ "rowCount": 0,
+ "radioCount": 0,
+ "checkboxCount": 0,
+ "firstRowText": "",
+ "afterSelectionValue": "",
+ "screenshot": "/Users/yunai/Java/yudao-all-in-vben/yudao-ui-admin-vben/output/playwright/2026-06-13T02-57-10-398Z-web-ele-outsource-issue-work-order.png",
+ "errors": [],
+ "consoleErrorCount": 38
+ },
+ {
+ "app": "web-antdv-next",
+ "baseUrl": "http://127.0.0.1:5999",
+ "id": "product-issue-work-order",
+ "pageName": "生产领料",
+ "ok": true,
+ "blocked": false,
+ "expectedParams": {
+ "status": "1"
+ },
+ "actualRequests": [
+ {
+ "path": "/admin-api/mes/pro/work-order/page",
+ "search": "?pageNo=1&pageSize=20&status=1",
+ "params": {
+ "pageNo": "1",
+ "pageSize": "20",
+ "status": "1"
+ }
+ }
+ ],
+ "paramChecks": {
+ "status": true
+ },
+ "rowCount": 5,
+ "radioCount": 10,
+ "checkboxCount": 0,
+ "firstRowText": "MO_ACCEPT_FB_20260526 验收生产报工工单-螺丝刀 客户订单 ACCEPT-FEEDBACK IF2022082439 螺丝刀【蓝色,一字型】 蓝色,一字型,3.2x75mm 个 200 C00197 博世 已确认 2026-06-02",
+ "afterSelectionValue": "MO_ACCEPT_FB_20260526",
+ "screenshot": "/Users/yunai/Java/yudao-all-in-vben/yudao-ui-admin-vben/output/playwright/2026-06-13T02-57-10-398Z-web-antdv-next-product-issue-work-order.png",
+ "errors": [],
+ "consoleErrorCount": 52
+ },
+ {
+ "app": "web-antdv-next",
+ "baseUrl": "http://127.0.0.1:5999",
+ "id": "outsource-issue-work-order",
+ "pageName": "外协发料",
+ "ok": true,
+ "blocked": false,
+ "expectedParams": {
+ "status": "1",
+ "type": "2"
+ },
+ "actualRequests": [
+ {
+ "path": "/admin-api/mes/pro/work-order/page",
+ "search": "?pageNo=1&pageSize=20&status=1&type=2",
+ "params": {
+ "pageNo": "1",
+ "pageSize": "20",
+ "status": "1",
+ "type": "2"
+ }
+ }
+ ],
+ "paramChecks": {
+ "status": true,
+ "type": true
+ },
+ "rowCount": 0,
+ "radioCount": 0,
+ "checkboxCount": 0,
+ "firstRowText": "",
+ "afterSelectionValue": "",
+ "screenshot": "/Users/yunai/Java/yudao-all-in-vben/yudao-ui-admin-vben/output/playwright/2026-06-13T02-57-10-398Z-web-antdv-next-outsource-issue-work-order.png",
+ "errors": [],
+ "consoleErrorCount": 37
+ }
+ ],
+ "passed": 4,
+ "failed": 0,
+ "blocked": 0
+}
\ No newline at end of file
diff --git a/output/playwright/2026-06-13T02-57-10-398Z-web-antdv-next-outsource-issue-work-order.png b/output/playwright/2026-06-13T02-57-10-398Z-web-antdv-next-outsource-issue-work-order.png
new file mode 100644
index 000000000..931f7e418
Binary files /dev/null and b/output/playwright/2026-06-13T02-57-10-398Z-web-antdv-next-outsource-issue-work-order.png differ
diff --git a/output/playwright/2026-06-13T02-57-10-398Z-web-antdv-next-product-issue-work-order.png b/output/playwright/2026-06-13T02-57-10-398Z-web-antdv-next-product-issue-work-order.png
new file mode 100644
index 000000000..2df78d362
Binary files /dev/null and b/output/playwright/2026-06-13T02-57-10-398Z-web-antdv-next-product-issue-work-order.png differ
diff --git a/output/playwright/2026-06-13T02-57-10-398Z-web-ele-outsource-issue-work-order.png b/output/playwright/2026-06-13T02-57-10-398Z-web-ele-outsource-issue-work-order.png
new file mode 100644
index 000000000..75e6f9169
Binary files /dev/null and b/output/playwright/2026-06-13T02-57-10-398Z-web-ele-outsource-issue-work-order.png differ
diff --git a/output/playwright/2026-06-13T02-57-10-398Z-web-ele-product-issue-work-order.png b/output/playwright/2026-06-13T02-57-10-398Z-web-ele-product-issue-work-order.png
new file mode 100644
index 000000000..c011fe0da
Binary files /dev/null and b/output/playwright/2026-06-13T02-57-10-398Z-web-ele-product-issue-work-order.png differ
diff --git a/output/playwright/im-full-2026-06-17T16-39-23-356Z/chat-01-vben-before.png b/output/playwright/im-full-2026-06-17T16-39-23-356Z/chat-01-vben-before.png
new file mode 100644
index 000000000..497e0c391
Binary files /dev/null and b/output/playwright/im-full-2026-06-17T16-39-23-356Z/chat-01-vben-before.png differ
diff --git a/output/playwright/im-full-2026-06-17T16-39-23-356Z/chat-01-vue3-before.png b/output/playwright/im-full-2026-06-17T16-39-23-356Z/chat-01-vue3-before.png
new file mode 100644
index 000000000..d3b400059
Binary files /dev/null and b/output/playwright/im-full-2026-06-17T16-39-23-356Z/chat-01-vue3-before.png differ
diff --git a/output/playwright/im-full-2026-06-17T16-39-23-356Z/chat-02-vben-after-two-way.png b/output/playwright/im-full-2026-06-17T16-39-23-356Z/chat-02-vben-after-two-way.png
new file mode 100644
index 000000000..38d6293de
Binary files /dev/null and b/output/playwright/im-full-2026-06-17T16-39-23-356Z/chat-02-vben-after-two-way.png differ
diff --git a/output/playwright/im-full-2026-06-17T16-39-23-356Z/chat-02-vue3-after-two-way.png b/output/playwright/im-full-2026-06-17T16-39-23-356Z/chat-02-vue3-after-two-way.png
new file mode 100644
index 000000000..1a8de41c9
Binary files /dev/null and b/output/playwright/im-full-2026-06-17T16-39-23-356Z/chat-02-vue3-after-two-way.png differ
diff --git a/output/playwright/im-full-2026-06-17T16-39-23-356Z/chat-03-vben-message-context-menu.png b/output/playwright/im-full-2026-06-17T16-39-23-356Z/chat-03-vben-message-context-menu.png
new file mode 100644
index 000000000..a8f0dd9b6
Binary files /dev/null and b/output/playwright/im-full-2026-06-17T16-39-23-356Z/chat-03-vben-message-context-menu.png differ
diff --git a/output/playwright/im-full-2026-06-17T16-39-23-356Z/chat-04-vben-contact.png b/output/playwright/im-full-2026-06-17T16-39-23-356Z/chat-04-vben-contact.png
new file mode 100644
index 000000000..fd323f33c
Binary files /dev/null and b/output/playwright/im-full-2026-06-17T16-39-23-356Z/chat-04-vben-contact.png differ
diff --git a/output/playwright/im-full-2026-06-17T16-39-23-356Z/chat-04-vue3-contact.png b/output/playwright/im-full-2026-06-17T16-39-23-356Z/chat-04-vue3-contact.png
new file mode 100644
index 000000000..66c2b6dbf
Binary files /dev/null and b/output/playwright/im-full-2026-06-17T16-39-23-356Z/chat-04-vue3-contact.png differ
diff --git a/output/playwright/im-full-2026-06-17T16-39-23-356Z/chat-05-vben-contact-search.png b/output/playwright/im-full-2026-06-17T16-39-23-356Z/chat-05-vben-contact-search.png
new file mode 100644
index 000000000..168901735
Binary files /dev/null and b/output/playwright/im-full-2026-06-17T16-39-23-356Z/chat-05-vben-contact-search.png differ
diff --git a/output/playwright/im-full-2026-06-17T16-39-23-356Z/manager-channel-add-form.png b/output/playwright/im-full-2026-06-17T16-39-23-356Z/manager-channel-add-form.png
new file mode 100644
index 000000000..39a6634d1
Binary files /dev/null and b/output/playwright/im-full-2026-06-17T16-39-23-356Z/manager-channel-add-form.png differ
diff --git a/output/playwright/im-full-2026-06-17T16-39-23-356Z/manager-channel-message-send-form.png b/output/playwright/im-full-2026-06-17T16-39-23-356Z/manager-channel-message-send-form.png
new file mode 100644
index 000000000..d55ced6af
Binary files /dev/null and b/output/playwright/im-full-2026-06-17T16-39-23-356Z/manager-channel-message-send-form.png differ
diff --git a/output/playwright/im-full-2026-06-17T16-39-23-356Z/manager-channel-message-user-multi-select.png b/output/playwright/im-full-2026-06-17T16-39-23-356Z/manager-channel-message-user-multi-select.png
new file mode 100644
index 000000000..81b8ab357
Binary files /dev/null and b/output/playwright/im-full-2026-06-17T16-39-23-356Z/manager-channel-message-user-multi-select.png differ
diff --git a/output/playwright/im-full-2026-06-17T16-39-23-356Z/manager-face-pack-add-form.png b/output/playwright/im-full-2026-06-17T16-39-23-356Z/manager-face-pack-add-form.png
new file mode 100644
index 000000000..0296f3614
Binary files /dev/null and b/output/playwright/im-full-2026-06-17T16-39-23-356Z/manager-face-pack-add-form.png differ
diff --git a/output/playwright/im-full-2026-06-17T16-39-23-356Z/manager-material-add-form.png b/output/playwright/im-full-2026-06-17T16-39-23-356Z/manager-material-add-form.png
new file mode 100644
index 000000000..35b502d3f
Binary files /dev/null and b/output/playwright/im-full-2026-06-17T16-39-23-356Z/manager-material-add-form.png differ
diff --git a/output/playwright/im-full-2026-06-17T16-39-23-356Z/manager-route-im-channel-list.png b/output/playwright/im-full-2026-06-17T16-39-23-356Z/manager-route-im-channel-list.png
new file mode 100644
index 000000000..ac8848f95
Binary files /dev/null and b/output/playwright/im-full-2026-06-17T16-39-23-356Z/manager-route-im-channel-list.png differ
diff --git a/output/playwright/im-full-2026-06-17T16-39-23-356Z/manager-route-im-channel-material.png b/output/playwright/im-full-2026-06-17T16-39-23-356Z/manager-route-im-channel-material.png
new file mode 100644
index 000000000..607462d4e
Binary files /dev/null and b/output/playwright/im-full-2026-06-17T16-39-23-356Z/manager-route-im-channel-material.png differ
diff --git a/output/playwright/im-full-2026-06-17T16-39-23-356Z/manager-route-im-channel-message.png b/output/playwright/im-full-2026-06-17T16-39-23-356Z/manager-route-im-channel-message.png
new file mode 100644
index 000000000..1440b78fc
Binary files /dev/null and b/output/playwright/im-full-2026-06-17T16-39-23-356Z/manager-route-im-channel-message.png differ
diff --git a/output/playwright/im-full-2026-06-17T16-39-23-356Z/manager-route-im-face-pack.png b/output/playwright/im-full-2026-06-17T16-39-23-356Z/manager-route-im-face-pack.png
new file mode 100644
index 000000000..8afcf401b
Binary files /dev/null and b/output/playwright/im-full-2026-06-17T16-39-23-356Z/manager-route-im-face-pack.png differ
diff --git a/output/playwright/im-full-2026-06-17T16-39-23-356Z/manager-route-im-face-user-item.png b/output/playwright/im-full-2026-06-17T16-39-23-356Z/manager-route-im-face-user-item.png
new file mode 100644
index 000000000..24fefb41b
Binary files /dev/null and b/output/playwright/im-full-2026-06-17T16-39-23-356Z/manager-route-im-face-user-item.png differ
diff --git a/output/playwright/im-full-2026-06-17T16-39-23-356Z/manager-route-im-group-list.png b/output/playwright/im-full-2026-06-17T16-39-23-356Z/manager-route-im-group-list.png
new file mode 100644
index 000000000..a1caa76bd
Binary files /dev/null and b/output/playwright/im-full-2026-06-17T16-39-23-356Z/manager-route-im-group-list.png differ
diff --git a/output/playwright/im-full-2026-06-17T16-39-23-356Z/manager-route-im-group-message.png b/output/playwright/im-full-2026-06-17T16-39-23-356Z/manager-route-im-group-message.png
new file mode 100644
index 000000000..cca8731d5
Binary files /dev/null and b/output/playwright/im-full-2026-06-17T16-39-23-356Z/manager-route-im-group-message.png differ
diff --git a/output/playwright/im-full-2026-06-17T16-39-23-356Z/manager-route-im-group-request.png b/output/playwright/im-full-2026-06-17T16-39-23-356Z/manager-route-im-group-request.png
new file mode 100644
index 000000000..42d413f56
Binary files /dev/null and b/output/playwright/im-full-2026-06-17T16-39-23-356Z/manager-route-im-group-request.png differ
diff --git a/output/playwright/im-full-2026-06-17T16-39-23-356Z/manager-route-im-private-friend-request.png b/output/playwright/im-full-2026-06-17T16-39-23-356Z/manager-route-im-private-friend-request.png
new file mode 100644
index 000000000..2732e68bf
Binary files /dev/null and b/output/playwright/im-full-2026-06-17T16-39-23-356Z/manager-route-im-private-friend-request.png differ
diff --git a/output/playwright/im-full-2026-06-17T16-39-23-356Z/manager-route-im-private-friend.png b/output/playwright/im-full-2026-06-17T16-39-23-356Z/manager-route-im-private-friend.png
new file mode 100644
index 000000000..56595e28f
Binary files /dev/null and b/output/playwright/im-full-2026-06-17T16-39-23-356Z/manager-route-im-private-friend.png differ
diff --git a/output/playwright/im-full-2026-06-17T16-39-23-356Z/manager-route-im-private-message.png b/output/playwright/im-full-2026-06-17T16-39-23-356Z/manager-route-im-private-message.png
new file mode 100644
index 000000000..d185fc6d5
Binary files /dev/null and b/output/playwright/im-full-2026-06-17T16-39-23-356Z/manager-route-im-private-message.png differ
diff --git a/output/playwright/im-full-2026-06-17T16-39-23-356Z/manager-route-im-rtc.png b/output/playwright/im-full-2026-06-17T16-39-23-356Z/manager-route-im-rtc.png
new file mode 100644
index 000000000..c0183f6c3
Binary files /dev/null and b/output/playwright/im-full-2026-06-17T16-39-23-356Z/manager-route-im-rtc.png differ
diff --git a/output/playwright/im-full-2026-06-17T16-39-23-356Z/manager-route-im-sensitive-word.png b/output/playwright/im-full-2026-06-17T16-39-23-356Z/manager-route-im-sensitive-word.png
new file mode 100644
index 000000000..b7b238909
Binary files /dev/null and b/output/playwright/im-full-2026-06-17T16-39-23-356Z/manager-route-im-sensitive-word.png differ
diff --git a/output/playwright/im-full-2026-06-17T16-39-23-356Z/manager-route-im-statistics.png b/output/playwright/im-full-2026-06-17T16-39-23-356Z/manager-route-im-statistics.png
new file mode 100644
index 000000000..e48fb588d
Binary files /dev/null and b/output/playwright/im-full-2026-06-17T16-39-23-356Z/manager-route-im-statistics.png differ
diff --git a/output/playwright/im-full-2026-06-17T16-39-23-356Z/result.json b/output/playwright/im-full-2026-06-17T16-39-23-356Z/result.json
new file mode 100644
index 000000000..90132e38c
--- /dev/null
+++ b/output/playwright/im-full-2026-06-17T16-39-23-356Z/result.json
@@ -0,0 +1,308 @@
+{
+ "runId": 1781714363357,
+ "outDir": "/Users/yunai/Java/yudao-all-in-vben/yudao-ui-admin-vben/output/playwright/im-full-2026-06-17T16-39-23-356Z",
+ "accounts": {
+ "vue3": "admin/admin123 userId=1",
+ "vben": "test01/123456 userId=142",
+ "manager": "admin/admin123 userId=1"
+ },
+ "messages": {
+ "vueText": "FULL Vue3 to Vben 1781714363357",
+ "vbenText": "FULL Vben to Vue3 1781714363357"
+ },
+ "checks": {
+ "vbenConversationKeys": [
+ {
+ "key": "1-1",
+ "text": "0芋道源码09:20E2E Vben to Vue3 1781713160946"
+ },
+ {
+ "key": "2-10084",
+ "text": "3芋道源码、a00001、test01、新用户等13人 群 昨天 11:37测试号: 123"
+ },
+ {
+ "key": "3-1",
+ "text": "3系统公告05/19[频道] 测试消息"
+ }
+ ],
+ "vue3ConversationKeys": [
+ {
+ "key": "1-141",
+ "text": "新0新用户13:57[语音]"
+ },
+ {
+ "key": "1-142",
+ "text": "TE0test0109:20E2E Vben to Vue3 1781713160946"
+ },
+ {
+ "key": "1-104",
+ "text": "测0测试号昨天 11:3732132321"
+ },
+ {
+ "key": "2-10084",
+ "text": "芋0芋道源码、a00001、test01、新用户等13人 群 昨天 11:36芋道源码 退出了群聊"
+ },
+ {
+ "key": "1-143",
+ "text": "A0a0000105/31[语音通话]"
+ },
+ {
+ "key": "1-139",
+ "text": "小0小秃头05/30小秃头 撤回了一条消息"
+ },
+ {
+ "key": "1-118",
+ "text": "狗0狗蛋05/30狗蛋 撤回了一条消息"
+ },
+ {
+ "key": "1-117",
+ "text": "测0测试号0205/30测试号02 撤回了一条消息"
+ },
+ {
+ "key": "1-115",
+ "text": "阿0阿呆05/30阿呆 撤回了一条消息"
+ },
+ {
+ "key": "1-114",
+ "text": "HR0hr 小姐姐05/30hr 小姐姐 撤回了一条消息"
+ },
+ {
+ "key": "1-112",
+ "text": "新0新对象05/30新对象 撤回了一条消息"
+ },
+ {
+ "key": "1-103",
+ "text": "源0源码05/30源码 撤回了一条消息"
+ }
+ ],
+ "vue3SentVisible": true,
+ "vbenReceived": true,
+ "vbenSentVisible": true,
+ "vue3Received": true,
+ "twoWayPrivateMessage": true,
+ "vbenInputToolbarIconCount": 14,
+ "vue3ContactLoaded": true,
+ "vbenContactLoaded": true
+ },
+ "routeChecks": [
+ {
+ "route": "/im/statistics",
+ "name": "统计看板",
+ "status": "passed",
+ "titleVisible": true,
+ "badResponseDelta": 0,
+ "eventDelta": 0,
+ "textSample": "芋道管理系统\n概览\n作者动态\nBoot 开发文档\nCloud 开发文档\n系统管理\n基础设施\n支付管理\n报表管理\n工作流程\n会员中心\n商城系统\n公众号管理\nCRM 系统\nERP 系统\nWMS 系统\nMES 系统\nAI 大模型\nIoT 物联网\nIM 即时通讯\n数据统计\n私聊管理\n群聊管理\n通话记录\n敏感词管理\n表情管理\n频道管理\nIM 即时通讯\n数据统计\n请选择"
+ },
+ {
+ "route": "/im/channel/list",
+ "name": "频道列表",
+ "status": "passed",
+ "titleVisible": true,
+ "badResponseDelta": 0,
+ "eventDelta": 0,
+ "textSample": "芋道管理系统\n概览\n作者动态\nBoot 开发文档\nCloud 开发文档\n系统管理\n基础设施\n支付管理\n报表管理\n工作流程\n会员中心\n商城系统\n公众号管理\nCRM 系统\nERP 系统\nWMS 系统\nMES 系统\nAI 大模型\nIoT 物联网\nIM 即时通讯\n数据统计\n私聊管理\n群聊管理\n通话记录\n敏感词管理\n表情管理\n频道管理\n频道列表\n频道素材\n频道消息\nI"
+ },
+ {
+ "route": "/im/channel/material",
+ "name": "频道素材",
+ "status": "passed",
+ "titleVisible": true,
+ "badResponseDelta": 0,
+ "eventDelta": 0,
+ "textSample": "芋道管理系统\n概览\n作者动态\nBoot 开发文档\nCloud 开发文档\n系统管理\n基础设施\n支付管理\n报表管理\n工作流程\n会员中心\n商城系统\n公众号管理\nCRM 系统\nERP 系统\nWMS 系统\nMES 系统\nAI 大模型\nIoT 物联网\nIM 即时通讯\n数据统计\n私聊管理\n群聊管理\n通话记录\n敏感词管理\n表情管理\n频道管理\n频道列表\n频道素材\n频道消息\nI"
+ },
+ {
+ "route": "/im/channel/message",
+ "name": "频道消息",
+ "status": "passed",
+ "titleVisible": true,
+ "badResponseDelta": 0,
+ "eventDelta": 0,
+ "textSample": "芋道管理系统\n概览\n作者动态\nBoot 开发文档\nCloud 开发文档\n系统管理\n基础设施\n支付管理\n报表管理\n工作流程\n会员中心\n商城系统\n公众号管理\nCRM 系统\nERP 系统\nWMS 系统\nMES 系统\nAI 大模型\nIoT 物联网\nIM 即时通讯\n数据统计\n私聊管理\n群聊管理\n通话记录\n敏感词管理\n表情管理\n频道管理\n频道列表\n频道素材\n频道消息\nI"
+ },
+ {
+ "route": "/im/face/pack",
+ "name": "表情包",
+ "status": "passed",
+ "titleVisible": true,
+ "badResponseDelta": 0,
+ "eventDelta": 0,
+ "textSample": "芋道管理系统\n概览\n作者动态\nBoot 开发文档\nCloud 开发文档\n系统管理\n基础设施\n支付管理\n报表管理\n工作流程\n会员中心\n商城系统\n公众号管理\nCRM 系统\nERP 系统\nWMS 系统\nMES 系统\nAI 大模型\nIoT 物联网\nIM 即时通讯\n数据统计\n私聊管理\n群聊管理\n通话记录\n敏感词管理\n表情管理\n系统表情\n用户表情\n频道管理\nIM 即时通"
+ },
+ {
+ "route": "/im/face/user-item",
+ "name": "用户表情",
+ "status": "passed",
+ "titleVisible": true,
+ "badResponseDelta": 0,
+ "eventDelta": 0,
+ "textSample": "芋道管理系统\n概览\n作者动态\nBoot 开发文档\nCloud 开发文档\n系统管理\n基础设施\n支付管理\n报表管理\n工作流程\n会员中心\n商城系统\n公众号管理\nCRM 系统\nERP 系统\nWMS 系统\nMES 系统\nAI 大模型\nIoT 物联网\nIM 即时通讯\n数据统计\n私聊管理\n群聊管理\n通话记录\n敏感词管理\n表情管理\n系统表情\n用户表情\n频道管理\nIM 即时通"
+ },
+ {
+ "route": "/im/private/friend",
+ "name": "好友管理",
+ "status": "passed",
+ "titleVisible": true,
+ "badResponseDelta": 0,
+ "eventDelta": 0,
+ "textSample": "芋道管理系统\n概览\n作者动态\nBoot 开发文档\nCloud 开发文档\n系统管理\n基础设施\n支付管理\n报表管理\n工作流程\n会员中心\n商城系统\n公众号管理\nCRM 系统\nERP 系统\nWMS 系统\nMES 系统\nAI 大模型\nIoT 物联网\nIM 即时通讯\n数据统计\n私聊管理\n好友列表\n好友申请\n好友消息\n群聊管理\n通话记录\n敏感词管理\n表情管理\n频道管理\nI"
+ },
+ {
+ "route": "/im/private/friend-request",
+ "name": "好友申请",
+ "status": "passed",
+ "titleVisible": true,
+ "badResponseDelta": 0,
+ "eventDelta": 0,
+ "textSample": "芋道管理系统\n概览\n作者动态\nBoot 开发文档\nCloud 开发文档\n系统管理\n基础设施\n支付管理\n报表管理\n工作流程\n会员中心\n商城系统\n公众号管理\nCRM 系统\nERP 系统\nWMS 系统\nMES 系统\nAI 大模型\nIoT 物联网\nIM 即时通讯\n数据统计\n私聊管理\n好友列表\n好友申请\n好友消息\n群聊管理\n通话记录\n敏感词管理\n表情管理\n频道管理\nI"
+ },
+ {
+ "route": "/im/group/list",
+ "name": "群管理",
+ "status": "passed",
+ "titleVisible": true,
+ "badResponseDelta": 0,
+ "eventDelta": 0,
+ "textSample": "芋道管理系统\n概览\n作者动态\nBoot 开发文档\nCloud 开发文档\n系统管理\n基础设施\n支付管理\n报表管理\n工作流程\n会员中心\n商城系统\n公众号管理\nCRM 系统\nERP 系统\nWMS 系统\nMES 系统\nAI 大模型\nIoT 物联网\nIM 即时通讯\n数据统计\n私聊管理\n群聊管理\n群聊列表\n群聊申请\n群聊消息\n通话记录\n敏感词管理\n表情管理\n频道管理\nI"
+ },
+ {
+ "route": "/im/group/request",
+ "name": "加群申请",
+ "status": "passed",
+ "titleVisible": true,
+ "badResponseDelta": 0,
+ "eventDelta": 0,
+ "textSample": "芋道管理系统\n概览\n作者动态\nBoot 开发文档\nCloud 开发文档\n系统管理\n基础设施\n支付管理\n报表管理\n工作流程\n会员中心\n商城系统\n公众号管理\nCRM 系统\nERP 系统\nWMS 系统\nMES 系统\nAI 大模型\nIoT 物联网\nIM 即时通讯\n数据统计\n私聊管理\n群聊管理\n群聊列表\n群聊申请\n群聊消息\n通话记录\n敏感词管理\n表情管理\n频道管理\nI"
+ },
+ {
+ "route": "/im/private/message",
+ "name": "私聊消息",
+ "status": "passed",
+ "titleVisible": true,
+ "badResponseDelta": 0,
+ "eventDelta": 0,
+ "textSample": "芋道管理系统\n概览\n作者动态\nBoot 开发文档\nCloud 开发文档\n系统管理\n基础设施\n支付管理\n报表管理\n工作流程\n会员中心\n商城系统\n公众号管理\nCRM 系统\nERP 系统\nWMS 系统\nMES 系统\nAI 大模型\nIoT 物联网\nIM 即时通讯\n数据统计\n私聊管理\n好友列表\n好友申请\n好友消息\n群聊管理\n通话记录\n敏感词管理\n表情管理\n频道管理\nI"
+ },
+ {
+ "route": "/im/group/message",
+ "name": "群聊消息",
+ "status": "passed",
+ "titleVisible": true,
+ "badResponseDelta": 0,
+ "eventDelta": 0,
+ "textSample": "芋道管理系统\n概览\n作者动态\nBoot 开发文档\nCloud 开发文档\n系统管理\n基础设施\n支付管理\n报表管理\n工作流程\n会员中心\n商城系统\n公众号管理\nCRM 系统\nERP 系统\nWMS 系统\nMES 系统\nAI 大模型\nIoT 物联网\nIM 即时通讯\n数据统计\n私聊管理\n群聊管理\n群聊列表\n群聊申请\n群聊消息\n通话记录\n敏感词管理\n表情管理\n频道管理\nI"
+ },
+ {
+ "route": "/im/rtc",
+ "name": "RTC 管理",
+ "status": "passed",
+ "titleVisible": true,
+ "badResponseDelta": 0,
+ "eventDelta": 0,
+ "textSample": "芋道管理系统\n概览\n作者动态\nBoot 开发文档\nCloud 开发文档\n系统管理\n基础设施\n支付管理\n报表管理\n工作流程\n会员中心\n商城系统\n公众号管理\nCRM 系统\nERP 系统\nWMS 系统\nMES 系统\nAI 大模型\nIoT 物联网\nIM 即时通讯\n数据统计\n私聊管理\n群聊管理\n通话记录\n敏感词管理\n表情管理\n频道管理\nIM 即时通讯\n通话记录\n请选择"
+ },
+ {
+ "route": "/im/sensitive-word",
+ "name": "敏感词",
+ "status": "passed",
+ "titleVisible": true,
+ "badResponseDelta": 0,
+ "eventDelta": 0,
+ "textSample": "芋道管理系统\n概览\n作者动态\nBoot 开发文档\nCloud 开发文档\n系统管理\n基础设施\n支付管理\n报表管理\n工作流程\n会员中心\n商城系统\n公众号管理\nCRM 系统\nERP 系统\nWMS 系统\nMES 系统\nAI 大模型\nIoT 物联网\nIM 即时通讯\n数据统计\n私聊管理\n群聊管理\n通话记录\n敏感词管理\n表情管理\n频道管理\nIM 即时通讯\n敏感词管理\n请选"
+ }
+ ],
+ "interactionChecks": [
+ {
+ "name": "C-201 文本输入和发送按钮",
+ "status": "passed"
+ },
+ {
+ "name": "C-301 消息右键菜单",
+ "status": "passed",
+ "observed": true
+ },
+ {
+ "name": "C-401/C-409 联系人和群列表",
+ "status": "passed"
+ },
+ {
+ "name": "C-402 好友搜索",
+ "status": "passed"
+ },
+ {
+ "name": "M-201 新增频道弹窗",
+ "status": "passed"
+ },
+ {
+ "name": "M-202 新增素材弹窗",
+ "status": "passed"
+ },
+ {
+ "name": "M-203 频道消息发送弹窗和选择组件",
+ "status": "passed",
+ "hasSelects": true
+ },
+ {
+ "name": "M-203 UserMultiSelect 渲染",
+ "status": "passed"
+ },
+ {
+ "name": "M-204 新增表情包弹窗",
+ "status": "passed"
+ }
+ ],
+ "events": {
+ "vue3": [],
+ "vbenChat": [],
+ "vbenManager": []
+ },
+ "ignoredEvents": {
+ "vue3": 16,
+ "vbenChat": 9,
+ "vbenManager": 57
+ },
+ "badResponses": {
+ "vue3": [],
+ "vbenChat": [],
+ "vbenManager": []
+ },
+ "screenshots": {
+ "chat-01-vben-before": "/Users/yunai/Java/yudao-all-in-vben/yudao-ui-admin-vben/output/playwright/im-full-2026-06-17T16-39-23-356Z/chat-01-vben-before.png",
+ "chat-01-vue3-before": "/Users/yunai/Java/yudao-all-in-vben/yudao-ui-admin-vben/output/playwright/im-full-2026-06-17T16-39-23-356Z/chat-01-vue3-before.png",
+ "chat-02-vue3-after-two-way": "/Users/yunai/Java/yudao-all-in-vben/yudao-ui-admin-vben/output/playwright/im-full-2026-06-17T16-39-23-356Z/chat-02-vue3-after-two-way.png",
+ "chat-02-vben-after-two-way": "/Users/yunai/Java/yudao-all-in-vben/yudao-ui-admin-vben/output/playwright/im-full-2026-06-17T16-39-23-356Z/chat-02-vben-after-two-way.png",
+ "chat-03-vben-message-context-menu": "/Users/yunai/Java/yudao-all-in-vben/yudao-ui-admin-vben/output/playwright/im-full-2026-06-17T16-39-23-356Z/chat-03-vben-message-context-menu.png",
+ "chat-04-vben-contact": "/Users/yunai/Java/yudao-all-in-vben/yudao-ui-admin-vben/output/playwright/im-full-2026-06-17T16-39-23-356Z/chat-04-vben-contact.png",
+ "chat-04-vue3-contact": "/Users/yunai/Java/yudao-all-in-vben/yudao-ui-admin-vben/output/playwright/im-full-2026-06-17T16-39-23-356Z/chat-04-vue3-contact.png",
+ "chat-05-vben-contact-search": "/Users/yunai/Java/yudao-all-in-vben/yudao-ui-admin-vben/output/playwright/im-full-2026-06-17T16-39-23-356Z/chat-05-vben-contact-search.png",
+ "manager-route-im-statistics": "/Users/yunai/Java/yudao-all-in-vben/yudao-ui-admin-vben/output/playwright/im-full-2026-06-17T16-39-23-356Z/manager-route-im-statistics.png",
+ "manager-route-im-channel-list": "/Users/yunai/Java/yudao-all-in-vben/yudao-ui-admin-vben/output/playwright/im-full-2026-06-17T16-39-23-356Z/manager-route-im-channel-list.png",
+ "manager-route-im-channel-material": "/Users/yunai/Java/yudao-all-in-vben/yudao-ui-admin-vben/output/playwright/im-full-2026-06-17T16-39-23-356Z/manager-route-im-channel-material.png",
+ "manager-route-im-channel-message": "/Users/yunai/Java/yudao-all-in-vben/yudao-ui-admin-vben/output/playwright/im-full-2026-06-17T16-39-23-356Z/manager-route-im-channel-message.png",
+ "manager-route-im-face-pack": "/Users/yunai/Java/yudao-all-in-vben/yudao-ui-admin-vben/output/playwright/im-full-2026-06-17T16-39-23-356Z/manager-route-im-face-pack.png",
+ "manager-route-im-face-user-item": "/Users/yunai/Java/yudao-all-in-vben/yudao-ui-admin-vben/output/playwright/im-full-2026-06-17T16-39-23-356Z/manager-route-im-face-user-item.png",
+ "manager-route-im-private-friend": "/Users/yunai/Java/yudao-all-in-vben/yudao-ui-admin-vben/output/playwright/im-full-2026-06-17T16-39-23-356Z/manager-route-im-private-friend.png",
+ "manager-route-im-private-friend-request": "/Users/yunai/Java/yudao-all-in-vben/yudao-ui-admin-vben/output/playwright/im-full-2026-06-17T16-39-23-356Z/manager-route-im-private-friend-request.png",
+ "manager-route-im-group-list": "/Users/yunai/Java/yudao-all-in-vben/yudao-ui-admin-vben/output/playwright/im-full-2026-06-17T16-39-23-356Z/manager-route-im-group-list.png",
+ "manager-route-im-group-request": "/Users/yunai/Java/yudao-all-in-vben/yudao-ui-admin-vben/output/playwright/im-full-2026-06-17T16-39-23-356Z/manager-route-im-group-request.png",
+ "manager-route-im-private-message": "/Users/yunai/Java/yudao-all-in-vben/yudao-ui-admin-vben/output/playwright/im-full-2026-06-17T16-39-23-356Z/manager-route-im-private-message.png",
+ "manager-route-im-group-message": "/Users/yunai/Java/yudao-all-in-vben/yudao-ui-admin-vben/output/playwright/im-full-2026-06-17T16-39-23-356Z/manager-route-im-group-message.png",
+ "manager-route-im-rtc": "/Users/yunai/Java/yudao-all-in-vben/yudao-ui-admin-vben/output/playwright/im-full-2026-06-17T16-39-23-356Z/manager-route-im-rtc.png",
+ "manager-route-im-sensitive-word": "/Users/yunai/Java/yudao-all-in-vben/yudao-ui-admin-vben/output/playwright/im-full-2026-06-17T16-39-23-356Z/manager-route-im-sensitive-word.png",
+ "manager-channel-add-form": "/Users/yunai/Java/yudao-all-in-vben/yudao-ui-admin-vben/output/playwright/im-full-2026-06-17T16-39-23-356Z/manager-channel-add-form.png",
+ "manager-material-add-form": "/Users/yunai/Java/yudao-all-in-vben/yudao-ui-admin-vben/output/playwright/im-full-2026-06-17T16-39-23-356Z/manager-material-add-form.png",
+ "manager-channel-message-send-form": "/Users/yunai/Java/yudao-all-in-vben/yudao-ui-admin-vben/output/playwright/im-full-2026-06-17T16-39-23-356Z/manager-channel-message-send-form.png",
+ "manager-channel-message-user-multi-select": "/Users/yunai/Java/yudao-all-in-vben/yudao-ui-admin-vben/output/playwright/im-full-2026-06-17T16-39-23-356Z/manager-channel-message-user-multi-select.png",
+ "manager-face-pack-add-form": "/Users/yunai/Java/yudao-all-in-vben/yudao-ui-admin-vben/output/playwright/im-full-2026-06-17T16-39-23-356Z/manager-face-pack-add-form.png"
+ },
+ "pages": {
+ "vbenChatAfterLogin": "http://127.0.0.1:5666/analytics",
+ "vue3AfterLogin": "http://127.0.0.1/index",
+ "vbenManagerAfterLogin": "http://127.0.0.1:5666/analytics",
+ "vueFinal": "http://127.0.0.1/im/home/contact",
+ "vbenChatFinal": "http://127.0.0.1:5666/im/home/contact",
+ "vbenManagerFinal": "http://127.0.0.1:5666/im/face/pack"
+ },
+ "error": "locator.click: Timeout 10000ms exceeded.\nCall log:\n\u001b[2m - waiting for locator('button, a').filter({ hasText: '管理表情' }).first()\u001b[22m\n\u001b[2m - locator resolved to \u001b[22m\n\u001b[2m - attempting click action\u001b[22m\n\u001b[2m 2 × waiting for element to be visible, enabled and stable\u001b[22m\n\u001b[2m - element is visible, enabled and stable\u001b[22m\n\u001b[2m - scrolling into view if needed\u001b[22m\n\u001b[2m - done scrolling\u001b[22m\n\u001b[2m - intercepts pointer events\u001b[22m\n\u001b[2m - retrying click action\u001b[22m\n\u001b[2m - waiting 20ms\u001b[22m\n\u001b[2m 2 × waiting for element to be visible, enabled and stable\u001b[22m\n\u001b[2m - element is visible, enabled and stable\u001b[22m\n\u001b[2m - scrolling into view if needed\u001b[22m\n\u001b[2m - done scrolling\u001b[22m\n\u001b[2m - intercepts pointer events\u001b[22m\n\u001b[2m - retrying click action\u001b[22m\n\u001b[2m - waiting 100ms\u001b[22m\n\u001b[2m 19 × waiting for element to be visible, enabled and stable\u001b[22m\n\u001b[2m - element is visible, enabled and stable\u001b[22m\n\u001b[2m - scrolling into view if needed\u001b[22m\n\u001b[2m - done scrolling\u001b[22m\n\u001b[2m - intercepts pointer events\u001b[22m\n\u001b[2m - retrying click action\u001b[22m\n\u001b[2m - waiting 500ms\u001b[22m\n\n at clickVisible (/Users/yunai/Java/yudao-all-in-vben/yudao-ui-admin-vben/[eval1]:68:18)\n at async openFirstRowAction (/Users/yunai/Java/yudao-all-in-vben/yudao-ui-admin-vben/[eval1]:145:14)\n at async testManager (/Users/yunai/Java/yudao-all-in-vben/yudao-ui-admin-vben/[eval1]:288:7)\n at async file:///Users/yunai/Java/yudao-all-in-vben/yudao-ui-admin-vben/[eval1]:357:3"
+}
\ No newline at end of file
diff --git a/output/playwright/im-full-chat-extra-2026-06-17T16-50-19-585Z/conversation-open.png b/output/playwright/im-full-chat-extra-2026-06-17T16-50-19-585Z/conversation-open.png
new file mode 100644
index 000000000..83a81c8e6
Binary files /dev/null and b/output/playwright/im-full-chat-extra-2026-06-17T16-50-19-585Z/conversation-open.png differ
diff --git a/output/playwright/im-full-chat-extra-2026-06-17T16-50-19-585Z/emoji-panel.png b/output/playwright/im-full-chat-extra-2026-06-17T16-50-19-585Z/emoji-panel.png
new file mode 100644
index 000000000..f1394306c
Binary files /dev/null and b/output/playwright/im-full-chat-extra-2026-06-17T16-50-19-585Z/emoji-panel.png differ
diff --git a/output/playwright/im-full-chat-extra-2026-06-17T16-50-19-585Z/forward-dialog.png b/output/playwright/im-full-chat-extra-2026-06-17T16-50-19-585Z/forward-dialog.png
new file mode 100644
index 000000000..6796d8d53
Binary files /dev/null and b/output/playwright/im-full-chat-extra-2026-06-17T16-50-19-585Z/forward-dialog.png differ
diff --git a/output/playwright/im-full-chat-extra-2026-06-17T16-50-19-585Z/friend-add-dialog.png b/output/playwright/im-full-chat-extra-2026-06-17T16-50-19-585Z/friend-add-dialog.png
new file mode 100644
index 000000000..ad87b0418
Binary files /dev/null and b/output/playwright/im-full-chat-extra-2026-06-17T16-50-19-585Z/friend-add-dialog.png differ
diff --git a/output/playwright/im-full-chat-extra-2026-06-17T16-50-19-585Z/group-create-dialog.png b/output/playwright/im-full-chat-extra-2026-06-17T16-50-19-585Z/group-create-dialog.png
new file mode 100644
index 000000000..eebdd3fe3
Binary files /dev/null and b/output/playwright/im-full-chat-extra-2026-06-17T16-50-19-585Z/group-create-dialog.png differ
diff --git a/output/playwright/im-full-chat-extra-2026-06-17T16-50-19-585Z/group-side-info.png b/output/playwright/im-full-chat-extra-2026-06-17T16-50-19-585Z/group-side-info.png
new file mode 100644
index 000000000..c1f3a74e8
Binary files /dev/null and b/output/playwright/im-full-chat-extra-2026-06-17T16-50-19-585Z/group-side-info.png differ
diff --git a/output/playwright/im-full-chat-extra-2026-06-17T16-50-19-585Z/message-context-menu-extra.png b/output/playwright/im-full-chat-extra-2026-06-17T16-50-19-585Z/message-context-menu-extra.png
new file mode 100644
index 000000000..d96438df3
Binary files /dev/null and b/output/playwright/im-full-chat-extra-2026-06-17T16-50-19-585Z/message-context-menu-extra.png differ
diff --git a/output/playwright/im-full-chat-extra-2026-06-17T16-50-19-585Z/message-history-drawer.png b/output/playwright/im-full-chat-extra-2026-06-17T16-50-19-585Z/message-history-drawer.png
new file mode 100644
index 000000000..598b7ea49
Binary files /dev/null and b/output/playwright/im-full-chat-extra-2026-06-17T16-50-19-585Z/message-history-drawer.png differ
diff --git a/output/playwright/im-full-chat-extra-2026-06-17T16-50-19-585Z/multi-select-bar.png b/output/playwright/im-full-chat-extra-2026-06-17T16-50-19-585Z/multi-select-bar.png
new file mode 100644
index 000000000..22f162572
Binary files /dev/null and b/output/playwright/im-full-chat-extra-2026-06-17T16-50-19-585Z/multi-select-bar.png differ
diff --git a/output/playwright/im-full-chat-extra-2026-06-17T16-50-19-585Z/private-side-info.png b/output/playwright/im-full-chat-extra-2026-06-17T16-50-19-585Z/private-side-info.png
new file mode 100644
index 000000000..73ca612ae
Binary files /dev/null and b/output/playwright/im-full-chat-extra-2026-06-17T16-50-19-585Z/private-side-info.png differ
diff --git a/output/playwright/im-full-chat-extra-2026-06-17T16-50-19-585Z/quote-preview.png b/output/playwright/im-full-chat-extra-2026-06-17T16-50-19-585Z/quote-preview.png
new file mode 100644
index 000000000..fb786041d
Binary files /dev/null and b/output/playwright/im-full-chat-extra-2026-06-17T16-50-19-585Z/quote-preview.png differ
diff --git a/output/playwright/im-full-chat-extra-2026-06-17T16-50-19-585Z/result.json b/output/playwright/im-full-chat-extra-2026-06-17T16-50-19-585Z/result.json
new file mode 100644
index 000000000..b89817d72
--- /dev/null
+++ b/output/playwright/im-full-chat-extra-2026-06-17T16-50-19-585Z/result.json
@@ -0,0 +1,75 @@
+{
+ "outDir": "/Users/yunai/Java/yudao-all-in-vben/yudao-ui-admin-vben/output/playwright/im-full-chat-extra-2026-06-17T16-50-19-585Z",
+ "checks": [
+ {
+ "name": "C-203 表情面板",
+ "status": "passed",
+ "faceCount": 17
+ },
+ {
+ "name": "C-208 语音面板",
+ "status": "passed"
+ },
+ {
+ "name": "C-202 Shift+Enter 换行",
+ "status": "passed",
+ "editorText": "line1\nline2"
+ },
+ {
+ "name": "C-302 引用消息",
+ "status": "weak",
+ "replyCount": 0
+ },
+ {
+ "name": "C-303 转发消息",
+ "status": "passed"
+ },
+ {
+ "name": "C-304 多选消息",
+ "status": "passed"
+ },
+ {
+ "name": "C-404 添加好友弹窗",
+ "status": "passed"
+ },
+ {
+ "name": "C-411 建群弹窗",
+ "status": "weak"
+ },
+ {
+ "name": "C-403 好友详情/聊天信息",
+ "status": "passed"
+ },
+ {
+ "name": "C-410 群详情侧栏",
+ "status": "passed"
+ },
+ {
+ "name": "C-108 消息历史抽屉",
+ "status": "weak"
+ },
+ {
+ "name": "C-501/C-502 私聊通话入口",
+ "status": "passed"
+ }
+ ],
+ "events": [],
+ "ignoredEvents": 24,
+ "badResponses": [],
+ "screenshots": {
+ "conversation-open": "/Users/yunai/Java/yudao-all-in-vben/yudao-ui-admin-vben/output/playwright/im-full-chat-extra-2026-06-17T16-50-19-585Z/conversation-open.png",
+ "emoji-panel": "/Users/yunai/Java/yudao-all-in-vben/yudao-ui-admin-vben/output/playwright/im-full-chat-extra-2026-06-17T16-50-19-585Z/emoji-panel.png",
+ "voice-panel": "/Users/yunai/Java/yudao-all-in-vben/yudao-ui-admin-vben/output/playwright/im-full-chat-extra-2026-06-17T16-50-19-585Z/voice-panel.png",
+ "shift-enter-newline": "/Users/yunai/Java/yudao-all-in-vben/yudao-ui-admin-vben/output/playwright/im-full-chat-extra-2026-06-17T16-50-19-585Z/shift-enter-newline.png",
+ "message-context-menu-extra": "/Users/yunai/Java/yudao-all-in-vben/yudao-ui-admin-vben/output/playwright/im-full-chat-extra-2026-06-17T16-50-19-585Z/message-context-menu-extra.png",
+ "quote-preview": "/Users/yunai/Java/yudao-all-in-vben/yudao-ui-admin-vben/output/playwright/im-full-chat-extra-2026-06-17T16-50-19-585Z/quote-preview.png",
+ "forward-dialog": "/Users/yunai/Java/yudao-all-in-vben/yudao-ui-admin-vben/output/playwright/im-full-chat-extra-2026-06-17T16-50-19-585Z/forward-dialog.png",
+ "multi-select-bar": "/Users/yunai/Java/yudao-all-in-vben/yudao-ui-admin-vben/output/playwright/im-full-chat-extra-2026-06-17T16-50-19-585Z/multi-select-bar.png",
+ "friend-add-dialog": "/Users/yunai/Java/yudao-all-in-vben/yudao-ui-admin-vben/output/playwright/im-full-chat-extra-2026-06-17T16-50-19-585Z/friend-add-dialog.png",
+ "group-create-dialog": "/Users/yunai/Java/yudao-all-in-vben/yudao-ui-admin-vben/output/playwright/im-full-chat-extra-2026-06-17T16-50-19-585Z/group-create-dialog.png",
+ "private-side-info": "/Users/yunai/Java/yudao-all-in-vben/yudao-ui-admin-vben/output/playwright/im-full-chat-extra-2026-06-17T16-50-19-585Z/private-side-info.png",
+ "group-side-info": "/Users/yunai/Java/yudao-all-in-vben/yudao-ui-admin-vben/output/playwright/im-full-chat-extra-2026-06-17T16-50-19-585Z/group-side-info.png",
+ "message-history-drawer": "/Users/yunai/Java/yudao-all-in-vben/yudao-ui-admin-vben/output/playwright/im-full-chat-extra-2026-06-17T16-50-19-585Z/message-history-drawer.png",
+ "rtc-call-popover": "/Users/yunai/Java/yudao-all-in-vben/yudao-ui-admin-vben/output/playwright/im-full-chat-extra-2026-06-17T16-50-19-585Z/rtc-call-popover.png"
+ }
+}
\ No newline at end of file
diff --git a/output/playwright/im-full-chat-extra-2026-06-17T16-50-19-585Z/rtc-call-popover.png b/output/playwright/im-full-chat-extra-2026-06-17T16-50-19-585Z/rtc-call-popover.png
new file mode 100644
index 000000000..733bde1b5
Binary files /dev/null and b/output/playwright/im-full-chat-extra-2026-06-17T16-50-19-585Z/rtc-call-popover.png differ
diff --git a/output/playwright/im-full-chat-extra-2026-06-17T16-50-19-585Z/shift-enter-newline.png b/output/playwright/im-full-chat-extra-2026-06-17T16-50-19-585Z/shift-enter-newline.png
new file mode 100644
index 000000000..974dcd3b0
Binary files /dev/null and b/output/playwright/im-full-chat-extra-2026-06-17T16-50-19-585Z/shift-enter-newline.png differ
diff --git a/output/playwright/im-full-chat-extra-2026-06-17T16-50-19-585Z/voice-panel.png b/output/playwright/im-full-chat-extra-2026-06-17T16-50-19-585Z/voice-panel.png
new file mode 100644
index 000000000..88e85eb97
Binary files /dev/null and b/output/playwright/im-full-chat-extra-2026-06-17T16-50-19-585Z/voice-panel.png differ
diff --git a/output/playwright/im-full-chat-gap-2026-06-17T16-58-44-542Z/failure.png b/output/playwright/im-full-chat-gap-2026-06-17T16-58-44-542Z/failure.png
new file mode 100644
index 000000000..578f586e6
Binary files /dev/null and b/output/playwright/im-full-chat-gap-2026-06-17T16-58-44-542Z/failure.png differ
diff --git a/output/playwright/im-full-chat-gap-2026-06-17T16-58-44-542Z/result.json b/output/playwright/im-full-chat-gap-2026-06-17T16-58-44-542Z/result.json
new file mode 100644
index 000000000..d7c92f86f
--- /dev/null
+++ b/output/playwright/im-full-chat-gap-2026-06-17T16-58-44-542Z/result.json
@@ -0,0 +1,11 @@
+{
+ "ok": false,
+ "outDir": "/Users/yunai/Java/yudao-all-in-vben/yudao-ui-admin-vben/output/playwright/im-full-chat-gap-2026-06-17T16-58-44-542Z",
+ "checks": [],
+ "events": [],
+ "badResponses": [],
+ "screenshots": {
+ "failure": "/Users/yunai/Java/yudao-all-in-vben/yudao-ui-admin-vben/output/playwright/im-full-chat-gap-2026-06-17T16-58-44-542Z/failure.png"
+ },
+ "error": "page.waitForURL: Timeout 30000ms exceeded.\n=========================== logs ===========================\nwaiting for navigation until \"load\"\n navigated to \"http://127.0.0.1:5666/login\"\n============================================================\n at loginVben (/Users/yunai/Java/yudao-all-in-vben/yudao-ui-admin-vben/[eval1]:44:14)\n at async file:///Users/yunai/Java/yudao-all-in-vben/yudao-ui-admin-vben/[eval1]:121:3"
+}
\ No newline at end of file
diff --git a/output/playwright/im-full-chat-gap-2026-06-17T17-01-10-176Z/blocked.exe b/output/playwright/im-full-chat-gap-2026-06-17T17-01-10-176Z/blocked.exe
new file mode 100644
index 000000000..2995a4d0e
--- /dev/null
+++ b/output/playwright/im-full-chat-gap-2026-06-17T17-01-10-176Z/blocked.exe
@@ -0,0 +1 @@
+dummy
\ No newline at end of file
diff --git a/output/playwright/im-full-chat-gap-2026-06-17T17-01-10-176Z/conversation-ready.png b/output/playwright/im-full-chat-gap-2026-06-17T17-01-10-176Z/conversation-ready.png
new file mode 100644
index 000000000..f8728c6bd
Binary files /dev/null and b/output/playwright/im-full-chat-gap-2026-06-17T17-01-10-176Z/conversation-ready.png differ
diff --git a/output/playwright/im-full-chat-gap-2026-06-17T17-01-10-176Z/face-sticker-after.png b/output/playwright/im-full-chat-gap-2026-06-17T17-01-10-176Z/face-sticker-after.png
new file mode 100644
index 000000000..1145fc819
Binary files /dev/null and b/output/playwright/im-full-chat-gap-2026-06-17T17-01-10-176Z/face-sticker-after.png differ
diff --git a/output/playwright/im-full-chat-gap-2026-06-17T17-01-10-176Z/group-side-operation-entries.png b/output/playwright/im-full-chat-gap-2026-06-17T17-01-10-176Z/group-side-operation-entries.png
new file mode 100644
index 000000000..9df60c541
Binary files /dev/null and b/output/playwright/im-full-chat-gap-2026-06-17T17-01-10-176Z/group-side-operation-entries.png differ
diff --git a/output/playwright/im-full-chat-gap-2026-06-17T17-01-10-176Z/history-drawer-gap.png b/output/playwright/im-full-chat-gap-2026-06-17T17-01-10-176Z/history-drawer-gap.png
new file mode 100644
index 000000000..2f106c929
Binary files /dev/null and b/output/playwright/im-full-chat-gap-2026-06-17T17-01-10-176Z/history-drawer-gap.png differ
diff --git a/output/playwright/im-full-chat-gap-2026-06-17T17-01-10-176Z/message-menu-recall-delete-copy.png b/output/playwright/im-full-chat-gap-2026-06-17T17-01-10-176Z/message-menu-recall-delete-copy.png
new file mode 100644
index 000000000..14a0f38f6
Binary files /dev/null and b/output/playwright/im-full-chat-gap-2026-06-17T17-01-10-176Z/message-menu-recall-delete-copy.png differ
diff --git a/output/playwright/im-full-chat-gap-2026-06-17T17-01-10-176Z/private-settings-entries.png b/output/playwright/im-full-chat-gap-2026-06-17T17-01-10-176Z/private-settings-entries.png
new file mode 100644
index 000000000..adedd364d
Binary files /dev/null and b/output/playwright/im-full-chat-gap-2026-06-17T17-01-10-176Z/private-settings-entries.png differ
diff --git a/output/playwright/im-full-chat-gap-2026-06-17T17-01-10-176Z/reply-preview-gap.png b/output/playwright/im-full-chat-gap-2026-06-17T17-01-10-176Z/reply-preview-gap.png
new file mode 100644
index 000000000..eef070907
Binary files /dev/null and b/output/playwright/im-full-chat-gap-2026-06-17T17-01-10-176Z/reply-preview-gap.png differ
diff --git a/output/playwright/im-full-chat-gap-2026-06-17T17-01-10-176Z/result.json b/output/playwright/im-full-chat-gap-2026-06-17T17-01-10-176Z/result.json
new file mode 100644
index 000000000..ed5f577cd
--- /dev/null
+++ b/output/playwright/im-full-chat-gap-2026-06-17T17-01-10-176Z/result.json
@@ -0,0 +1,108 @@
+{
+ "ok": true,
+ "outDir": "/Users/yunai/Java/yudao-all-in-vben/yudao-ui-admin-vben/output/playwright/im-full-chat-gap-2026-06-17T17-01-10-176Z",
+ "checks": [
+ {
+ "name": "C-201 文本发送基线",
+ "status": "passed",
+ "text": "Gap text 1781715683208"
+ },
+ {
+ "name": "C-204 发送 Unicode 表情",
+ "status": "skipped",
+ "reason": "未定位到 emoji 按钮"
+ },
+ {
+ "name": "C-204 发送贴图表情",
+ "status": "weak"
+ },
+ {
+ "name": "C-205 图片上传入口",
+ "status": "skipped"
+ },
+ {
+ "name": "C-206 文件上传入口",
+ "status": "skipped"
+ },
+ {
+ "name": "C-207 视频上传入口",
+ "status": "skipped"
+ },
+ {
+ "name": "C-209 危险文件限制",
+ "status": "passed",
+ "badResponseDelta": 0
+ },
+ {
+ "name": "C-302 引用消息预览",
+ "status": "weak"
+ },
+ {
+ "name": "C-306 撤回入口",
+ "status": "passed"
+ },
+ {
+ "name": "C-307 删除本地消息入口",
+ "status": "weak"
+ },
+ {
+ "name": "C-310 复制入口",
+ "status": "weak"
+ },
+ {
+ "name": "C-406 好友免打扰入口",
+ "status": "weak"
+ },
+ {
+ "name": "C-407 好友置顶入口",
+ "status": "weak"
+ },
+ {
+ "name": "C-408 拉黑/删除入口",
+ "status": "weak"
+ },
+ {
+ "name": "C-412 邀请群成员入口",
+ "status": "weak"
+ },
+ {
+ "name": "C-413 移除群成员入口",
+ "status": "weak"
+ },
+ {
+ "name": "C-414 设置管理员入口",
+ "status": "weak"
+ },
+ {
+ "name": "C-415 转让群主入口",
+ "status": "weak"
+ },
+ {
+ "name": "C-416 禁言成员入口",
+ "status": "weak"
+ },
+ {
+ "name": "C-417 加群申请入口",
+ "status": "weak"
+ },
+ {
+ "name": "C-503 群通话入口",
+ "status": "weak"
+ },
+ {
+ "name": "C-108 消息历史抽屉补强",
+ "status": "passed"
+ }
+ ],
+ "events": [],
+ "badResponses": [],
+ "screenshots": {
+ "conversation-ready": "/Users/yunai/Java/yudao-all-in-vben/yudao-ui-admin-vben/output/playwright/im-full-chat-gap-2026-06-17T17-01-10-176Z/conversation-ready.png",
+ "face-sticker-after": "/Users/yunai/Java/yudao-all-in-vben/yudao-ui-admin-vben/output/playwright/im-full-chat-gap-2026-06-17T17-01-10-176Z/face-sticker-after.png",
+ "reply-preview-gap": "/Users/yunai/Java/yudao-all-in-vben/yudao-ui-admin-vben/output/playwright/im-full-chat-gap-2026-06-17T17-01-10-176Z/reply-preview-gap.png",
+ "message-menu-recall-delete-copy": "/Users/yunai/Java/yudao-all-in-vben/yudao-ui-admin-vben/output/playwright/im-full-chat-gap-2026-06-17T17-01-10-176Z/message-menu-recall-delete-copy.png",
+ "private-settings-entries": "/Users/yunai/Java/yudao-all-in-vben/yudao-ui-admin-vben/output/playwright/im-full-chat-gap-2026-06-17T17-01-10-176Z/private-settings-entries.png",
+ "group-side-operation-entries": "/Users/yunai/Java/yudao-all-in-vben/yudao-ui-admin-vben/output/playwright/im-full-chat-gap-2026-06-17T17-01-10-176Z/group-side-operation-entries.png",
+ "history-drawer-gap": "/Users/yunai/Java/yudao-all-in-vben/yudao-ui-admin-vben/output/playwright/im-full-chat-gap-2026-06-17T17-01-10-176Z/history-drawer-gap.png"
+ }
+}
\ No newline at end of file
diff --git a/output/playwright/im-full-chat-toolbar-2026-06-17T17-03-09-169Z/emoji-dom-send.png b/output/playwright/im-full-chat-toolbar-2026-06-17T17-03-09-169Z/emoji-dom-send.png
new file mode 100644
index 000000000..9529e690e
Binary files /dev/null and b/output/playwright/im-full-chat-toolbar-2026-06-17T17-03-09-169Z/emoji-dom-send.png differ
diff --git a/output/playwright/im-full-chat-toolbar-2026-06-17T17-03-09-169Z/menu-dom-entries.png b/output/playwright/im-full-chat-toolbar-2026-06-17T17-03-09-169Z/menu-dom-entries.png
new file mode 100644
index 000000000..1c56b4b92
Binary files /dev/null and b/output/playwright/im-full-chat-toolbar-2026-06-17T17-03-09-169Z/menu-dom-entries.png differ
diff --git a/output/playwright/im-full-chat-toolbar-2026-06-17T17-03-09-169Z/result.json b/output/playwright/im-full-chat-toolbar-2026-06-17T17-03-09-169Z/result.json
new file mode 100644
index 000000000..3faefc6ae
--- /dev/null
+++ b/output/playwright/im-full-chat-toolbar-2026-06-17T17-03-09-169Z/result.json
@@ -0,0 +1,56 @@
+{
+ "ok": false,
+ "outDir": "/Users/yunai/Java/yudao-all-in-vben/yudao-ui-admin-vben/output/playwright/im-full-chat-toolbar-2026-06-17T17-03-09-169Z",
+ "checks": [
+ {
+ "name": "C-203 表情面板 DOM 顺序定位",
+ "status": "passed",
+ "emojiButtonCount": 136
+ },
+ {
+ "name": "C-204 Unicode 表情插入/发送",
+ "status": "passed",
+ "editorText": "😀"
+ },
+ {
+ "name": "C-205 图片上传入口",
+ "status": "passed"
+ },
+ {
+ "name": "C-206 文件上传入口",
+ "status": "passed"
+ },
+ {
+ "name": "C-207 视频上传入口",
+ "status": "passed"
+ },
+ {
+ "name": "C-208 语音面板 DOM 顺序定位",
+ "status": "passed"
+ },
+ {
+ "name": "C-302 引用入口菜单",
+ "status": "failed"
+ },
+ {
+ "name": "C-306 撤回入口菜单",
+ "status": "passed"
+ },
+ {
+ "name": "C-307 删除入口菜单",
+ "status": "passed"
+ },
+ {
+ "name": "C-310 复制入口菜单",
+ "status": "passed"
+ }
+ ],
+ "events": [],
+ "badResponses": [],
+ "screenshots": {
+ "toolbar-ready": "/Users/yunai/Java/yudao-all-in-vben/yudao-ui-admin-vben/output/playwright/im-full-chat-toolbar-2026-06-17T17-03-09-169Z/toolbar-ready.png",
+ "emoji-dom-send": "/Users/yunai/Java/yudao-all-in-vben/yudao-ui-admin-vben/output/playwright/im-full-chat-toolbar-2026-06-17T17-03-09-169Z/emoji-dom-send.png",
+ "voice-dom-panel": "/Users/yunai/Java/yudao-all-in-vben/yudao-ui-admin-vben/output/playwright/im-full-chat-toolbar-2026-06-17T17-03-09-169Z/voice-dom-panel.png",
+ "menu-dom-entries": "/Users/yunai/Java/yudao-all-in-vben/yudao-ui-admin-vben/output/playwright/im-full-chat-toolbar-2026-06-17T17-03-09-169Z/menu-dom-entries.png"
+ }
+}
\ No newline at end of file
diff --git a/output/playwright/im-full-chat-toolbar-2026-06-17T17-03-09-169Z/toolbar-ready.png b/output/playwright/im-full-chat-toolbar-2026-06-17T17-03-09-169Z/toolbar-ready.png
new file mode 100644
index 000000000..a664239ed
Binary files /dev/null and b/output/playwright/im-full-chat-toolbar-2026-06-17T17-03-09-169Z/toolbar-ready.png differ
diff --git a/output/playwright/im-full-chat-toolbar-2026-06-17T17-03-09-169Z/voice-dom-panel.png b/output/playwright/im-full-chat-toolbar-2026-06-17T17-03-09-169Z/voice-dom-panel.png
new file mode 100644
index 000000000..3b896acd6
Binary files /dev/null and b/output/playwright/im-full-chat-toolbar-2026-06-17T17-03-09-169Z/voice-dom-panel.png differ
diff --git a/output/playwright/im-full-manager-retry-2026-06-17T16-42-45-907Z/delete-confirm-entry.png b/output/playwright/im-full-manager-retry-2026-06-17T16-42-45-907Z/delete-confirm-entry.png
new file mode 100644
index 000000000..465146248
Binary files /dev/null and b/output/playwright/im-full-manager-retry-2026-06-17T16-42-45-907Z/delete-confirm-entry.png differ
diff --git a/output/playwright/im-full-manager-retry-2026-06-17T16-42-45-907Z/face-item-add-form.png b/output/playwright/im-full-manager-retry-2026-06-17T16-42-45-907Z/face-item-add-form.png
new file mode 100644
index 000000000..0f3f3f7d2
Binary files /dev/null and b/output/playwright/im-full-manager-retry-2026-06-17T16-42-45-907Z/face-item-add-form.png differ
diff --git a/output/playwright/im-full-manager-retry-2026-06-17T16-42-45-907Z/face-item-drawer.png b/output/playwright/im-full-manager-retry-2026-06-17T16-42-45-907Z/face-item-drawer.png
new file mode 100644
index 000000000..b300a32ce
Binary files /dev/null and b/output/playwright/im-full-manager-retry-2026-06-17T16-42-45-907Z/face-item-drawer.png differ
diff --git a/output/playwright/im-full-manager-retry-2026-06-17T16-42-45-907Z/group-ban-or-unban-entry.png b/output/playwright/im-full-manager-retry-2026-06-17T16-42-45-907Z/group-ban-or-unban-entry.png
new file mode 100644
index 000000000..0d37b106b
Binary files /dev/null and b/output/playwright/im-full-manager-retry-2026-06-17T16-42-45-907Z/group-ban-or-unban-entry.png differ
diff --git a/output/playwright/im-full-manager-retry-2026-06-17T16-42-45-907Z/group-detail.png b/output/playwright/im-full-manager-retry-2026-06-17T16-42-45-907Z/group-detail.png
new file mode 100644
index 000000000..3bfb9aeca
Binary files /dev/null and b/output/playwright/im-full-manager-retry-2026-06-17T16-42-45-907Z/group-detail.png differ
diff --git a/output/playwright/im-full-manager-retry-2026-06-17T16-42-45-907Z/group-message-detail.png b/output/playwright/im-full-manager-retry-2026-06-17T16-42-45-907Z/group-message-detail.png
new file mode 100644
index 000000000..bc0d7425d
Binary files /dev/null and b/output/playwright/im-full-manager-retry-2026-06-17T16-42-45-907Z/group-message-detail.png differ
diff --git a/output/playwright/im-full-manager-retry-2026-06-17T16-42-45-907Z/private-message-detail.png b/output/playwright/im-full-manager-retry-2026-06-17T16-42-45-907Z/private-message-detail.png
new file mode 100644
index 000000000..b61ff5195
Binary files /dev/null and b/output/playwright/im-full-manager-retry-2026-06-17T16-42-45-907Z/private-message-detail.png differ
diff --git a/output/playwright/im-full-manager-retry-2026-06-17T16-42-45-907Z/result.json b/output/playwright/im-full-manager-retry-2026-06-17T16-42-45-907Z/result.json
new file mode 100644
index 000000000..8369c780e
--- /dev/null
+++ b/output/playwright/im-full-manager-retry-2026-06-17T16-42-45-907Z/result.json
@@ -0,0 +1,55 @@
+{
+ "outDir": "/Users/yunai/Java/yudao-all-in-vben/yudao-ui-admin-vben/output/playwright/im-full-manager-retry-2026-06-17T16-42-45-907Z",
+ "checks": [
+ {
+ "name": "M-205 表情项抽屉",
+ "status": "passed"
+ },
+ {
+ "name": "M-206 新增表情弹窗",
+ "status": "passed"
+ },
+ {
+ "name": "M-207 群详情抽屉",
+ "status": "passed"
+ },
+ {
+ "name": "M-208 群封禁/解封入口",
+ "status": "passed"
+ },
+ {
+ "name": "M-209 私聊消息详情",
+ "status": "passed"
+ },
+ {
+ "name": "M-210 群聊消息详情",
+ "status": "passed"
+ },
+ {
+ "name": "M-211 RTC 详情",
+ "status": "passed"
+ },
+ {
+ "name": "M-212 新增敏感词弹窗",
+ "status": "passed"
+ },
+ {
+ "name": "M-301 删除二次确认入口",
+ "status": "passed"
+ }
+ ],
+ "events": [],
+ "ignoredEvents": 30,
+ "badResponses": [],
+ "screenshots": {
+ "face-item-drawer": "/Users/yunai/Java/yudao-all-in-vben/yudao-ui-admin-vben/output/playwright/im-full-manager-retry-2026-06-17T16-42-45-907Z/face-item-drawer.png",
+ "face-item-add-form": "/Users/yunai/Java/yudao-all-in-vben/yudao-ui-admin-vben/output/playwright/im-full-manager-retry-2026-06-17T16-42-45-907Z/face-item-add-form.png",
+ "group-detail": "/Users/yunai/Java/yudao-all-in-vben/yudao-ui-admin-vben/output/playwright/im-full-manager-retry-2026-06-17T16-42-45-907Z/group-detail.png",
+ "group-ban-or-unban-entry": "/Users/yunai/Java/yudao-all-in-vben/yudao-ui-admin-vben/output/playwright/im-full-manager-retry-2026-06-17T16-42-45-907Z/group-ban-or-unban-entry.png",
+ "private-message-detail": "/Users/yunai/Java/yudao-all-in-vben/yudao-ui-admin-vben/output/playwright/im-full-manager-retry-2026-06-17T16-42-45-907Z/private-message-detail.png",
+ "group-message-detail": "/Users/yunai/Java/yudao-all-in-vben/yudao-ui-admin-vben/output/playwright/im-full-manager-retry-2026-06-17T16-42-45-907Z/group-message-detail.png",
+ "rtc-detail": "/Users/yunai/Java/yudao-all-in-vben/yudao-ui-admin-vben/output/playwright/im-full-manager-retry-2026-06-17T16-42-45-907Z/rtc-detail.png",
+ "sensitive-word-add-form": "/Users/yunai/Java/yudao-all-in-vben/yudao-ui-admin-vben/output/playwright/im-full-manager-retry-2026-06-17T16-42-45-907Z/sensitive-word-add-form.png",
+ "delete-confirm-entry": "/Users/yunai/Java/yudao-all-in-vben/yudao-ui-admin-vben/output/playwright/im-full-manager-retry-2026-06-17T16-42-45-907Z/delete-confirm-entry.png"
+ }
+}
\ No newline at end of file
diff --git a/output/playwright/im-full-manager-retry-2026-06-17T16-42-45-907Z/rtc-detail.png b/output/playwright/im-full-manager-retry-2026-06-17T16-42-45-907Z/rtc-detail.png
new file mode 100644
index 000000000..2023cb5ef
Binary files /dev/null and b/output/playwright/im-full-manager-retry-2026-06-17T16-42-45-907Z/rtc-detail.png differ
diff --git a/output/playwright/im-full-manager-retry-2026-06-17T16-42-45-907Z/sensitive-word-add-form.png b/output/playwright/im-full-manager-retry-2026-06-17T16-42-45-907Z/sensitive-word-add-form.png
new file mode 100644
index 000000000..ef1e37425
Binary files /dev/null and b/output/playwright/im-full-manager-retry-2026-06-17T16-42-45-907Z/sensitive-word-add-form.png differ
diff --git a/output/playwright/im-full-media-upload-2026-06-17T17-04-21-697Z/after-file-upload.png b/output/playwright/im-full-media-upload-2026-06-17T17-04-21-697Z/after-file-upload.png
new file mode 100644
index 000000000..fafcde766
Binary files /dev/null and b/output/playwright/im-full-media-upload-2026-06-17T17-04-21-697Z/after-file-upload.png differ
diff --git a/output/playwright/im-full-media-upload-2026-06-17T17-04-21-697Z/after-image-upload.png b/output/playwright/im-full-media-upload-2026-06-17T17-04-21-697Z/after-image-upload.png
new file mode 100644
index 000000000..8220d84a8
Binary files /dev/null and b/output/playwright/im-full-media-upload-2026-06-17T17-04-21-697Z/after-image-upload.png differ
diff --git a/output/playwright/im-full-media-upload-2026-06-17T17-04-21-697Z/after-video-upload.png b/output/playwright/im-full-media-upload-2026-06-17T17-04-21-697Z/after-video-upload.png
new file mode 100644
index 000000000..719c99720
Binary files /dev/null and b/output/playwright/im-full-media-upload-2026-06-17T17-04-21-697Z/after-video-upload.png differ
diff --git a/output/playwright/im-full-media-upload-2026-06-17T17-04-21-697Z/before-media-upload.png b/output/playwright/im-full-media-upload-2026-06-17T17-04-21-697Z/before-media-upload.png
new file mode 100644
index 000000000..c0f070866
Binary files /dev/null and b/output/playwright/im-full-media-upload-2026-06-17T17-04-21-697Z/before-media-upload.png differ
diff --git a/output/playwright/im-full-media-upload-2026-06-17T17-04-21-697Z/im-upload-test.txt b/output/playwright/im-full-media-upload-2026-06-17T17-04-21-697Z/im-upload-test.txt
new file mode 100644
index 000000000..27cd87a42
--- /dev/null
+++ b/output/playwright/im-full-media-upload-2026-06-17T17-04-21-697Z/im-upload-test.txt
@@ -0,0 +1 @@
+im upload test file
\ No newline at end of file
diff --git a/output/playwright/im-full-media-upload-2026-06-17T17-04-21-697Z/result.json b/output/playwright/im-full-media-upload-2026-06-17T17-04-21-697Z/result.json
new file mode 100644
index 000000000..129fdf9b7
--- /dev/null
+++ b/output/playwright/im-full-media-upload-2026-06-17T17-04-21-697Z/result.json
@@ -0,0 +1,40 @@
+{
+ "ok": false,
+ "outDir": "/Users/yunai/Java/yudao-all-in-vben/yudao-ui-admin-vben/output/playwright/im-full-media-upload-2026-06-17T17-04-21-697Z",
+ "checks": [
+ {
+ "name": "C-205 图片真实上传发送",
+ "status": "passed",
+ "badDelta": 0,
+ "eventDelta": 0,
+ "visible": true
+ },
+ {
+ "name": "C-206 文件真实上传发送",
+ "status": "passed",
+ "badDelta": 0,
+ "eventDelta": 0,
+ "visible": true
+ },
+ {
+ "name": "C-207 视频上传链路",
+ "status": "failed",
+ "badDelta": 0,
+ "eventDelta": 1,
+ "visible": true
+ }
+ ],
+ "events": [
+ {
+ "type": "warning",
+ "text": "[IM] 视频元信息加载失败,降级为仅 url + size Error: video metadata load error\n at video.addEventListener.once (http://127.0.0.1:5666/src/views/im/home/pages/conversation/components/input/MessageInput.vue:732:51)"
+ }
+ ],
+ "badResponses": [],
+ "screenshots": {
+ "before-media-upload": "/Users/yunai/Java/yudao-all-in-vben/yudao-ui-admin-vben/output/playwright/im-full-media-upload-2026-06-17T17-04-21-697Z/before-media-upload.png",
+ "after-image-upload": "/Users/yunai/Java/yudao-all-in-vben/yudao-ui-admin-vben/output/playwright/im-full-media-upload-2026-06-17T17-04-21-697Z/after-image-upload.png",
+ "after-file-upload": "/Users/yunai/Java/yudao-all-in-vben/yudao-ui-admin-vben/output/playwright/im-full-media-upload-2026-06-17T17-04-21-697Z/after-file-upload.png",
+ "after-video-upload": "/Users/yunai/Java/yudao-all-in-vben/yudao-ui-admin-vben/output/playwright/im-full-media-upload-2026-06-17T17-04-21-697Z/after-video-upload.png"
+ }
+}
\ No newline at end of file
diff --git a/output/playwright/im-full-media-upload-2026-06-17T17-04-21-697Z/tiny.mp4 b/output/playwright/im-full-media-upload-2026-06-17T17-04-21-697Z/tiny.mp4
new file mode 100644
index 000000000..f455052e4
Binary files /dev/null and b/output/playwright/im-full-media-upload-2026-06-17T17-04-21-697Z/tiny.mp4 differ
diff --git a/output/playwright/im-full-media-upload-2026-06-17T17-04-21-697Z/tiny.png b/output/playwright/im-full-media-upload-2026-06-17T17-04-21-697Z/tiny.png
new file mode 100644
index 000000000..e0ccec79f
Binary files /dev/null and b/output/playwright/im-full-media-upload-2026-06-17T17-04-21-697Z/tiny.png differ
diff --git a/output/playwright/im-header-entry-2026-06-17T17-12-10-321Z/header-with-im-entry.png b/output/playwright/im-header-entry-2026-06-17T17-12-10-321Z/header-with-im-entry.png
new file mode 100644
index 000000000..0afa5e57f
Binary files /dev/null and b/output/playwright/im-header-entry-2026-06-17T17-12-10-321Z/header-with-im-entry.png differ
diff --git a/output/playwright/im-header-entry-2026-06-17T17-12-10-321Z/im-home-opened.png b/output/playwright/im-header-entry-2026-06-17T17-12-10-321Z/im-home-opened.png
new file mode 100644
index 000000000..528c9e82b
Binary files /dev/null and b/output/playwright/im-header-entry-2026-06-17T17-12-10-321Z/im-home-opened.png differ
diff --git a/output/playwright/im-header-entry-2026-06-17T17-12-10-321Z/result.json b/output/playwright/im-header-entry-2026-06-17T17-12-10-321Z/result.json
new file mode 100644
index 000000000..aa9f81343
--- /dev/null
+++ b/output/playwright/im-header-entry-2026-06-17T17-12-10-321Z/result.json
@@ -0,0 +1,22 @@
+{
+ "ok": true,
+ "outDir": "/Users/yunai/Java/yudao-all-in-vben/yudao-ui-admin-vben/output/playwright/im-header-entry-2026-06-17T17-12-10-321Z",
+ "checks": [
+ {
+ "name": "右上角 IM 聊天入口可见",
+ "status": "passed",
+ "buttonCount": 13
+ },
+ {
+ "name": "点击 IM 入口新开聊天页",
+ "status": "passed",
+ "newPageUrl": "http://127.0.0.1:5666/im/home"
+ }
+ ],
+ "events": [],
+ "badResponses": [],
+ "screenshots": {
+ "header-with-im-entry": "/Users/yunai/Java/yudao-all-in-vben/yudao-ui-admin-vben/output/playwright/im-header-entry-2026-06-17T17-12-10-321Z/header-with-im-entry.png",
+ "im-home-opened": "/Users/yunai/Java/yudao-all-in-vben/yudao-ui-admin-vben/output/playwright/im-header-entry-2026-06-17T17-12-10-321Z/im-home-opened.png"
+ }
+}
\ No newline at end of file
diff --git a/output/playwright/im-header-entry-right-2026-06-17T17-19-24-151Z/header-right-im-entry.png b/output/playwright/im-header-entry-right-2026-06-17T17-19-24-151Z/header-right-im-entry.png
new file mode 100644
index 000000000..cf88fe724
Binary files /dev/null and b/output/playwright/im-header-entry-right-2026-06-17T17-19-24-151Z/header-right-im-entry.png differ
diff --git a/output/playwright/im-header-entry-right-2026-06-17T17-19-24-151Z/im-home-from-right-entry.png b/output/playwright/im-header-entry-right-2026-06-17T17-19-24-151Z/im-home-from-right-entry.png
new file mode 100644
index 000000000..0200a5701
Binary files /dev/null and b/output/playwright/im-header-entry-right-2026-06-17T17-19-24-151Z/im-home-from-right-entry.png differ
diff --git a/output/playwright/im-header-entry-right-2026-06-17T17-19-24-151Z/result.json b/output/playwright/im-header-entry-right-2026-06-17T17-19-24-151Z/result.json
new file mode 100644
index 000000000..cec79b24b
--- /dev/null
+++ b/output/playwright/im-header-entry-right-2026-06-17T17-19-24-151Z/result.json
@@ -0,0 +1,27 @@
+{
+ "ok": true,
+ "outDir": "/Users/yunai/Java/yudao-all-in-vben/yudao-ui-admin-vben/output/playwright/im-header-entry-right-2026-06-17T17-19-24-151Z",
+ "checks": [
+ {
+ "name": "右上角 IM 入口位于头像前",
+ "status": "passed",
+ "box": {
+ "x": 1348,
+ "y": 8.5,
+ "width": 32,
+ "height": 32
+ }
+ },
+ {
+ "name": "点击 IM 入口新开聊天页",
+ "status": "passed",
+ "url": "http://127.0.0.1:5666/im/home"
+ }
+ ],
+ "screenshots": {
+ "header-right-im-entry": "/Users/yunai/Java/yudao-all-in-vben/yudao-ui-admin-vben/output/playwright/im-header-entry-right-2026-06-17T17-19-24-151Z/header-right-im-entry.png",
+ "im-home-from-right-entry": "/Users/yunai/Java/yudao-all-in-vben/yudao-ui-admin-vben/output/playwright/im-header-entry-right-2026-06-17T17-19-24-151Z/im-home-from-right-entry.png"
+ },
+ "events": [],
+ "badResponses": []
+}
\ No newline at end of file
diff --git a/output/playwright/im-icon-size-2026-06-17/conversation-icon-size.png b/output/playwright/im-icon-size-2026-06-17/conversation-icon-size.png
new file mode 100644
index 000000000..637749961
Binary files /dev/null and b/output/playwright/im-icon-size-2026-06-17/conversation-icon-size.png differ
diff --git a/output/playwright/im-icon-size-2026-06-17/icon-size.json b/output/playwright/im-icon-size-2026-06-17/icon-size.json
new file mode 100644
index 000000000..7f324a9f7
--- /dev/null
+++ b/output/playwright/im-icon-size-2026-06-17/icon-size.json
@@ -0,0 +1,48 @@
+{
+ "toolbarIcons": [
+ {
+ "tag": "svg",
+ "width": 22,
+ "height": 22,
+ "svgWidth": 22,
+ "svgHeight": 22
+ },
+ {
+ "tag": "svg",
+ "width": 22,
+ "height": 22,
+ "svgWidth": 22,
+ "svgHeight": 22
+ },
+ {
+ "tag": "svg",
+ "width": 22,
+ "height": 22,
+ "svgWidth": 22,
+ "svgHeight": 22
+ }
+ ],
+ "headerIcons": [
+ {
+ "tag": "svg",
+ "width": 28,
+ "height": 28,
+ "svgWidth": 28,
+ "svgHeight": 28
+ },
+ {
+ "tag": "svg",
+ "width": 28,
+ "height": 28,
+ "svgWidth": 28,
+ "svgHeight": 28
+ },
+ {
+ "tag": "svg",
+ "width": 28,
+ "height": 28,
+ "svgWidth": 28,
+ "svgHeight": 28
+ }
+ ]
+}
\ No newline at end of file
diff --git a/output/playwright/im-light-vben-antd.png b/output/playwright/im-light-vben-antd.png
new file mode 100644
index 000000000..f750b067a
Binary files /dev/null and b/output/playwright/im-light-vben-antd.png differ
diff --git a/output/playwright/im-light-vue3-ep.png b/output/playwright/im-light-vue3-ep.png
new file mode 100644
index 000000000..b39052962
Binary files /dev/null and b/output/playwright/im-light-vue3-ep.png differ
diff --git a/output/playwright/im-line-style-2026-06-17/conversation-line-style-after-dark.png b/output/playwright/im-line-style-2026-06-17/conversation-line-style-after-dark.png
new file mode 100644
index 000000000..ca1f38a83
Binary files /dev/null and b/output/playwright/im-line-style-2026-06-17/conversation-line-style-after-dark.png differ
diff --git a/output/playwright/im-line-style-2026-06-17/conversation-line-style-after-light.png b/output/playwright/im-line-style-2026-06-17/conversation-line-style-after-light.png
new file mode 100644
index 000000000..c96abbeef
Binary files /dev/null and b/output/playwright/im-line-style-2026-06-17/conversation-line-style-after-light.png differ
diff --git a/output/playwright/im-line-style-2026-06-17/conversation-line-style-after.png b/output/playwright/im-line-style-2026-06-17/conversation-line-style-after.png
new file mode 100644
index 000000000..3a8f4e22d
Binary files /dev/null and b/output/playwright/im-line-style-2026-06-17/conversation-line-style-after.png differ
diff --git a/output/playwright/im-line-style-2026-06-17/conversation-line-style-final-light.png b/output/playwright/im-line-style-2026-06-17/conversation-line-style-final-light.png
new file mode 100644
index 000000000..0718ce30a
Binary files /dev/null and b/output/playwright/im-line-style-2026-06-17/conversation-line-style-final-light.png differ
diff --git a/output/playwright/im-line-style-2026-06-17/conversation-line-style.png b/output/playwright/im-line-style-2026-06-17/conversation-line-style.png
new file mode 100644
index 000000000..d7b10b87a
Binary files /dev/null and b/output/playwright/im-line-style-2026-06-17/conversation-line-style.png differ
diff --git a/output/playwright/im-line-style-2026-06-17/line-style-after-dark.json b/output/playwright/im-line-style-2026-06-17/line-style-after-dark.json
new file mode 100644
index 000000000..85c9de794
--- /dev/null
+++ b/output/playwright/im-line-style-2026-06-17/line-style-after-dark.json
@@ -0,0 +1,30 @@
+{
+ "url": "http://127.0.0.1:5666/im/home/conversation",
+ "className": "dark",
+ "rootVar": "rgb(255 255 255 / 12%)",
+ "imHomeVar": "rgb(255 255 255 / 12%)",
+ "aside": {
+ "borderTopColor": "rgba(255, 255, 255, 0.12)",
+ "borderRightColor": "rgba(255, 255, 255, 0.12)",
+ "borderBottomColor": "rgba(255, 255, 255, 0.12)",
+ "borderLeftColor": "rgba(255, 255, 255, 0.12)"
+ },
+ "leftHeader": {
+ "borderTopColor": "rgba(255, 255, 255, 0.12)",
+ "borderRightColor": "rgba(255, 255, 255, 0.12)",
+ "borderBottomColor": "rgba(255, 255, 255, 0.12)",
+ "borderLeftColor": "rgba(255, 255, 255, 0.12)"
+ },
+ "inputCard": {
+ "borderTopColor": "rgba(255, 255, 255, 0.12)",
+ "borderRightColor": "rgba(255, 255, 255, 0.12)",
+ "borderBottomColor": "rgba(255, 255, 255, 0.12)",
+ "borderLeftColor": "rgba(255, 255, 255, 0.12)"
+ },
+ "toolbar": {
+ "borderTopColor": "rgba(255, 255, 255, 0.12)",
+ "borderRightColor": "rgba(255, 255, 255, 0.12)",
+ "borderBottomColor": "rgba(255, 255, 255, 0.12)",
+ "borderLeftColor": "rgba(255, 255, 255, 0.12)"
+ }
+}
\ No newline at end of file
diff --git a/output/playwright/im-line-style-2026-06-17/line-style-after-light.json b/output/playwright/im-line-style-2026-06-17/line-style-after-light.json
new file mode 100644
index 000000000..95ffe2227
--- /dev/null
+++ b/output/playwright/im-line-style-2026-06-17/line-style-after-light.json
@@ -0,0 +1,28 @@
+{
+ "className": " ",
+ "rootVar": "#e8eaed",
+ "aside": {
+ "borderTopColor": "rgb(232, 234, 237)",
+ "borderRightColor": "rgb(232, 234, 237)",
+ "borderBottomColor": "rgb(232, 234, 237)",
+ "borderLeftColor": "rgb(232, 234, 237)"
+ },
+ "leftHeader": {
+ "borderTopColor": "rgb(232, 234, 237)",
+ "borderRightColor": "rgb(232, 234, 237)",
+ "borderBottomColor": "rgb(232, 234, 237)",
+ "borderLeftColor": "rgb(232, 234, 237)"
+ },
+ "inputCard": {
+ "borderTopColor": "rgb(232, 234, 237)",
+ "borderRightColor": "rgb(232, 234, 237)",
+ "borderBottomColor": "rgb(232, 234, 237)",
+ "borderLeftColor": "rgb(232, 234, 237)"
+ },
+ "toolbar": {
+ "borderTopColor": "rgb(232, 234, 237)",
+ "borderRightColor": "rgb(232, 234, 237)",
+ "borderBottomColor": "rgb(232, 234, 237)",
+ "borderLeftColor": "rgb(232, 234, 237)"
+ }
+}
\ No newline at end of file
diff --git a/output/playwright/im-line-style-2026-06-17/line-style-after.json b/output/playwright/im-line-style-2026-06-17/line-style-after.json
new file mode 100644
index 000000000..b7652f2f3
--- /dev/null
+++ b/output/playwright/im-line-style-2026-06-17/line-style-after.json
@@ -0,0 +1,59 @@
+{
+ "values": {
+ "url": "http://127.0.0.1:5666/im/home/conversation",
+ "className": "dark",
+ "rootVar": "rgb(255 255 255 / 12%)",
+ "imHomeVar": "#e8eaed",
+ "aside": {
+ "borderTopColor": "rgb(232, 234, 237)",
+ "borderRightColor": "rgb(232, 234, 237)",
+ "borderBottomColor": "rgb(232, 234, 237)",
+ "borderLeftColor": "rgb(232, 234, 237)"
+ },
+ "leftHeader": {
+ "borderTopColor": "rgb(232, 234, 237)",
+ "borderRightColor": "rgb(232, 234, 237)",
+ "borderBottomColor": "rgb(232, 234, 237)",
+ "borderLeftColor": "rgb(232, 234, 237)"
+ },
+ "inputCard": {
+ "borderTopColor": "rgb(232, 234, 237)",
+ "borderRightColor": "rgb(232, 234, 237)",
+ "borderBottomColor": "rgb(232, 234, 237)",
+ "borderLeftColor": "rgb(232, 234, 237)"
+ },
+ "toolbar": {
+ "borderTopColor": "rgb(232, 234, 237)",
+ "borderRightColor": "rgb(232, 234, 237)",
+ "borderBottomColor": "rgb(232, 234, 237)",
+ "borderLeftColor": "rgb(232, 234, 237)"
+ },
+ "antSecondary": ""
+ },
+ "events": [
+ {
+ "type": "warning",
+ "text": "[StorageManager] empty prefix combined with LocalStorageDriver — clear()/keys() will affect every localStorage entry."
+ },
+ {
+ "type": "error",
+ "text": "menu name duplicate: 库存管理, id: 6440 Proxy(Object)"
+ },
+ {
+ "type": "error",
+ "text": "menu name duplicate: 基础数据, id: 5101 Proxy(Object)"
+ },
+ {
+ "type": "warning",
+ "text": "[StorageManager] empty prefix combined with LocalStorageDriver — clear()/keys() will affect every localStorage entry."
+ },
+ {
+ "type": "error",
+ "text": "menu name duplicate: 库存管理, id: 6440 Proxy(Object)"
+ },
+ {
+ "type": "error",
+ "text": "menu name duplicate: 基础数据, id: 5101 Proxy(Object)"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/output/playwright/im-line-style-2026-06-17/line-style-final-light.json b/output/playwright/im-line-style-2026-06-17/line-style-final-light.json
new file mode 100644
index 000000000..c5201dbce
--- /dev/null
+++ b/output/playwright/im-line-style-2026-06-17/line-style-final-light.json
@@ -0,0 +1,34 @@
+{
+ "className": " ",
+ "rootVar": "#e8eaed",
+ "aside": {
+ "borderTopColor": "rgb(232, 234, 237)",
+ "borderRightColor": "rgb(232, 234, 237)",
+ "borderBottomColor": "rgb(232, 234, 237)",
+ "borderLeftColor": "rgb(232, 234, 237)"
+ },
+ "leftHeader": {
+ "borderTopColor": "rgb(232, 234, 237)",
+ "borderRightColor": "rgb(232, 234, 237)",
+ "borderBottomColor": "rgb(232, 234, 237)",
+ "borderLeftColor": "rgb(232, 234, 237)"
+ },
+ "messagePanelHeader": {
+ "borderTopColor": "rgb(232, 234, 237)",
+ "borderRightColor": "rgb(232, 234, 237)",
+ "borderBottomColor": "rgb(232, 234, 237)",
+ "borderLeftColor": "rgb(232, 234, 237)"
+ },
+ "inputCard": {
+ "borderTopColor": "rgb(232, 234, 237)",
+ "borderRightColor": "rgb(232, 234, 237)",
+ "borderBottomColor": "rgb(232, 234, 237)",
+ "borderLeftColor": "rgb(232, 234, 237)"
+ },
+ "toolbar": {
+ "borderTopColor": "rgb(232, 234, 237)",
+ "borderRightColor": "rgb(232, 234, 237)",
+ "borderBottomColor": "rgb(232, 234, 237)",
+ "borderLeftColor": "rgb(232, 234, 237)"
+ }
+}
\ No newline at end of file
diff --git a/output/playwright/im-line-style-2026-06-17/line-style.json b/output/playwright/im-line-style-2026-06-17/line-style.json
new file mode 100644
index 000000000..f65a8f8b0
--- /dev/null
+++ b/output/playwright/im-line-style-2026-06-17/line-style.json
@@ -0,0 +1,10 @@
+{
+ "rootVar": "",
+ "imHomeVar": "",
+ "aside": null,
+ "leftHeader": null,
+ "messageHeader": null,
+ "inputCard": null,
+ "editorParent": null,
+ "toolbar": null
+}
\ No newline at end of file
diff --git a/output/playwright/im-vben-e2e-2026-06-17-run2/01-vben-conversation-before.png b/output/playwright/im-vben-e2e-2026-06-17-run2/01-vben-conversation-before.png
new file mode 100644
index 000000000..572b72d3f
Binary files /dev/null and b/output/playwright/im-vben-e2e-2026-06-17-run2/01-vben-conversation-before.png differ
diff --git a/output/playwright/im-vben-e2e-2026-06-17-run2/01-vue3-conversation-before.png b/output/playwright/im-vben-e2e-2026-06-17-run2/01-vue3-conversation-before.png
new file mode 100644
index 000000000..5399f1b60
Binary files /dev/null and b/output/playwright/im-vben-e2e-2026-06-17-run2/01-vue3-conversation-before.png differ
diff --git a/output/playwright/im-vben-e2e-2026-06-17-run2/02-vben-received.png b/output/playwright/im-vben-e2e-2026-06-17-run2/02-vben-received.png
new file mode 100644
index 000000000..a604dd224
Binary files /dev/null and b/output/playwright/im-vben-e2e-2026-06-17-run2/02-vben-received.png differ
diff --git a/output/playwright/im-vben-e2e-2026-06-17-run2/02-vue3-sent.png b/output/playwright/im-vben-e2e-2026-06-17-run2/02-vue3-sent.png
new file mode 100644
index 000000000..f9b559559
Binary files /dev/null and b/output/playwright/im-vben-e2e-2026-06-17-run2/02-vue3-sent.png differ
diff --git a/output/playwright/im-vben-e2e-2026-06-17-run2/03-vben-sent.png b/output/playwright/im-vben-e2e-2026-06-17-run2/03-vben-sent.png
new file mode 100644
index 000000000..2395ff8f3
Binary files /dev/null and b/output/playwright/im-vben-e2e-2026-06-17-run2/03-vben-sent.png differ
diff --git a/output/playwright/im-vben-e2e-2026-06-17-run2/03-vue3-received.png b/output/playwright/im-vben-e2e-2026-06-17-run2/03-vue3-received.png
new file mode 100644
index 000000000..537d4fe33
Binary files /dev/null and b/output/playwright/im-vben-e2e-2026-06-17-run2/03-vue3-received.png differ
diff --git a/output/playwright/im-vben-e2e-2026-06-17-run2/04-vben-contact.png b/output/playwright/im-vben-e2e-2026-06-17-run2/04-vben-contact.png
new file mode 100644
index 000000000..701b4eec6
Binary files /dev/null and b/output/playwright/im-vben-e2e-2026-06-17-run2/04-vben-contact.png differ
diff --git a/output/playwright/im-vben-e2e-2026-06-17-run2/04-vue3-contact.png b/output/playwright/im-vben-e2e-2026-06-17-run2/04-vue3-contact.png
new file mode 100644
index 000000000..66c2b6dbf
Binary files /dev/null and b/output/playwright/im-vben-e2e-2026-06-17-run2/04-vue3-contact.png differ
diff --git a/output/playwright/im-vben-e2e-2026-06-17-run2/05-vben-face-pack.png b/output/playwright/im-vben-e2e-2026-06-17-run2/05-vben-face-pack.png
new file mode 100644
index 000000000..6d5ecb4e1
Binary files /dev/null and b/output/playwright/im-vben-e2e-2026-06-17-run2/05-vben-face-pack.png differ
diff --git a/output/playwright/im-vben-e2e-2026-06-17-run2/06-vben-face-item-drawer.png b/output/playwright/im-vben-e2e-2026-06-17-run2/06-vben-face-item-drawer.png
new file mode 100644
index 000000000..0ae9d88d9
Binary files /dev/null and b/output/playwright/im-vben-e2e-2026-06-17-run2/06-vben-face-item-drawer.png differ
diff --git a/output/playwright/im-vben-e2e-2026-06-17-run2/07-vben-group-message.png b/output/playwright/im-vben-e2e-2026-06-17-run2/07-vben-group-message.png
new file mode 100644
index 000000000..b8d50d432
Binary files /dev/null and b/output/playwright/im-vben-e2e-2026-06-17-run2/07-vben-group-message.png differ
diff --git a/output/playwright/im-vben-e2e-2026-06-17-run2/result.json b/output/playwright/im-vben-e2e-2026-06-17-run2/result.json
new file mode 100644
index 000000000..7db63f1ad
--- /dev/null
+++ b/output/playwright/im-vben-e2e-2026-06-17-run2/result.json
@@ -0,0 +1,191 @@
+{
+ "runId": 1781712966734,
+ "accounts": {
+ "vue3": "admin/admin123 userId=1",
+ "vben": "test01/123456 userId=142"
+ },
+ "messages": {
+ "vueText": "E2E Vue3 to Vben 1781712966734",
+ "vbenText": "E2E Vben to Vue3 1781712966734"
+ },
+ "events": {
+ "vue3": [
+ {
+ "type": "warning",
+ "text": "[IM groupStore] 本地群缓存写入失败 DataCloneError: Failed to execute 'put' on 'IDBObjectStore': [object Array] could not be cloned.\n at DbClient.put (http://127.0.0.1/src/views/im/utils/db.ts?t=1781712513755:200:53)\n at http://127.0.0.1/src/views/im/home/store/groupStore.ts?t=1781712513755:88:15\n at async DbClient.transaction (http://127.0.0.1/src/views/im/utils/db.ts?t=1781712513755:252:13)",
+ "url": "http://127.0.0.1/im/home/conversation"
+ },
+ {
+ "type": "warning",
+ "text": "[IM groupStore] 本地群缓存写入失败 DataCloneError: Failed to execute 'put' on 'IDBObjectStore': [object Array] could not be cloned.\n at DbClient.put (http://127.0.0.1/src/views/im/utils/db.ts?t=1781712513755:200:53)\n at http://127.0.0.1/src/views/im/home/store/groupStore.ts?t=1781712513755:88:15\n at async DbClient.transaction (http://127.0.0.1/src/views/im/utils/db.ts?t=1781712513755:252:13)",
+ "url": "http://127.0.0.1/im/home/contact"
+ },
+ {
+ "type": "warning",
+ "text": "[IM groupStore] 本地群缓存写入失败 DataCloneError: Failed to execute 'put' on 'IDBObjectStore': [object Array] could not be cloned.\n at DbClient.put (http://127.0.0.1/src/views/im/utils/db.ts?t=1781712513755:200:53)\n at http://127.0.0.1/src/views/im/home/store/groupStore.ts?t=1781712513755:88:15\n at async DbClient.transaction (http://127.0.0.1/src/views/im/utils/db.ts?t=1781712513755:252:13)",
+ "url": "http://127.0.0.1/im/home/contact"
+ }
+ ],
+ "vben": [
+ {
+ "type": "error",
+ "text": "menu name duplicate: 库存管理, id: 6440 Proxy(Object)",
+ "url": "http://127.0.0.1:5666/auth/login"
+ },
+ {
+ "type": "error",
+ "text": "menu name duplicate: 基础数据, id: 5101 Proxy(Object)",
+ "url": "http://127.0.0.1:5666/auth/login"
+ },
+ {
+ "type": "error",
+ "text": "menu name duplicate: 库存管理, id: 6440 Proxy(Object)",
+ "url": "http://127.0.0.1:5666/im/home/conversation"
+ },
+ {
+ "type": "error",
+ "text": "menu name duplicate: 基础数据, id: 5101 Proxy(Object)",
+ "url": "http://127.0.0.1:5666/im/home/conversation"
+ },
+ {
+ "type": "error",
+ "text": "menu name duplicate: 库存管理, id: 6440 Proxy(Object)",
+ "url": "http://127.0.0.1:5666/im/home/contact"
+ },
+ {
+ "type": "error",
+ "text": "menu name duplicate: 基础数据, id: 5101 Proxy(Object)",
+ "url": "http://127.0.0.1:5666/im/home/contact"
+ },
+ {
+ "type": "error",
+ "text": "menu name duplicate: 库存管理, id: 6440 Proxy(Object)",
+ "url": "http://127.0.0.1:5666/im/face/pack"
+ },
+ {
+ "type": "error",
+ "text": "menu name duplicate: 基础数据, id: 5101 Proxy(Object)",
+ "url": "http://127.0.0.1:5666/im/face/pack"
+ },
+ {
+ "type": "error",
+ "text": "menu name duplicate: 库存管理, id: 6440 Proxy(Object)",
+ "url": "http://127.0.0.1:5666/im/group/message"
+ },
+ {
+ "type": "error",
+ "text": "menu name duplicate: 基础数据, id: 5101 Proxy(Object)",
+ "url": "http://127.0.0.1:5666/im/group/message"
+ }
+ ]
+ },
+ "badResponses": {
+ "vue3": [],
+ "vben": []
+ },
+ "checks": {
+ "vbenConversationKeys": [
+ {
+ "key": "2-10084",
+ "text": "0芋道源码、a00001、test01、新用户等13人 群 昨天 11:37测试号: 123"
+ },
+ {
+ "key": "1-1",
+ "text": "10芋道源码05/30你撤回了一条消息"
+ },
+ {
+ "key": "3-1",
+ "text": "3系统公告05/19[频道] 测试消息"
+ }
+ ],
+ "vue3ConversationKeys": [
+ {
+ "key": "1-141",
+ "text": "新0新用户13:57[语音]"
+ },
+ {
+ "key": "1-104",
+ "text": "测0测试号昨天 11:3732132321"
+ },
+ {
+ "key": "2-10084",
+ "text": "芋0芋道源码、a00001、test01、新用户等13人 群 昨天 11:36芋道源码 退出了群聊"
+ },
+ {
+ "key": "1-143",
+ "text": "A0a0000105/31[语音通话]"
+ },
+ {
+ "key": "1-142",
+ "text": "TE0test0105/30test01 撤回了一条消息"
+ },
+ {
+ "key": "1-139",
+ "text": "小0小秃头05/30小秃头 撤回了一条消息"
+ },
+ {
+ "key": "1-118",
+ "text": "狗0狗蛋05/30狗蛋 撤回了一条消息"
+ },
+ {
+ "key": "1-117",
+ "text": "测0测试号0205/30测试号02 撤回了一条消息"
+ },
+ {
+ "key": "1-115",
+ "text": "阿0阿呆05/30阿呆 撤回了一条消息"
+ },
+ {
+ "key": "1-114",
+ "text": "HR0hr 小姐姐05/30hr 小姐姐 撤回了一条消息"
+ },
+ {
+ "key": "1-112",
+ "text": "新0新对象05/30新对象 撤回了一条消息"
+ },
+ {
+ "key": "1-103",
+ "text": "源0源码05/30源码 撤回了一条消息"
+ },
+ {
+ "key": "1-100",
+ "text": "EE0EEEE105/30EEEE1 撤回了一条消息"
+ },
+ {
+ "key": "3-1",
+ "text": "0系统公告05/19[频道] 测试消息"
+ }
+ ],
+ "vue3SentVisible": true,
+ "vbenReceived": true,
+ "vbenSentVisible": true,
+ "vue3Received": true,
+ "twoWayPrivateMessage": true,
+ "vue3ContactLoaded": true,
+ "vbenContactLoaded": true,
+ "vbenFacePackLoaded": true,
+ "vbenFaceDrawerOpened": true,
+ "vbenGroupMessageLoaded": true
+ },
+ "screenshots": {
+ "01-vue3-conversation-before": "/Users/yunai/Java/yudao-all-in-vben/yudao-ui-admin-vben/output/playwright/im-vben-e2e-2026-06-17-run2/01-vue3-conversation-before.png",
+ "01-vben-conversation-before": "/Users/yunai/Java/yudao-all-in-vben/yudao-ui-admin-vben/output/playwright/im-vben-e2e-2026-06-17-run2/01-vben-conversation-before.png",
+ "02-vben-received": "/Users/yunai/Java/yudao-all-in-vben/yudao-ui-admin-vben/output/playwright/im-vben-e2e-2026-06-17-run2/02-vben-received.png",
+ "02-vue3-sent": "/Users/yunai/Java/yudao-all-in-vben/yudao-ui-admin-vben/output/playwright/im-vben-e2e-2026-06-17-run2/02-vue3-sent.png",
+ "03-vben-sent": "/Users/yunai/Java/yudao-all-in-vben/yudao-ui-admin-vben/output/playwright/im-vben-e2e-2026-06-17-run2/03-vben-sent.png",
+ "03-vue3-received": "/Users/yunai/Java/yudao-all-in-vben/yudao-ui-admin-vben/output/playwright/im-vben-e2e-2026-06-17-run2/03-vue3-received.png",
+ "04-vben-contact": "/Users/yunai/Java/yudao-all-in-vben/yudao-ui-admin-vben/output/playwright/im-vben-e2e-2026-06-17-run2/04-vben-contact.png",
+ "04-vue3-contact": "/Users/yunai/Java/yudao-all-in-vben/yudao-ui-admin-vben/output/playwright/im-vben-e2e-2026-06-17-run2/04-vue3-contact.png",
+ "05-vben-face-pack": "/Users/yunai/Java/yudao-all-in-vben/yudao-ui-admin-vben/output/playwright/im-vben-e2e-2026-06-17-run2/05-vben-face-pack.png",
+ "06-vben-face-item-drawer": "/Users/yunai/Java/yudao-all-in-vben/yudao-ui-admin-vben/output/playwright/im-vben-e2e-2026-06-17-run2/06-vben-face-item-drawer.png",
+ "07-vben-group-message": "/Users/yunai/Java/yudao-all-in-vben/yudao-ui-admin-vben/output/playwright/im-vben-e2e-2026-06-17-run2/07-vben-group-message.png"
+ },
+ "pages": {
+ "vbenAfterLogin": "http://127.0.0.1:5666/analytics",
+ "vue3AfterLogin": "http://127.0.0.1/index",
+ "vbenConversation": "http://127.0.0.1:5666/im/home/conversation",
+ "vue3Conversation": "http://127.0.0.1/im/home/conversation",
+ "vue3Final": "http://127.0.0.1/im/home/contact",
+ "vbenFinal": "http://127.0.0.1:5666/im/group/message"
+ }
+}
\ No newline at end of file
diff --git a/output/playwright/im-vben-e2e-2026-06-17-run3/01-vben-conversation-before.png b/output/playwright/im-vben-e2e-2026-06-17-run3/01-vben-conversation-before.png
new file mode 100644
index 000000000..9ee05b03a
Binary files /dev/null and b/output/playwright/im-vben-e2e-2026-06-17-run3/01-vben-conversation-before.png differ
diff --git a/output/playwright/im-vben-e2e-2026-06-17-run3/01-vue3-conversation-before.png b/output/playwright/im-vben-e2e-2026-06-17-run3/01-vue3-conversation-before.png
new file mode 100644
index 000000000..b6079b4a4
Binary files /dev/null and b/output/playwright/im-vben-e2e-2026-06-17-run3/01-vue3-conversation-before.png differ
diff --git a/output/playwright/im-vben-e2e-2026-06-17-run3/02-vben-received.png b/output/playwright/im-vben-e2e-2026-06-17-run3/02-vben-received.png
new file mode 100644
index 000000000..b335d800c
Binary files /dev/null and b/output/playwright/im-vben-e2e-2026-06-17-run3/02-vben-received.png differ
diff --git a/output/playwright/im-vben-e2e-2026-06-17-run3/02-vue3-sent.png b/output/playwright/im-vben-e2e-2026-06-17-run3/02-vue3-sent.png
new file mode 100644
index 000000000..3f2afdea1
Binary files /dev/null and b/output/playwright/im-vben-e2e-2026-06-17-run3/02-vue3-sent.png differ
diff --git a/output/playwright/im-vben-e2e-2026-06-17-run3/03-vben-sent.png b/output/playwright/im-vben-e2e-2026-06-17-run3/03-vben-sent.png
new file mode 100644
index 000000000..e4f748099
Binary files /dev/null and b/output/playwright/im-vben-e2e-2026-06-17-run3/03-vben-sent.png differ
diff --git a/output/playwright/im-vben-e2e-2026-06-17-run3/03-vue3-received.png b/output/playwright/im-vben-e2e-2026-06-17-run3/03-vue3-received.png
new file mode 100644
index 000000000..20106dfd1
Binary files /dev/null and b/output/playwright/im-vben-e2e-2026-06-17-run3/03-vue3-received.png differ
diff --git a/output/playwright/im-vben-e2e-2026-06-17-run3/04-vben-contact.png b/output/playwright/im-vben-e2e-2026-06-17-run3/04-vben-contact.png
new file mode 100644
index 000000000..701b4eec6
Binary files /dev/null and b/output/playwright/im-vben-e2e-2026-06-17-run3/04-vben-contact.png differ
diff --git a/output/playwright/im-vben-e2e-2026-06-17-run3/04-vue3-contact.png b/output/playwright/im-vben-e2e-2026-06-17-run3/04-vue3-contact.png
new file mode 100644
index 000000000..696c62435
Binary files /dev/null and b/output/playwright/im-vben-e2e-2026-06-17-run3/04-vue3-contact.png differ
diff --git a/output/playwright/im-vben-e2e-2026-06-17-run3/05-vben-face-pack.png b/output/playwright/im-vben-e2e-2026-06-17-run3/05-vben-face-pack.png
new file mode 100644
index 000000000..643739361
Binary files /dev/null and b/output/playwright/im-vben-e2e-2026-06-17-run3/05-vben-face-pack.png differ
diff --git a/output/playwright/im-vben-e2e-2026-06-17-run3/06-vben-face-item-drawer.png b/output/playwright/im-vben-e2e-2026-06-17-run3/06-vben-face-item-drawer.png
new file mode 100644
index 000000000..3cd2ab887
Binary files /dev/null and b/output/playwright/im-vben-e2e-2026-06-17-run3/06-vben-face-item-drawer.png differ
diff --git a/output/playwright/im-vben-e2e-2026-06-17-run3/07-vben-group-message.png b/output/playwright/im-vben-e2e-2026-06-17-run3/07-vben-group-message.png
new file mode 100644
index 000000000..b8d50d432
Binary files /dev/null and b/output/playwright/im-vben-e2e-2026-06-17-run3/07-vben-group-message.png differ
diff --git a/output/playwright/im-vben-e2e-2026-06-17-run3/result.json b/output/playwright/im-vben-e2e-2026-06-17-run3/result.json
new file mode 100644
index 000000000..7a5374639
--- /dev/null
+++ b/output/playwright/im-vben-e2e-2026-06-17-run3/result.json
@@ -0,0 +1,118 @@
+{
+ "runId": 1781713160946,
+ "accounts": {
+ "vue3": "admin/admin123 userId=1",
+ "vben": "test01/123456 userId=142"
+ },
+ "messages": {
+ "vueText": "E2E Vue3 to Vben 1781713160946",
+ "vbenText": "E2E Vben to Vue3 1781713160946"
+ },
+ "events": {
+ "vue3": [],
+ "vben": [
+ {
+ "type": "error",
+ "text": "Failed to load resource: net::ERR_TIMED_OUT",
+ "url": "http://127.0.0.1:5666/analytics"
+ }
+ ]
+ },
+ "ignoredEvents": {
+ "vue3": 16,
+ "vben": 15
+ },
+ "badResponses": {
+ "vue3": [],
+ "vben": []
+ },
+ "checks": {
+ "vbenConversationKeys": [
+ {
+ "key": "1-1",
+ "text": "0芋道源码09:16E2E Vben to Vue3 1781712966734"
+ },
+ {
+ "key": "2-10084",
+ "text": "3芋道源码、a00001、test01、新用户等13人 群 昨天 11:37测试号: 123"
+ },
+ {
+ "key": "3-1",
+ "text": "3系统公告05/19[频道] 测试消息"
+ }
+ ],
+ "vue3ConversationKeys": [
+ {
+ "key": "1-141",
+ "text": "新0新用户13:57[语音]"
+ },
+ {
+ "key": "1-142",
+ "text": "TE0test0109:16E2E Vben to Vue3 1781712966734"
+ },
+ {
+ "key": "1-104",
+ "text": "测0测试号昨天 11:3732132321"
+ },
+ {
+ "key": "2-10084",
+ "text": "芋0芋道源码、a00001、test01、新用户等13人 群 昨天 11:36芋道源码 退出了群聊"
+ },
+ {
+ "key": "1-143",
+ "text": "A0a0000105/31[语音通话]"
+ },
+ {
+ "key": "1-139",
+ "text": "小0小秃头05/30小秃头 撤回了一条消息"
+ },
+ {
+ "key": "1-118",
+ "text": "狗0狗蛋05/30狗蛋 撤回了一条消息"
+ },
+ {
+ "key": "1-117",
+ "text": "测0测试号0205/30测试号02 撤回了一条消息"
+ },
+ {
+ "key": "1-115",
+ "text": "阿0阿呆05/30阿呆 撤回了一条消息"
+ },
+ {
+ "key": "1-114",
+ "text": "HR0hr 小姐姐05/30hr 小姐姐 撤回了一条消息"
+ }
+ ],
+ "vue3SentVisible": true,
+ "vbenReceived": true,
+ "vbenSentVisible": true,
+ "vue3Received": true,
+ "twoWayPrivateMessage": true,
+ "vue3ContactLoaded": true,
+ "vbenContactLoaded": true,
+ "vbenFacePackLoaded": true,
+ "vbenFaceDrawerOpened": true,
+ "vbenGroupMessageLoaded": true
+ },
+ "screenshots": {
+ "01-vben-conversation-before": "/Users/yunai/Java/yudao-all-in-vben/yudao-ui-admin-vben/output/playwright/im-vben-e2e-2026-06-17-run3/01-vben-conversation-before.png",
+ "01-vue3-conversation-before": "/Users/yunai/Java/yudao-all-in-vben/yudao-ui-admin-vben/output/playwright/im-vben-e2e-2026-06-17-run3/01-vue3-conversation-before.png",
+ "02-vue3-sent": "/Users/yunai/Java/yudao-all-in-vben/yudao-ui-admin-vben/output/playwright/im-vben-e2e-2026-06-17-run3/02-vue3-sent.png",
+ "02-vben-received": "/Users/yunai/Java/yudao-all-in-vben/yudao-ui-admin-vben/output/playwright/im-vben-e2e-2026-06-17-run3/02-vben-received.png",
+ "03-vue3-received": "/Users/yunai/Java/yudao-all-in-vben/yudao-ui-admin-vben/output/playwright/im-vben-e2e-2026-06-17-run3/03-vue3-received.png",
+ "03-vben-sent": "/Users/yunai/Java/yudao-all-in-vben/yudao-ui-admin-vben/output/playwright/im-vben-e2e-2026-06-17-run3/03-vben-sent.png",
+ "04-vben-contact": "/Users/yunai/Java/yudao-all-in-vben/yudao-ui-admin-vben/output/playwright/im-vben-e2e-2026-06-17-run3/04-vben-contact.png",
+ "04-vue3-contact": "/Users/yunai/Java/yudao-all-in-vben/yudao-ui-admin-vben/output/playwright/im-vben-e2e-2026-06-17-run3/04-vue3-contact.png",
+ "05-vben-face-pack": "/Users/yunai/Java/yudao-all-in-vben/yudao-ui-admin-vben/output/playwright/im-vben-e2e-2026-06-17-run3/05-vben-face-pack.png",
+ "06-vben-face-item-drawer": "/Users/yunai/Java/yudao-all-in-vben/yudao-ui-admin-vben/output/playwright/im-vben-e2e-2026-06-17-run3/06-vben-face-item-drawer.png",
+ "07-vben-group-message": "/Users/yunai/Java/yudao-all-in-vben/yudao-ui-admin-vben/output/playwright/im-vben-e2e-2026-06-17-run3/07-vben-group-message.png"
+ },
+ "pages": {
+ "vue3AfterLogin": "http://127.0.0.1/index",
+ "vbenAfterLogin": "http://127.0.0.1:5666/analytics",
+ "vbenConversation": "http://127.0.0.1:5666/im/home/conversation",
+ "vue3Conversation": "http://127.0.0.1/im/home/conversation",
+ "vue3Final": "http://127.0.0.1/im/home/contact",
+ "vbenFinal": "http://127.0.0.1:5666/im/group/message"
+ }
+}
\ No newline at end of file
diff --git a/output/playwright/im-vben-e2e-2026-06-17/result.json b/output/playwright/im-vben-e2e-2026-06-17/result.json
new file mode 100644
index 000000000..be4f37780
--- /dev/null
+++ b/output/playwright/im-vben-e2e-2026-06-17/result.json
@@ -0,0 +1,94 @@
+{
+ "runId": 1781712833339,
+ "messages": {
+ "vueText": "E2E Vue3 to Vben 1781712833339",
+ "vbenText": "E2E Vben to Vue3 1781712833339"
+ },
+ "pages": {
+ "vue3": {
+ "afterLoginUrl": "http://127.0.0.1/index",
+ "finalUrl": "http://127.0.0.1/index"
+ },
+ "vben": {
+ "finalUrl": "http://127.0.0.1:5666/auth/login"
+ }
+ },
+ "events": {
+ "vue3": [
+ {
+ "type": "warning",
+ "text": "[Vue Router warn]: The `next()` callback in navigation guards is deprecated. Return the value instead of calling `next(value)`.",
+ "url": "http://127.0.0.1/"
+ },
+ {
+ "type": "warning",
+ "text": "[Vue Router warn]: The `next()` callback in navigation guards is deprecated. Return the value instead of calling `next(value)`.",
+ "url": "http://127.0.0.1/"
+ },
+ {
+ "type": "warning",
+ "text": "[Vue Router warn]: The `next()` callback in navigation guards is deprecated. Return the value instead of calling `next(value)`.",
+ "url": "http://127.0.0.1/login?redirect=/index"
+ },
+ {
+ "type": "warning",
+ "text": "[Vue Router warn]: The `next()` callback in navigation guards is deprecated. Return the value instead of calling `next(value)`.",
+ "url": "http://127.0.0.1/login?redirect=/index"
+ },
+ {
+ "type": "warning",
+ "text": "ElementPlusError: [el-link] [API] The underline option (boolean) is about to be deprecated in version 3.0.0, please use 'always' | 'hover' | 'never' instead.\nFor more detail, please visit: https://element-plus.org/en-US/component/link.html#underline\n\n at debugWarn (http://127.0.0.1/node_modules/.vite/deps/error-Ce0Y4MfB.js?v=cb5944c8:100:35)\n at watch.immediate (http://127.0.0.1/node_modules/.vite/deps/es-DnGNPDoU.js?v=cb5944c8:491:12)\n at callWithErrorHandling (http://127.0.0.1/node_modules/.vite/deps/runtime-dom.esm-bundler-FHiQ_YXQ.js?v=cb5944c8:2075:17)\n at callWithAsyncErrorHandling (http://127.0.0.1/node_modules/.vite/deps/runtime-dom.esm-bundler-FHiQ_YXQ.js?v=cb5944c8:2082:15)\n at baseWatchOptions.call (http://127.0.0.1/node_modules/.vite/deps/runtime-dom.esm-bundler-FHiQ_YXQ.js?v=cb5944c8:2528:46)\n at job (http://127.0.0.1/node_modules/.vite/deps/runtime-dom.esm-bundler-FHiQ_YXQ.js?v=cb5944c8:1246:13)\n at watch$1 (http://127.0.0.1/node_modules/.vite/deps/runtime-dom.esm-bundler-FHiQ_YXQ.js?v=cb5944c8:1267:25)\n at doWatch (http://127.0.0.1/node_modules/.vite/deps/runtime-dom.esm-bundler-FHiQ_YXQ.js?v=cb5944c8:2550:22)\n at watch (http://127.0.0.1/node_modules/.vite/deps/runtime-dom.esm-bundler-FHiQ_YXQ.js?v=cb5944c8:2502:9)\n at useDeprecated (http://127.0.0.1/node_modules/.vite/deps/es-DnGNPDoU.js?v=cb5944c8:490:2)",
+ "url": "http://127.0.0.1/index"
+ },
+ {
+ "type": "warning",
+ "text": "ElementPlusError: [el-link] [API] The underline option (boolean) is about to be deprecated in version 3.0.0, please use 'always' | 'hover' | 'never' instead.\nFor more detail, please visit: https://element-plus.org/en-US/component/link.html#underline\n\n at debugWarn (http://127.0.0.1/node_modules/.vite/deps/error-Ce0Y4MfB.js?v=cb5944c8:100:35)\n at watch.immediate (http://127.0.0.1/node_modules/.vite/deps/es-DnGNPDoU.js?v=cb5944c8:491:12)\n at callWithErrorHandling (http://127.0.0.1/node_modules/.vite/deps/runtime-dom.esm-bundler-FHiQ_YXQ.js?v=cb5944c8:2075:17)\n at callWithAsyncErrorHandling (http://127.0.0.1/node_modules/.vite/deps/runtime-dom.esm-bundler-FHiQ_YXQ.js?v=cb5944c8:2082:15)\n at baseWatchOptions.call (http://127.0.0.1/node_modules/.vite/deps/runtime-dom.esm-bundler-FHiQ_YXQ.js?v=cb5944c8:2528:46)\n at job (http://127.0.0.1/node_modules/.vite/deps/runtime-dom.esm-bundler-FHiQ_YXQ.js?v=cb5944c8:1246:13)\n at watch$1 (http://127.0.0.1/node_modules/.vite/deps/runtime-dom.esm-bundler-FHiQ_YXQ.js?v=cb5944c8:1267:25)\n at doWatch (http://127.0.0.1/node_modules/.vite/deps/runtime-dom.esm-bundler-FHiQ_YXQ.js?v=cb5944c8:2550:22)\n at watch (http://127.0.0.1/node_modules/.vite/deps/runtime-dom.esm-bundler-FHiQ_YXQ.js?v=cb5944c8:2502:9)\n at useDeprecated (http://127.0.0.1/node_modules/.vite/deps/es-DnGNPDoU.js?v=cb5944c8:490:2)",
+ "url": "http://127.0.0.1/index"
+ },
+ {
+ "type": "warning",
+ "text": "ElementPlusError: [el-link] [API] The underline option (boolean) is about to be deprecated in version 3.0.0, please use 'always' | 'hover' | 'never' instead.\nFor more detail, please visit: https://element-plus.org/en-US/component/link.html#underline\n\n at debugWarn (http://127.0.0.1/node_modules/.vite/deps/error-Ce0Y4MfB.js?v=cb5944c8:100:35)\n at watch.immediate (http://127.0.0.1/node_modules/.vite/deps/es-DnGNPDoU.js?v=cb5944c8:491:12)\n at callWithErrorHandling (http://127.0.0.1/node_modules/.vite/deps/runtime-dom.esm-bundler-FHiQ_YXQ.js?v=cb5944c8:2075:17)\n at callWithAsyncErrorHandling (http://127.0.0.1/node_modules/.vite/deps/runtime-dom.esm-bundler-FHiQ_YXQ.js?v=cb5944c8:2082:15)\n at baseWatchOptions.call (http://127.0.0.1/node_modules/.vite/deps/runtime-dom.esm-bundler-FHiQ_YXQ.js?v=cb5944c8:2528:46)\n at job (http://127.0.0.1/node_modules/.vite/deps/runtime-dom.esm-bundler-FHiQ_YXQ.js?v=cb5944c8:1246:13)\n at watch$1 (http://127.0.0.1/node_modules/.vite/deps/runtime-dom.esm-bundler-FHiQ_YXQ.js?v=cb5944c8:1267:25)\n at doWatch (http://127.0.0.1/node_modules/.vite/deps/runtime-dom.esm-bundler-FHiQ_YXQ.js?v=cb5944c8:2550:22)\n at watch (http://127.0.0.1/node_modules/.vite/deps/runtime-dom.esm-bundler-FHiQ_YXQ.js?v=cb5944c8:2502:9)\n at useDeprecated (http://127.0.0.1/node_modules/.vite/deps/es-DnGNPDoU.js?v=cb5944c8:490:2)",
+ "url": "http://127.0.0.1/index"
+ },
+ {
+ "type": "warning",
+ "text": "ElementPlusError: [el-link] [API] The underline option (boolean) is about to be deprecated in version 3.0.0, please use 'always' | 'hover' | 'never' instead.\nFor more detail, please visit: https://element-plus.org/en-US/component/link.html#underline\n\n at debugWarn (http://127.0.0.1/node_modules/.vite/deps/error-Ce0Y4MfB.js?v=cb5944c8:100:35)\n at watch.immediate (http://127.0.0.1/node_modules/.vite/deps/es-DnGNPDoU.js?v=cb5944c8:491:12)\n at callWithErrorHandling (http://127.0.0.1/node_modules/.vite/deps/runtime-dom.esm-bundler-FHiQ_YXQ.js?v=cb5944c8:2075:17)\n at callWithAsyncErrorHandling (http://127.0.0.1/node_modules/.vite/deps/runtime-dom.esm-bundler-FHiQ_YXQ.js?v=cb5944c8:2082:15)\n at baseWatchOptions.call (http://127.0.0.1/node_modules/.vite/deps/runtime-dom.esm-bundler-FHiQ_YXQ.js?v=cb5944c8:2528:46)\n at job (http://127.0.0.1/node_modules/.vite/deps/runtime-dom.esm-bundler-FHiQ_YXQ.js?v=cb5944c8:1246:13)\n at watch$1 (http://127.0.0.1/node_modules/.vite/deps/runtime-dom.esm-bundler-FHiQ_YXQ.js?v=cb5944c8:1267:25)\n at doWatch (http://127.0.0.1/node_modules/.vite/deps/runtime-dom.esm-bundler-FHiQ_YXQ.js?v=cb5944c8:2550:22)\n at watch (http://127.0.0.1/node_modules/.vite/deps/runtime-dom.esm-bundler-FHiQ_YXQ.js?v=cb5944c8:2502:9)\n at useDeprecated (http://127.0.0.1/node_modules/.vite/deps/es-DnGNPDoU.js?v=cb5944c8:490:2)",
+ "url": "http://127.0.0.1/index"
+ },
+ {
+ "type": "warning",
+ "text": "ElementPlusError: [el-link] [API] The underline option (boolean) is about to be deprecated in version 3.0.0, please use 'always' | 'hover' | 'never' instead.\nFor more detail, please visit: https://element-plus.org/en-US/component/link.html#underline\n\n at debugWarn (http://127.0.0.1/node_modules/.vite/deps/error-Ce0Y4MfB.js?v=cb5944c8:100:35)\n at watch.immediate (http://127.0.0.1/node_modules/.vite/deps/es-DnGNPDoU.js?v=cb5944c8:491:12)\n at callWithErrorHandling (http://127.0.0.1/node_modules/.vite/deps/runtime-dom.esm-bundler-FHiQ_YXQ.js?v=cb5944c8:2075:17)\n at callWithAsyncErrorHandling (http://127.0.0.1/node_modules/.vite/deps/runtime-dom.esm-bundler-FHiQ_YXQ.js?v=cb5944c8:2082:15)\n at baseWatchOptions.call (http://127.0.0.1/node_modules/.vite/deps/runtime-dom.esm-bundler-FHiQ_YXQ.js?v=cb5944c8:2528:46)\n at job (http://127.0.0.1/node_modules/.vite/deps/runtime-dom.esm-bundler-FHiQ_YXQ.js?v=cb5944c8:1246:13)\n at watch$1 (http://127.0.0.1/node_modules/.vite/deps/runtime-dom.esm-bundler-FHiQ_YXQ.js?v=cb5944c8:1267:25)\n at doWatch (http://127.0.0.1/node_modules/.vite/deps/runtime-dom.esm-bundler-FHiQ_YXQ.js?v=cb5944c8:2550:22)\n at watch (http://127.0.0.1/node_modules/.vite/deps/runtime-dom.esm-bundler-FHiQ_YXQ.js?v=cb5944c8:2502:9)\n at useDeprecated (http://127.0.0.1/node_modules/.vite/deps/es-DnGNPDoU.js?v=cb5944c8:490:2)",
+ "url": "http://127.0.0.1/index"
+ },
+ {
+ "type": "warning",
+ "text": "ElementPlusError: [el-link] [API] The underline option (boolean) is about to be deprecated in version 3.0.0, please use 'always' | 'hover' | 'never' instead.\nFor more detail, please visit: https://element-plus.org/en-US/component/link.html#underline\n\n at debugWarn (http://127.0.0.1/node_modules/.vite/deps/error-Ce0Y4MfB.js?v=cb5944c8:100:35)\n at watch.immediate (http://127.0.0.1/node_modules/.vite/deps/es-DnGNPDoU.js?v=cb5944c8:491:12)\n at callWithErrorHandling (http://127.0.0.1/node_modules/.vite/deps/runtime-dom.esm-bundler-FHiQ_YXQ.js?v=cb5944c8:2075:17)\n at callWithAsyncErrorHandling (http://127.0.0.1/node_modules/.vite/deps/runtime-dom.esm-bundler-FHiQ_YXQ.js?v=cb5944c8:2082:15)\n at baseWatchOptions.call (http://127.0.0.1/node_modules/.vite/deps/runtime-dom.esm-bundler-FHiQ_YXQ.js?v=cb5944c8:2528:46)\n at job (http://127.0.0.1/node_modules/.vite/deps/runtime-dom.esm-bundler-FHiQ_YXQ.js?v=cb5944c8:1246:13)\n at watch$1 (http://127.0.0.1/node_modules/.vite/deps/runtime-dom.esm-bundler-FHiQ_YXQ.js?v=cb5944c8:1267:25)\n at doWatch (http://127.0.0.1/node_modules/.vite/deps/runtime-dom.esm-bundler-FHiQ_YXQ.js?v=cb5944c8:2550:22)\n at watch (http://127.0.0.1/node_modules/.vite/deps/runtime-dom.esm-bundler-FHiQ_YXQ.js?v=cb5944c8:2502:9)\n at useDeprecated (http://127.0.0.1/node_modules/.vite/deps/es-DnGNPDoU.js?v=cb5944c8:490:2)",
+ "url": "http://127.0.0.1/index"
+ },
+ {
+ "type": "warning",
+ "text": "ElementPlusError: [el-link] [API] The underline option (boolean) is about to be deprecated in version 3.0.0, please use 'always' | 'hover' | 'never' instead.\nFor more detail, please visit: https://element-plus.org/en-US/component/link.html#underline\n\n at debugWarn (http://127.0.0.1/node_modules/.vite/deps/error-Ce0Y4MfB.js?v=cb5944c8:100:35)\n at watch.immediate (http://127.0.0.1/node_modules/.vite/deps/es-DnGNPDoU.js?v=cb5944c8:491:12)\n at callWithErrorHandling (http://127.0.0.1/node_modules/.vite/deps/runtime-dom.esm-bundler-FHiQ_YXQ.js?v=cb5944c8:2075:17)\n at callWithAsyncErrorHandling (http://127.0.0.1/node_modules/.vite/deps/runtime-dom.esm-bundler-FHiQ_YXQ.js?v=cb5944c8:2082:15)\n at baseWatchOptions.call (http://127.0.0.1/node_modules/.vite/deps/runtime-dom.esm-bundler-FHiQ_YXQ.js?v=cb5944c8:2528:46)\n at job (http://127.0.0.1/node_modules/.vite/deps/runtime-dom.esm-bundler-FHiQ_YXQ.js?v=cb5944c8:1246:13)\n at watch$1 (http://127.0.0.1/node_modules/.vite/deps/runtime-dom.esm-bundler-FHiQ_YXQ.js?v=cb5944c8:1267:25)\n at doWatch (http://127.0.0.1/node_modules/.vite/deps/runtime-dom.esm-bundler-FHiQ_YXQ.js?v=cb5944c8:2550:22)\n at watch (http://127.0.0.1/node_modules/.vite/deps/runtime-dom.esm-bundler-FHiQ_YXQ.js?v=cb5944c8:2502:9)\n at useDeprecated (http://127.0.0.1/node_modules/.vite/deps/es-DnGNPDoU.js?v=cb5944c8:490:2)",
+ "url": "http://127.0.0.1/index"
+ },
+ {
+ "type": "warning",
+ "text": "ElementPlusError: [el-link] [API] The underline option (boolean) is about to be deprecated in version 3.0.0, please use 'always' | 'hover' | 'never' instead.\nFor more detail, please visit: https://element-plus.org/en-US/component/link.html#underline\n\n at debugWarn (http://127.0.0.1/node_modules/.vite/deps/error-Ce0Y4MfB.js?v=cb5944c8:100:35)\n at watch.immediate (http://127.0.0.1/node_modules/.vite/deps/es-DnGNPDoU.js?v=cb5944c8:491:12)\n at callWithErrorHandling (http://127.0.0.1/node_modules/.vite/deps/runtime-dom.esm-bundler-FHiQ_YXQ.js?v=cb5944c8:2075:17)\n at callWithAsyncErrorHandling (http://127.0.0.1/node_modules/.vite/deps/runtime-dom.esm-bundler-FHiQ_YXQ.js?v=cb5944c8:2082:15)\n at baseWatchOptions.call (http://127.0.0.1/node_modules/.vite/deps/runtime-dom.esm-bundler-FHiQ_YXQ.js?v=cb5944c8:2528:46)\n at job (http://127.0.0.1/node_modules/.vite/deps/runtime-dom.esm-bundler-FHiQ_YXQ.js?v=cb5944c8:1246:13)\n at watch$1 (http://127.0.0.1/node_modules/.vite/deps/runtime-dom.esm-bundler-FHiQ_YXQ.js?v=cb5944c8:1267:25)\n at doWatch (http://127.0.0.1/node_modules/.vite/deps/runtime-dom.esm-bundler-FHiQ_YXQ.js?v=cb5944c8:2550:22)\n at watch (http://127.0.0.1/node_modules/.vite/deps/runtime-dom.esm-bundler-FHiQ_YXQ.js?v=cb5944c8:2502:9)\n at useDeprecated (http://127.0.0.1/node_modules/.vite/deps/es-DnGNPDoU.js?v=cb5944c8:490:2)",
+ "url": "http://127.0.0.1/index"
+ }
+ ],
+ "vben": [
+ {
+ "type": "warning",
+ "text": "[StorageManager] empty prefix combined with LocalStorageDriver — clear()/keys() will affect every localStorage entry.",
+ "url": "http://127.0.0.1:5666/"
+ }
+ ]
+ },
+ "requests": {
+ "vue3": [],
+ "vben": []
+ },
+ "screenshots": {},
+ "checks": {},
+ "error": "locator.click: Timeout 30000ms exceeded.\nCall log:\n\u001b[2m - waiting for getByRole('button', { name: /^登录\\s*$/ }).first()\u001b[22m\n\n at login (/Users/yunai/Java/yudao-all-in-vben/yudao-ui-admin-vben/[eval1]:49:63)\n at async file:///Users/yunai/Java/yudao-all-in-vben/yudao-ui-admin-vben/[eval1]:115:3"
+}
\ No newline at end of file