diff --git a/Dockerfile b/Dockerfile index 40d8114..2c423ac 100644 --- a/Dockerfile +++ b/Dockerfile @@ -15,8 +15,8 @@ COPY api/ ./api/ # 拷贝编译后的前端产物 COPY api/webui/ ./api/webui/ -# 创建数据和日志目录 -RUN mkdir -p api/data api/logs +# 创建日志目录 +RUN mkdir -p api/logs EXPOSE 23994 diff --git a/WebUI/src/api/backup.ts b/WebUI/src/api/backup.ts new file mode 100644 index 0000000..54cfcda --- /dev/null +++ b/WebUI/src/api/backup.ts @@ -0,0 +1,13 @@ +import request from './request' + +export function exportBackup(): Promise { + return request.get('/backup/export', { responseType: 'blob' }) +} + +export function importBackup(file: File): Promise<{ message: string; count: number }> { + const form = new FormData() + form.append('file', file) + return request.post('/backup/import', form, { + headers: { 'Content-Type': 'multipart/form-data' }, + }) +} diff --git a/WebUI/src/api/goals.ts b/WebUI/src/api/goals.ts index ac863b1..7d2ec6b 100644 --- a/WebUI/src/api/goals.ts +++ b/WebUI/src/api/goals.ts @@ -50,6 +50,10 @@ export function toggleStep(goalId: number, stepId: number): Promise { return patch(`/goals/${goalId}/steps/${stepId}/toggle`) } +export function reorderSteps(goalId: number, items: { id: number; sort_order: number }[]): Promise<{ message: string }> { + return put<{ message: string }>(`/goals/${goalId}/steps/reorder`, { items }) +} + // ============ Reviews ============ export function createReview(goalId: number, data: GoalReviewFormData): Promise { diff --git a/WebUI/src/components/GoalDialog.vue b/WebUI/src/components/GoalDialog.vue index 9f04855..2bc6c87 100644 --- a/WebUI/src/components/GoalDialog.vue +++ b/WebUI/src/components/GoalDialog.vue @@ -2,6 +2,7 @@ import { ref, watch } from 'vue' import { useGoalStore } from '@/stores/useGoalStore' import { useCategoryStore } from '@/stores/useCategoryStore' +import { useUIStore } from '@/stores/useUIStore' import type { Goal, GoalFormData } from '@/api/types' const props = defineProps<{ @@ -16,6 +17,7 @@ const emit = defineEmits<{ const goalStore = useGoalStore() const categoryStore = useCategoryStore() +const uiStore = useUIStore() const form = ref({ title: '', @@ -119,14 +121,19 @@ const iconOptions = ['flag', 'star', 'trophy', 'aim', 'medal', 'magic', 'sunny', - + - - - +
+ + + + + + +
- +