Skip to content

Commit 53b2d31

Browse files
feat: folder
1 parent e402f00 commit 53b2d31

12 files changed

Lines changed: 230 additions & 176 deletions

File tree

‎ui/src/api/admin/workspace/folder.ts‎

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { del, get, post, put } from '../core/request'
2-
import type { FolderSource, FolderItem, RequestParams, FolderRequest } from '@/api/types'
2+
import type { FolderSource, FolderItem, RequestParams, FolderPayload } from '@/api/types'
33
import { getWorkspaceId } from '@/utils/workspace-context'
44

55
const getPrefix = (source: FolderSource) => {
@@ -13,17 +13,17 @@ const getFolderTree = (source: FolderSource, query?: RequestParams) => {
1313
}
1414

1515
/** 更新 Workspace 的文件夹。 */
16-
const putFolder = (folderId: string, source: FolderSource, payload?: FolderRequest) => {
17-
return put<FolderRequest, FolderItem>(`${getPrefix(source)}/${folderId}`, payload)
16+
const putFolder = (folderId: string, source: FolderSource, payload?: FolderPayload) => {
17+
return put<FolderPayload, FolderItem>(`${getPrefix(source)}/${folderId}`, payload)
1818
}
1919

2020
/** 在指定资源模块中创建 Workspace 文件夹。 */
21-
const postFolder = (source: FolderSource, payload: FolderRequest) => {
22-
return post<FolderRequest, FolderItem>(getPrefix(source), payload)
21+
const postFolder = (source: FolderSource, payload: FolderPayload) => {
22+
return post<FolderPayload, FolderItem>(getPrefix(source), payload)
2323
}
2424

2525
/** 删除指定 Workspace 文件夹及其中的资源。 */
26-
const deleteFolder = (source: FolderSource, folderId: string) => {
26+
const deleteFolder = (folderId: string, source: FolderSource) => {
2727
return del<boolean>(`${getPrefix(source)}/${folderId}`)
2828
}
2929

‎ui/src/api/types/folder.ts‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ export interface FolderItem {
1616
workspace_id?: string
1717
}
1818

19-
export interface FolderRequest {
19+
export interface FolderPayload {
2020
desc?: string | null
2121
name?: string
2222
parent_id?: string | null

‎ui/src/components/business/folder-tree/FolderFormDialog.vue‎

Lines changed: 56 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -1,104 +1,112 @@
11
<script setup lang="ts">
2-
import { computed, nextTick, reactive, ref, useTemplateRef } from 'vue'
2+
import { reactive, ref, useTemplateRef } from 'vue'
33
import type { FormInstance, FormRules } from 'element-plus'
4-
import type { WorkspaceFolder } from '@/api/types'
5-
import type { FolderFormSubmit } from './types'
4+
import FolderApi from '@/api/admin/workspace/folder'
5+
import type { FolderItem, FolderSource } from '@/api/types'
6+
import { MsgSuccess } from '@/utils/message'
67
78
defineOptions({ name: 'FolderFormDialog' })
89
9-
defineProps<{
10-
loading: boolean
10+
const props = defineProps<{
11+
title: string
12+
source: FolderSource
1113
}>()
1214
1315
const emit = defineEmits<{
14-
submit: [form: FolderFormSubmit]
16+
refresh: [folder: FolderItem, isEdit: boolean]
1517
}>()
1618
17-
interface FolderForm {
18-
desc: string
19-
name: string
20-
parent_id: string
21-
}
22-
2319
const folderFormRef = useTemplateRef<FormInstance>('folderFormRef')
2420
const visible = ref(false)
25-
const editingFolderId = ref('')
26-
const folderForm = reactive<FolderForm>({
21+
const editId = ref('')
22+
const folderForm = reactive({
2723
desc: '',
2824
name: '',
2925
parent_id: '',
3026
})
3127
32-
const dialogTitle = computed(() => (editingFolderId.value ? '编辑文件夹' : '创建文件夹'))
33-
const rules: FormRules<FolderForm> = {
28+
const rules: FormRules<typeof folderForm> = {
3429
name: [{ message: '请输入文件夹名称', required: true, trigger: 'blur' }],
3530
}
3631
37-
function resetData() {
38-
editingFolderId.value = ''
39-
folderForm.desc = ''
40-
folderForm.name = ''
41-
folderForm.parent_id = ''
42-
folderFormRef.value?.clearValidate()
32+
const loading = ref(false)
33+
function handleSubmit() {
34+
folderFormRef.value?.validate((valid) => {
35+
if (!valid) return
36+
loading.value = true
37+
const isEdit = Boolean(editId.value)
38+
const request = isEdit
39+
? FolderApi.putFolder(editId.value, props.source, folderForm)
40+
: FolderApi.postFolder(props.source, folderForm)
41+
42+
return request
43+
.then((folder) => {
44+
MsgSuccess(isEdit ? '保存成功' : '创建成功')
45+
visible.value = false
46+
emit('refresh', folder, isEdit)
47+
})
48+
.finally(() => {
49+
loading.value = false
50+
})
51+
})
4352
}
4453
45-
function open(parentId: string, folder?: WorkspaceFolder) {
46-
resetData()
47-
editingFolderId.value = folder?.id ?? ''
48-
folderForm.desc = folder?.desc ?? ''
49-
folderForm.name = folder?.name ?? ''
50-
folderForm.parent_id = folder?.parent_id ?? parentId
54+
function open(id: string, folder?: FolderItem) {
55+
if (folder) {
56+
// 编辑当前id
57+
editId.value = folder?.id
58+
folderForm.name = folder?.name ?? ''
59+
folderForm.desc = folder?.desc ?? ''
60+
folderForm.parent_id = folder.parent_id ?? ''
61+
} else {
62+
// 给当前id添加子id
63+
folderForm.parent_id = id
64+
}
65+
5166
visible.value = true
52-
nextTick(() => folderFormRef.value?.clearValidate())
5367
}
5468
5569
function close() {
5670
visible.value = false
5771
resetData()
5872
}
59-
60-
function handleSubmit() {
61-
folderFormRef.value?.validate((valid) => {
62-
if (!valid) return
63-
emit('submit', {
64-
folderId: editingFolderId.value || undefined,
65-
payload: {
66-
desc: folderForm.desc.trim(),
67-
name: folderForm.name.trim(),
68-
parent_id: folderForm.parent_id,
69-
},
70-
})
71-
})
73+
function resetData() {
74+
editId.value = ''
75+
folderForm.desc = ''
76+
folderForm.name = ''
77+
folderForm.parent_id = ''
78+
folderFormRef.value?.clearValidate()
7279
}
7380
7481
defineExpose({ close, open })
7582
</script>
7683

7784
<template>
78-
<MkDialog v-model="visible" :title="dialogTitle" width="600" @closed="resetData">
85+
<MkDialog v-model="visible" :title="title" @closed="resetData">
7986
<el-form
8087
ref="folderFormRef"
8188
:model="folderForm"
8289
:rules="rules"
8390
label-position="top"
91+
require-asterisk-position="right"
8492
@submit.prevent
8593
>
8694
<el-form-item label="名称" prop="name">
8795
<el-input
8896
v-model="folderForm.name"
8997
maxlength="64"
90-
placeholder="请输入文件夹名称"
98+
placeholder="请输入名称"
9199
show-word-limit
92100
@blur="folderForm.name = folderForm.name.trim()"
93101
/>
94102
</el-form-item>
95103
<el-form-item label="描述" prop="desc">
96104
<el-input
97105
v-model="folderForm.desc"
98-
:autosize="{ minRows: 3 }"
99-
maxlength="200"
100-
placeholder="请输入文件夹描述"
106+
placeholder="请输入描述"
107+
maxlength="128"
101108
show-word-limit
109+
:autosize="{ minRows: 3 }"
102110
type="textarea"
103111
@blur="folderForm.desc = folderForm.desc.trim()"
104112
/>
@@ -108,7 +116,7 @@ defineExpose({ close, open })
108116
<template #footer>
109117
<el-button :disabled="loading" @click="close">取消</el-button>
110118
<el-button type="primary" :loading="loading" @click="handleSubmit">
111-
{{ editingFolderId ? '保存' : '创建' }}
119+
{{ editId ? '保存' : '创建' }}
112120
</el-button>
113121
</template>
114122
</MkDialog>

ui/src/components/business/folder-tree/MoveFolderDialog.vue renamed to ui/src/components/business/folder-tree/MoveToDialog.vue

Lines changed: 23 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
<script setup lang="ts">
22
import { computed, ref } from 'vue'
33
import type { WorkspaceFolder } from '@/api/types'
4-
import type { FolderMoveSubmit } from './types'
5-
import FolderVirtualizedTree from './VirtualizedTree.vue'
4+
import type { FolderMoveSubmit } from './types.ts'
5+
import FolderTree from './index.vue'
66
77
defineOptions({ name: 'MoveFolderDialog' })
88
@@ -79,24 +79,31 @@ function handleSubmit() {
7979
})
8080
}
8181
82+
// function handleMoveFolder({ folder, targetFolderId }: FolderMoveSubmit) {
83+
// submiting.value = true
84+
// return FolderApi.putFolder(workspaceId, props.source, folder.id, {
85+
// parent_id: targetFolderId,
86+
// })
87+
// .then((updatedFolder) => {
88+
// MsgSuccess('移动成功')
89+
// moveFolderDialogRef.value?.close()
90+
// return loadFolders().then(() => emit('moved', updatedFolder))
91+
// })
92+
// .finally(() => {
93+
// submiting.value = false
94+
// })
95+
// }
96+
8297
defineExpose({ close, open })
8398
</script>
8499

85100
<template>
86-
<MkDialog v-model="visible" title="移动到" width="600" @closed="resetData">
87-
<div class="flex h-100 flex-col gap-3">
88-
<MkSearchInput v-model="searchKeyword" class="shrink-0" />
89-
<div class="min-h-0 flex-1 rounded-md border p-2">
90-
<FolderVirtualizedTree
91-
:can-manage="false"
92-
:current-node-key="selectedTargetId"
93-
:data="moveFolders"
94-
:filter-text="searchKeyword"
95-
@select="handleTargetSelect"
96-
/>
97-
</div>
98-
</div>
99-
101+
<MkDialog v-model="visible" title="移动到" @closed="resetData">
102+
<FolderTree
103+
:current-node-key="selectedTargetId"
104+
:data="moveFolders"
105+
@select="handleTargetSelect"
106+
/>
100107
<template #footer>
101108
<el-button :disabled="loading" @click="close">取消</el-button>
102109
<el-button type="primary" :disabled="!canSubmit" :loading="loading" @click="handleSubmit">

‎ui/src/components/business/folder-tree/VirtualizedTree.vue‎

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,6 @@ function containsCurrentFolder(folder: FolderTreeNode): boolean {
8787
}
8888
8989
function handleStat<T extends FolderStat>(stat: T): T {
90-
stat.open = stat.level === 1
9190
if (props.filterText || containsCurrentFolder(stat.data)) stat.open = true
9291
return stat
9392
}
@@ -157,8 +156,8 @@ function handleAfterDrop() {
157156
</slot>
158157
</template>
159158

160-
<template #action-dropdown="{ row }">
161-
<slot name="action-dropdown" :row="row"></slot>
159+
<template #action-dropdown>
160+
<slot name="action-dropdown" :row="node"></slot>
162161
</template>
163162
</MkListItem>
164163
</template>

0 commit comments

Comments
 (0)