提交 506c37f5 authored 作者: 王鹏飞's avatar 王鹏飞

chore: update pnpm-workspace.yaml to exclude minimum release age for vite@8.2.2

上级 91d8ca2c
...@@ -55,10 +55,10 @@ ...@@ -55,10 +55,10 @@
"@vitejs/plugin-react": "^6.0.5", "@vitejs/plugin-react": "^6.0.5",
"jsdom": "^29.1.1", "jsdom": "^29.1.1",
"less": "^4.2.0", "less": "^4.2.0",
"oxfmt": "^0.59.0", "oxfmt": "^0.64.0",
"oxlint": "^1.74.0", "oxlint": "^1.79.0",
"typescript": "^7.0.2", "typescript": "^7.0.2",
"vite": "^8.2.1", "vite": "^8.2.2",
"vite-plugin-mkcert": "^2.1.0", "vite-plugin-mkcert": "^2.1.0",
"vitest": "^4.1.10" "vitest": "^4.1.10"
} }
......
...@@ -70,14 +70,6 @@ dd { ...@@ -70,14 +70,6 @@ dd {
display: inline-block !important; display: inline-block !important;
} }
.ant-space-item {
.ant-btn.css-dev-only-do-not-override-1scgnrh {
display: flex;
align-items: center;
justify-content: center;
}
}
.form-devices-inline { .form-devices-inline {
.ant-form-inline { .ant-form-inline {
.ant-form-item { .ant-form-item {
......
...@@ -2,13 +2,13 @@ ...@@ -2,13 +2,13 @@
.wrap-phone-privew { .wrap-phone-privew {
.ant-modal { .ant-modal {
.ant-modal-close { .phone-close {
inset-inline-end: 17px; inset-inline-end: 17px;
top: 0px; top: 0;
right: 0; right: 0;
} }
.ant-modal-content { .phone-content {
background: url('@/assets/images/phone_6.7.png') no-repeat; background: url('@/assets/images/phone_6.7.png') no-repeat;
background-size: 100% 100%; background-size: 100% 100%;
box-shadow: none; box-shadow: none;
...@@ -16,7 +16,7 @@ ...@@ -16,7 +16,7 @@
border-radius: 48px; border-radius: 48px;
padding: 36px 32px 34px 32px; padding: 36px 32px 34px 32px;
} }
.priview-modal { .preview-modal {
padding-top: 40px; padding-top: 40px;
width: 430px; width: 430px;
height: 932px; height: 932px;
...@@ -33,7 +33,7 @@ ...@@ -33,7 +33,7 @@
width: 430px; width: 430px;
border-radius: 30px; border-radius: 30px;
} }
.previee-container { .preview-container {
height: 100%; height: 100%;
overflow: hidden; overflow: hidden;
position: relative; position: relative;
...@@ -431,7 +431,7 @@ ...@@ -431,7 +431,7 @@
} }
// 画廊展示 // 画廊展示
.gallery-prview-container { .gallery-preview-container {
.gallery-img { .gallery-img {
max-height: 300px; max-height: 300px;
height: 300px; height: 300px;
...@@ -680,17 +680,17 @@ ...@@ -680,17 +680,17 @@
} }
} }
.priview-drawer-container { .preview-drawer-container {
height: 932px; height: 932px;
top: 42px; top: 42px;
left: 0px; left: 0px;
width: 430px; width: 430px;
border-radius: 15px 0 40px 40px; border-radius: 15px 0 40px 40px;
overflow: hidden; overflow: hidden;
.priview-drawer-header { .preview-drawer-header {
padding: 10px; padding: 10px;
} }
.priview-drawer-body { .preview-drawer-body {
padding: 10px; padding: 10px;
height: 100%; height: 100%;
overflow-x: hidden; overflow-x: hidden;
......
...@@ -45,6 +45,7 @@ export default function DigitalHumanDialog({ editor }) { ...@@ -45,6 +45,7 @@ export default function DigitalHumanDialog({ editor }) {
footer={null} footer={null}
width={1600} width={1600}
className='digital-human-modal' className='digital-human-modal'
classNames={{ container: 'digital-human-container', body: 'digital-human-body' }}
centered centered
destroyOnHidden destroyOnHidden
> >
......
...@@ -74,6 +74,10 @@ export default function DigitalHumanFigureField({ figures, loading, value, onCha ...@@ -74,6 +74,10 @@ export default function DigitalHumanFigureField({ figures, loading, value, onCha
onCancel={() => setOpen(false)} onCancel={() => setOpen(false)}
width={920} width={920}
className='digital-human-picker-modal figure-picker-modal' className='digital-human-picker-modal figure-picker-modal'
classNames={{
container: 'digital-human-picker-container',
body: 'digital-human-picker-body figure-picker-body',
}}
> >
{loading && figures.length === 0 ? ( {loading && figures.length === 0 ? (
<div className='picker-loading'> <div className='picker-loading'>
......
...@@ -151,6 +151,10 @@ export default function DigitalHumanVoiceSettings({ ...@@ -151,6 +151,10 @@ export default function DigitalHumanVoiceSettings({
onCancel={() => setOpen(false)} onCancel={() => setOpen(false)}
width={620} width={620}
className='digital-human-picker-modal voice-picker-modal' className='digital-human-picker-modal voice-picker-modal'
classNames={{
container: 'digital-human-picker-container',
body: 'digital-human-picker-body',
}}
> >
<div className='picker-tabs' role='tablist' aria-label='声音性别'> <div className='picker-tabs' role='tablist' aria-label='声音性别'>
<button <button
......
...@@ -8,12 +8,12 @@ ...@@ -8,12 +8,12 @@
--dh-canvas: #f8f6f7; --dh-canvas: #f8f6f7;
max-width: calc(100vw - 24px); max-width: calc(100vw - 24px);
.ant-modal-content { .digital-human-container {
overflow: hidden; overflow: hidden;
border-radius: 10px; border-radius: 10px;
} }
.ant-modal-body { .digital-human-body {
max-height: calc(100vh - 96px); max-height: calc(100vh - 96px);
overflow-y: auto; overflow-y: auto;
overscroll-behavior: contain; overscroll-behavior: contain;
...@@ -988,17 +988,17 @@ ...@@ -988,17 +988,17 @@
} }
.digital-human-picker-modal { .digital-human-picker-modal {
.ant-modal-content { .digital-human-picker-container {
border-radius: 14px; border-radius: 14px;
} }
.ant-modal-body { .digital-human-picker-body {
max-height: 65vh; max-height: 65vh;
overflow-y: auto; overflow-y: auto;
} }
} }
.figure-picker-modal .ant-modal-body { .figure-picker-modal .figure-picker-body {
overflow: hidden; overflow: hidden;
} }
...@@ -1178,7 +1178,7 @@ ...@@ -1178,7 +1178,7 @@
width: calc(100vw - 24px) !important; width: calc(100vw - 24px) !important;
max-width: calc(100vw - 24px); max-width: calc(100vw - 24px);
.ant-modal-body { .digital-human-body {
padding: 12px; padding: 12px;
} }
} }
......
...@@ -19,9 +19,6 @@ const AudioModal = ({ open, onClose, payload = {}, runtime }) => { ...@@ -19,9 +19,6 @@ const AudioModal = ({ open, onClose, payload = {}, runtime }) => {
const fileAccept = ['.mp3', '.wav', '.ogg'] const fileAccept = ['.mp3', '.wav', '.ogg']
const [form] = Form.useForm() const [form] = Form.useForm()
const [uploading, setUploading] = useState(false) // 文件上传状态 const [uploading, setUploading] = useState(false) // 文件上传状态
const [progress, setProgress] = useState(0)
const [file, setFile] = useState({})
const [audioUrl, setAudioUrl] = useState('') const [audioUrl, setAudioUrl] = useState('')
useEffect(() => { useEffect(() => {
...@@ -44,17 +41,21 @@ const AudioModal = ({ open, onClose, payload = {}, runtime }) => { ...@@ -44,17 +41,21 @@ const AudioModal = ({ open, onClose, payload = {}, runtime }) => {
message.error('请上传正确格式的音频文件') message.error('请上传正确格式的音频文件')
return false return false
} }
setProgress(0) return true
setUploading(false)
setFile(file)
}, },
customRequest: async () => { customRequest: async ({ file, onSuccess, onError }) => {
setUploading(true) setUploading(true)
try {
const url = await uploadFile(file) const url = await uploadFile(file)
setAudioUrl(url) setAudioUrl(url)
form.setFieldsValue({ audioUrl: url }) form.setFieldsValue({ audioUrl: url })
onSuccess?.({ url })
} catch (error) {
message.error('音频上传失败,请重试')
onError?.(error instanceof Error ? error : new Error('音频上传失败'))
} finally {
setUploading(false) setUploading(false)
}
}, },
} }
...@@ -80,7 +81,6 @@ const AudioModal = ({ open, onClose, payload = {}, runtime }) => { ...@@ -80,7 +81,6 @@ const AudioModal = ({ open, onClose, payload = {}, runtime }) => {
children: [{ text: '' }], children: [{ text: '' }],
}) })
setAudioUrl('') setAudioUrl('')
setProgress(0)
setUploading(false) setUploading(false)
form.resetFields() form.resetFields()
onClose() onClose()
...@@ -106,7 +106,7 @@ const AudioModal = ({ open, onClose, payload = {}, runtime }) => { ...@@ -106,7 +106,7 @@ const AudioModal = ({ open, onClose, payload = {}, runtime }) => {
<div className='editor-content-form'> <div className='editor-content-form'>
<Form layout='vertical' name='validate_other' form={form} onFinish={onFinish}> <Form layout='vertical' name='validate_other' form={form} onFinish={onFinish}>
<Form.Item label='上传音频' name='audioUrl'> <Form.Item label='上传音频' name='audioUrl'>
<Spin spinning={uploading} description={`${progress}%`}> <Spin spinning={uploading} tip='上传中'>
<div className='editor-dragger'> <div className='editor-dragger'>
<Dragger {...uploadProps} showUploadList={false}> <Dragger {...uploadProps} showUploadList={false}>
{!audioUrl && ( {!audioUrl && (
......
...@@ -35,8 +35,6 @@ const ImageModal = (props, ref) => { ...@@ -35,8 +35,6 @@ const ImageModal = (props, ref) => {
const [bgColorValue, setBgColorValue] = useState('#000000') const [bgColorValue, setBgColorValue] = useState('#000000')
const [textColor, setTextColor] = useState('#ffffff') const [textColor, setTextColor] = useState('#ffffff')
const [uploading, setUploading] = useState(false) // 文件上传状态 const [uploading, setUploading] = useState(false) // 文件上传状态
const [progress, setProgress] = useState(0)
const [file, setFile] = useState({})
const [imgUrl, setImgUrl] = useState('') const [imgUrl, setImgUrl] = useState('')
const [initValues, setInitValues] = useState({ const [initValues, setInitValues] = useState({
title: '', title: '',
...@@ -108,15 +106,21 @@ const ImageModal = (props, ref) => { ...@@ -108,15 +106,21 @@ const ImageModal = (props, ref) => {
message.error('请上传正确格式的图片') message.error('请上传正确格式的图片')
return false return false
} }
setFile(file) return true
}, },
customRequest: async () => { customRequest: async ({ file, onSuccess, onError }) => {
setUploading(true) setUploading(true)
try {
const url = await uploadFile(file) const url = await uploadFile(file)
setImgUrl(url) setImgUrl(url)
form.setFieldsValue({ bgImgUrl: url }) form.setFieldsValue({ bgImgUrl: url })
onSuccess?.({ url })
} catch (error) {
message.error('图片上传失败,请重试')
onError?.(error instanceof Error ? error : new Error('图片上传失败'))
} finally {
setUploading(false) setUploading(false)
}
}, },
} }
...@@ -144,7 +148,6 @@ const ImageModal = (props, ref) => { ...@@ -144,7 +148,6 @@ const ImageModal = (props, ref) => {
if (parseInt(node.random) === parseInt(nowRandom)) { if (parseInt(node.random) === parseInt(nowRandom)) {
SlateTransforms.setNodes(editor, { ...node, ...values }, { at: path }) SlateTransforms.setNodes(editor, { ...node, ...values }, { at: path })
setImgUrl('') setImgUrl('')
setProgress(0)
setUploading(false) setUploading(false)
form.resetFields() form.resetFields()
setTitleVisible(false) setTitleVisible(false)
...@@ -179,7 +182,6 @@ const ImageModal = (props, ref) => { ...@@ -179,7 +182,6 @@ const ImageModal = (props, ref) => {
children: [{ text: '' }], children: [{ text: '' }],
}) })
setImgUrl('') setImgUrl('')
setProgress(0)
setUploading(false) setUploading(false)
form.resetFields() form.resetFields()
setTitleVisible(false) setTitleVisible(false)
...@@ -197,7 +199,7 @@ const ImageModal = (props, ref) => { ...@@ -197,7 +199,7 @@ const ImageModal = (props, ref) => {
initialValues={initValues} initialValues={initValues}
> >
<Form.Item label='章头背景图片' name='bgImgUrl'> <Form.Item label='章头背景图片' name='bgImgUrl'>
<Spin spinning={uploading} description={`${progress}%`}> <Spin spinning={uploading}>
<div className='editor-dragger'> <div className='editor-dragger'>
<Dragger {...uploadProps} showUploadList={false}> <Dragger {...uploadProps} showUploadList={false}>
{!imgUrl && ( {!imgUrl && (
......
import { useState, useEffect, useImperativeHandle, forwardRef } from 'react' import { useState, useEffect, useImperativeHandle, forwardRef } from 'react'
import { CloudUploadOutlined } from '@ant-design/icons' import { CloudUploadOutlined } from '@ant-design/icons'
import { Form, Input, Spin, Upload, Button } from 'antd' import { Form, Input, Spin, Upload, Button, message } from 'antd'
import OnlineImageList from '../../shared/online-image/OnlineImageList' import OnlineImageList from '../../shared/online-image/OnlineImageList'
import { uploadFile } from '@/utils/oss' import { uploadFile } from '@/utils/oss'
...@@ -11,7 +11,6 @@ const GalleryFormItem = (props, ref) => { ...@@ -11,7 +11,6 @@ const GalleryFormItem = (props, ref) => {
const { activeKey, form, setPicList, galleryInfo, isOnline = false } = props const { activeKey, form, setPicList, galleryInfo, isOnline = false } = props
const [uploading, setUploading] = useState(false) // 文件上传状态 const [uploading, setUploading] = useState(false) // 文件上传状态
const [file, setFile] = useState({})
const [imgUrl, setImgUrl] = useState('') const [imgUrl, setImgUrl] = useState('')
useImperativeHandle(ref, () => { useImperativeHandle(ref, () => {
...@@ -59,11 +58,9 @@ const GalleryFormItem = (props, ref) => { ...@@ -59,11 +58,9 @@ const GalleryFormItem = (props, ref) => {
maxCount: 1, maxCount: 1,
showUploadList: false, showUploadList: false,
accept: fileAccept.join(','), accept: fileAccept.join(','),
beforeUpload: (file) => { customRequest: async ({ file, onSuccess, onError }) => {
setFile(file)
},
customRequest: async () => {
setUploading(true) setUploading(true)
try {
const url = await uploadFile(file) const url = await uploadFile(file)
const values = { const values = {
['content']: { ['content']: {
...@@ -84,7 +81,13 @@ const GalleryFormItem = (props, ref) => { ...@@ -84,7 +81,13 @@ const GalleryFormItem = (props, ref) => {
} }
setPicList(newGalleryList) setPicList(newGalleryList)
form.setFieldsValue({ gallery: newGalleryList }) form.setFieldsValue({ gallery: newGalleryList })
onSuccess?.({ url })
} catch (error) {
message.error('图片上传失败,请重试')
onError?.(error instanceof Error ? error : new Error('图片上传失败'))
} finally {
setUploading(false) setUploading(false)
}
}, },
} }
...@@ -169,7 +172,15 @@ const GalleryFormItem = (props, ref) => { ...@@ -169,7 +172,15 @@ const GalleryFormItem = (props, ref) => {
<img src={imgUrl} alt='' /> <img src={imgUrl} alt='' />
</div> </div>
<div className='editor-uploader-result-tips'> <div className='editor-uploader-result-tips'>
<Button size='small' color='primary' variant='outlined' onClick={() => setImgUrl(null)}> <Button
size='small'
color='primary'
variant='outlined'
onClick={() => {
setImgUrl(null)
form.setFieldValue(['content', activeKey, 'url'], '')
}}
>
替换 替换
</Button> </Button>
</div> </div>
......
...@@ -14,6 +14,7 @@ export default function HistoryFeatureDialog({ open, onClose, runtime }) { ...@@ -14,6 +14,7 @@ export default function HistoryFeatureDialog({ open, onClose, runtime }) {
mask={{ closable: false }} mask={{ closable: false }}
width='90%' width='90%'
onCancel={onClose} onCancel={onClose}
classNames={{ container: 'history-content' }}
wrapClassName='history1' wrapClassName='history1'
style={{ padding: 0 }} style={{ padding: 0 }}
> >
......
...@@ -10,7 +10,7 @@ const HistoryEditor = (props) => { ...@@ -10,7 +10,7 @@ const HistoryEditor = (props) => {
const { setHistoryVisible, chapterId, bookId, setContent, saveContent } = props const { setHistoryVisible, chapterId, bookId, setContent, saveContent } = props
const [loading, setLoading] = useState(false) const [loading, setLoading] = useState(false)
const [delMoadal, setDelModal] = useState(false) const [delModal, setDelModal] = useState(false)
const [recordContent, setRecordContent] = useState('') // 内容 const [recordContent, setRecordContent] = useState('') // 内容
const [recordList, setRecordList] = useState([]) // 列表 const [recordList, setRecordList] = useState([]) // 列表
const [recordId, setRecordId] = useState(null) // 当前的记录id const [recordId, setRecordId] = useState(null) // 当前的记录id
...@@ -134,7 +134,8 @@ const HistoryEditor = (props) => { ...@@ -134,7 +134,8 @@ const HistoryEditor = (props) => {
mask={false} mask={false}
centered centered
className='history2' className='history2'
open={delMoadal} classNames={{ container: 'history2-content' }}
open={delModal}
onOk={handleSuccess} onOk={handleSuccess}
onCancel={() => setDelModal(false)} onCancel={() => setDelModal(false)}
footer={(_, { OkBtn, CancelBtn }) => { footer={(_, { OkBtn, CancelBtn }) => {
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
overflow: hidden; overflow: hidden;
} }
.ant-modal, .ant-modal,
.ant-modal-content, .history-content,
.ant-modal-body { .ant-modal-body {
max-height: 90vh; max-height: 90vh;
min-height: 90vh; min-height: 90vh;
...@@ -17,7 +17,7 @@ ...@@ -17,7 +17,7 @@
} }
} }
.history1 { .history1 {
.ant-modal-content { .history-content {
padding: 0; padding: 0;
.history-content-container { .history-content-container {
...@@ -297,7 +297,7 @@ ...@@ -297,7 +297,7 @@
} }
// 画廊展示 // 画廊展示
.gallery-prview-container { .gallery-preview-container {
.gallery-img { .gallery-img {
max-height: 300px; max-height: 300px;
height: 300px; height: 300px;
...@@ -493,7 +493,7 @@ ...@@ -493,7 +493,7 @@
.history2 { .history2 {
z-index: 1000; z-index: 1000;
.ant-modal-content { .history2-content {
padding: 20px; padding: 20px;
} }
} }
...@@ -20,8 +20,6 @@ const ImageModal = (props, ref) => { ...@@ -20,8 +20,6 @@ const ImageModal = (props, ref) => {
const fileAccept = ['.png', '.jpg', '.jpeg', '.svg'] const fileAccept = ['.png', '.jpg', '.jpeg', '.svg']
const [form] = Form.useForm() const [form] = Form.useForm()
const [uploading, setUploading] = useState(false) // 文件上传状态 const [uploading, setUploading] = useState(false) // 文件上传状态
const [progress, setProgress] = useState(0)
const [file, setFile] = useState({})
const [initValues, setInitValues] = useState({ imgUrl: '', imgTitle: '', imgDescript: '' }) const [initValues, setInitValues] = useState({ imgUrl: '', imgTitle: '', imgDescript: '' })
const [tempNodeInfo, setTempNodeInfo] = useState(null) const [tempNodeInfo, setTempNodeInfo] = useState(null)
...@@ -32,7 +30,6 @@ const ImageModal = (props, ref) => { ...@@ -32,7 +30,6 @@ const ImageModal = (props, ref) => {
setInitValues({ imgUrl: image.src, imgTitle: image.alt, imgDescript: image.href }) setInitValues({ imgUrl: image.src, imgTitle: image.alt, imgDescript: image.href })
form.setFieldsValue({ imgUrl: image.src, imgTitle: image.alt, imgDescript: image.href }) form.setFieldsValue({ imgUrl: image.src, imgTitle: image.alt, imgDescript: image.href })
setTempNodeInfo(imageInfo) setTempNodeInfo(imageInfo)
setFile({})
setImageInfo({}) setImageInfo({})
} }
}, [imageInfo]) }, [imageInfo])
...@@ -48,20 +45,26 @@ const ImageModal = (props, ref) => { ...@@ -48,20 +45,26 @@ const ImageModal = (props, ref) => {
message.error('请上传正确格式的图片') message.error('请上传正确格式的图片')
return false return false
} }
setFile(file) return true
}, },
customRequest: async () => { customRequest: async ({ file, onSuccess, onError }) => {
setUploading(true) setUploading(true)
try {
const url = await uploadFile(file) const url = await uploadFile(file)
setImgUrl(url) setImgUrl(url)
form.setFieldsValue({ imgUrl: url }) form.setFieldsValue({ imgUrl: url })
onSuccess?.({ url })
} catch (error) {
message.error('图片上传失败,请重试')
onError?.(error instanceof Error ? error : new Error('图片上传失败'))
} finally {
setUploading(false) setUploading(false)
}
}, },
} }
const clear = () => { const clear = () => {
setImgUrl('') setImgUrl('')
setProgress(0)
setUploading(false) setUploading(false)
setTempNodeInfo(null) setTempNodeInfo(null)
setInitValues({ imgUrl: imgUrl, imgTitle: '', imgDescript: '' }) setInitValues({ imgUrl: imgUrl, imgTitle: '', imgDescript: '' })
...@@ -158,7 +161,7 @@ const ImageModal = (props, ref) => { ...@@ -158,7 +161,7 @@ const ImageModal = (props, ref) => {
name='imgUrl' name='imgUrl'
rules={[{ required: true, message: '请上传图片' }]} rules={[{ required: true, message: '请上传图片' }]}
> >
<Spin spinning={uploading} description={`${progress}%`}> <Spin spinning={uploading}>
<div className='editor-dragger'> <div className='editor-dragger'>
<Dragger {...uploadProps} showUploadList={false}> <Dragger {...uploadProps} showUploadList={false}>
{!imgUrl && ( {!imgUrl && (
...@@ -178,7 +181,15 @@ const ImageModal = (props, ref) => { ...@@ -178,7 +181,15 @@ const ImageModal = (props, ref) => {
<img src={imgUrl} alt='' /> <img src={imgUrl} alt='' />
</div> </div>
<div className='editor-uploader-result-tips'> <div className='editor-uploader-result-tips'>
<Button size='small' color='primary' variant='outlined' onClick={() => setImgUrl(null)}> <Button
size='small'
color='primary'
variant='outlined'
onClick={() => {
setImgUrl(null)
form.setFieldsValue({ imgUrl: '' })
}}
>
替换 替换
</Button> </Button>
</div> </div>
......
...@@ -54,6 +54,7 @@ export function PracticeSettingsFeatureDialog({ open, onClose, payload, runtime ...@@ -54,6 +54,7 @@ export function PracticeSettingsFeatureDialog({ open, onClose, payload, runtime
header: 'practice-topic-header', header: 'practice-topic-header',
body: 'practice-topic-content', body: 'practice-topic-content',
wrapper: 'practice-topic-modal', wrapper: 'practice-topic-modal',
container: 'practice-topic-container',
}} }}
mask={{ closable: false }} mask={{ closable: false }}
closeIcon={false} closeIcon={false}
......
...@@ -5,7 +5,7 @@ import { useEditorStore } from '@/stores/editorStore' ...@@ -5,7 +5,7 @@ import { useEditorStore } from '@/stores/editorStore'
import TopicItem from './topicItem' import TopicItem from './topicItem'
import { addChapterTopic, getChapterTopic } from '../../../shared/request' import { addChapterTopic, getChapterTopic } from '../../../shared/request'
import { clacTopicText } from '@/utils/common' import { calcTopicText } from '@/utils/common'
const InsertTopic = (props, ref) => { const InsertTopic = (props, ref) => {
const { const {
...@@ -77,7 +77,7 @@ const InsertTopic = (props, ref) => { ...@@ -77,7 +77,7 @@ const InsertTopic = (props, ref) => {
<div className='practice-insert-topic list-topic-box'> <div className='practice-insert-topic list-topic-box'>
{radioList.length > 0 && ( {radioList.length > 0 && (
<div className='list-topic-container'> <div className='list-topic-container'>
<h4>{clacTopicText('radio')}. 单选题</h4> <h4>{calcTopicText('radio')}. 单选题</h4>
<div> <div>
{radioList.map((item, index) => { {radioList.map((item, index) => {
return ( return (
...@@ -108,7 +108,7 @@ const InsertTopic = (props, ref) => { ...@@ -108,7 +108,7 @@ const InsertTopic = (props, ref) => {
{checkboxList.length > 0 && ( {checkboxList.length > 0 && (
<div className='list-topic-container'> <div className='list-topic-container'>
<h4>{clacTopicText('checkbox', radioList)}. 多选题</h4> <h4>{calcTopicText('checkbox', radioList)}. 多选题</h4>
<div> <div>
{checkboxList.map((item, index) => { {checkboxList.map((item, index) => {
return ( return (
...@@ -138,7 +138,7 @@ const InsertTopic = (props, ref) => { ...@@ -138,7 +138,7 @@ const InsertTopic = (props, ref) => {
)} )}
{equalsList.length > 0 && ( {equalsList.length > 0 && (
<div className='list-topic-container'> <div className='list-topic-container'>
<h4>{clacTopicText('judge', radioList, checkboxList)}. 判断题</h4> <h4>{calcTopicText('judge', radioList, checkboxList)}. 判断题</h4>
<div> <div>
{equalsList.map((item, index) => { {equalsList.map((item, index) => {
return ( return (
...@@ -168,7 +168,7 @@ const InsertTopic = (props, ref) => { ...@@ -168,7 +168,7 @@ const InsertTopic = (props, ref) => {
)} )}
{pressList.length > 0 && ( {pressList.length > 0 && (
<div className='list-topic-container'> <div className='list-topic-container'>
<h4>{clacTopicText('fill', radioList, checkboxList, equalsList)}. 填空题</h4> <h4>{calcTopicText('fill', radioList, checkboxList, equalsList)}. 填空题</h4>
<div> <div>
{pressList.map((item, index) => { {pressList.map((item, index) => {
return ( return (
...@@ -199,7 +199,7 @@ const InsertTopic = (props, ref) => { ...@@ -199,7 +199,7 @@ const InsertTopic = (props, ref) => {
{textareaList.length > 0 && ( {textareaList.length > 0 && (
<div className='list-topic-container'> <div className='list-topic-container'>
<h4> <h4>
{clacTopicText('textarea', radioList, checkboxList, equalsList, pressList)}. 简答题 {calcTopicText('textarea', radioList, checkboxList, equalsList, pressList)}. 简答题
</h4> </h4>
<div> <div>
{textareaList.map((item, index) => { {textareaList.map((item, index) => {
......
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
inset-inline-end: 17px; inset-inline-end: 17px;
top: 16px; top: 16px;
} }
.ant-modal-content { .practice-topic-container {
padding: 15px 18px; padding: 15px 18px;
} }
.ant-divider { .ant-divider {
......
...@@ -13,7 +13,12 @@ export default function PreviewFeatureDialog({ open, onClose, runtime }) { ...@@ -13,7 +13,12 @@ export default function PreviewFeatureDialog({ open, onClose, runtime }) {
keyboard={false} keyboard={false}
closeIcon={<CloseOutlined style={{ fontSize: 20, color: '#fff' }} />} closeIcon={<CloseOutlined style={{ fontSize: 20, color: '#fff' }} />}
mask={{ closable: false }} mask={{ closable: false }}
classNames={{ body: 'phone-body', wrapper: 'phone-wrapper' }} classNames={{
container: 'phone-content',
body: 'phone-body',
wrapper: 'phone-wrapper',
close: 'phone-close',
}}
wrapClassName='wrap-phone-privew' wrapClassName='wrap-phone-privew'
width='494px' width='494px'
onCancel={onClose} onCancel={onClose}
......
...@@ -9,7 +9,7 @@ import { getChapterTopic, expandReadInfo } from '../../shared/request' ...@@ -9,7 +9,7 @@ import { getChapterTopic, expandReadInfo } from '../../shared/request'
import TopicItem from '../practice/components/topicItem' import TopicItem from '../practice/components/topicItem'
import '@/components/editor/preview.less' import '@/components/editor/preview.less'
import { clacTopicText } from '@/utils/common' import { calcTopicText } from '@/utils/common'
import hljs from 'highlight.js' import hljs from 'highlight.js'
import 'highlight.js/styles/github.css' import 'highlight.js/styles/github.css'
...@@ -46,7 +46,7 @@ const correctList = [ ...@@ -46,7 +46,7 @@ const correctList = [
const PreviewScreen = (props, ref) => { const PreviewScreen = (props, ref) => {
const { editor, bookId, chapterId, gData, nowTitle } = props const { editor, bookId, chapterId, gData, nowTitle } = props
const [loading, setLoading] = useState(false) // 展示 const [loading, setLoading] = useState(false) // 展示
const [prviewHtml, setPrviewHtml] = useState('') // 预览html const [previewHtml, setPrviewHtml] = useState('') // 预览html
const [open, setOpen] = useState(false) // 抽屉 const [open, setOpen] = useState(false) // 抽屉
const [toolTip, setTooltip] = useState({}) const [toolTip, setTooltip] = useState({})
...@@ -114,12 +114,15 @@ const PreviewScreen = (props, ref) => { ...@@ -114,12 +114,15 @@ const PreviewScreen = (props, ref) => {
} }
const handlerClick = () => { const handlerClick = () => {
const eventNamespace = '.editorPreview'
const previewContent = $('.preview-content-html')
const secondaryContent = $('.expand-content, .gallery-preview-container')
const iParentW = $('.preview-content-it').innerWidth() const iParentW = $('.preview-content-it').innerWidth()
const iParentH = $('.preview-content-it').innerHeight() const iParentH = $('.preview-content-it').innerHeight()
const parentOffset = $('.preview-content-it').offset() // 获取父元素相对于文档的位置 const parentOffset = $('.preview-content-it').offset() // 获取父元素相对于文档的位置
const parentRect = $('.preview-content-it')[0].getBoundingClientRect() // 获取父元素相对于文档的位置 const parentRect = $('.preview-content-it')[0].getBoundingClientRect() // 获取父元素相对于文档的位置
$('.preview-content-html').on('click', (ev) => { previewContent.off(eventNamespace).on(`click${eventNamespace}`, (ev) => {
ev.stopPropagation() ev.stopPropagation()
const target = ev.target const target = ev.target
...@@ -326,7 +329,7 @@ const PreviewScreen = (props, ref) => { ...@@ -326,7 +329,7 @@ const PreviewScreen = (props, ref) => {
setGallery([]) setGallery([])
}) })
$('.expand-content, .gallery-prview-container').on('click', (ev) => { secondaryContent.off(eventNamespace).on(`click${eventNamespace}`, (ev) => {
const target = ev.target const target = ev.target
if (target.nodeName.toLowerCase() === 'img') { if (target.nodeName.toLowerCase() === 'img') {
...@@ -338,10 +341,15 @@ const PreviewScreen = (props, ref) => { ...@@ -338,10 +341,15 @@ const PreviewScreen = (props, ref) => {
setSecondType('扩展图片') setSecondType('扩展图片')
} }
}) })
return () => {
previewContent.off(eventNamespace)
secondaryContent.off(eventNamespace)
}
} }
useEffect(() => { useEffect(() => {
handlerClick() return handlerClick()
}, []) }, [])
const getChapterId = async () => { const getChapterId = async () => {
...@@ -356,7 +364,7 @@ const PreviewScreen = (props, ref) => { ...@@ -356,7 +364,7 @@ const PreviewScreen = (props, ref) => {
if (data) { if (data) {
const content = get(data, 'content', '') const content = get(data, 'content', '')
setPrviewHtml(content) setPrviewHtml(content)
$('#previee-container') $('#preview-container')
.find('video audio') .find('video audio')
.each((index, item) => { .each((index, item) => {
$(item).attr('controls', true).attr('controlslist', 'nodownload') $(item).attr('controls', true).attr('controlslist', 'nodownload')
...@@ -383,7 +391,7 @@ const PreviewScreen = (props, ref) => { ...@@ -383,7 +391,7 @@ const PreviewScreen = (props, ref) => {
// if (data) { // if (data) {
// const content = get(data, 'content', ''); // const content = get(data, 'content', '');
// setPrviewHtml(content); // setPrviewHtml(content);
// $('#previee-container') // $('#preview-container')
// .find('video audio') // .find('video audio')
// .each((index, item) => { // .each((index, item) => {
// $(item).attr('controls', true); // $(item).attr('controls', true);
...@@ -417,8 +425,8 @@ const PreviewScreen = (props, ref) => { ...@@ -417,8 +425,8 @@ const PreviewScreen = (props, ref) => {
} }
return ( return (
<div className='priview-modal'> <div className='preview-modal'>
<div className='previee-container' id='previee-container'> <div className='preview-container' id='preview-container'>
<div className='chapter-head-title'> <div className='chapter-head-title'>
<h2> <h2>
{opend ? ( {opend ? (
...@@ -456,14 +464,14 @@ const PreviewScreen = (props, ref) => { ...@@ -456,14 +464,14 @@ const PreviewScreen = (props, ref) => {
<Spin spinning={loading} classNames={{ root: 'chapter-loading' }}> <Spin spinning={loading} classNames={{ root: 'chapter-loading' }}>
<div <div
className='preview-content-html' className='preview-content-html'
dangerouslySetInnerHTML={{ __html: prviewHtml }} dangerouslySetInnerHTML={{ __html: previewHtml }}
></div> ></div>
</Spin> </Spin>
</div> </div>
{isType && ( {isType && (
<div className='preview-content-other'> <div className='preview-content-other'>
{isType === 'gallery' && ( {isType === 'gallery' && (
<div className='gallery-prview-container'> <div className='gallery-preview-container'>
{gallery && gallery.length > 0 ? ( {gallery && gallery.length > 0 ? (
<> <>
<div className='gallery-img'> <div className='gallery-img'>
...@@ -491,7 +499,7 @@ const PreviewScreen = (props, ref) => { ...@@ -491,7 +499,7 @@ const PreviewScreen = (props, ref) => {
<div className='practice-insert-topic'> <div className='practice-insert-topic'>
{radioList.length > 0 && ( {radioList.length > 0 && (
<div className='topic_style'> <div className='topic_style'>
<h3>{clacTopicText('radio')}. 单选题</h3> <h3>{calcTopicText('radio')}. 单选题</h3>
<div className='practice-list'> <div className='practice-list'>
{radioList.map((item, index) => { {radioList.map((item, index) => {
return ( return (
...@@ -540,7 +548,7 @@ const PreviewScreen = (props, ref) => { ...@@ -540,7 +548,7 @@ const PreviewScreen = (props, ref) => {
)} )}
{checkBoxList.length > 0 && ( {checkBoxList.length > 0 && (
<div className='topic_style'> <div className='topic_style'>
<h3>{clacTopicText('checkbox', radioList)}. 多选题</h3> <h3>{calcTopicText('checkbox', radioList)}. 多选题</h3>
<div className='practice-list'> <div className='practice-list'>
{checkBoxList.map((item, index) => { {checkBoxList.map((item, index) => {
return ( return (
...@@ -589,7 +597,7 @@ const PreviewScreen = (props, ref) => { ...@@ -589,7 +597,7 @@ const PreviewScreen = (props, ref) => {
)} )}
{judgeList.length > 0 && ( {judgeList.length > 0 && (
<div className='topic_style'> <div className='topic_style'>
<h3>{clacTopicText('judge', radioList, checkBoxList)}. 判断题</h3> <h3>{calcTopicText('judge', radioList, checkBoxList)}. 判断题</h3>
<div className='practice-list'> <div className='practice-list'>
{judgeList.map((item, index) => { {judgeList.map((item, index) => {
return ( return (
...@@ -638,7 +646,7 @@ const PreviewScreen = (props, ref) => { ...@@ -638,7 +646,7 @@ const PreviewScreen = (props, ref) => {
)} )}
{fillList.length > 0 && ( {fillList.length > 0 && (
<div className='topic_style'> <div className='topic_style'>
<h3>{clacTopicText('fill', radioList, checkBoxList, judgeList)}. 填空题</h3> <h3>{calcTopicText('fill', radioList, checkBoxList, judgeList)}. 填空题</h3>
<div className='practice-list'> <div className='practice-list'>
{fillList.map((item, index) => { {fillList.map((item, index) => {
return ( return (
...@@ -688,7 +696,7 @@ const PreviewScreen = (props, ref) => { ...@@ -688,7 +696,7 @@ const PreviewScreen = (props, ref) => {
{textareaList.length > 0 && ( {textareaList.length > 0 && (
<div className='topic_style'> <div className='topic_style'>
<h3> <h3>
{clacTopicText('textarea', radioList, checkBoxList, judgeList, fillList)}. {calcTopicText('textarea', radioList, checkBoxList, judgeList, fillList)}.
简答题 简答题
</h3> </h3>
<div className='practice-list'> <div className='practice-list'>
...@@ -786,10 +794,10 @@ const PreviewScreen = (props, ref) => { ...@@ -786,10 +794,10 @@ const PreviewScreen = (props, ref) => {
open={open} open={open}
getContainer={false} getContainer={false}
placement='left' placement='left'
classNames={{ header: 'priview-drawer-header', body: 'priview-drawer-body' }} classNames={{ header: 'preview-drawer-header', body: 'preview-drawer-body' }}
width='200' width='200'
title='章节目录' title='章节目录'
rootClassName='priview-drawer-container' rootClassName='preview-drawer-container'
> >
<Tree <Tree
className='draggable-tree' className='draggable-tree'
......
...@@ -20,9 +20,6 @@ const VideoModal = ({ open, onClose, payload = {}, runtime }) => { ...@@ -20,9 +20,6 @@ const VideoModal = ({ open, onClose, payload = {}, runtime }) => {
const fileAccept = ['.ogg', '.mp4', '.webm'] const fileAccept = ['.ogg', '.mp4', '.webm']
const [form] = Form.useForm() const [form] = Form.useForm()
const [uploading, setUploading] = useState(false) // 文件上传状态 const [uploading, setUploading] = useState(false) // 文件上传状态
const [progress, setProgress] = useState(0)
const [file, setFile] = useState({})
const [videoUrl, setVideoUrl] = useState('') const [videoUrl, setVideoUrl] = useState('')
useEffect(() => { useEffect(() => {
...@@ -45,16 +42,21 @@ const VideoModal = ({ open, onClose, payload = {}, runtime }) => { ...@@ -45,16 +42,21 @@ const VideoModal = ({ open, onClose, payload = {}, runtime }) => {
message.error('请上传正确格式的视频') message.error('请上传正确格式的视频')
return false return false
} }
setProgress(0) return true
setUploading(false)
setFile(file)
}, },
customRequest: async () => { customRequest: async ({ file, onSuccess, onError }) => {
setUploading(true) setUploading(true)
try {
const url = await uploadFile(file) const url = await uploadFile(file)
setVideoUrl(url) setVideoUrl(url)
form.setFieldsValue({ videoUrl: url }) form.setFieldsValue({ videoUrl: url })
onSuccess?.({ url })
} catch (error) {
message.error('视频上传失败,请重试')
onError?.(error instanceof Error ? error : new Error('视频上传失败'))
} finally {
setUploading(false) setUploading(false)
}
}, },
} }
...@@ -81,7 +83,6 @@ const VideoModal = ({ open, onClose, payload = {}, runtime }) => { ...@@ -81,7 +83,6 @@ const VideoModal = ({ open, onClose, payload = {}, runtime }) => {
}) })
setVideoUrl('') setVideoUrl('')
setProgress(0)
setUploading(false) setUploading(false)
form.resetFields() form.resetFields()
onClose() onClose()
...@@ -111,7 +112,7 @@ const VideoModal = ({ open, onClose, payload = {}, runtime }) => { ...@@ -111,7 +112,7 @@ const VideoModal = ({ open, onClose, payload = {}, runtime }) => {
name='videoUrl' name='videoUrl'
rules={[{ required: true, message: '请上传视频' }]} rules={[{ required: true, message: '请上传视频' }]}
> >
<Spin spinning={uploading} description={`${progress}%`}> <Spin spinning={uploading} tip='上传中'>
<div className='editor-dragger'> <div className='editor-dragger'>
<Dragger {...uploadProps} showUploadList={false}> <Dragger {...uploadProps} showUploadList={false}>
{!videoUrl && ( {!videoUrl && (
......
...@@ -131,11 +131,9 @@ export function usePagedList<Row, Filters, Query>({ ...@@ -131,11 +131,9 @@ export function usePagedList<Row, Filters, Query>({
}, [initialFilters, initialPage, loadFor, state.pageSize]) }, [initialFilters, initialPage, loadFor, state.pageSize])
const refresh = useCallback(() => { const refresh = useCallback(() => {
if (useAppliedFilters) { const filters = useAppliedFilters ? state.appliedFilters : state.filters
setState((current) => ({ ...current, appliedFilters: state.filters })) void loadFor(state.page, state.pageSize, filters)
} }, [loadFor, state.appliedFilters, state.filters, state.page, state.pageSize, useAppliedFilters])
void loadFor(state.page, state.pageSize, state.filters)
}, [loadFor, state.filters, state.page, state.pageSize, useAppliedFilters])
const refreshUnfiltered = useCallback(() => { const refreshUnfiltered = useCallback(() => {
void loadFor(state.page, state.pageSize, initialFilters) void loadFor(state.page, state.pageSize, initialFilters)
......
...@@ -38,7 +38,7 @@ ...@@ -38,7 +38,7 @@
} }
.audit-preview-tree, .audit-preview-tree,
.previee-container { .preview-container {
height: 100%; height: 100%;
min-width: 0; min-width: 0;
border: 0; border: 0;
...@@ -94,13 +94,13 @@ ...@@ -94,13 +94,13 @@
} }
} }
.previee-container { .preview-container {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
border-radius: 0; border-radius: 0;
} }
&.wrap-phone-privew .previee-container .chapter-head-title { &.wrap-phone-privew .preview-container .chapter-head-title {
flex: 0 0 var(--audit-review-header-height); flex: 0 0 var(--audit-review-header-height);
height: var(--audit-review-header-height); height: var(--audit-review-header-height);
line-height: var(--audit-review-header-height); line-height: var(--audit-review-header-height);
...@@ -528,7 +528,7 @@ ...@@ -528,7 +528,7 @@
.audit-review-preview { .audit-review-preview {
.audit-preview-tree, .audit-preview-tree,
.previee-container { .preview-container {
height: 360px; height: 360px;
} }
} }
......
...@@ -15,7 +15,7 @@ import { ...@@ -15,7 +15,7 @@ import {
convertToAntdTreeData, convertToAntdTreeData,
findTreeElementByKey, findTreeElementByKey,
findFirstNotHasChildren, findFirstNotHasChildren,
clacTopicText, calcTopicText,
} from '@/utils/common' } from '@/utils/common'
import { findReviewCommentRange, useReviewHighlights } from '../../review-comments/highlights' import { findReviewCommentRange, useReviewHighlights } from '../../review-comments/highlights'
import { get } from 'lodash-es' import { get } from 'lodash-es'
...@@ -86,7 +86,7 @@ const PreviewScreen = (props, ref) => { ...@@ -86,7 +86,7 @@ const PreviewScreen = (props, ref) => {
} = props } = props
const [gData, setGData] = useState([]) const [gData, setGData] = useState([])
const [loading, setLoading] = useState(false) // 展示 const [loading, setLoading] = useState(false) // 展示
const [prviewHtml, setPrviewHtml] = useState('') // 预览html const [previewHtml, setPrviewHtml] = useState('') // 预览html
const [open, setOpen] = useState(false) // 抽屉 const [open, setOpen] = useState(false) // 抽屉
const [secondType, setSecondType] = useState(false) const [secondType, setSecondType] = useState(false)
const [pageMap, setPageMap] = useState({}) // 叶子节点页码映射 const [pageMap, setPageMap] = useState({}) // 叶子节点页码映射
...@@ -118,9 +118,9 @@ const PreviewScreen = (props, ref) => { ...@@ -118,9 +118,9 @@ const PreviewScreen = (props, ref) => {
const previewContentRef = useRef(null) const previewContentRef = useRef(null)
const previewText = useMemo(() => { const previewText = useMemo(() => {
const element = document.createElement('div') const element = document.createElement('div')
element.innerHTML = prviewHtml || '' element.innerHTML = previewHtml || ''
return element.textContent || '' return element.textContent || ''
}, [prviewHtml]) }, [previewHtml])
const getPreviewRoot = useCallback(() => previewContentRef.current || undefined, []) const getPreviewRoot = useCallback(() => previewContentRef.current || undefined, [])
useReviewHighlights({ useReviewHighlights({
...@@ -130,7 +130,7 @@ const PreviewScreen = (props, ref) => { ...@@ -130,7 +130,7 @@ const PreviewScreen = (props, ref) => {
draftAnchor: draftCommentAnchor, draftAnchor: draftCommentAnchor,
activeCommentId, activeCommentId,
enabled: true, enabled: true,
rootVersion: prviewHtml, rootVersion: previewHtml,
}) })
// 递归函数,获取所有节点的key // 递归函数,获取所有节点的key
...@@ -225,7 +225,7 @@ const PreviewScreen = (props, ref) => { ...@@ -225,7 +225,7 @@ const PreviewScreen = (props, ref) => {
content, content,
text: contentElement.textContent || '', text: contentElement.textContent || '',
}) })
$('#previee-container') $('#preview-container')
.find('video audio') .find('video audio')
.each((index, item) => { .each((index, item) => {
$(item).attr('controls', true).attr('controlslist', 'nodownload') $(item).attr('controls', true).attr('controlslist', 'nodownload')
...@@ -244,12 +244,15 @@ const PreviewScreen = (props, ref) => { ...@@ -244,12 +244,15 @@ const PreviewScreen = (props, ref) => {
} }
const handlerClick = () => { const handlerClick = () => {
const eventNamespace = '.auditPreview'
const previewContent = $('.preview-content-html')
const secondaryContent = $('.expand-content, .gallery-preview-container')
const iParentW = $('.preview-content-it').innerWidth() const iParentW = $('.preview-content-it').innerWidth()
const iParentH = $('.preview-content-it').innerHeight() const iParentH = $('.preview-content-it').innerHeight()
const parentOffset = $('.preview-content-it').offset() // 获取父元素相对于文档的位置 const parentOffset = $('.preview-content-it').offset() // 获取父元素相对于文档的位置
const parentRect = $('.preview-content-it')[0].getBoundingClientRect() // 获取父元素相对于文档的位置 const parentRect = $('.preview-content-it')[0].getBoundingClientRect() // 获取父元素相对于文档的位置
$('.preview-content-html').on('click', async (ev) => { previewContent.off(eventNamespace).on(`click${eventNamespace}`, async (ev) => {
ev.stopPropagation() ev.stopPropagation()
const target = ev.target const target = ev.target
...@@ -455,7 +458,7 @@ const PreviewScreen = (props, ref) => { ...@@ -455,7 +458,7 @@ const PreviewScreen = (props, ref) => {
setGallery([]) setGallery([])
}) })
$('.expand-content, .gallery-prview-container').on('click', (ev) => { secondaryContent.off(eventNamespace).on(`click${eventNamespace}`, (ev) => {
const target = ev.target const target = ev.target
if (target.nodeName.toLowerCase() === 'img') { if (target.nodeName.toLowerCase() === 'img') {
...@@ -467,10 +470,15 @@ const PreviewScreen = (props, ref) => { ...@@ -467,10 +470,15 @@ const PreviewScreen = (props, ref) => {
setSecondType('扩展图片') setSecondType('扩展图片')
} }
}) })
return () => {
previewContent.off(eventNamespace)
secondaryContent.off(eventNamespace)
}
} }
useEffect(() => { useEffect(() => {
handlerClick() return handlerClick()
}, [isType]) }, [isType])
useEffect(() => { useEffect(() => {
...@@ -594,7 +602,7 @@ const PreviewScreen = (props, ref) => { ...@@ -594,7 +602,7 @@ const PreviewScreen = (props, ref) => {
) )
return ( return (
<div className={`priview-modal${desktop ? ' desktop-preview' : ''}`}> <div className={`preview-modal${desktop ? ' desktop-preview' : ''}`}>
{/* <Spin spinning={loading}> */} {/* <Spin spinning={loading}> */}
{desktop && ( {desktop && (
<aside <aside
...@@ -613,7 +621,7 @@ const PreviewScreen = (props, ref) => { ...@@ -613,7 +621,7 @@ const PreviewScreen = (props, ref) => {
{!treeCollapsed && renderChapterTree()} {!treeCollapsed && renderChapterTree()}
</aside> </aside>
)} )}
<div className='previee-container' id='previee-container'> <div className='preview-container' id='preview-container'>
<div className='chapter-head-title'> <div className='chapter-head-title'>
<h2 className='tree'> <h2 className='tree'>
{opend ? ( {opend ? (
...@@ -658,7 +666,7 @@ const PreviewScreen = (props, ref) => { ...@@ -658,7 +666,7 @@ const PreviewScreen = (props, ref) => {
<div <div
ref={previewContentRef} ref={previewContentRef}
className='preview-content-html' className='preview-content-html'
dangerouslySetInnerHTML={{ __html: prviewHtml }} dangerouslySetInnerHTML={{ __html: previewHtml }}
onMouseDown={() => { onMouseDown={() => {
onTextSelection?.(null) onTextSelection?.(null)
}} }}
...@@ -676,7 +684,7 @@ const PreviewScreen = (props, ref) => { ...@@ -676,7 +684,7 @@ const PreviewScreen = (props, ref) => {
{isType && ( {isType && (
<div className='preview-content-other'> <div className='preview-content-other'>
{isType === 'gallery' && ( {isType === 'gallery' && (
<div className='gallery-prview-container'> <div className='gallery-preview-container'>
{gallery && gallery.length > 0 ? ( {gallery && gallery.length > 0 ? (
<> <>
<div className='gallery-img'> <div className='gallery-img'>
...@@ -704,7 +712,7 @@ const PreviewScreen = (props, ref) => { ...@@ -704,7 +712,7 @@ const PreviewScreen = (props, ref) => {
<div className='practice-insert-topic'> <div className='practice-insert-topic'>
{radioList.length > 0 && ( {radioList.length > 0 && (
<div className='topic_style'> <div className='topic_style'>
<h3>{clacTopicText('radio')}. 单选题</h3> <h3>{calcTopicText('radio')}. 单选题</h3>
<div className='practice-list'> <div className='practice-list'>
{radioList.map((item, index) => { {radioList.map((item, index) => {
return ( return (
...@@ -753,7 +761,7 @@ const PreviewScreen = (props, ref) => { ...@@ -753,7 +761,7 @@ const PreviewScreen = (props, ref) => {
)} )}
{checkBoxList.length > 0 && ( {checkBoxList.length > 0 && (
<div className='topic_style'> <div className='topic_style'>
<h3>{clacTopicText('checkbox', radioList)}. 多选题</h3> <h3>{calcTopicText('checkbox', radioList)}. 多选题</h3>
<div className='practice-list'> <div className='practice-list'>
{checkBoxList.map((item, index) => { {checkBoxList.map((item, index) => {
return ( return (
...@@ -802,7 +810,7 @@ const PreviewScreen = (props, ref) => { ...@@ -802,7 +810,7 @@ const PreviewScreen = (props, ref) => {
)} )}
{judgeList.length > 0 && ( {judgeList.length > 0 && (
<div className='topic_style'> <div className='topic_style'>
<h3>{clacTopicText('judge', radioList, checkBoxList)}. 判断题</h3> <h3>{calcTopicText('judge', radioList, checkBoxList)}. 判断题</h3>
<div className='practice-list'> <div className='practice-list'>
{judgeList.map((item, index) => { {judgeList.map((item, index) => {
return ( return (
...@@ -851,7 +859,7 @@ const PreviewScreen = (props, ref) => { ...@@ -851,7 +859,7 @@ const PreviewScreen = (props, ref) => {
)} )}
{fillList.length > 0 && ( {fillList.length > 0 && (
<div className='topic_style'> <div className='topic_style'>
<h3>{clacTopicText('fill', radioList, checkBoxList, judgeList)}. 填空题</h3> <h3>{calcTopicText('fill', radioList, checkBoxList, judgeList)}. 填空题</h3>
<div className='practice-list'> <div className='practice-list'>
{fillList.map((item, index) => { {fillList.map((item, index) => {
return ( return (
...@@ -901,7 +909,7 @@ const PreviewScreen = (props, ref) => { ...@@ -901,7 +909,7 @@ const PreviewScreen = (props, ref) => {
{textareaList.length > 0 && ( {textareaList.length > 0 && (
<div className='topic_style'> <div className='topic_style'>
<h3> <h3>
{clacTopicText('textarea', radioList, checkBoxList, judgeList, fillList)}. {calcTopicText('textarea', radioList, checkBoxList, judgeList, fillList)}.
简答题 简答题
</h3> </h3>
<div className='practice-list'> <div className='practice-list'>
...@@ -1007,10 +1015,10 @@ const PreviewScreen = (props, ref) => { ...@@ -1007,10 +1015,10 @@ const PreviewScreen = (props, ref) => {
open={open} open={open}
getContainer={false} getContainer={false}
placement='left' placement='left'
classNames={{ header: 'priview-drawer-header', body: 'priview-drawer-body' }} classNames={{ header: 'preview-drawer-header', body: 'preview-drawer-body' }}
size={300} size={300}
title='章节目录' title='章节目录'
rootClassName='priview-drawer-container' rootClassName='preview-drawer-container'
> >
{renderChapterTree()} {renderChapterTree()}
</Drawer> </Drawer>
......
...@@ -586,6 +586,7 @@ const Examine = () => { ...@@ -586,6 +586,7 @@ const Examine = () => {
onCancel={() => setEditKey(false)} onCancel={() => setEditKey(false)}
classNames={{ classNames={{
wrapper: 'chapter-title-modal', wrapper: 'chapter-title-modal',
container: 'chapter-title-container',
}} }}
> >
<EditChapterTitle <EditChapterTitle
......
...@@ -123,7 +123,7 @@ ...@@ -123,7 +123,7 @@
inset-inline-end: 17px; inset-inline-end: 17px;
top: 16px; top: 16px;
} }
.ant-modal-content { .chapter-title-container {
padding: 15px 18px; padding: 15px 18px;
} }
.ant-divider { .ant-divider {
......
...@@ -8,7 +8,7 @@ import { getCommentInfo, commentReply, commentDel } from '../api' ...@@ -8,7 +8,7 @@ import { getCommentInfo, commentReply, commentDel } from '../api'
const { TextArea } = Input const { TextArea } = Input
const DiscussDetail = () => { const DiscussDetail = () => {
const [showReply, setShowReply] = useState(false) const [showReply, setShowReply] = useState(false)
const [delMoadal, setDelModal] = useState(false) const [delModal, setDelModal] = useState(false)
const [searchParams] = useSearchParams() const [searchParams] = useSearchParams()
const id = Number(searchParams.get('id')) const id = Number(searchParams.get('id'))
const name = searchParams.get('book_name') || '' const name = searchParams.get('book_name') || ''
...@@ -97,7 +97,7 @@ const DiscussDetail = () => { ...@@ -97,7 +97,7 @@ const DiscussDetail = () => {
<Modal <Modal
mask={false} mask={false}
centered centered
open={delMoadal} open={delModal}
onOk={handleDel} onOk={handleDel}
onCancel={() => setDelModal(false)} onCancel={() => setDelModal(false)}
footer={(_, { OkBtn, CancelBtn }) => { footer={(_, { OkBtn, CancelBtn }) => {
......
...@@ -37,7 +37,7 @@ const AppVersion = () => { ...@@ -37,7 +37,7 @@ const AppVersion = () => {
changePageSize, changePageSize,
} = useAppVersionList() } = useAppVersionList()
const [isEdit, setIsEdit] = useState(false) const [isEdit, setIsEdit] = useState(false)
const [delMoadal, setDelModal] = useState(false) const [delModal, setDelModal] = useState(false)
const [isadd, setisadd] = useState(true) const [isadd, setisadd] = useState(true)
const [form] = Form.useForm() const [form] = Form.useForm()
const checkPermission = usePermission() const checkPermission = usePermission()
...@@ -264,7 +264,7 @@ const AppVersion = () => { ...@@ -264,7 +264,7 @@ const AppVersion = () => {
<Modal <Modal
mask={false} mask={false}
centered centered
open={delMoadal} open={delModal}
onOk={handleDel} onOk={handleDel}
onCancel={() => setDelModal(false)} onCancel={() => setDelModal(false)}
footer={(_, { OkBtn, CancelBtn }) => { footer={(_, { OkBtn, CancelBtn }) => {
......
import { useState, useEffect, useRef } from 'react' import { useState, useEffect, useRef } from 'react'
import { Button, Row, Col, Descriptions, Tree, Dropdown, Spin, App } from 'antd' import { Button, Row, Col, Descriptions, Tree, Spin } from 'antd'
import { import { MenuFoldOutlined, MenuUnfoldOutlined } from '@ant-design/icons'
EllipsisOutlined,
DiffOutlined,
MenuFoldOutlined,
MenuUnfoldOutlined,
} from '@ant-design/icons'
import WangEditorCustomer from '@/components/editor/wangeditor-customer' import WangEditorCustomer from '@/components/editor/wangeditor-customer'
import { useLocation, useNavigate, useSearchParams } from 'react-router' import { useNavigate, useSearchParams } from 'react-router'
import { useEditorStore } from '@/stores/editorStore'
import { useUserStore } from '@/stores/userStore' import { useUserStore } from '@/stores/userStore'
import { get } from 'lodash-es'
import md5 from 'js-md5'
import { import {
convertToAntdTreeData, convertToAntdTreeData,
findTreeElementByKey, findTreeElementByKey,
findFirstNotHasChildren, findFirstNotHasChildren,
findParentLevelOne,
findTreeToIndex,
findNodeById,
} from '@/utils/common' } from '@/utils/common'
import { import { getAllList, getInfoByChapterId } from '@/modules/books/management/chapters/api.js'
getAllList,
getInfoByChapterId,
sectionEdit,
chapterDel,
dragOrder,
} from '@/modules/books/management/chapters/api.js'
import './StudentBookView.less' import './StudentBookView.less'
const Examine = () => { const Examine = () => {
const { modal } = App.useApp()
const [searchParams] = useSearchParams() const [searchParams] = useSearchParams()
const location = useLocation()
const id = searchParams.get('book_id') const id = searchParams.get('book_id')
const isAdminOrCreator = get(location, 'state.isAdminOrCreator', false)
const treeChapter = useUserStore((state) => state.treeChapter) const treeChapter = useUserStore((state) => state.treeChapter)
const userInfo = useUserStore((state) => state.userInfo)
const setTreeChapter = useUserStore((state) => state.setTreeChapter) const setTreeChapter = useUserStore((state) => state.setTreeChapter)
const setAutosaveTime = useEditorStore((state) => state.setAutosaveTime)
const navigate = useNavigate() const navigate = useNavigate()
const [gData, setGData] = useState([]) const [gData, setGData] = useState([])
const [chapterId, setChapterId] = useState(0) const [chapterId, setChapterId] = useState(0)
const [bookId, setBookId] = useState(0)
// 树节点设置 // 树节点设置
const [expandedKeys, setExpandedKeys] = useState([]) const [expandedKeys, setExpandedKeys] = useState([])
...@@ -53,21 +30,9 @@ const Examine = () => { ...@@ -53,21 +30,9 @@ const Examine = () => {
const [nowTitle, setNowTitle] = useState('') const [nowTitle, setNowTitle] = useState('')
// 编辑操作 // 编辑操作
const [isCollapse, setisCollapse] = useState(false) const [isCollapse, setisCollapse] = useState(false)
const [editKey, setEditKey] = useState(null)
const [parentId, setParentId] = useState(null)
const [editValue, setEditValue] = useState('')
const [loading, setLoading] = useState(false) const [loading, setLoading] = useState(false)
const [contentMd5, setContentMd5] = useState('')
// 设置编者
const [currentChapter, setCurrentChapter] = useState(null)
const [editChapterEditorsIsOpen, setEditChapterEditorsIsOpen] = useState(false)
const onChapterEditorsChange = () => {
setEditChapterEditorsIsOpen(false)
}
// 编辑器内容 // 编辑器内容
const editorRef = useRef() const editorRef = useRef()
const saveInterRef = useRef()
const [html, setHtml] = useState('') const [html, setHtml] = useState('')
const [contentId, setContentId] = useState(false) const [contentId, setContentId] = useState(false)
...@@ -86,8 +51,6 @@ const Examine = () => { ...@@ -86,8 +51,6 @@ const Examine = () => {
return return
} }
const uniqueBookList = [...new Set(data.map((item) => item.book_id))][0]
setBookId(uniqueBookList)
const arr = convertToAntdTreeData(data, 'name') const arr = convertToAntdTreeData(data, 'name')
setGData(arr) setGData(arr)
const allKeys = getAllNodeKeys(arr) const allKeys = getAllNodeKeys(arr)
...@@ -126,11 +89,6 @@ const Examine = () => { ...@@ -126,11 +89,6 @@ const Examine = () => {
setLoading(false) setLoading(false)
} }
const newChapterChange = (id, title) => {
setChapterId(parseInt(id))
setCheckedKeys([parseInt(id)])
setNowTitle(title)
}
// 递归函数,获取所有节点的key // 递归函数,获取所有节点的key
const getAllNodeKeys = (nodes) => { const getAllNodeKeys = (nodes) => {
let keys = [] let keys = []
...@@ -142,18 +100,13 @@ const Examine = () => { ...@@ -142,18 +100,13 @@ const Examine = () => {
}) })
return keys return keys
} }
const [disabled, setDisabled] = useState(false)
// 获取内容 // 获取内容
const getChapterVal = async () => { const getChapterVal = async () => {
setLoading(true) setLoading(true)
const data = await getInfoByChapterId({ chapter_id: chapterId }) const data = await getInfoByChapterId({ chapter_id: chapterId })
setDisabled(!data.selected_editor_ids.includes(userInfo.id) && !isAdminOrCreator)
setTreeChapter({ saveBookId: id, saveChapterId: chapterId, ...data }) setTreeChapter({ saveBookId: id, saveChapterId: chapterId, ...data })
const { content, id: cId } = data const { content, id: cId } = data
if (content) {
setContentMd5(md5(content))
}
setHtml(content) setHtml(content)
setContentId(cId) setContentId(cId)
if (editorRef.current && editorRef.current.editor) { if (editorRef.current && editorRef.current.editor) {
...@@ -165,46 +118,20 @@ const Examine = () => { ...@@ -165,46 +118,20 @@ const Examine = () => {
const onExpand = (expandedKeys) => { const onExpand = (expandedKeys) => {
setExpandedKeys(expandedKeys) setExpandedKeys(expandedKeys)
} }
const handleSelect = async (checkedKeys, info) => { const handleSelect = (selectedKeys, info) => {
const { key } = info.node const { key } = info.node
const childInKey = findTreeElementByKey(gData, 'key', key) const childInKey = findTreeElementByKey(gData, 'key', key)
if (childInKey.children && childInKey.children.length > 0) { if (childInKey.children && childInKey.children.length > 0) {
clearInterval(saveInterRef.current) setExpandedKeys((keys) =>
// 进行展开操作 keys.includes(key) ? keys.filter((item) => item !== key) : [...keys, key],
const tempExpandeds = JSON.parse(JSON.stringify(expandedKeys)) )
let newExpand = ''
if (expandedKeys.includes(key)) {
newExpand = tempExpandeds.filter((item) => parseInt(item) !== parseInt(key))
} else {
newExpand = [...tempExpandeds, key]
}
setExpandedKeys(newExpand)
setCheckedKeys([key])
return return
} else { }
const { key, title } = info.node
if (info.selected === false) {
setLoading(true)
setChapterId(key) setChapterId(key)
setCheckedKeys([key]) setCheckedKeys([key])
setNowTitle(title)
setLoading(false)
} else {
setLoading(true)
clearInterval(saveInterRef.current)
await saveContent()
if (key !== chapterId) {
editorRef.current.editor.clear()
}
setLoading(true)
setChapterId(checkedKeys[0])
setCheckedKeys([checkedKeys[0]])
setNowTitle(info.node.title) setNowTitle(info.node.title)
setLoading(false)
}
}
} }
useEffect(() => { useEffect(() => {
...@@ -217,86 +144,6 @@ const Examine = () => { ...@@ -217,86 +144,6 @@ const Examine = () => {
} }
}, [chapterId]) }, [chapterId])
// 保存方法
const saveContent = async () => {
return
if ((contentId, editorRef.current, editorRef.current.editor, !loading)) {
const contentHtml = editorRef.current.editor.getHtml()
const newMd5 = md5(contentHtml)
clearInterval(saveInterRef.current)
const word_count = editorRef.current.editor.getText().length
// 保存
const data = await sectionEdit({
id: contentId,
content: contentHtml,
word_count,
})
if (data) {
if ((data.code && data.code === 3000) || data.code === '3000') {
navigate('/books/management/list')
return
} else {
setContentMd5(newMd5)
setAutosaveTime(Date.now())
}
}
}
}
useEffect(() => {
if (!loading && contentId) {
clearInterval(saveInterRef.current)
} else {
clearInterval(saveInterRef.current)
}
}, [contentId, loading, contentMd5, html])
const addChapterParent = () => {
setEditKey(-1)
setEditValue('')
setParentId(-1)
}
const delChapter = async (node) => {
const childInKey = findParentLevelOne(gData, 'key', node.key)
let current = null
if (childInKey && childInKey.children && childInKey.children.length > 0) {
const index = findTreeToIndex(childInKey.children, 'key', node.key)
if (childInKey.children.length === 1) {
current = childInKey
} else {
// 前面还有
if (index <= childInKey.children.length) {
if (index === 0) {
current = childInKey.children[index + 1]
} else {
current = childInKey.children[index - 1]
}
}
}
} else {
const index = findTreeToIndex(gData, 'key', node.key)
let child = null
if (index === 0) {
child = gData[index + 1]
} else {
child = gData[index - 1]
}
if (child && child.children && child.children.length > 0) {
current = child.children[0]
} else {
current = child
}
}
const data = await chapterDel({ id: node.key })
if (data) {
setTreeChapter({ saveBookId: id, saveChapterId: current ? current.key : null })
await getChapterTreeList()
}
}
useEffect(() => { useEffect(() => {
if (gData && gData.length > 0 && treeChapter && Object.entries(treeChapter).length > 0) { if (gData && gData.length > 0 && treeChapter && Object.entries(treeChapter).length > 0) {
if (parseInt(treeChapter.saveBookId) === parseInt(id)) { if (parseInt(treeChapter.saveBookId) === parseInt(id)) {
...@@ -310,115 +157,6 @@ const Examine = () => { ...@@ -310,115 +157,6 @@ const Examine = () => {
} }
}, [gData, treeChapter]) }, [gData, treeChapter])
const chapterMenuItems = [
{ key: '1', label: '展开全部' },
// { key: '2', label: '添加子节' },
// { key: '5', label: '设置编者' },
// { key: '3', label: '编辑' },
// { key: '4', label: '删除' }
]
// if (!isAdminOrCreator) {
// chapterMenuItems = [{ key: '1', label: '展开全部' }]
// }
const handleMenuClick = async (e, node) => {
e.domEvent.stopPropagation()
setCurrentChapter(node)
if (parseInt(e.key) === 1) {
// 展开全部
const ids = findNodeById([node], 'key', node.key)
const expandedKeysTemp = [...expandedKeys, node.key, ...ids]
setExpandedKeys(expandedKeysTemp)
} else if (parseInt(e.key) === 2) {
// 添加子节
setEditKey(-1)
setEditValue('')
setParentId(node.key)
} else if (parseInt(e.key) === 3) {
// 编辑
setEditKey(node.key)
setEditValue(node.title)
setParentId(false)
} else if (parseInt(e.key) === 4) {
await modal.confirm({
title: '删除确认',
content: `确认删除子节【${node.title}】?`,
onOk() {
delChapter(node)
},
})
} else if (e.key == 5) {
setEditChapterEditorsIsOpen(true)
}
}
// 章节名称
const chapterTitleRender = (node) => {
return (
<div className='chapter-tree-item'>
<p className='title'>{node.title}</p>
<Dropdown
trigger={['click']}
menu={{ items: chapterMenuItems, onClick: (e) => handleMenuClick(e, node) }}
>
<EllipsisOutlined onClick={(e) => e.stopPropagation()} />
</Dropdown>
</div>
)
}
const onDrop = async (info) => {
const dropToGap = info.dropToGap // true 为同级或最大级 false 为子级
const nowDropNode = info.dragNode.key
const sideDropNode = info.node.key
let data = null
if (dropToGap) {
// 同级
const dragOverGapBottom = info.node.dragOverGapBottom
const dragOver = info.node.dragOver
const dragOverGapTop = info.node.dragOverGapTop
if (!dragOverGapTop && !dragOver && !dragOverGapBottom) {
// 拖到最底部
// 拖拽到最顶层
data = await dragOrder({
book_id: id,
drag_node: nowDropNode,
position_node: sideDropNode,
drop_type: 'after',
})
} else {
if (dragOverGapTop) {
// 拖拽到最顶层
data = await dragOrder({
book_id: id,
drag_node: nowDropNode,
position_node: sideDropNode,
drop_type: 'before',
})
} else if (dragOverGapBottom) {
data = await dragOrder({
book_id: id,
drag_node: nowDropNode,
position_node: sideDropNode,
drop_type: 'after',
})
}
}
} else {
// 子级
data = await dragOrder({
book_id: id,
drag_node: nowDropNode,
position_node: sideDropNode,
drop_type: 'inner',
})
}
if (data) {
await getChapterTreeList()
}
}
return ( return (
<div <div
className='examine' className='examine'
...@@ -445,13 +183,6 @@ const Examine = () => { ...@@ -445,13 +183,6 @@ const Examine = () => {
> >
<Col>章节目录</Col> <Col>章节目录</Col>
<Col> <Col>
{isAdminOrCreator && (
<Button
type='text'
icon={<DiffOutlined />}
onClick={addChapterParent}
></Button>
)}
<Button <Button
type='text' type='text'
icon={<MenuFoldOutlined />} icon={<MenuFoldOutlined />}
...@@ -476,7 +207,6 @@ const Examine = () => { ...@@ -476,7 +207,6 @@ const Examine = () => {
disabled={loading} disabled={loading}
treeData={gData} treeData={gData}
onExpand={onExpand} onExpand={onExpand}
titleRender={(nodeData) => chapterTitleRender(nodeData)}
/> />
)} )}
</> </>
...@@ -514,10 +244,9 @@ const Examine = () => { ...@@ -514,10 +244,9 @@ const Examine = () => {
contentId={contentId} contentId={contentId}
setHtml={setHtml} setHtml={setHtml}
html={html} html={html}
saveContent={saveContent}
gData={gData} gData={gData}
nowTitle={nowTitle} nowTitle={nowTitle}
disabled={disabled} disabled
isView={true} isView={true}
/> />
</Spin> </Spin>
......
...@@ -86,7 +86,7 @@ ...@@ -86,7 +86,7 @@
inset-inline-end: 17px; inset-inline-end: 17px;
top: 16px; top: 16px;
} }
.ant-modal-content { .chapter-title-container {
padding: 15px 18px; padding: 15px 18px;
} }
.ant-divider { .ant-divider {
......
...@@ -180,7 +180,7 @@ export const hexToRgb = (hex) => { ...@@ -180,7 +180,7 @@ export const hexToRgb = (hex) => {
: null : null
} }
export const clacTopicText = (type, radio, checkbox, judge, fill, textarea) => { export const calcTopicText = (type, radio, checkbox, judge, fill, textarea) => {
let i = 0 let i = 0
const arr = ['一', '二', '三', '四', '五'] const arr = ['一', '二', '三', '四', '五']
if (type === 'radio') { if (type === 'radio') {
......
...@@ -15,12 +15,12 @@ export default defineConfig(() => { ...@@ -15,12 +15,12 @@ export default defineConfig(() => {
port: 5174, port: 5174,
strictPort: true, strictPort: true,
proxy: { proxy: {
'/api/admin': { // '/api/admin': {
target: 'http://127.0.0.1:7419', // target: 'http://127.0.0.1:7419',
changeOrigin: true, // changeOrigin: true,
secure: false, // secure: false,
rewrite: (path) => path.replace(/^\/api\/admin/, ''), // rewrite: (path) => path.replace(/^\/api\/admin/, ''),
}, // },
'/api': 'https://zijingebook.ezijing.com', '/api': 'https://zijingebook.ezijing.com',
}, },
}, },
......
...@@ -33,10 +33,10 @@ ...@@ -33,10 +33,10 @@
"@types/react-dom": "^19.2.3", "@types/react-dom": "^19.2.3",
"@vitejs/plugin-react": "^6.0.5", "@vitejs/plugin-react": "^6.0.5",
"jsdom": "^29.1.1", "jsdom": "^29.1.1",
"oxfmt": "^0.59.0", "oxfmt": "^0.64.0",
"oxlint": "^1.74.0", "oxlint": "^1.79.0",
"typescript": "^7.0.2", "typescript": "^7.0.2",
"vite": "^8.2.1", "vite": "^8.2.2",
"vite-plugin-mkcert": "^2.1.0", "vite-plugin-mkcert": "^2.1.0",
"vitest": "^4.1.10" "vitest": "^4.1.10"
} }
......
.mobile-download-modal .ant-modal-content { .mobile-download-modal .mobile-download-modal__container {
padding: 40px 52px 48px; padding: 40px 52px 48px;
border-radius: 24px; border-radius: 24px;
font-family: font-family:
...@@ -6,14 +6,14 @@ ...@@ -6,14 +6,14 @@
'Helvetica Neue', Arial, sans-serif; 'Helvetica Neue', Arial, sans-serif;
} }
.mobile-download-modal .ant-modal-close { .mobile-download-modal .mobile-download-modal__close {
top: 22px; top: 22px;
right: 26px; right: 26px;
color: #b8bcc3; color: #b8bcc3;
font-size: 28px; font-size: 28px;
} }
.mobile-download-modal .ant-modal-close:hover { .mobile-download-modal .mobile-download-modal__close:hover {
color: #90959d; color: #90959d;
background: transparent; background: transparent;
} }
...@@ -125,7 +125,7 @@ ...@@ -125,7 +125,7 @@
.mobile-download-modal { .mobile-download-modal {
max-width: calc(100vw - 32px); max-width: calc(100vw - 32px);
} }
.mobile-download-modal .ant-modal-content { .mobile-download-modal .mobile-download-modal__container {
padding: 28px 24px 36px; padding: 28px 24px 36px;
} }
.mobile-download-modal__content h2.ant-typography { .mobile-download-modal__content h2.ant-typography {
......
...@@ -38,6 +38,10 @@ export function MobileDownloadModal() { ...@@ -38,6 +38,10 @@ export function MobileDownloadModal() {
<Modal <Modal
centered centered
className='mobile-download-modal' className='mobile-download-modal'
classNames={{
container: 'mobile-download-modal__container',
close: 'mobile-download-modal__close',
}}
closeIcon={<CloseCircleFilled />} closeIcon={<CloseCircleFilled />}
footer={null} footer={null}
open={open} open={open}
......
...@@ -118,7 +118,7 @@ importers: ...@@ -118,7 +118,7 @@ importers:
version: 19.2.3(@types/react@19.2.17) version: 19.2.3(@types/react@19.2.17)
'@vitejs/plugin-react': '@vitejs/plugin-react':
specifier: ^6.0.5 specifier: ^6.0.5
version: 6.0.5(vite@8.2.1(@types/node@22.20.1)(esbuild@0.28.1)(less@4.6.7)(terser@5.49.0)) version: 6.0.5(vite@8.2.2(@types/node@22.20.1)(esbuild@0.28.1)(less@4.6.7)(terser@5.49.0))
jsdom: jsdom:
specifier: ^29.1.1 specifier: ^29.1.1
version: 29.1.1 version: 29.1.1
...@@ -126,23 +126,23 @@ importers: ...@@ -126,23 +126,23 @@ importers:
specifier: ^4.2.0 specifier: ^4.2.0
version: 4.6.7 version: 4.6.7
oxfmt: oxfmt:
specifier: ^0.59.0 specifier: ^0.64.0
version: 0.59.0 version: 0.64.0
oxlint: oxlint:
specifier: ^1.74.0 specifier: ^1.79.0
version: 1.74.0 version: 1.79.0
typescript: typescript:
specifier: ^7.0.2 specifier: ^7.0.2
version: 7.0.2 version: 7.0.2
vite: vite:
specifier: ^8.2.1 specifier: ^8.2.2
version: 8.2.1(@types/node@22.20.1)(esbuild@0.28.1)(less@4.6.7)(terser@5.49.0) version: 8.2.2(@types/node@22.20.1)(esbuild@0.28.1)(less@4.6.7)(terser@5.49.0)
vite-plugin-mkcert: vite-plugin-mkcert:
specifier: ^2.1.0 specifier: ^2.1.0
version: 2.1.0(vite@8.2.1(@types/node@22.20.1)(esbuild@0.28.1)(less@4.6.7)(terser@5.49.0)) version: 2.1.0(vite@8.2.2(@types/node@22.20.1)(esbuild@0.28.1)(less@4.6.7)(terser@5.49.0))
vitest: vitest:
specifier: ^4.1.10 specifier: ^4.1.10
version: 4.1.10(@types/node@22.20.1)(jsdom@29.1.1)(vite@8.2.1(@types/node@22.20.1)(esbuild@0.28.1)(less@4.6.7)(terser@5.49.0)) version: 4.1.10(@types/node@22.20.1)(jsdom@29.1.1)(vite@8.2.2(@types/node@22.20.1)(esbuild@0.28.1)(less@4.6.7)(terser@5.49.0))
apps/learning: apps/learning:
dependencies: dependencies:
...@@ -200,28 +200,28 @@ importers: ...@@ -200,28 +200,28 @@ importers:
version: 19.2.3(@types/react@19.2.17) version: 19.2.3(@types/react@19.2.17)
'@vitejs/plugin-react': '@vitejs/plugin-react':
specifier: ^6.0.5 specifier: ^6.0.5
version: 6.0.5(vite@8.2.1(@types/node@22.20.1)(esbuild@0.28.1)(less@4.6.7)(terser@5.49.0)) version: 6.0.5(vite@8.2.2(@types/node@22.20.1)(esbuild@0.28.1)(less@4.6.7)(terser@5.49.0))
jsdom: jsdom:
specifier: ^29.1.1 specifier: ^29.1.1
version: 29.1.1 version: 29.1.1
oxfmt: oxfmt:
specifier: ^0.59.0 specifier: ^0.64.0
version: 0.59.0 version: 0.64.0
oxlint: oxlint:
specifier: ^1.74.0 specifier: ^1.79.0
version: 1.74.0 version: 1.79.0
typescript: typescript:
specifier: ^7.0.2 specifier: ^7.0.2
version: 7.0.2 version: 7.0.2
vite: vite:
specifier: ^8.2.1 specifier: ^8.2.2
version: 8.2.1(@types/node@22.20.1)(esbuild@0.28.1)(less@4.6.7)(terser@5.49.0) version: 8.2.2(@types/node@22.20.1)(esbuild@0.28.1)(less@4.6.7)(terser@5.49.0)
vite-plugin-mkcert: vite-plugin-mkcert:
specifier: ^2.1.0 specifier: ^2.1.0
version: 2.1.0(vite@8.2.1(@types/node@22.20.1)(esbuild@0.28.1)(less@4.6.7)(terser@5.49.0)) version: 2.1.0(vite@8.2.2(@types/node@22.20.1)(esbuild@0.28.1)(less@4.6.7)(terser@5.49.0))
vitest: vitest:
specifier: ^4.1.10 specifier: ^4.1.10
version: 4.1.10(@types/node@22.20.1)(jsdom@29.1.1)(vite@8.2.1(@types/node@22.20.1)(esbuild@0.28.1)(less@4.6.7)(terser@5.49.0)) version: 4.1.10(@types/node@22.20.1)(jsdom@29.1.1)(vite@8.2.2(@types/node@22.20.1)(esbuild@0.28.1)(less@4.6.7)(terser@5.49.0))
packages: packages:
...@@ -538,246 +538,246 @@ packages: ...@@ -538,246 +538,246 @@ packages:
'@oxc-project/types@0.144.0': '@oxc-project/types@0.144.0':
resolution: {integrity: sha512-nuhZIOLuI6TFQ32I/WnUx+SCPY7SdSKwgnFHydAuoS1+Z4BRcaP+RRJmGzl9lw+0OFF7UmaESf7KQRXaNLHypg==} resolution: {integrity: sha512-nuhZIOLuI6TFQ32I/WnUx+SCPY7SdSKwgnFHydAuoS1+Z4BRcaP+RRJmGzl9lw+0OFF7UmaESf7KQRXaNLHypg==}
'@oxfmt/binding-android-arm-eabi@0.59.0': '@oxfmt/binding-android-arm-eabi@0.64.0':
resolution: {integrity: sha512-bNTnfbuG7sAwb2PakMNaDukx5kXeW9duXOBeWtTOiLz3fXz3q2DlWguufPZ+c2IHEVrRXHD+M4aUgEWm841LDA==} resolution: {integrity: sha512-o6uzh/jTOQeAY5TdkAeXdqv7MBRcPxiRA08zrcBtkKj5cSu/FMu0Hl7Q6Fi1KCKyCWZ6lJVjBzdsJvsKltUsGQ==}
engines: {node: ^20.19.0 || >=22.12.0} engines: {node: ^20.19.0 || >=22.12.0}
cpu: [arm] cpu: [arm]
os: [android] os: [android]
'@oxfmt/binding-android-arm64@0.59.0': '@oxfmt/binding-android-arm64@0.64.0':
resolution: {integrity: sha512-R/Sn7z52QtdAKNqQLLY0EK7hVMjXiz3XUlvoCFCm/60jgIzAnQtiqLKBCFaBkimCQL5rs2ezPMcicpjCsrl54Q==} resolution: {integrity: sha512-jRGSUeeP7p3Gynw2YaCVtjBIA6ZxY6bEB/ES5i54OhqmRTyuVg7ZgstEtzgq6GOAJd+2QZ5pvf+bFfmW5Mp9cw==}
engines: {node: ^20.19.0 || >=22.12.0} engines: {node: ^20.19.0 || >=22.12.0}
cpu: [arm64] cpu: [arm64]
os: [android] os: [android]
'@oxfmt/binding-darwin-arm64@0.59.0': '@oxfmt/binding-darwin-arm64@0.64.0':
resolution: {integrity: sha512-vm/ynUqE4HjC0ZIEjmXv1UJu1/GngccQ+T+TJudTMxUxm6r+GQTg1TO3E5jJfI71pBaXxSzs1+vWHIwuilGHhw==} resolution: {integrity: sha512-JINwtU2lW7nOFSqi+H2qplipNUqah9Gc1jgGmB82kTD4UnZrZIVxCJ9qEmFiKfjNq27gYLFhrUb0to86aCwMjw==}
engines: {node: ^20.19.0 || >=22.12.0} engines: {node: ^20.19.0 || >=22.12.0}
cpu: [arm64] cpu: [arm64]
os: [darwin] os: [darwin]
'@oxfmt/binding-darwin-x64@0.59.0': '@oxfmt/binding-darwin-x64@0.64.0':
resolution: {integrity: sha512-uTtYDpLN/obfKVWGpgEc8BqYlLZBQTPz2uYEvLRy3HPZxjZ34wiFzukUBU2bf64JuCYZI//GTV1EOMmWlPjf/w==} resolution: {integrity: sha512-gCmuswrgrOSajV4HCRFkVCGIruPq8bjYuPYgSE2WQB3mD6XrdyZ3JMSRZCkQ8zCxOyGWriBo6QoZ5nmMHQ1BfA==}
engines: {node: ^20.19.0 || >=22.12.0} engines: {node: ^20.19.0 || >=22.12.0}
cpu: [x64] cpu: [x64]
os: [darwin] os: [darwin]
'@oxfmt/binding-freebsd-x64@0.59.0': '@oxfmt/binding-freebsd-x64@0.64.0':
resolution: {integrity: sha512-e2UnxL/ifStSPy8ffBCDbdy595SYsGy+U1pur4G65TuMmWxAMBzYGG7atZo/3mp515p8rZdsflxVD/E1FAdPLQ==} resolution: {integrity: sha512-Ab8g7a38pT0MMImjh7anRSTve6buWBIlcXIFBYa5xl4s6UxEgKSc2xOOhbGtLwvXnEi2PsEDGoJh3oUU7xkehQ==}
engines: {node: ^20.19.0 || >=22.12.0} engines: {node: ^20.19.0 || >=22.12.0}
cpu: [x64] cpu: [x64]
os: [freebsd] os: [freebsd]
'@oxfmt/binding-linux-arm-gnueabihf@0.59.0': '@oxfmt/binding-linux-arm-gnueabihf@0.64.0':
resolution: {integrity: sha512-LtdeZ1l0urxte3VNi3g8cocZwv1xGM1NKHSgF/fJEEVhyQmlgGh7WFWKFd/pNuO7djfvPNtNO1+MS+FEWkgVSA==} resolution: {integrity: sha512-BgvS3CoQ+Xy2deoZqEN8JVKabcCZi2RxA3yant8G9OAv9KuPJ9TCjHkqigzdHUVwErZxEP5d2bzLIEyKYyBDLg==}
engines: {node: ^20.19.0 || >=22.12.0} engines: {node: ^20.19.0 || >=22.12.0}
cpu: [arm] cpu: [arm]
os: [linux] os: [linux]
'@oxfmt/binding-linux-arm-musleabihf@0.59.0': '@oxfmt/binding-linux-arm-musleabihf@0.64.0':
resolution: {integrity: sha512-dBTciSsj9GTMl7p+h2gMSI0hoPn2ijfc/dUsbnWsP0RbwgPl2r0C/5zkMb3Pb+gGj17LH7f1o4qLo9aes/pAvA==} resolution: {integrity: sha512-QXpNxwoMj0YvnceCNZadNSden3bIcnvjn/sDp/rwZhRoZoZYGpHvtPyhGsdJz9uvT9GkaMW7SsLddurU56dt8w==}
engines: {node: ^20.19.0 || >=22.12.0} engines: {node: ^20.19.0 || >=22.12.0}
cpu: [arm] cpu: [arm]
os: [linux] os: [linux]
'@oxfmt/binding-linux-arm64-gnu@0.59.0': '@oxfmt/binding-linux-arm64-gnu@0.64.0':
resolution: {integrity: sha512-tXVdJ/JINsNWdponPHN0OuKHtC+HdpyoS9sd6IDPNiiEYsRki8b7tefRZ1iMnRkdbyT4SEbguWsr6o+5awvbPQ==} resolution: {integrity: sha512-BBgH3I1ppDsI5pZ4Pdhw0ceYxwVCfbU/bZEBCeZ6caRS9x0ZabErxubP7riGUn11PXZBhe8DYdjkDKP1FlVQ5w==}
engines: {node: ^20.19.0 || >=22.12.0} engines: {node: ^20.19.0 || >=22.12.0}
cpu: [arm64] cpu: [arm64]
os: [linux] os: [linux]
libc: [glibc] libc: [glibc]
'@oxfmt/binding-linux-arm64-musl@0.59.0': '@oxfmt/binding-linux-arm64-musl@0.64.0':
resolution: {integrity: sha512-RRTq38i2zT5fnw6XGHjvT6w2mh6x/G3m6AZcAZ56OTDTT/lsOeYnG3SVjwmH40z5kPqF+lf+o35e6m6PpKy9Dw==} resolution: {integrity: sha512-v19HSjC/BGXdt26qEvKZtwAHgGmQ2Agcap2kQP+KIqoRZqivVzYth3ui2dJA1i+6/fjpjga85lIOaJJjQ/bOOw==}
engines: {node: ^20.19.0 || >=22.12.0} engines: {node: ^20.19.0 || >=22.12.0}
cpu: [arm64] cpu: [arm64]
os: [linux] os: [linux]
libc: [musl] libc: [musl]
'@oxfmt/binding-linux-ppc64-gnu@0.59.0': '@oxfmt/binding-linux-ppc64-gnu@0.64.0':
resolution: {integrity: sha512-lD3k7glAJSaXW0D6xzu8VOZbYbosvy+0ktOVkfLEoQF5HJlMSxTQ2KNW0JO+08ccP/1ElOKktVEMI0fqRbVB4w==} resolution: {integrity: sha512-PElLnOo4xFTBZrxPhgTIj0eHqZXwEBQoNWtb7facUV170T0B0FRET0iNbb3LUeLWTybkUW+vsdyv4ihOdyXGyw==}
engines: {node: ^20.19.0 || >=22.12.0} engines: {node: ^20.19.0 || >=22.12.0}
cpu: [ppc64] cpu: [ppc64]
os: [linux] os: [linux]
libc: [glibc] libc: [glibc]
'@oxfmt/binding-linux-riscv64-gnu@0.59.0': '@oxfmt/binding-linux-riscv64-gnu@0.64.0':
resolution: {integrity: sha512-WH5ZP1RbuHKBO/yfPRQKpNO/ijHcEDNbnmC4VPf/Bcd3+mbMAZpRiJWRa1PL5bREdIZZHo343mk3sqlc9x7Usw==} resolution: {integrity: sha512-Qzsg15n4F5CH+MorcRW4MkAEMiLzXmeG+DiDSbP/bBTqCmWOH3K9DHryNrve+JHlV0txS+B6Z9P5Xz+cmWeL+g==}
engines: {node: ^20.19.0 || >=22.12.0} engines: {node: ^20.19.0 || >=22.12.0}
cpu: [riscv64] cpu: [riscv64]
os: [linux] os: [linux]
libc: [glibc] libc: [glibc]
'@oxfmt/binding-linux-riscv64-musl@0.59.0': '@oxfmt/binding-linux-riscv64-musl@0.64.0':
resolution: {integrity: sha512-743wOiaI9RZY4QVGkWkfGRavD5ZJUJ6gscFjVrVu1dP8AZh9jM+a6v3NhlR+OIzHdS6DhLM96w+gcVskskz7rw==} resolution: {integrity: sha512-/GZ358wnQ/Ez4UVnCcZIi56JkY0sOdZ+B108pqXKqZz3jLS59F4KEAB1Qv3fRlObrFEk+3L2vUQ/xoPx+3vjXw==}
engines: {node: ^20.19.0 || >=22.12.0} engines: {node: ^20.19.0 || >=22.12.0}
cpu: [riscv64] cpu: [riscv64]
os: [linux] os: [linux]
libc: [musl] libc: [musl]
'@oxfmt/binding-linux-s390x-gnu@0.59.0': '@oxfmt/binding-linux-s390x-gnu@0.64.0':
resolution: {integrity: sha512-xjRXQsRnrRZCcCkIEnbd2lmsQNobtwwkJxdy2bWXhZ1lIN0ouZwsBXRsoovW3yATuziAYwr9HMiQuR/Cc75NIw==} resolution: {integrity: sha512-/C9We3DXegowfLXtVCYHeNiU9azwCDr5cQkEtCVlc74vyn+lLQSPApJ1CZmxAduqeq/Oi3gQ+IVptyhCaTMtkQ==}
engines: {node: ^20.19.0 || >=22.12.0} engines: {node: ^20.19.0 || >=22.12.0}
cpu: [s390x] cpu: [s390x]
os: [linux] os: [linux]
libc: [glibc] libc: [glibc]
'@oxfmt/binding-linux-x64-gnu@0.59.0': '@oxfmt/binding-linux-x64-gnu@0.64.0':
resolution: {integrity: sha512-4hNjqq/Rbr9B+StY9zMMAfm72+mtM4v80xYL5Qkb59Qd72g2vJMI0iFlPj3kf6miMsie/yJ7rt4urJT292HBgA==} resolution: {integrity: sha512-91KM2CeRWscIEHlj1NsW2WSnzGeq1Ehq+39bfDowTdkn+fcvK/x4Y1RcyqT7glyBjZio0ldkeCG6Usj3v7ASog==}
engines: {node: ^20.19.0 || >=22.12.0} engines: {node: ^20.19.0 || >=22.12.0}
cpu: [x64] cpu: [x64]
os: [linux] os: [linux]
libc: [glibc] libc: [glibc]
'@oxfmt/binding-linux-x64-musl@0.59.0': '@oxfmt/binding-linux-x64-musl@0.64.0':
resolution: {integrity: sha512-NH579iN8EVQYsWowUB8B5vFchcylJtwPVJ7NmUAqEQHNLfhPbDT3K56KrECNAkUN4QpF4qiMgN2vsfZwVvjm7g==} resolution: {integrity: sha512-gw7uEk9I+7zoT1EYLra1eWArIzNcz8e3jkv+Noo2+o2T7wPvsNSQbfoa4DSfZlvn1i6mJ05RiZ4/omaXPDNhQg==}
engines: {node: ^20.19.0 || >=22.12.0} engines: {node: ^20.19.0 || >=22.12.0}
cpu: [x64] cpu: [x64]
os: [linux] os: [linux]
libc: [musl] libc: [musl]
'@oxfmt/binding-openharmony-arm64@0.59.0': '@oxfmt/binding-openharmony-arm64@0.64.0':
resolution: {integrity: sha512-mzZy3Z5Aj1D75Aq9FVlmoRQH5ei8Ga4o/NZmlXkKyeZ5EmPrUXRR7c6BMBteV1ZuZ/356UYDuLRLjAMxTDTiBA==} resolution: {integrity: sha512-HYHFf616FHSPSO07c09mjmXBfQ73wIVM3m0txOiooa5XZkGoxFd6B14PVj0LB0DXIqJ6wAO/dDR/NX/5UUaqnw==}
engines: {node: ^20.19.0 || >=22.12.0} engines: {node: ^20.19.0 || >=22.12.0}
cpu: [arm64] cpu: [arm64]
os: [openharmony] os: [openharmony]
'@oxfmt/binding-win32-arm64-msvc@0.59.0': '@oxfmt/binding-win32-arm64-msvc@0.64.0':
resolution: {integrity: sha512-0CpDJ1gE3jN1Gk6xms1Ie6LPfPcOtY4FAtoOmVLHQoAf8DvO2wd0DW2dIX2f7YTp5dxrr0ND8JeUEjm3DP3k5g==} resolution: {integrity: sha512-uQjFp081IZSWD6VAofX2iO2z01awAdHmfC+NrieWIPKrT2hZKQDyq/U18M7ifC0sm0Wz8aHY/p6+FDYIzs/CrQ==}
engines: {node: ^20.19.0 || >=22.12.0} engines: {node: ^20.19.0 || >=22.12.0}
cpu: [arm64] cpu: [arm64]
os: [win32] os: [win32]
'@oxfmt/binding-win32-ia32-msvc@0.59.0': '@oxfmt/binding-win32-ia32-msvc@0.64.0':
resolution: {integrity: sha512-zwdKBu3pt87uW0bRcywZb0oGMS7C6n87qogwRYFUgmk44T90ZzYlPjtlFYXs/DnBFrgNCvlHwCuWKfVWLeE7kw==} resolution: {integrity: sha512-lNM6byTAQ881jugzFu8juJTbNRgsUTlswMA6pJmwi1XDvmIqnnb49lcUAs5gz94fCJLrVN+/X3s3jOKqx23WIQ==}
engines: {node: ^20.19.0 || >=22.12.0} engines: {node: ^20.19.0 || >=22.12.0}
cpu: [ia32] cpu: [ia32]
os: [win32] os: [win32]
'@oxfmt/binding-win32-x64-msvc@0.59.0': '@oxfmt/binding-win32-x64-msvc@0.64.0':
resolution: {integrity: sha512-dUUbZkKgWrmAeI/puzv4bxN8lzcYaFnQVwFTFtwO2Gp8M7lZGSE2qJjC58g518+1bltJ8mizjYwD0BGHym0l/w==} resolution: {integrity: sha512-BtmbtL/QjMtF1a6C3CqoDluH2IfB6fJt62E+B9RFfUPtFk4Iz9PFS6+y/SzzOvSxc7aUk2Kphwg7Dh8lMbwu6g==}
engines: {node: ^20.19.0 || >=22.12.0} engines: {node: ^20.19.0 || >=22.12.0}
cpu: [x64] cpu: [x64]
os: [win32] os: [win32]
'@oxlint/binding-android-arm-eabi@1.74.0': '@oxlint/binding-android-arm-eabi@1.79.0':
resolution: {integrity: sha512-+gHd12muVI9ZLBaWLPkHt3Fj7jihFjgQ1MGtBaRL8vWrWrI0P7dLUty/cHrHS0oqPYIRgQUJsPu2CExQuMcwNw==} resolution: {integrity: sha512-TebFaaMklO/RXzTv7PucaCq9l3X6D1gA+C8H6K4njtjFOV+zWE9MKLpulcJZN9bzytbUbQIY0mZuz12nQ5Kv4Q==}
engines: {node: ^20.19.0 || >=22.12.0} engines: {node: ^20.19.0 || >=22.12.0}
cpu: [arm] cpu: [arm]
os: [android] os: [android]
'@oxlint/binding-android-arm64@1.74.0': '@oxlint/binding-android-arm64@1.79.0':
resolution: {integrity: sha512-xjKdoMB+H+RCOByv/7l7nfIGW9mlOisqYdcyC75UqYuQecLpReAeEYUf2CNeDEI3KtmUgxpRw/+c63y4AeF/Bw==} resolution: {integrity: sha512-KqqnOtAVgNsPPF0YSodkFZA1O80jcKoCZCTu3bgsszxA+MrMP9TLzfXitKjEj1FmrPprKDMdRDMmY3weESO9sg==}
engines: {node: ^20.19.0 || >=22.12.0} engines: {node: ^20.19.0 || >=22.12.0}
cpu: [arm64] cpu: [arm64]
os: [android] os: [android]
'@oxlint/binding-darwin-arm64@1.74.0': '@oxlint/binding-darwin-arm64@1.79.0':
resolution: {integrity: sha512-iUK7wvc6sejMKsC+Pt67mntoF5weFcyEunhZfLJceU6gL419mexz5wBkSx/EnkFBExMLNtOi9fnDSc5xfK0IzQ==} resolution: {integrity: sha512-BVC2nsMzqQzRDPc5RhixkZ+m1p7iH4bxRRvqkbwDXX0PlQKm1BPy8J8cRjnAFafOq2QzI+BfO3vE8w2GZ3CBag==}
engines: {node: ^20.19.0 || >=22.12.0} engines: {node: ^20.19.0 || >=22.12.0}
cpu: [arm64] cpu: [arm64]
os: [darwin] os: [darwin]
'@oxlint/binding-darwin-x64@1.74.0': '@oxlint/binding-darwin-x64@1.79.0':
resolution: {integrity: sha512-ggKc/tn5SJ1u2yG2izC6VKODfYKV8MQ2AicJlNzOjuyrC29udvOef6/JzK2r32xqCnBDLFouR1VCkjzEI0/N9Q==} resolution: {integrity: sha512-p6Lm+snmhGuLKL1+CpCV8L6ijkE/qJzK2H2jG9+eKJT0n31RbY4FLsdhexekgP3bLpw4Kgde+9DZuDZQ4yIInA==}
engines: {node: ^20.19.0 || >=22.12.0} engines: {node: ^20.19.0 || >=22.12.0}
cpu: [x64] cpu: [x64]
os: [darwin] os: [darwin]
'@oxlint/binding-freebsd-x64@1.74.0': '@oxlint/binding-freebsd-x64@1.79.0':
resolution: {integrity: sha512-u++dH/43jy9hTLbneaWlS0gla/Bp1JdwJ2zgevCl8nDFUh6qRCGMxcL0f0lb7By3A9p/LfFr+7cG4HU1hG856g==} resolution: {integrity: sha512-qDMm0dXZnoHyRqSL4N4xUq82T4sqK5cbKSjvd/dF/YbMUXc2R1wEPf+vmA5S0qUmi0nwXfNbjXBtZaIqzQLIMg==}
engines: {node: ^20.19.0 || >=22.12.0} engines: {node: ^20.19.0 || >=22.12.0}
cpu: [x64] cpu: [x64]
os: [freebsd] os: [freebsd]
'@oxlint/binding-linux-arm-gnueabihf@1.74.0': '@oxlint/binding-linux-arm-gnueabihf@1.79.0':
resolution: {integrity: sha512-Sj1zmtFDVTPeIbIz4ZfcXAbFHqCmKCXdCUlAJzvTF7I20NTH1RDpoF2PhkqNODutJzVhJYmm3oz0GwgY+tvE2g==} resolution: {integrity: sha512-2od7s0nuKPzqyUZAWk9KkCyGg7eI9dwFPZg+20lB15fKFkVZ0c9ZFxqPfiBAyDTlTkh9stPI0t+JlPCqMbItVA==}
engines: {node: ^20.19.0 || >=22.12.0} engines: {node: ^20.19.0 || >=22.12.0}
cpu: [arm] cpu: [arm]
os: [linux] os: [linux]
'@oxlint/binding-linux-arm-musleabihf@1.74.0': '@oxlint/binding-linux-arm-musleabihf@1.79.0':
resolution: {integrity: sha512-//PKyQb/tQXcHArx2f7z+oVI/eMS2Jpv+edNuAtOrgIhWdGcpHxogveAxzmF2rpH1AIHp4Hq04RF/rgJdiICnQ==} resolution: {integrity: sha512-ZOQUjkzDnvlhSE3+tWC3YXx94MMl+sYMlwH+u1+YGApGHOJP/YAc8ZBRFOXZ6eOBmxtXAWuS/fBcdZr8qqNO1A==}
engines: {node: ^20.19.0 || >=22.12.0} engines: {node: ^20.19.0 || >=22.12.0}
cpu: [arm] cpu: [arm]
os: [linux] os: [linux]
'@oxlint/binding-linux-arm64-gnu@1.74.0': '@oxlint/binding-linux-arm64-gnu@1.79.0':
resolution: {integrity: sha512-/k1Me+aX2tjuH10K62mLS0y8cLkJBHX6Ce0xPK+eWeel4bSdEGZ8dv4+hYMzg0GrSmjwy4yAYsDPeEeKBft/2w==} resolution: {integrity: sha512-lu158FR4nGqGeRS3BQvtG85wRgU/Fy4MD5Cxp1hzJXizGiLo6u2742wJSCDKh8cFcZntvX7fcxlq4mMmfryH1g==}
engines: {node: ^20.19.0 || >=22.12.0} engines: {node: ^20.19.0 || >=22.12.0}
cpu: [arm64] cpu: [arm64]
os: [linux] os: [linux]
libc: [glibc] libc: [glibc]
'@oxlint/binding-linux-arm64-musl@1.74.0': '@oxlint/binding-linux-arm64-musl@1.79.0':
resolution: {integrity: sha512-3tFSjBxc5D8/zvjEuLvOqcA8ZXKD0+6NuaVO/edeamNc49MoAsbfaC9s1UiwODwgF6slGaF8yJA2TPkukd77tg==} resolution: {integrity: sha512-mbpKQeE2aflTjddaHK7MP8KP/OFbUM++lt5M635ENM8IyIdK0jm2t9pb+2v9mVVIvhF6TqA4l7F79Pll1mi+uw==}
engines: {node: ^20.19.0 || >=22.12.0} engines: {node: ^20.19.0 || >=22.12.0}
cpu: [arm64] cpu: [arm64]
os: [linux] os: [linux]
libc: [musl] libc: [musl]
'@oxlint/binding-linux-ppc64-gnu@1.74.0': '@oxlint/binding-linux-ppc64-gnu@1.79.0':
resolution: {integrity: sha512-9QggtPkSPXOCTu8Szis7auOK/sC7KdQaN+/TujP7YVVhzCAOhgdRfgv8uEz0r2tk5xdgus5rLYUrCDoZNtiRUw==} resolution: {integrity: sha512-WpGNua7gaxaHnpSDeog2ji8IDHn/QLPl9LPzwkR/FvVv58vT5BcXjRXnU+wbu3N75cpeha8CdC7ho/U2OIsB4g==}
engines: {node: ^20.19.0 || >=22.12.0} engines: {node: ^20.19.0 || >=22.12.0}
cpu: [ppc64] cpu: [ppc64]
os: [linux] os: [linux]
libc: [glibc] libc: [glibc]
'@oxlint/binding-linux-riscv64-gnu@1.74.0': '@oxlint/binding-linux-riscv64-gnu@1.79.0':
resolution: {integrity: sha512-VM5VPUJ4DJIWiK+AZn8FScUqMr6OFrCAYybMYjEEi7W13ParI64MByiXTkKMqZpBmvQ9zxl9Ebq2VUOiZRJYUg==} resolution: {integrity: sha512-tK1E93A5LVzISg4ngpKJnfTs7EqtIUceGI7MQ4GyDjJiLi8wPCkEyKlj2xkyKWZ1yzkDJyLHTBJ5/iFWRdnJvg==}
engines: {node: ^20.19.0 || >=22.12.0} engines: {node: ^20.19.0 || >=22.12.0}
cpu: [riscv64] cpu: [riscv64]
os: [linux] os: [linux]
libc: [glibc] libc: [glibc]
'@oxlint/binding-linux-riscv64-musl@1.74.0': '@oxlint/binding-linux-riscv64-musl@1.79.0':
resolution: {integrity: sha512-SaDY1gh9rOA592J54g+gu5hkOFFQBZsMmIYHs+NRHG+Uq0OxtuuCXMWQ3vu1830Eugv5uMXyjG+bv2Z9y4IXjw==} resolution: {integrity: sha512-qhQvUIrngXivA2A9pQ+xPCychztn/5qUv7yS3gDwXv3w7Rag+eTeeXWmRyx+t7XsW5x6LuY/8AsTq36UgFIblg==}
engines: {node: ^20.19.0 || >=22.12.0} engines: {node: ^20.19.0 || >=22.12.0}
cpu: [riscv64] cpu: [riscv64]
os: [linux] os: [linux]
libc: [musl] libc: [musl]
'@oxlint/binding-linux-s390x-gnu@1.74.0': '@oxlint/binding-linux-s390x-gnu@1.79.0':
resolution: {integrity: sha512-ZATQeHZCyr6MbDveg0obD5sxLHFOghtOdC5jwVwYlvFWqtFOxctgFEG6Ef/64hYvZrWyhyCckB10AelqLopeDA==} resolution: {integrity: sha512-sv6AaVgU/eE6u+6WFiQVDcPPwTxP6IJMSB9k701W2r/r6Tx465e8vPvVyRxquNH4Vy6KwRNu90mVbxXJN8+5gg==}
engines: {node: ^20.19.0 || >=22.12.0} engines: {node: ^20.19.0 || >=22.12.0}
cpu: [s390x] cpu: [s390x]
os: [linux] os: [linux]
libc: [glibc] libc: [glibc]
'@oxlint/binding-linux-x64-gnu@1.74.0': '@oxlint/binding-linux-x64-gnu@1.79.0':
resolution: {integrity: sha512-+aIvJyrdeD7LwCQ2WYLMUWNmnbeDRSPb40aBYtPjD9+PTqUwgJnk+HK5yLfSMeqXrMrDhE9uTmtt2y50tvjhHw==} resolution: {integrity: sha512-iFZL02deziHslb3jEX9KdqlAkYoo4fGyotchKDzdfK1f5mxlIBeiQeHhvK3iFpuEJSB4ma/qeFn9oxPiwnhUPQ==}
engines: {node: ^20.19.0 || >=22.12.0} engines: {node: ^20.19.0 || >=22.12.0}
cpu: [x64] cpu: [x64]
os: [linux] os: [linux]
libc: [glibc] libc: [glibc]
'@oxlint/binding-linux-x64-musl@1.74.0': '@oxlint/binding-linux-x64-musl@1.79.0':
resolution: {integrity: sha512-XyktaR8lhK2qWiCK0Tk8oYD+/cgn+oHA6ddRnxSSXUKkkojkV78CmShZUxQF+yrBFs0SuW+JBOPG6hecyc/iZg==} resolution: {integrity: sha512-3DtZR2raqObnh7wXZoFYFd0Fw7skBvcb3f7A+/lkEiDuh8hrE6vv9b/62Qxao1a9/OeHLw/FcXlXzgsW9wTRFg==}
engines: {node: ^20.19.0 || >=22.12.0} engines: {node: ^20.19.0 || >=22.12.0}
cpu: [x64] cpu: [x64]
os: [linux] os: [linux]
libc: [musl] libc: [musl]
'@oxlint/binding-openharmony-arm64@1.74.0': '@oxlint/binding-openharmony-arm64@1.79.0':
resolution: {integrity: sha512-mzbjrPl4neaVUiJ1fUiEUxTGaSZBoiKtaoB6jmIpz9S+VOA2vDYmJpihQ82w6178V5jxziclTg8Cgj5yF6tTDg==} resolution: {integrity: sha512-Oatt4GuA1WJkqzk2ozx4HrWROOi7opV3AKDw/U8qDIqeTqzsjn5K2x3REJMNjU3/KU/Bkq96Zi3CknaiDTaC/Q==}
engines: {node: ^20.19.0 || >=22.12.0} engines: {node: ^20.19.0 || >=22.12.0}
cpu: [arm64] cpu: [arm64]
os: [openharmony] os: [openharmony]
'@oxlint/binding-win32-arm64-msvc@1.74.0': '@oxlint/binding-win32-arm64-msvc@1.79.0':
resolution: {integrity: sha512-vUAe9okpS2Oa5+lX67lqHMuNUvfkleRKwrUDJ/WJBsgmddvZ1mrsh2HVmuFDRzqFELhaJhFaCNOuR6a7L3rtIA==} resolution: {integrity: sha512-NAgZr9Qp8nIA9rpo0JEvwiabTF/2UVqBNnupBG9X4kxXcQoScJUTi+qHhvabb9s/thgj5wQ4XcIaJvb+ZMgoKw==}
engines: {node: ^20.19.0 || >=22.12.0} engines: {node: ^20.19.0 || >=22.12.0}
cpu: [arm64] cpu: [arm64]
os: [win32] os: [win32]
'@oxlint/binding-win32-ia32-msvc@1.74.0': '@oxlint/binding-win32-ia32-msvc@1.79.0':
resolution: {integrity: sha512-yyXXJyYYSXL4I8K8jAWjJs+J3fa9gH2JmEbo4f5adm+1tNC9itseicBNuwK7BDHvqQ5J534s+yDULu89vYL2ZQ==} resolution: {integrity: sha512-+KyXjIvcpaXmWW/j9NNY5yWjrIVxaX18VyIheQy3jwc2GSYgpCr7MGI/HxIGQ/shAL5IWEKbhsqoMpAO5Stiog==}
engines: {node: ^20.19.0 || >=22.12.0} engines: {node: ^20.19.0 || >=22.12.0}
cpu: [ia32] cpu: [ia32]
os: [win32] os: [win32]
'@oxlint/binding-win32-x64-msvc@1.74.0': '@oxlint/binding-win32-x64-msvc@1.79.0':
resolution: {integrity: sha512-VTC9IYTIMrVUk/i6Ms1ohzzDKZFkWn0KU2OBbPBzgmVZ2V30165T/zK4LztTr0Xgp9fZ1qQZ1rsZAu/rEmySlA==} resolution: {integrity: sha512-mEelcCMMBS57sIXh2veGMNy+pQwuGtcMxHxGIZWQ5Ba9pJ5jCCUFOZB9E2JhBaxGsURe+WGe0zJp4RVre52gpQ==}
engines: {node: ^20.19.0 || >=22.12.0} engines: {node: ^20.19.0 || >=22.12.0}
cpu: [x64] cpu: [x64]
os: [win32] os: [win32]
...@@ -2359,8 +2359,8 @@ packages: ...@@ -2359,8 +2359,8 @@ packages:
engines: {node: '>=0.10.0'} engines: {node: '>=0.10.0'}
hasBin: true hasBin: true
oxfmt@0.59.0: oxfmt@0.64.0:
resolution: {integrity: sha512-Xqk6cPZS1yMvVa7OAuenaDZUsgMDutvvbZ9/L5gSvAfW64+WN4HVhgipLj5rVERbYQt8fLs9TopyZ1rU1XEG/w==} resolution: {integrity: sha512-XZ4GFBN/PLbXKq+0zrgpQfPKYuJlUuj+nzZJY7UpIbFMNyefNLCdN9EwViycNqnYcv0wrn0jXcQLlqJp8RCKBg==}
engines: {node: ^20.19.0 || >=22.12.0} engines: {node: ^20.19.0 || >=22.12.0}
hasBin: true hasBin: true
peerDependencies: peerDependencies:
...@@ -2372,12 +2372,12 @@ packages: ...@@ -2372,12 +2372,12 @@ packages:
vite-plus: vite-plus:
optional: true optional: true
oxlint@1.74.0: oxlint@1.79.0:
resolution: {integrity: sha512-odGl2s2x5IOJoj3A0v1k0PGBXVFBZeZ2+AK/+K2MJur7Ghi3bkyX5NuLUWHKqa4js1wjep3hJeuTQJOlr+4+dA==} resolution: {integrity: sha512-hVJ9hq9m2unPS+Of4eJJgCPdIeCC+3DHEUX3tkmrPJr3OK2hz7PhXwgC+ZP71ZcYu8cCDEtQrqLxWNvxBppBVg==}
engines: {node: ^20.19.0 || >=22.12.0} engines: {node: ^20.19.0 || >=22.12.0}
hasBin: true hasBin: true
peerDependencies: peerDependencies:
oxlint-tsgolint: '>=0.24.0' oxlint-tsgolint: '>=7.0.2001'
vite-plus: '*' vite-plus: '*'
peerDependenciesMeta: peerDependenciesMeta:
oxlint-tsgolint: oxlint-tsgolint:
...@@ -2794,13 +2794,13 @@ packages: ...@@ -2794,13 +2794,13 @@ packages:
peerDependencies: peerDependencies:
vite: '>=3' vite: '>=3'
vite@8.2.1: vite@8.2.2:
resolution: {integrity: sha512-EU/eS7BH3XROHh2YnBefjM6DBKA6ZeMZEYQbj7NLWg5wHYlhB8B/Mayd5XsgWq+NFYccDOTemRpdETWR6Ka/lw==} resolution: {integrity: sha512-cFKLV/PRgAUlIRm5WjMjJ86jrftzpqcgH+Us+DS8mI3CDNiH30Whrz8uHL3+MOLPAgqbMBAqWdAHAphOAM+z/Q==}
engines: {node: ^20.19.0 || >=22.12.0} engines: {node: ^20.19.0 || >=22.12.0}
hasBin: true hasBin: true
peerDependencies: peerDependencies:
'@types/node': ^20.19.0 || >=22.12.0 '@types/node': ^20.19.0 || >=22.12.0
'@vitejs/devtools': ^0.4.0 '@vitejs/devtools': ^0.4.0 || ^0.5.0
esbuild: ^0.27.0 || ^0.28.0 esbuild: ^0.27.0 || ^0.28.0
jiti: '>=1.21.0' jiti: '>=1.21.0'
less: ^4.0.0 less: ^4.0.0
...@@ -3203,118 +3203,118 @@ snapshots: ...@@ -3203,118 +3203,118 @@ snapshots:
'@oxc-project/types@0.144.0': {} '@oxc-project/types@0.144.0': {}
'@oxfmt/binding-android-arm-eabi@0.59.0': '@oxfmt/binding-android-arm-eabi@0.64.0':
optional: true optional: true
'@oxfmt/binding-android-arm64@0.59.0': '@oxfmt/binding-android-arm64@0.64.0':
optional: true optional: true
'@oxfmt/binding-darwin-arm64@0.59.0': '@oxfmt/binding-darwin-arm64@0.64.0':
optional: true optional: true
'@oxfmt/binding-darwin-x64@0.59.0': '@oxfmt/binding-darwin-x64@0.64.0':
optional: true optional: true
'@oxfmt/binding-freebsd-x64@0.59.0': '@oxfmt/binding-freebsd-x64@0.64.0':
optional: true optional: true
'@oxfmt/binding-linux-arm-gnueabihf@0.59.0': '@oxfmt/binding-linux-arm-gnueabihf@0.64.0':
optional: true optional: true
'@oxfmt/binding-linux-arm-musleabihf@0.59.0': '@oxfmt/binding-linux-arm-musleabihf@0.64.0':
optional: true optional: true
'@oxfmt/binding-linux-arm64-gnu@0.59.0': '@oxfmt/binding-linux-arm64-gnu@0.64.0':
optional: true optional: true
'@oxfmt/binding-linux-arm64-musl@0.59.0': '@oxfmt/binding-linux-arm64-musl@0.64.0':
optional: true optional: true
'@oxfmt/binding-linux-ppc64-gnu@0.59.0': '@oxfmt/binding-linux-ppc64-gnu@0.64.0':
optional: true optional: true
'@oxfmt/binding-linux-riscv64-gnu@0.59.0': '@oxfmt/binding-linux-riscv64-gnu@0.64.0':
optional: true optional: true
'@oxfmt/binding-linux-riscv64-musl@0.59.0': '@oxfmt/binding-linux-riscv64-musl@0.64.0':
optional: true optional: true
'@oxfmt/binding-linux-s390x-gnu@0.59.0': '@oxfmt/binding-linux-s390x-gnu@0.64.0':
optional: true optional: true
'@oxfmt/binding-linux-x64-gnu@0.59.0': '@oxfmt/binding-linux-x64-gnu@0.64.0':
optional: true optional: true
'@oxfmt/binding-linux-x64-musl@0.59.0': '@oxfmt/binding-linux-x64-musl@0.64.0':
optional: true optional: true
'@oxfmt/binding-openharmony-arm64@0.59.0': '@oxfmt/binding-openharmony-arm64@0.64.0':
optional: true optional: true
'@oxfmt/binding-win32-arm64-msvc@0.59.0': '@oxfmt/binding-win32-arm64-msvc@0.64.0':
optional: true optional: true
'@oxfmt/binding-win32-ia32-msvc@0.59.0': '@oxfmt/binding-win32-ia32-msvc@0.64.0':
optional: true optional: true
'@oxfmt/binding-win32-x64-msvc@0.59.0': '@oxfmt/binding-win32-x64-msvc@0.64.0':
optional: true optional: true
'@oxlint/binding-android-arm-eabi@1.74.0': '@oxlint/binding-android-arm-eabi@1.79.0':
optional: true optional: true
'@oxlint/binding-android-arm64@1.74.0': '@oxlint/binding-android-arm64@1.79.0':
optional: true optional: true
'@oxlint/binding-darwin-arm64@1.74.0': '@oxlint/binding-darwin-arm64@1.79.0':
optional: true optional: true
'@oxlint/binding-darwin-x64@1.74.0': '@oxlint/binding-darwin-x64@1.79.0':
optional: true optional: true
'@oxlint/binding-freebsd-x64@1.74.0': '@oxlint/binding-freebsd-x64@1.79.0':
optional: true optional: true
'@oxlint/binding-linux-arm-gnueabihf@1.74.0': '@oxlint/binding-linux-arm-gnueabihf@1.79.0':
optional: true optional: true
'@oxlint/binding-linux-arm-musleabihf@1.74.0': '@oxlint/binding-linux-arm-musleabihf@1.79.0':
optional: true optional: true
'@oxlint/binding-linux-arm64-gnu@1.74.0': '@oxlint/binding-linux-arm64-gnu@1.79.0':
optional: true optional: true
'@oxlint/binding-linux-arm64-musl@1.74.0': '@oxlint/binding-linux-arm64-musl@1.79.0':
optional: true optional: true
'@oxlint/binding-linux-ppc64-gnu@1.74.0': '@oxlint/binding-linux-ppc64-gnu@1.79.0':
optional: true optional: true
'@oxlint/binding-linux-riscv64-gnu@1.74.0': '@oxlint/binding-linux-riscv64-gnu@1.79.0':
optional: true optional: true
'@oxlint/binding-linux-riscv64-musl@1.74.0': '@oxlint/binding-linux-riscv64-musl@1.79.0':
optional: true optional: true
'@oxlint/binding-linux-s390x-gnu@1.74.0': '@oxlint/binding-linux-s390x-gnu@1.79.0':
optional: true optional: true
'@oxlint/binding-linux-x64-gnu@1.74.0': '@oxlint/binding-linux-x64-gnu@1.79.0':
optional: true optional: true
'@oxlint/binding-linux-x64-musl@1.74.0': '@oxlint/binding-linux-x64-musl@1.79.0':
optional: true optional: true
'@oxlint/binding-openharmony-arm64@1.74.0': '@oxlint/binding-openharmony-arm64@1.79.0':
optional: true optional: true
'@oxlint/binding-win32-arm64-msvc@1.74.0': '@oxlint/binding-win32-arm64-msvc@1.79.0':
optional: true optional: true
'@oxlint/binding-win32-ia32-msvc@1.74.0': '@oxlint/binding-win32-ia32-msvc@1.79.0':
optional: true optional: true
'@oxlint/binding-win32-x64-msvc@1.74.0': '@oxlint/binding-win32-x64-msvc@1.79.0':
optional: true optional: true
'@rc-component/async-validator@6.0.0': '@rc-component/async-validator@6.0.0':
...@@ -3993,10 +3993,10 @@ snapshots: ...@@ -3993,10 +3993,10 @@ snapshots:
'@uppy/utils': 4.1.3 '@uppy/utils': 4.1.3
nanoid: 3.3.18 nanoid: 3.3.18
'@vitejs/plugin-react@6.0.5(vite@8.2.1(@types/node@22.20.1)(esbuild@0.28.1)(less@4.6.7)(terser@5.49.0))': '@vitejs/plugin-react@6.0.5(vite@8.2.2(@types/node@22.20.1)(esbuild@0.28.1)(less@4.6.7)(terser@5.49.0))':
dependencies: dependencies:
'@rolldown/pluginutils': 1.0.1 '@rolldown/pluginutils': 1.0.1
vite: 8.2.1(@types/node@22.20.1)(esbuild@0.28.1)(less@4.6.7)(terser@5.49.0) vite: 8.2.2(@types/node@22.20.1)(esbuild@0.28.1)(less@4.6.7)(terser@5.49.0)
'@vitest/expect@4.1.10': '@vitest/expect@4.1.10':
dependencies: dependencies:
...@@ -4007,13 +4007,13 @@ snapshots: ...@@ -4007,13 +4007,13 @@ snapshots:
chai: 6.2.2 chai: 6.2.2
tinyrainbow: 3.1.0 tinyrainbow: 3.1.0
'@vitest/mocker@4.1.10(vite@8.2.1(@types/node@22.20.1)(esbuild@0.28.1)(less@4.6.7)(terser@5.49.0))': '@vitest/mocker@4.1.10(vite@8.2.2(@types/node@22.20.1)(esbuild@0.28.1)(less@4.6.7)(terser@5.49.0))':
dependencies: dependencies:
'@vitest/spy': 4.1.10 '@vitest/spy': 4.1.10
estree-walker: 3.0.3 estree-walker: 3.0.3
magic-string: 0.30.21 magic-string: 0.30.21
optionalDependencies: optionalDependencies:
vite: 8.2.1(@types/node@22.20.1)(esbuild@0.28.1)(less@4.6.7)(terser@5.49.0) vite: 8.2.2(@types/node@22.20.1)(esbuild@0.28.1)(less@4.6.7)(terser@5.49.0)
'@vitest/pretty-format@4.1.10': '@vitest/pretty-format@4.1.10':
dependencies: dependencies:
...@@ -4988,51 +4988,51 @@ snapshots: ...@@ -4988,51 +4988,51 @@ snapshots:
dependencies: dependencies:
minimist: 1.2.8 minimist: 1.2.8
oxfmt@0.59.0: oxfmt@0.64.0:
dependencies: dependencies:
tinypool: 2.1.0 tinypool: 2.1.0
optionalDependencies: optionalDependencies:
'@oxfmt/binding-android-arm-eabi': 0.59.0 '@oxfmt/binding-android-arm-eabi': 0.64.0
'@oxfmt/binding-android-arm64': 0.59.0 '@oxfmt/binding-android-arm64': 0.64.0
'@oxfmt/binding-darwin-arm64': 0.59.0 '@oxfmt/binding-darwin-arm64': 0.64.0
'@oxfmt/binding-darwin-x64': 0.59.0 '@oxfmt/binding-darwin-x64': 0.64.0
'@oxfmt/binding-freebsd-x64': 0.59.0 '@oxfmt/binding-freebsd-x64': 0.64.0
'@oxfmt/binding-linux-arm-gnueabihf': 0.59.0 '@oxfmt/binding-linux-arm-gnueabihf': 0.64.0
'@oxfmt/binding-linux-arm-musleabihf': 0.59.0 '@oxfmt/binding-linux-arm-musleabihf': 0.64.0
'@oxfmt/binding-linux-arm64-gnu': 0.59.0 '@oxfmt/binding-linux-arm64-gnu': 0.64.0
'@oxfmt/binding-linux-arm64-musl': 0.59.0 '@oxfmt/binding-linux-arm64-musl': 0.64.0
'@oxfmt/binding-linux-ppc64-gnu': 0.59.0 '@oxfmt/binding-linux-ppc64-gnu': 0.64.0
'@oxfmt/binding-linux-riscv64-gnu': 0.59.0 '@oxfmt/binding-linux-riscv64-gnu': 0.64.0
'@oxfmt/binding-linux-riscv64-musl': 0.59.0 '@oxfmt/binding-linux-riscv64-musl': 0.64.0
'@oxfmt/binding-linux-s390x-gnu': 0.59.0 '@oxfmt/binding-linux-s390x-gnu': 0.64.0
'@oxfmt/binding-linux-x64-gnu': 0.59.0 '@oxfmt/binding-linux-x64-gnu': 0.64.0
'@oxfmt/binding-linux-x64-musl': 0.59.0 '@oxfmt/binding-linux-x64-musl': 0.64.0
'@oxfmt/binding-openharmony-arm64': 0.59.0 '@oxfmt/binding-openharmony-arm64': 0.64.0
'@oxfmt/binding-win32-arm64-msvc': 0.59.0 '@oxfmt/binding-win32-arm64-msvc': 0.64.0
'@oxfmt/binding-win32-ia32-msvc': 0.59.0 '@oxfmt/binding-win32-ia32-msvc': 0.64.0
'@oxfmt/binding-win32-x64-msvc': 0.59.0 '@oxfmt/binding-win32-x64-msvc': 0.64.0
oxlint@1.74.0: oxlint@1.79.0:
optionalDependencies: optionalDependencies:
'@oxlint/binding-android-arm-eabi': 1.74.0 '@oxlint/binding-android-arm-eabi': 1.79.0
'@oxlint/binding-android-arm64': 1.74.0 '@oxlint/binding-android-arm64': 1.79.0
'@oxlint/binding-darwin-arm64': 1.74.0 '@oxlint/binding-darwin-arm64': 1.79.0
'@oxlint/binding-darwin-x64': 1.74.0 '@oxlint/binding-darwin-x64': 1.79.0
'@oxlint/binding-freebsd-x64': 1.74.0 '@oxlint/binding-freebsd-x64': 1.79.0
'@oxlint/binding-linux-arm-gnueabihf': 1.74.0 '@oxlint/binding-linux-arm-gnueabihf': 1.79.0
'@oxlint/binding-linux-arm-musleabihf': 1.74.0 '@oxlint/binding-linux-arm-musleabihf': 1.79.0
'@oxlint/binding-linux-arm64-gnu': 1.74.0 '@oxlint/binding-linux-arm64-gnu': 1.79.0
'@oxlint/binding-linux-arm64-musl': 1.74.0 '@oxlint/binding-linux-arm64-musl': 1.79.0
'@oxlint/binding-linux-ppc64-gnu': 1.74.0 '@oxlint/binding-linux-ppc64-gnu': 1.79.0
'@oxlint/binding-linux-riscv64-gnu': 1.74.0 '@oxlint/binding-linux-riscv64-gnu': 1.79.0
'@oxlint/binding-linux-riscv64-musl': 1.74.0 '@oxlint/binding-linux-riscv64-musl': 1.79.0
'@oxlint/binding-linux-s390x-gnu': 1.74.0 '@oxlint/binding-linux-s390x-gnu': 1.79.0
'@oxlint/binding-linux-x64-gnu': 1.74.0 '@oxlint/binding-linux-x64-gnu': 1.79.0
'@oxlint/binding-linux-x64-musl': 1.74.0 '@oxlint/binding-linux-x64-musl': 1.79.0
'@oxlint/binding-openharmony-arm64': 1.74.0 '@oxlint/binding-openharmony-arm64': 1.79.0
'@oxlint/binding-win32-arm64-msvc': 1.74.0 '@oxlint/binding-win32-arm64-msvc': 1.79.0
'@oxlint/binding-win32-ia32-msvc': 1.74.0 '@oxlint/binding-win32-ia32-msvc': 1.79.0
'@oxlint/binding-win32-x64-msvc': 1.74.0 '@oxlint/binding-win32-x64-msvc': 1.79.0
parse-node-version@1.0.1: {} parse-node-version@1.0.1: {}
...@@ -5454,14 +5454,14 @@ snapshots: ...@@ -5454,14 +5454,14 @@ snapshots:
mz: 2.7.0 mz: 2.7.0
unescape: 1.0.1 unescape: 1.0.1
vite-plugin-mkcert@2.1.0(vite@8.2.1(@types/node@22.20.1)(esbuild@0.28.1)(less@4.6.7)(terser@5.49.0)): vite-plugin-mkcert@2.1.0(vite@8.2.2(@types/node@22.20.1)(esbuild@0.28.1)(less@4.6.7)(terser@5.49.0)):
dependencies: dependencies:
debug: 4.4.3(supports-color@10.2.2) debug: 4.4.3(supports-color@10.2.2)
supports-color: 10.2.2 supports-color: 10.2.2
undici: 8.10.0 undici: 8.10.0
vite: 8.2.1(@types/node@22.20.1)(esbuild@0.28.1)(less@4.6.7)(terser@5.49.0) vite: 8.2.2(@types/node@22.20.1)(esbuild@0.28.1)(less@4.6.7)(terser@5.49.0)
vite@8.2.1(@types/node@22.20.1)(esbuild@0.28.1)(less@4.6.7)(terser@5.49.0): vite@8.2.2(@types/node@22.20.1)(esbuild@0.28.1)(less@4.6.7)(terser@5.49.0):
dependencies: dependencies:
lightningcss: 1.33.0 lightningcss: 1.33.0
picomatch: 4.0.5 picomatch: 4.0.5
...@@ -5475,10 +5475,10 @@ snapshots: ...@@ -5475,10 +5475,10 @@ snapshots:
less: 4.6.7 less: 4.6.7
terser: 5.49.0 terser: 5.49.0
vitest@4.1.10(@types/node@22.20.1)(jsdom@29.1.1)(vite@8.2.1(@types/node@22.20.1)(esbuild@0.28.1)(less@4.6.7)(terser@5.49.0)): vitest@4.1.10(@types/node@22.20.1)(jsdom@29.1.1)(vite@8.2.2(@types/node@22.20.1)(esbuild@0.28.1)(less@4.6.7)(terser@5.49.0)):
dependencies: dependencies:
'@vitest/expect': 4.1.10 '@vitest/expect': 4.1.10
'@vitest/mocker': 4.1.10(vite@8.2.1(@types/node@22.20.1)(esbuild@0.28.1)(less@4.6.7)(terser@5.49.0)) '@vitest/mocker': 4.1.10(vite@8.2.2(@types/node@22.20.1)(esbuild@0.28.1)(less@4.6.7)(terser@5.49.0))
'@vitest/pretty-format': 4.1.10 '@vitest/pretty-format': 4.1.10
'@vitest/runner': 4.1.10 '@vitest/runner': 4.1.10
'@vitest/snapshot': 4.1.10 '@vitest/snapshot': 4.1.10
...@@ -5495,7 +5495,7 @@ snapshots: ...@@ -5495,7 +5495,7 @@ snapshots:
tinyexec: 1.2.4 tinyexec: 1.2.4
tinyglobby: 0.2.17 tinyglobby: 0.2.17
tinyrainbow: 3.1.0 tinyrainbow: 3.1.0
vite: 8.2.1(@types/node@22.20.1)(esbuild@0.28.1)(less@4.6.7)(terser@5.49.0) vite: 8.2.2(@types/node@22.20.1)(esbuild@0.28.1)(less@4.6.7)(terser@5.49.0)
why-is-node-running: 2.3.0 why-is-node-running: 2.3.0
optionalDependencies: optionalDependencies:
'@types/node': 22.20.1 '@types/node': 22.20.1
......
...@@ -5,3 +5,6 @@ packages: ...@@ -5,3 +5,6 @@ packages:
allowBuilds: allowBuilds:
es5-ext: false es5-ext: false
esbuild: true esbuild: true
minimumReleaseAgeExclude:
- vite@8.2.2
Markdown 格式
0% 或
您添加了 0 人 到此讨论。请谨慎行事。
请先完成此评论的编辑!
请 注册 或者 后发表评论