diff --git a/eslint.config.mjs b/eslint.config.mjs index 87afdc853..f0bdb944e 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -17,24 +17,24 @@ const __dirname = path.dirname(__filename) const compat = new FlatCompat({ baseDirectory: __dirname, recommendedConfig: js.configs.recommended, - allConfig: js.configs.all, + allConfig: js.configs.all }) // npx @eslint/migrate-config .eslintrc.json export default [ { - ignores: ['node_modules/**/*', '**/CHANGELOG.md', '**/package-lock.json', 'dist/**/*', 'build/**/*', '**/coverage'], + ignores: ['node_modules/**/*', '**/CHANGELOG.md', '**/package-lock.json', 'dist/**/*', 'build/**/*', '**/coverage'] }, ...compat.extends('plugin:react/recommended', 'prettier'), { plugins: { react, '@typescript-eslint': typescriptEslint, - 'react-hooks': fixupPluginRules(reactHooks), + 'react-hooks': fixupPluginRules(reactHooks) }, languageOptions: { globals: { - ...globals.browser, + ...globals.browser }, parser: tsParser, @@ -43,15 +43,15 @@ export default [ parserOptions: { ecmaFeatures: { - jsx: true, - }, - }, + jsx: true + } + } }, settings: { react: { - version: 'detect', - }, + version: 'detect' + } }, rules: { @@ -87,8 +87,8 @@ export default [ 'no-inner-declarations': 'off', 'no-unused-expressions': 'off', 'no-unused-vars': 'off', - 'no-plusplus': 'off', - }, + 'no-plusplus': 'off' + } }, - ...storybook.configs['flat/recommended'], + ...storybook.configs['flat/recommended'] ] diff --git a/jest.config.cjs b/jest.config.cjs index bdb1802c1..38ac887eb 100644 --- a/jest.config.cjs +++ b/jest.config.cjs @@ -2,13 +2,13 @@ module.exports = { testEnvironment: 'jsdom', collectCoverage: true, transform: { - '^.+\\.(t|j)sx?$': 'babel-jest', + '^.+\\.(t|j)sx?$': 'babel-jest' }, moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'json'], moduleNameMapper: { '\\.(css|less|scss)$': '/jest/styleMock.js', - '^@\\/(.*)$': '/src/$1', + '^@\\/(.*)$': '/src/$1' }, testPathIgnorePatterns: ['/tests/e2e/'], - setupFilesAfterEnv: ['/jest/setupTests.js'], + setupFilesAfterEnv: ['/jest/setupTests.js'] } diff --git a/scripts/depcheck.mjs b/scripts/depcheck.mjs index 0cfe205dc..5c9bd8c69 100644 --- a/scripts/depcheck.mjs +++ b/scripts/depcheck.mjs @@ -59,7 +59,7 @@ const buildScriptDeps = () => { const depNames = [ ...Object.keys(pkg.dependencies || {}), ...Object.keys(pkg.devDependencies || {}), - ...Object.keys(pkg.optionalDependencies || {}), + ...Object.keys(pkg.optionalDependencies || {}) ] for (const name of depNames) { @@ -112,7 +112,7 @@ const buildConfigDeps = () => { const depNames = [ ...Object.keys(pkg.dependencies || {}), ...Object.keys(pkg.devDependencies || {}), - ...Object.keys(pkg.optionalDependencies || {}), + ...Object.keys(pkg.optionalDependencies || {}) ] const files = [] @@ -192,7 +192,7 @@ const report = await new Promise((resolve, reject) => { 'storybook-static', 'coverage', 'playwright-report', - 'test-results', + 'test-results' ], // Avoid the ttypescript special (it reads tsconfig.json as strict JSON and can fail on JSONC). specials: [ @@ -203,8 +203,8 @@ const report = await new Promise((resolve, reject) => { depcheck.special.webpack, depcheck.special.husky, depcheck.special.prettier, - depcheck.special.commitizen, - ], + depcheck.special.commitizen + ] }, (unused) => resolve(unused) ) @@ -221,7 +221,7 @@ const ignoreMissingPrefixes = [ '@assets/', '@app-hooks/', '@container/', - '@theme/', + '@theme/' ] const pickArray = (key) => { diff --git a/scripts/optimize-media.mjs b/scripts/optimize-media.mjs index 08c501746..77cad714f 100644 --- a/scripts/optimize-media.mjs +++ b/scripts/optimize-media.mjs @@ -21,14 +21,14 @@ const MP4_AUDIO_BITRATE = process.env.MP4_AUDIO_BITRATE || '128k' const MIN_SAVINGS_PCT = Number(process.env.MEDIA_MIN_SAVINGS_PCT || '5') const SKIP_SMALL_KB = Number(process.env.MEDIA_SKIP_SMALL_KB || '256') -function bytesToMiB(bytes) { +function bytesToMiB (bytes) { return (bytes / 1024 / 1024).toFixed(2) } -function runFfmpeg(args) { +function runFfmpeg (args) { const result = spawnSync('ffmpeg', args, { stdio: 'inherit', - windowsHide: true, + windowsHide: true }) if (result.error) { throw result.error @@ -38,7 +38,7 @@ function runFfmpeg(args) { } } -function isFileExists(filePath) { +function isFileExists (filePath) { try { fsSync.accessSync(filePath) return true @@ -47,29 +47,29 @@ function isFileExists(filePath) { } } -async function ensureDir(dirPath) { +async function ensureDir (dirPath) { await fs.mkdir(dirPath, { recursive: true }) } -async function cleanDir(dirPath) { +async function cleanDir (dirPath) { await fs.rm(dirPath, { recursive: true, force: true }) await ensureDir(dirPath) } -async function* walkFiles(dirPath) { +async function * walkFiles (dirPath) { if (!isFileExists(dirPath)) return const entries = await fs.readdir(dirPath, { withFileTypes: true }) for (const entry of entries) { const fullPath = path.join(dirPath, entry.name) if (entry.isDirectory()) { - yield* walkFiles(fullPath) + yield * walkFiles(fullPath) } else if (entry.isFile()) { yield fullPath } } } -async function optimizeOne({ inputPath, inputBaseDir, outputBaseDir }) { +async function optimizeOne ({ inputPath, inputBaseDir, outputBaseDir }) { const relPath = path.relative(inputBaseDir, inputPath) const outputPath = path.join(outputBaseDir, relPath) @@ -111,7 +111,7 @@ async function optimizeOne({ inputPath, inputBaseDir, outputBaseDir }) { MP3_BITRATE, '-id3v2_version', '3', - tmpPath, + tmpPath ]) } else { // Re-encode MP4 (H.264 + AAC) and enable faststart @@ -133,7 +133,7 @@ async function optimizeOne({ inputPath, inputBaseDir, outputBaseDir }) { MP4_AUDIO_BITRATE, '-movflags', '+faststart', - tmpPath, + tmpPath ]) } @@ -151,12 +151,12 @@ async function optimizeOne({ inputPath, inputBaseDir, outputBaseDir }) { return { changed: true, reason: 'optimized', before: stat.size, after: outStat.size, outputPath } } -function checkFfmpegAvailable() { +function checkFfmpegAvailable () { const result = spawnSync('ffmpeg', ['-version'], { stdio: 'ignore', windowsHide: true }) return result.status === 0 } -async function main() { +async function main () { if (!checkFfmpegAvailable()) { console.error('[optimize:media] ffmpeg not found in PATH.') console.error('Install ffmpeg and ensure `ffmpeg` is available in your terminal, then re-run.') @@ -167,7 +167,7 @@ async function main() { const targets = [ { inputDir: SRC_AUDIO_DIR, outputDir: OUT_AUDIO_DIR }, { inputDir: SRC_VIDEO_DIR, outputDir: OUT_VIDEO_DIR }, - { inputDir: SRC_PUBLIC_AUDIO_DIR, outputDir: OUT_PUBLIC_AUDIO_DIR }, + { inputDir: SRC_PUBLIC_AUDIO_DIR, outputDir: OUT_PUBLIC_AUDIO_DIR } ] let changedCount = 0 @@ -188,7 +188,7 @@ async function main() { const result = await optimizeOne({ inputPath, inputBaseDir: target.inputDir, - outputBaseDir: target.outputDir, + outputBaseDir: target.outputDir }) if (result.changed) { changedCount += 1 diff --git a/scripts/prepare-lib-publish.mjs b/scripts/prepare-lib-publish.mjs index 35d7ad680..21298a0eb 100644 --- a/scripts/prepare-lib-publish.mjs +++ b/scripts/prepare-lib-publish.mjs @@ -1,7 +1,7 @@ import fs from 'node:fs/promises' import path from 'node:path' -async function fileExists(filePath) { +async function fileExists (filePath) { try { await fs.access(filePath) return true @@ -10,11 +10,11 @@ async function fileExists(filePath) { } } -function pickDefined(obj) { +function pickDefined (obj) { return Object.fromEntries(Object.entries(obj).filter(([, v]) => v !== undefined)) } -async function main() { +async function main () { const repoRoot = process.cwd() const rootPkgPath = path.join(repoRoot, 'package.json') const distDir = path.join(repoRoot, 'dist-lib') @@ -46,25 +46,25 @@ async function main() { '.': { types: './index.d.ts', import: './pro-react-components.es.js', - require: './pro-react-components.umd.js', + require: './pro-react-components.umd.js' }, './core': { types: './entries/core.d.ts', import: './entries/core.es.js', - require: './entries/core.cjs.js', + require: './entries/core.cjs.js' }, './stateful': { types: './entries/stateful.d.ts', import: './entries/stateful.es.js', - require: './entries/stateful.cjs.js', + require: './entries/stateful.cjs.js' }, './stateless': { types: './entries/stateless.d.ts', import: './entries/stateless.es.js', - require: './entries/stateless.cjs.js', + require: './entries/stateless.cjs.js' }, - './style.css': './style.css', - }, + './style.css': './style.css' + } } const distPkgPath = path.join(distDir, 'package.json') diff --git a/scripts/run-lighthouse.mjs b/scripts/run-lighthouse.mjs index 58d1317f4..5f204619d 100644 --- a/scripts/run-lighthouse.mjs +++ b/scripts/run-lighthouse.mjs @@ -9,7 +9,10 @@ const buildPortList = () => { const raw = process.env.LH_PORTS if (raw && raw.trim()) { // supports: "8080,8081,8090" or "8080-8090" - const parts = raw.split(',').map((s) => s.trim()).filter(Boolean) + const parts = raw + .split(',') + .map((s) => s.trim()) + .filter(Boolean) const ports = [] for (const part of parts) { const range = part.split('-').map((s) => s.trim()) @@ -48,8 +51,8 @@ const fetchOk = async (url) => { signal: controller.signal, headers: { // Some dev servers behave differently for default fetch UA. - 'User-Agent': 'wui-react-lighthouse-probe', - }, + 'User-Agent': 'wui-react-lighthouse-probe' + } }) if (!res.ok) return false const text = await res.text() @@ -104,7 +107,7 @@ const runLighthouse = (url) => { const args = ['--view', url, '--preset=desktop'] const result = spawnSync('lighthouse', args, { stdio: 'inherit', - shell: process.platform === 'win32', + shell: process.platform === 'win32' }) process.exit(result.status ?? 1) diff --git a/src/components/KeepAlive/index.jsx b/src/components/KeepAlive/index.jsx index f67ac3b97..f80bea9e9 100644 --- a/src/components/KeepAlive/index.jsx +++ b/src/components/KeepAlive/index.jsx @@ -88,15 +88,16 @@ const createKeepAliveManager = () => { // set global options: { deactivateDelay, keepInactiveCount, limit } setOptions: (opts = {}) => { if (typeof opts.deactivateDelay === 'number') deactivateDelay = opts.deactivateDelay - if (typeof opts.keepInactiveCount === 'number') + if (typeof opts.keepInactiveCount === 'number') { keepInactiveCount = Math.max(0, Math.floor(opts.keepInactiveCount)) + } if (typeof opts.limit === 'number') limit = Math.max(0, Math.floor(opts.limit)) }, register: (id, opts) => { // opts: { setShouldRender, persistOnUnmount } instances.set(id, { setShouldRender: opts.setShouldRender, - persistOnUnmount: !!opts.persistOnUnmount, + persistOnUnmount: !!opts.persistOnUnmount }) }, unregister: (id) => { @@ -196,7 +197,7 @@ const createKeepAliveManager = () => { instances.delete(id) activeMap.delete(id) keys = keys.filter((k) => k !== id) - }, + } } } @@ -239,7 +240,7 @@ const KeepAlive = ({ id, active = false, children, persistOnUnmount = false, cac const effectivePersist = ActivityComponent ? true : persistOnUnmount keepAliveManager.register(id, { setShouldRender, - persistOnUnmount: effectivePersist, + persistOnUnmount: effectivePersist }) } return () => { @@ -308,14 +309,14 @@ const KeepAlive = ({ id, active = false, children, persistOnUnmount = false, cac if (!active) return scrollPos.current.set(e.target, { left: e.target.scrollLeft, - top: e.target.scrollTop, + top: e.target.scrollTop }) } // Capture scroll events to record positions container.addEventListener('scroll', onScroll, { capture: true, - passive: true, + passive: true }) return () => { @@ -359,7 +360,7 @@ const KeepAlive = ({ id, active = false, children, persistOnUnmount = false, cac if (container.parentNode !== placeholder) { // 在移动DOM之前,发送自定义事件通知子组件 const event = new CustomEvent('keepalive-dom-move', { - detail: { from: container.parentNode, to: placeholder }, + detail: { from: container.parentNode, to: placeholder } }) container.dispatchEvent(event) @@ -429,7 +430,7 @@ KeepAlive.propTypes = { active: PropTypes.bool, children: PropTypes.node, persistOnUnmount: PropTypes.bool, - cacheLimit: PropTypes.number, + cacheLimit: PropTypes.number } export default KeepAlive diff --git a/src/components/hooks/useRemoveGlobalLoader.js b/src/components/hooks/useRemoveGlobalLoader.js index cd79d8afb..3fb2adc22 100644 --- a/src/components/hooks/useRemoveGlobalLoader.js +++ b/src/components/hooks/useRemoveGlobalLoader.js @@ -20,7 +20,7 @@ export const useRemoveGlobalLoader = () => { } loader.addEventListener('transitionend', handleTransitionEnd, { - once: true, + once: true }) // 兜底:如果动画没触发(例如页面不可见),强制移除 diff --git a/src/components/stateless/FixMusicPlayer/SongCard.jsx b/src/components/stateless/FixMusicPlayer/SongCard.jsx index 5ad0590bc..14ee0a6e1 100644 --- a/src/components/stateless/FixMusicPlayer/SongCard.jsx +++ b/src/components/stateless/FixMusicPlayer/SongCard.jsx @@ -8,44 +8,43 @@ const SongCard = ({ song, isPlaying, isActive, onClick, themeMode, textColor, se return (
-
+
song_img
- {isCurrentSong ? ( - - ) : ( - - )} + {isCurrentSong + ? ( + + ) + : ( + + )}
{isCurrentSong && ( -
-
+
+
)}
-
-

+

+

{song.title}

-

+

{song.subtitle}

diff --git a/src/components/stateless/NotificationDrawer/index.jsx b/src/components/stateless/NotificationDrawer/index.jsx index b9ca19084..bc14fa9fa 100644 --- a/src/components/stateless/NotificationDrawer/index.jsx +++ b/src/components/stateless/NotificationDrawer/index.jsx @@ -10,36 +10,36 @@ const initialNotifications = [ title: '欢迎使用 Pro React Admin', description: '感谢您的体验与支持!', read: false, - time: '1分钟前', + time: '1分钟前' }, { id: 2, title: '新功能上线', description: '全站菜单查询功能全新上线,支持快速定位与跳转!', read: false, - time: '5分钟前', + time: '5分钟前' }, { id: 3, title: '新功能上线', description: 'ResponsiveTable高复用表格上线,欢迎试用!', read: false, - time: '10分钟前', + time: '10分钟前' }, { id: 4, title: '新功能上线', description: '权限系统与主题切换已支持。', read: false, - time: '15分钟前', + time: '15分钟前' }, { id: 5, title: '文档更新', description: 'README.md 已优化,欢迎查阅。', read: true, - time: '1天前', - }, + time: '1天前' + } ] const NotificationDropdown = ({ iconColor, variant = 'inline', buttonStyle, ghost = false }) => { @@ -76,7 +76,7 @@ const NotificationDropdown = ({ iconColor, variant = 'inline', buttonStyle, ghos } const { - token: { colorBgContainer, colorBorder, colorText, colorTextSecondary, colorTextTertiary }, + token: { colorBgContainer, colorBorder, colorText, colorTextSecondary, colorTextTertiary } } = theme.useToken() // content structure: header (optional) / list (scrollable) / footer (fixed) @@ -87,68 +87,70 @@ const NotificationDropdown = ({ iconColor, variant = 'inline', buttonStyle, ghos backgroundColor: colorBgContainer, color: colorText, display: 'flex', - flexDirection: 'column', + flexDirection: 'column' }} >
- {notifications.length === 0 ? ( -
- 暂无通知 -
- ) : ( - notifications.slice(0, MAX_ITEMS).map((item) => ( - - )) - )} + 暂无通知 +
+ ) + : ( + notifications.slice(0, MAX_ITEMS).map((item) => ( + + )) + )}
- - - @@ -177,56 +179,58 @@ const NotificationDropdown = ({ iconColor, variant = 'inline', buttonStyle, ghos const openDrawer = () => setPopVisible(true) const iconNode = ( - + ) const triggerNode = - variant === 'button' ? ( - - ) : ( - - ) + variant === 'button' + ? ( + + ) + : ( + + ) return ( <> {triggerNode} setPopVisible(false)} open={popVisible} size={360} @@ -242,7 +246,7 @@ NotificationDropdown.propTypes = { iconColor: PropTypes.string, variant: PropTypes.oneOf(['inline', 'button']), buttonStyle: PropTypes.object, - ghost: PropTypes.bool, + ghost: PropTypes.bool } export default NotificationDropdown diff --git a/src/components/stateless/PieNestCharts/index.jsx b/src/components/stateless/PieNestCharts/index.jsx index 1cb5078ef..55f2d9134 100644 --- a/src/components/stateless/PieNestCharts/index.jsx +++ b/src/components/stateless/PieNestCharts/index.jsx @@ -28,11 +28,11 @@ const PieNestChart = ({ data = [], height = '100%', eOptions = {} }) => { const defaultOption = { tooltip: { - show: false, + show: false }, legend: { show: false, - ...eOptions?.options?.legend, + ...eOptions?.options?.legend }, series: eOptions?.options?.series?.map((item, index) => { if (index === 0) { @@ -43,8 +43,8 @@ const PieNestChart = ({ data = [], height = '100%', eOptions = {} }) => { radius: [0, '24%'], emphasis: { label: { - show: true, - }, + show: true + } }, label: { show: true, @@ -52,27 +52,27 @@ const PieNestChart = ({ data = [], height = '100%', eOptions = {} }) => { fontSize: 14, formatter: '{a|{b}}', rich: { - a: { color: '#fff', fontSize: 12 }, + a: { color: '#fff', fontSize: 12 } }, - ...item.label, + ...item.label }, labelLine: { - show: false, + show: false }, itemStyle: { borderColor: '#fff', - borderWidth: 2, + borderWidth: 2 }, data: item?.data?.map((temp, idx) => ({ ...temp, - itemStyle: { color: innerColors[idx % innerColors.length] }, + itemStyle: { color: innerColors[idx % innerColors.length] } })), tooltip: { show: false, trigger: 'item', formatter: (params) => `${params.name}: ${params.value}(${params.percent}%)`, - ...item?.tooltip, - }, + ...item?.tooltip + } } } else { return { @@ -81,7 +81,7 @@ const PieNestChart = ({ data = [], height = '100%', eOptions = {} }) => { radius: ['24%', '40%'], labelLine: { length: 30, - length2: 60, + length2: 60 }, label: { show: false, @@ -92,40 +92,40 @@ const PieNestChart = ({ data = [], height = '100%', eOptions = {} }) => { color: '#fff', fontSize: 14, fontWeight: 'bold', - lineHeight: 33, - }, + lineHeight: 33 + } }, - ...item?.label, + ...item?.label }, labelLayout: (params) => { return { hideOverlap: true, - moveOverlap: true, + moveOverlap: true } }, emphasis: { label: { - show: true, - }, + show: true + } }, itemStyle: { opacity: 0.8, borderColor: '#fff', - borderWidth: 2, + borderWidth: 2 }, data: item?.data?.map((temp, idx) => ({ ...temp, - itemStyle: { color: outerColors[idx % outerColors.length] }, + itemStyle: { color: outerColors[idx % outerColors.length] } })), tooltip: { show: false, trigger: 'item', formatter: (params) => `${params.name}: ${params.value}(${params.percent}%)`, - ...item?.tooltip, - }, + ...item?.tooltip + } } } - }), + }) } myChartRef.current.setOption(defaultOption) diff --git a/src/components/stateless/SmartVideoPlayer/index.jsx b/src/components/stateless/SmartVideoPlayer/index.jsx index 7273642b7..21bc677ae 100644 --- a/src/components/stateless/SmartVideoPlayer/index.jsx +++ b/src/components/stateless/SmartVideoPlayer/index.jsx @@ -17,13 +17,13 @@ import { PictureInPicture, ExternalLink, X, - Minimize2, + Minimize2 } from 'lucide-react' import * as stylesModule from './index.module.less' import { createSvpI18n, setStoredSvpUiLanguage } from './svpI18n' -function unwrapCssModule(mod) { +function unwrapCssModule (mod) { if (!mod) return null const candidates = [] @@ -50,10 +50,10 @@ function unwrapCssModule(mod) { const stylesRaw = unwrapCssModule(stylesModule) || {} const styles = new Proxy(stylesRaw, { - get(target, prop) { + get (target, prop) { if (typeof prop !== 'string') return target[prop] return target[prop] || prop - }, + } }) const DEFAULT_INITIAL_CONFIG = { @@ -62,10 +62,10 @@ const DEFAULT_INITIAL_CONFIG = { autoPlay: true, autoMute: true, playbackRate: 1, - ytControls: true, + ytControls: true } -function isSameConfig(a, b) { +function isSameConfig (a, b) { if (a === b) return true if (!a || !b) return false return ( @@ -78,13 +78,13 @@ function isSameConfig(a, b) { ) } -const IconButton = React.memo(function IconButton({ +const IconButton = React.memo(function IconButton ({ Icon, label, onClick, disabled = false, buttonRef, - tooltipPlacement = 'top', + tooltipPlacement = 'top' }) { const tooltipPlacementClass = tooltipPlacement === 'topLeft' @@ -107,7 +107,7 @@ const IconButton = React.memo(function IconButton({ - {speedOpen ? ( -
- {[0.5, 0.75, 1, 1.25, 1.5, 2].map((rate) => { - const active = Number(config.playbackRate ?? 1) === rate - return ( - - ) - })} -
- ) : null} + {speedOpen + ? ( +
+ {[0.5, 0.75, 1, 1.25, 1.5, 2].map((rate) => { + const active = Number(config.playbackRate ?? 1) === rate + return ( + + ) + })} +
+ ) + : null}
- ) : null} + ) + : null} - {!isEmbed && captionTracks.length > 0 ? ( + {!isEmbed && captionTracks.length > 0 + ? (
{t('svp.captions')} -
+
- {captionsOpen ? ( -
- - - {captionTracks.map((t) => { - const active = captionsEnabled && captionTrackIndex === t.index - return ( - - ) - })} -
- ) : null} -
-
- ) : null} - -
- {t('svp.uiLanguage')} -
- + + {captionTracks.map((t) => { + const active = captionsEnabled && captionTrackIndex === t.index + return ( + + ) + })} +
+ ) + : null} +
+
+ ) + : null} - {uiLangOpen ? ( -
+
+ {t('svp.uiLanguage')} +
+ + + {uiLangOpen + ? ( +
- ) : null} -
+ ) + : null}
+
-
- {!isEmbed ? ( +
+ {!isEmbed + ? ( <> setConfigItem('miniPlayer', v)} /> - ) : isYouTube ? ( - setConfigItem('ytControls', v)} - /> - ) : null} - setConfigItem('autoPlay', v)} - /> - setConfigItem('autoMute', v)} - /> -
-
, - document.body - ) + ) + : isYouTube + ? ( + setConfigItem('ytControls', v)} + /> + ) + : null} + setConfigItem('autoPlay', v)} + /> + setConfigItem('autoMute', v)} + /> +
+
, + document.body + ) : null return ( <> - {!isMini && config.miniPlayer && fullyOut && !isPiP && miniDismissed ? ( -
- -
- ) : null} + {!isMini && config.miniPlayer && fullyOut && !isPiP && miniDismissed + ? ( +
+ +
+ ) + : null}
{isMini ?
: null} @@ -1726,247 +1742,293 @@ const SmartVideoPlayerInner = React.forwardRef(function SmartVideoPlayerInner( className={`${styles.videoWrap} ${isMini ? styles.mini : ''} ${settingsOpen ? styles.controlsPinnedWrap : ''}`} tabIndex={0} onKeyDown={handlePlayerKeyDown} - role="region" + role='region' aria-label={t('svp.ariaPlayer')} > - {isEmbed ? ( - computedEmbedSrc ? ( -
-