feat: share lesson feedback with owner-only access

This commit is contained in:
richarjiang
2026-10-18 16:09:39 +08:00
parent f085852943
commit b2a785b27b
12 changed files with 310 additions and 11 deletions

View File

@@ -32,7 +32,7 @@
<text v-if="active !== apparatus && notes[apparatus]?.trim()" class="preview">{{ notes[apparatus]?.trim() }}</text>
</view>
</view>
<view class="visibility"><view><text class="visibility-title">分享给学员</text><text class="section-caption">{{ shared ? '保存后,学员可在成长档案中查看' : '当前仅馆主可见' }}</text></view><switch :checked="shared" :disabled="busy" color="#617d70" @change="changeShared" /></view>
<view class="visibility"><view><text class="visibility-title">允许学员查看</text><text class="section-caption">{{ shared ? '保存后,学员可在成长档案中查看' : '当前仅馆主可见' }}</text></view><switch :checked="shared" :disabled="busy" color="#617d70" @change="changeShared" /></view>
</view>
</scroll-view>
<view class="sheet-footer">
@@ -49,7 +49,7 @@ import { LESSON_APPARATUS, LESSON_NOTE_MAX_LENGTH, filledApparatusNotes } from '
import type { ApparatusNotes, LessonApparatus } from '@mp-pilates/shared'
import { post } from '../utils/request'
const props = defineProps<{ userId: string; bookingId?: string }>()
const emit = defineEmits<{ close: []; saved: [] }>()
const emit = defineEmits<{ close: []; saved: [id: string] }>()
const content = ref(''), notes = ref<ApparatusNotes>({}), active = ref<LessonApparatus | null>(null), shared = ref(false)
const confirmingClose = ref(false)
const busy = ref(false), closing = ref(false), error = ref('')
@@ -59,10 +59,13 @@ const hasDraft = computed(() => !!content.value || Object.values(notes.value).so
let closeTimer: ReturnType<typeof setTimeout> | undefined
function toggle(apparatus: LessonApparatus) { active.value = active.value === apparatus ? null : apparatus }
function changeShared(event: Event) { shared.value = (event as unknown as { detail: { value: boolean } }).detail.value }
function close() {
function close(savedId?: string) {
uni.hideKeyboard()
closing.value = true
closeTimer = setTimeout(() => emit('close'), 220)
closeTimer = setTimeout(() => {
emit('close')
if (savedId) emit('saved', savedId)
}, 220)
}
async function requestClose() {
if (busy.value || closing.value || confirmingClose.value) return
@@ -78,15 +81,14 @@ async function save() {
busy.value = true
error.value = ''
try {
await post(`/admin/members/${props.userId}/progress/notes`, {
const note = await post<{ id: string }>(`/admin/members/${props.userId}/progress/notes`, {
content: content.value.trim(),
apparatusNotes: Object.fromEntries(filledApparatusNotes(notes.value).map(note => [note.apparatus, note.content])),
shared: shared.value,
...(props.bookingId ? { bookingId: props.bookingId } : {}),
})
emit('saved')
uni.showToast({ title: '课后评价已保存', icon: 'success' })
close()
close(note.id)
} catch (e) { error.value = e instanceof Error ? e.message : '保存失败,请重试' }
finally { busy.value = false }
}