@@ -12,6 +12,8 @@ import {
1212 _dateFormat ,
1313 _getDictDataByUrl ,
1414 _nextTick ,
15+ ensureCustomDictCopy ,
16+ findOfficialSourceDict ,
1517 msToHourMinute ,
1618 resourceWrap ,
1719 total ,
@@ -46,6 +48,7 @@ const practice = usePracticeWordPersistence()
4648let isEdit = $ref (false )
4749let isAdd = $ref (false )
4850let studyLoading = $ref (false )
51+ let _copyData: Dict | null = null // createCopy 生成的副本数据,作为 initialData 传给 EditBook
4952let articleRef = $ref <HTMLDivElement >()
5053let audioRef = $ref <HTMLAudioElement >()
5154
@@ -94,8 +97,17 @@ const showBookDetail = computed(() => {
9497
9598const { loading } = useGetDict ()
9699
100+ function createCopy() {
101+ // 生成副本数据,不写入 store。经由 initialData 传给 EditBook,确认后才写入
102+ const copy = ensureCustomDictCopy (runtimeStore .editDict )
103+ copy .name = runtimeStore .editDict .name + ' (副本)'
104+ _copyData = copy
105+ isAdd = true
106+ }
107+
97108onMounted (() => {
98- if (route .query ?.isAdd ) {
109+ // id='new' 或 ?isAdd=true 均为新建场景(兼容从 /book/new 进入)
110+ if (route .query ?.isAdd || route .params ?.id === ' new' ) {
99111 isAdd = true
100112 runtimeStore .editDict = getDefaultDict ()
101113 }
@@ -113,8 +125,26 @@ function handleResize() {
113125}
114126
115127function formClose() {
116- if (isEdit ) isEdit = false
117- else router .back ()
128+ if (isEdit ) {
129+ isEdit = false
130+ } else if (isAdd ) {
131+ if (_copyData ) {
132+ // 创建副本场景:取消回到书籍详情
133+ _copyData = null
134+ isAdd = false
135+ } else {
136+ // 直接新建场景(/book/new):取消返回上一页
137+ router .back ()
138+ }
139+ } else {
140+ router .back ()
141+ }
142+ }
143+
144+ function handleSubmit() {
145+ _copyData = null
146+ isEdit = false
147+ isAdd = false
118148}
119149
120150const { data : book_list } = useFetch (resourceWrap (DICT_LIST .ARTICLE .ALL )).json ()
@@ -124,17 +154,24 @@ function reset() {
124154 ' 继续此操作会重置所有文章,并从官方书籍获取最新文章列表,学习记录不会被重置。确认恢复默认吗?' ,
125155 ' 恢复默认' ,
126156 async () => {
127- let dict = book_list .value . find ( v => v . url === runtimeStore .editDict . url ) as Dict
157+ let dict = findOfficialSourceDict ( book_list .value ?? [], runtimeStore .editDict ) as Dict
128158 if (dict && dict .id ) {
129159 dict = await _getDictDataByUrl (dict , DictType .article )
130160 let rIndex = store .article .bookList .findIndex (v => v .id === runtimeStore .editDict .id )
131161 if (rIndex > - 1 ) {
132162 let item = store .article .bookList [rIndex ]
133- item .custom = false
134- item .id = dict .id
135163 item .articles = dict .articles
164+ item .length = dict .articles .length
165+ item .url = dict .url
166+ item .cover = dict .cover
167+ item .description = dict .description
168+ item .name = dict .name
169+ item .category = dict .category
170+ item .tags = dict .tags
171+ item .enName = dict .enName
172+ item .sourceId = String (dict .id )
136173 if (item .lastLearnIndex >= item .articles .length ) {
137- item .lastLearnIndex = item .articles .length - 1
174+ item .lastLearnIndex = Math . max ( item .articles .length - 1 , 0 )
138175 }
139176 runtimeStore .editDict = item
140177 Toast .success (' 恢复成功' )
@@ -285,10 +322,11 @@ watch(
285322 <BaseButton v-if =" runtimeStore .editDict .custom && runtimeStore .editDict .url " type="info" @click =" reset " >
286323 {{ $t('restore_default') }}
287324 </BaseButton >
288- <BaseButton :loading =" studyLoading || loading " type="info" @click =" isEdit = true " >{{
289- $t('edit')
290- }}</BaseButton >
291- <BaseButton type="info" @click =" router .push (' /batch-edit-article' )" >{{
325+ <BaseButton v-if =" ! runtimeStore .editDict .custom " type="info" @click =" createCopy " >{{ $t('create_copy') }}</BaseButton >
326+ <BaseButton v-if =" runtimeStore .editDict .custom " :loading =" studyLoading || loading " type="info" @click =" isEdit = true " >{{
327+ $t('edit')
328+ }}</BaseButton >
329+ <BaseButton v-if =" runtimeStore .editDict .custom || runtimeStore .editDict .system " type="info" @click =" router .push (' /batch-edit-article' )" >{{
292330 $t('article_management')
293331 }}</BaseButton >
294332 <BaseButton :loading =" studyLoading || loading " @click =" startPractice " >{{ $t('learn') }}</BaseButton >
@@ -489,13 +527,13 @@ watch(
489527 </div >
490528 <div class =" " v-else >
491529 <div class =" dict-header flex justify-between items-center relative" >
492- <BackIcon class="dict-back z-2" @click =" isAdd ? $router . back () : ( isEdit = false ) " />
493- <div class =" dict-title absolute text-2xl text-align-center w-full" >
494- {{ runtimeStore.editDict.id ? $t('edit_book ') : $t('create_book ') }}
530+ <BackIcon class="dict-back z-2" @click =" formClose " />
531+ <div class =" dict-title absolute text-2xl text-align-center w-full" >
532+ {{ isAdd ? $t('create_book ') : $t('edit_book ') }}
495533 </div >
496534 </div >
497535 <div class =" center" >
498- <EditBook :is-add =" isAdd " :is-book =" true " @close =" formClose " @submit =" isEdit = isAdd = false " />
536+ <EditBook :is-add =" isAdd " :is-book =" true " : initial-data = " _copyData " @close =" formClose " @submit =" handleSubmit " />
499537 </div >
500538 </div >
501539 </div >
@@ -658,4 +696,4 @@ $article-lh: 2.4;
658696 line-height : 1.35 ;
659697 }
660698}
661- </style >
699+ </style >
0 commit comments