feat: 工作进度管理页面,优化用户资料更新,优化部分接口请求
This commit is contained in:
parent
0b9e99d00f
commit
91f7d2212d
6
components.d.ts
vendored
6
components.d.ts
vendored
@ -14,15 +14,21 @@ declare module 'vue' {
|
|||||||
WdCellGroup: typeof import('wot-design-uni/components/wd-cell-group/wd-cell-group.vue')['default']
|
WdCellGroup: typeof import('wot-design-uni/components/wd-cell-group/wd-cell-group.vue')['default']
|
||||||
WdCollapse: typeof import('wot-design-uni/components/wd-collapse/wd-collapse.vue')['default']
|
WdCollapse: typeof import('wot-design-uni/components/wd-collapse/wd-collapse.vue')['default']
|
||||||
WdCollapseItem: typeof import('wot-design-uni/components/wd-collapse-item/wd-collapse-item.vue')['default']
|
WdCollapseItem: typeof import('wot-design-uni/components/wd-collapse-item/wd-collapse-item.vue')['default']
|
||||||
|
WdDivider: typeof import('wot-design-uni/components/wd-divider/wd-divider.vue')['default']
|
||||||
WdDropMenu: typeof import('wot-design-uni/components/wd-drop-menu/wd-drop-menu.vue')['default']
|
WdDropMenu: typeof import('wot-design-uni/components/wd-drop-menu/wd-drop-menu.vue')['default']
|
||||||
WdDropMenuItem: typeof import('wot-design-uni/components/wd-drop-menu-item/wd-drop-menu-item.vue')['default']
|
WdDropMenuItem: typeof import('wot-design-uni/components/wd-drop-menu-item/wd-drop-menu-item.vue')['default']
|
||||||
WdForm: typeof import('wot-design-uni/components/wd-form/wd-form.vue')['default']
|
WdForm: typeof import('wot-design-uni/components/wd-form/wd-form.vue')['default']
|
||||||
WdIcon: typeof import('wot-design-uni/components/wd-icon/wd-icon.vue')['default']
|
WdIcon: typeof import('wot-design-uni/components/wd-icon/wd-icon.vue')['default']
|
||||||
WdInput: typeof import('wot-design-uni/components/wd-input/wd-input.vue')['default']
|
WdInput: typeof import('wot-design-uni/components/wd-input/wd-input.vue')['default']
|
||||||
|
WdMessageBox: typeof import('wot-design-uni/components/wd-message-box/wd-message-box.vue')['default']
|
||||||
|
WdPicker: typeof import('wot-design-uni/components/wd-picker/wd-picker.vue')['default']
|
||||||
WdProgress: typeof import('wot-design-uni/components/wd-progress/wd-progress.vue')['default']
|
WdProgress: typeof import('wot-design-uni/components/wd-progress/wd-progress.vue')['default']
|
||||||
|
WdRadio: typeof import('wot-design-uni/components/wd-radio/wd-radio.vue')['default']
|
||||||
|
WdRadioGroup: typeof import('wot-design-uni/components/wd-radio-group/wd-radio-group.vue')['default']
|
||||||
WdStatusTip: typeof import('wot-design-uni/components/wd-status-tip/wd-status-tip.vue')['default']
|
WdStatusTip: typeof import('wot-design-uni/components/wd-status-tip/wd-status-tip.vue')['default']
|
||||||
WdStep: typeof import('wot-design-uni/components/wd-step/wd-step.vue')['default']
|
WdStep: typeof import('wot-design-uni/components/wd-step/wd-step.vue')['default']
|
||||||
WdSteps: typeof import('wot-design-uni/components/wd-steps/wd-steps.vue')['default']
|
WdSteps: typeof import('wot-design-uni/components/wd-steps/wd-steps.vue')['default']
|
||||||
|
WdSwitch: typeof import('wot-design-uni/components/wd-switch/wd-switch.vue')['default']
|
||||||
WdTabbar: typeof import('wot-design-uni/components/wd-tabbar/wd-tabbar.vue')['default']
|
WdTabbar: typeof import('wot-design-uni/components/wd-tabbar/wd-tabbar.vue')['default']
|
||||||
WdTabbarItem: typeof import('wot-design-uni/components/wd-tabbar-item/wd-tabbar-item.vue')['default']
|
WdTabbarItem: typeof import('wot-design-uni/components/wd-tabbar-item/wd-tabbar-item.vue')['default']
|
||||||
WdToast: typeof import('wot-design-uni/components/wd-toast/wd-toast.vue')['default']
|
WdToast: typeof import('wot-design-uni/components/wd-toast/wd-toast.vue')['default']
|
||||||
|
22
src/App.vue
22
src/App.vue
@ -1,18 +1,34 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { onLaunch, onShow, onHide } from "@dcloudio/uni-app";
|
import { onLaunch, onShow, onHide } from "@dcloudio/uni-app";
|
||||||
import { useTabbar } from "./stores/useTabbar";
|
import { useTabbar } from "./stores/useTabbar";
|
||||||
|
import BussApi from "./api/BussApi";
|
||||||
|
import { useUser } from "./stores/useUser";
|
||||||
|
import { useToast } from "wot-design-uni";
|
||||||
|
|
||||||
const tab = useTabbar()
|
const tab = useTabbar()
|
||||||
|
const user = useUser()
|
||||||
|
const toast = useToast()
|
||||||
|
|
||||||
onLaunch(() => {
|
onLaunch(() => {
|
||||||
console.log("App Launch");
|
console.debug("App Launch");
|
||||||
|
|
||||||
|
// reset tabbar
|
||||||
tab.activeTab = 'home'
|
tab.activeTab = 'home'
|
||||||
|
|
||||||
|
// refersh user info
|
||||||
|
BussApi.profile(user.token!).then(res => {
|
||||||
|
user.userinfo = res
|
||||||
|
}).catch(err => {
|
||||||
|
toast.error({ msg: err.message })
|
||||||
|
})
|
||||||
});
|
});
|
||||||
|
|
||||||
onShow(() => {
|
onShow(() => {
|
||||||
console.log("App Show");
|
console.debug("App Show");
|
||||||
});
|
});
|
||||||
|
|
||||||
onHide(() => {
|
onHide(() => {
|
||||||
console.log("App Hide");
|
console.debug("App Hide");
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
<style></style>
|
<style></style>
|
||||||
|
@ -29,20 +29,24 @@ export default class BussApi {
|
|||||||
.then((res) => res.data);
|
.then((res) => res.data);
|
||||||
}
|
}
|
||||||
|
|
||||||
static lessons(
|
static lessons(page: number = 1, limit: number = 20) {
|
||||||
page: number = 1,
|
|
||||||
limit: number = 20
|
|
||||||
): Promise<PagedData<Lesson>> {
|
|
||||||
const user = useUser();
|
const user = useUser();
|
||||||
return http
|
return http
|
||||||
.server()
|
.server()
|
||||||
.get("/lesson/task", {
|
.get<PagedData<Lesson>>("/lesson/task", {
|
||||||
headers: {
|
headers: {
|
||||||
Authorization: `Bearer ${user.token}`,
|
Authorization: `Bearer ${user.token}`,
|
||||||
},
|
},
|
||||||
params: { page, limit },
|
params: { page, limit },
|
||||||
})
|
})
|
||||||
.then((res) => res.data);
|
.then((res) => {
|
||||||
|
if (user.hasJobTag("A")) {
|
||||||
|
res.data.data = res.data.data.filter(
|
||||||
|
(lesson) => lesson.user_id === user.userinfo?.id
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return res.data;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
static course(id: number): Promise<Lesson> {
|
static course(id: number): Promise<Lesson> {
|
||||||
@ -56,4 +60,16 @@ export default class BussApi {
|
|||||||
})
|
})
|
||||||
.then((res) => res.data);
|
.then((res) => res.data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static editCourse(id: number, params: Partial<Lesson>): Promise<Lesson> {
|
||||||
|
const user = useUser();
|
||||||
|
return http
|
||||||
|
.server()
|
||||||
|
.put(`/lesson/task/${id}`, params, {
|
||||||
|
headers: {
|
||||||
|
Authorization: `Bearer ${user.token}`,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
.then((res) => res.data);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,20 +1,12 @@
|
|||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import TabBar from '@/components/TabBar.vue';
|
import TabBar from '@/components/TabBar.vue';
|
||||||
|
|
||||||
// const router = useRouter()
|
|
||||||
// const user = useUser()
|
|
||||||
|
|
||||||
// onMounted(() => {
|
|
||||||
// if (!user.userinfo) {
|
|
||||||
// router.replaceAll('/pages/login/index')
|
|
||||||
// }
|
|
||||||
// })
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<slot></slot>
|
<slot></slot>
|
||||||
<wd-toast />
|
<wd-toast />
|
||||||
|
<wd-message-box />
|
||||||
<tab-bar current-name="home" />
|
<tab-bar current-name="home" />
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
@ -7,6 +7,13 @@
|
|||||||
"navigationBarTitleText": "进度查看"
|
"navigationBarTitleText": "进度查看"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "progress",
|
||||||
|
"path": "pages/progress/index",
|
||||||
|
"style": {
|
||||||
|
"navigationBarTitleText": "工作进度管理"
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "my",
|
"name": "my",
|
||||||
"path": "pages/my/index",
|
"path": "pages/my/index",
|
||||||
@ -25,7 +32,7 @@
|
|||||||
"name": "lesson",
|
"name": "lesson",
|
||||||
"path": "pages/lesson/index",
|
"path": "pages/lesson/index",
|
||||||
"style": {
|
"style": {
|
||||||
"navigationBarTitleText": "课程进度"
|
"navigationBarTitleText": "微课进度"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
@ -39,6 +46,10 @@
|
|||||||
"pagePath": "pages/index/index",
|
"pagePath": "pages/index/index",
|
||||||
"text": "进度查看"
|
"text": "进度查看"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"pagePath": "pages/progress/index",
|
||||||
|
"text": "进度管理"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"pagePath": "pages/my/index",
|
"pagePath": "pages/my/index",
|
||||||
"text": "我的"
|
"text": "我的"
|
||||||
|
@ -1,8 +1,10 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import BussApi from '@/api/BussApi';
|
import BussApi from '@/api/BussApi';
|
||||||
import pageWrapper from '@/components/page-wrapper.vue';
|
import pageWrapper from '@/components/page-wrapper.vue';
|
||||||
|
import { useUser } from '@/stores/useUser';
|
||||||
import type { Lesson } from '@/types/api/lesson';
|
import type { Lesson } from '@/types/api/lesson';
|
||||||
import { calcLessonProgress } from '@/utils/lesson';
|
import { calcLessonProgress } from '@/utils/lesson';
|
||||||
|
import { onPageShow } from '@dcloudio/uni-app';
|
||||||
import { useRouter } from 'uni-mini-router';
|
import { useRouter } from 'uni-mini-router';
|
||||||
import { onMounted, ref } from 'vue';
|
import { onMounted, ref } from 'vue';
|
||||||
import { useToast } from 'wot-design-uni';
|
import { useToast } from 'wot-design-uni';
|
||||||
@ -12,6 +14,8 @@ import WdTag from 'wot-design-uni/components/wd-tag/wd-tag.vue';
|
|||||||
const toast = useToast()
|
const toast = useToast()
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
|
|
||||||
|
const user = useUser()
|
||||||
|
|
||||||
const teacherFilterValue = ref<number>(0)
|
const teacherFilterValue = ref<number>(0)
|
||||||
|
|
||||||
const teacherFilterOptions = ref<Record<string, any>[]>([
|
const teacherFilterOptions = ref<Record<string, any>[]>([
|
||||||
@ -36,7 +40,7 @@ const openLessonDetail = (courseId: number) => {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
onMounted(() => {
|
onPageShow(() => {
|
||||||
toast.loading({
|
toast.loading({
|
||||||
msg: '加载中...'
|
msg: '加载中...'
|
||||||
})
|
})
|
||||||
@ -52,8 +56,10 @@ onMounted(() => {
|
|||||||
return acc
|
return acc
|
||||||
}, {})
|
}, {})
|
||||||
groupedLessons.value = groupData
|
groupedLessons.value = groupData
|
||||||
// auto expand all course
|
// expand courses with lessons in progress
|
||||||
// expandedCourse.value = Object.keys(groupData)
|
expandedCourse.value = Object.keys(groupData).filter(courseName => {
|
||||||
|
return groupData[courseName].filter((lesson: Lesson) => calcLessonProgress(lesson) !== 0 && calcLessonProgress(lesson) !== 100).length > 0
|
||||||
|
})
|
||||||
}).catch(err => {
|
}).catch(err => {
|
||||||
toast.error({ msg: err.message })
|
toast.error({ msg: err.message })
|
||||||
})
|
})
|
||||||
@ -64,11 +70,12 @@ onMounted(() => {
|
|||||||
<page-wrapper>
|
<page-wrapper>
|
||||||
<div>
|
<div>
|
||||||
<!-- todo teacher filter [for role B] -->
|
<!-- todo teacher filter [for role B] -->
|
||||||
<wd-drop-menu>
|
<wd-drop-menu v-if="user.hasJobTag('B')">
|
||||||
<wd-drop-menu-item v-model="teacherFilterValue" :options="teacherFilterOptions" :before-toggle="handleBeforeToggle" />
|
<wd-drop-menu-item v-model="teacherFilterValue" :options="teacherFilterOptions"
|
||||||
|
:before-toggle="handleBeforeToggle" />
|
||||||
</wd-drop-menu>
|
</wd-drop-menu>
|
||||||
<wd-collapse v-model="expandedCourse">
|
<wd-collapse v-model="expandedCourse">
|
||||||
<wd-status-tip v-if="Object.keys(groupedLessons).length === 0" image="content" tip="没有微课" />
|
<wd-status-tip v-if="Object.keys(groupedLessons).length === 0" image="content" tip="当前账号没有分配微课" />
|
||||||
<wd-collapse-item v-else v-for="(courses, courseName) in groupedLessons" :name="`${courseName}`"
|
<wd-collapse-item v-else v-for="(courses, courseName) in groupedLessons" :name="`${courseName}`"
|
||||||
:key="courseName">
|
:key="courseName">
|
||||||
<template #title="{ expanded, disabled, isFirst }">
|
<template #title="{ expanded, disabled, isFirst }">
|
||||||
@ -97,7 +104,7 @@ onMounted(() => {
|
|||||||
<div class="w-1.5 aspect-square rounded-full bg-blue"></div>
|
<div class="w-1.5 aspect-square rounded-full bg-blue"></div>
|
||||||
<span class="text-xs text-blue font-bold font-mono">
|
<span class="text-xs text-blue font-bold font-mono">
|
||||||
{{ courses.filter(lesson => calcLessonProgress(lesson) !== 0 && calcLessonProgress(lesson) !==
|
{{ courses.filter(lesson => calcLessonProgress(lesson) !== 0 && calcLessonProgress(lesson) !==
|
||||||
100).length }}
|
100).length }}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex items-center gap-0.5">
|
<div class="flex items-center gap-0.5">
|
||||||
|
@ -37,7 +37,7 @@ onMounted(() => {
|
|||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<div :class="`pattern p-4 flex flex-col gap-6 relative ${lessonProgress === 100 ? 'bg-emerald' : 'bg-blue'}`">
|
<div :class="`pattern p-4 flex flex-col gap-6 relative ${lessonProgress === 100 ? 'bg-emerald' : (lessonProgress === 0 ? 'bg-neutral' : 'bg-blue')}`">
|
||||||
<div class="flex flex-col gap-0">
|
<div class="flex flex-col gap-0">
|
||||||
<h2 class="text-sm text-white font-black op-50">{{ lesson?.course_name }}</h2>
|
<h2 class="text-sm text-white font-black op-50">{{ lesson?.course_name }}</h2>
|
||||||
<h1 class="text-lg text-white font-bold">{{ lesson?.m_lesson_name }}</h1>
|
<h1 class="text-lg text-white font-bold">{{ lesson?.m_lesson_name }}</h1>
|
||||||
|
155
src/pages/progress/index.vue
Normal file
155
src/pages/progress/index.vue
Normal file
@ -0,0 +1,155 @@
|
|||||||
|
<script lang="ts" setup>
|
||||||
|
import BussApi from '@/api/BussApi';
|
||||||
|
import { useDayjs } from '@/composables/useDayjs';
|
||||||
|
import type { Lesson, ScriptFileDestination } from '@/types/api/lesson';
|
||||||
|
import { extractLessonStage, getLessonSteps } from '@/utils/lesson';
|
||||||
|
import { computed, onMounted, ref } from 'vue';
|
||||||
|
import { useMessage, useToast } from 'wot-design-uni';
|
||||||
|
|
||||||
|
const message = useMessage()
|
||||||
|
const toast = useToast()
|
||||||
|
const dayjs = useDayjs()
|
||||||
|
|
||||||
|
type GroupedLessons = { [key: string]: Lesson[] }
|
||||||
|
|
||||||
|
const groupedLessons = ref<GroupedLessons>({})
|
||||||
|
|
||||||
|
const pickerCourseColumns = ref<string[]>([])
|
||||||
|
const pickerCourseValue = ref()
|
||||||
|
|
||||||
|
const pickerLessonColumns = computed(() => {
|
||||||
|
return pickerCourseValue.value ? groupedLessons.value[pickerCourseValue.value].map((lesson: Lesson) => {
|
||||||
|
return {
|
||||||
|
label: (extractLessonStage(lesson).step === 4 ? '✅ ' : '') + lesson.m_lesson_name,
|
||||||
|
value: lesson.id
|
||||||
|
}
|
||||||
|
}) : []
|
||||||
|
})
|
||||||
|
const pickerLessonValue = ref()
|
||||||
|
|
||||||
|
const selectedLesson = computed(() => {
|
||||||
|
if (!pickerLessonValue.value) return null
|
||||||
|
return groupedLessons.value[pickerCourseValue.value].find((lesson: Lesson) => lesson.id === pickerLessonValue.value)
|
||||||
|
})
|
||||||
|
|
||||||
|
const selectedLessonStage = computed(() => {
|
||||||
|
if (!selectedLesson.value) return null
|
||||||
|
return extractLessonStage(selectedLesson.value)
|
||||||
|
})
|
||||||
|
|
||||||
|
const onCoursePick = ({ value }: { value: string }) => {
|
||||||
|
pickerCourseValue.value = value
|
||||||
|
pickerLessonValue.value = void 0
|
||||||
|
}
|
||||||
|
|
||||||
|
const onLessonPick = ({ value }: { value: number }) => {
|
||||||
|
pickerLessonValue.value = value
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* lesson progress modifition steps
|
||||||
|
*/
|
||||||
|
|
||||||
|
const script_file_destination = ref<ScriptFileDestination>('wechat')
|
||||||
|
|
||||||
|
const onStep0 = () => {
|
||||||
|
message.confirm({
|
||||||
|
title: '提交脚本',
|
||||||
|
msg: '请确认已经通过微信或平台上传了脚本文件,再确认提交'
|
||||||
|
}).then(() => {
|
||||||
|
if (!selectedLesson.value?.id) {
|
||||||
|
toast.error({
|
||||||
|
msg: '参数错误'
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
toast.loading({
|
||||||
|
msg: '正在提交...'
|
||||||
|
})
|
||||||
|
BussApi.editCourse(selectedLesson.value.id, {
|
||||||
|
script_file: script_file_destination.value,
|
||||||
|
script_upload_time: dayjs().unix()
|
||||||
|
}).then(res => {
|
||||||
|
toast.success({
|
||||||
|
msg: '提交成功'
|
||||||
|
})
|
||||||
|
setTimeout(() => {
|
||||||
|
updateLessons()
|
||||||
|
}, 1500);
|
||||||
|
}).catch(err => {
|
||||||
|
toast.error({ msg: err.message })
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const updateLessons = () => {
|
||||||
|
toast.loading({
|
||||||
|
msg: '加载中...'
|
||||||
|
})
|
||||||
|
BussApi.lessons(1, 512).then(res => {
|
||||||
|
toast.close()
|
||||||
|
const groupData = res.data.sort((a: Lesson, b: Lesson) => {
|
||||||
|
return a.id - b.id
|
||||||
|
}).reduce((acc: any, cur: any) => {
|
||||||
|
if (!acc[cur.course_name]) {
|
||||||
|
acc[cur.course_name] = []
|
||||||
|
}
|
||||||
|
acc[cur.course_name].push(cur)
|
||||||
|
return acc
|
||||||
|
}, {})
|
||||||
|
groupedLessons.value = groupData
|
||||||
|
pickerCourseColumns.value = [
|
||||||
|
...Object.keys(groupData)
|
||||||
|
]
|
||||||
|
}).catch(err => {
|
||||||
|
toast.error({ msg: err.message })
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
updateLessons()
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<page-wrapper>
|
||||||
|
<div class="m-2 rounded-lg border border-solid border-neutral-100 shadow-md shadow-op-50 overflow-hidden">
|
||||||
|
<wd-picker :columns="pickerCourseColumns" label="课程选择" v-model="pickerCourseValue" @confirm="onCoursePick"
|
||||||
|
:columns-height="280" label-width="80px" safe-area-inset-bottom title="课程选择" />
|
||||||
|
<wd-picker :columns="pickerLessonColumns" label="微课选择" v-model="pickerLessonValue" @confirm="onLessonPick"
|
||||||
|
:columns-height="280" label-width="80px" safe-area-inset-bottom title="微课选择" :disabled="!pickerCourseValue" />
|
||||||
|
</div>
|
||||||
|
<div class="p-2 pt-4">
|
||||||
|
<wd-status-tip v-if="!pickerLessonValue" image="search" tip="请先选择微课" />
|
||||||
|
<div v-else class="space-y-6">
|
||||||
|
<div>
|
||||||
|
<wd-steps :active="selectedLessonStage?.step || 0" align-center>
|
||||||
|
<wd-step v-for="(step, index) in getLessonSteps(selectedLesson!, true)" :key="index" :title="step.title"
|
||||||
|
:description="(selectedLessonStage?.step || 0 <= index) ? step.description : undefined" />
|
||||||
|
</wd-steps>
|
||||||
|
</div>
|
||||||
|
<div v-if="selectedLessonStage?.step === 0" class="px-2">
|
||||||
|
<wd-cell-group>
|
||||||
|
<wd-cell title="脚本提交途径" :title-width="'100px'" center custom-class="mb-4">
|
||||||
|
<wd-radio-group v-model="script_file_destination" shape="button">
|
||||||
|
<wd-radio value="wechat">微信</wd-radio>
|
||||||
|
<wd-radio value="qq">QQ</wd-radio>
|
||||||
|
<wd-radio value="platform">平台</wd-radio>
|
||||||
|
</wd-radio-group>
|
||||||
|
</wd-cell>
|
||||||
|
</wd-cell-group>
|
||||||
|
|
||||||
|
<wd-button type="primary" block @click="onStep0" custom-class="w-full">提交脚本</wd-button>
|
||||||
|
</div>
|
||||||
|
<div v-if="selectedLessonStage?.step === 1"></div>
|
||||||
|
<div v-if="selectedLessonStage?.step === 2"></div>
|
||||||
|
<div v-if="selectedLessonStage?.step === 3"></div>
|
||||||
|
<div v-else-if="selectedLessonStage?.step === 4">
|
||||||
|
<wd-status-tip image="comment" tip="该微课已完成" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</page-wrapper>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped></style>
|
@ -6,14 +6,25 @@ export const useUser = defineStore("user", () => {
|
|||||||
const token = ref<string | null>(null);
|
const token = ref<string | null>(null);
|
||||||
const userinfo = ref<User | null>(null);
|
const userinfo = ref<User | null>(null);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 判断是否有权限
|
||||||
|
* @param tag A: 课程制作教师(3) B: 课程制作方沟通联络人(2) C: 课程购买方项目负责人(1) D: 系统制作方项目负责人(4)
|
||||||
|
* @returns 是否有权限
|
||||||
|
*/
|
||||||
|
function hasJobTag(tag: "A" | "B" | "C" | "D") {
|
||||||
|
if (!userinfo.value) return false;
|
||||||
|
return userinfo.value?.jobs.some((job) => job.description === tag) || false;
|
||||||
|
}
|
||||||
|
|
||||||
function logout() {
|
function logout() {
|
||||||
token.value = null
|
token.value = null;
|
||||||
userinfo.value = null
|
userinfo.value = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
token,
|
token,
|
||||||
userinfo,
|
userinfo,
|
||||||
|
hasJobTag,
|
||||||
logout,
|
logout,
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
@ -2,16 +2,18 @@ export interface Lesson {
|
|||||||
id: number;
|
id: number;
|
||||||
course_name: string;
|
course_name: string;
|
||||||
m_lesson_name: string;
|
m_lesson_name: string;
|
||||||
user_id: number | null;
|
user_id: number;
|
||||||
schedule_status: number;
|
schedule_status: number;
|
||||||
script_confirm_time: number;
|
|
||||||
video_confirm_time: number;
|
|
||||||
finish_time: number;
|
|
||||||
script_upload_time: number;
|
script_upload_time: number;
|
||||||
|
script_confirm_time: number;
|
||||||
video_capture_time: number;
|
video_capture_time: number;
|
||||||
script_file: null;
|
video_confirm_time: number;
|
||||||
|
script_file: ScriptFileDestination;
|
||||||
|
finish_time: number;
|
||||||
material_file: null;
|
material_file: null;
|
||||||
capture_file: null;
|
capture_file: null;
|
||||||
advise: null;
|
advise: null;
|
||||||
created_at: string;
|
created_at: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type ScriptFileDestination = "qq" | "wechat" | "platform";
|
||||||
|
@ -77,3 +77,16 @@ export interface RolePivot {
|
|||||||
user_id: number;
|
user_id: number;
|
||||||
role_id: number;
|
role_id: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export enum Roles {
|
||||||
|
Teacher = 1,
|
||||||
|
GeneralAdmin,
|
||||||
|
Contactor,
|
||||||
|
}
|
||||||
|
|
||||||
|
export enum Jobs {
|
||||||
|
BuyerManager = 1,
|
||||||
|
MakerContactor,
|
||||||
|
MakerTeacher,
|
||||||
|
SystemManager,
|
||||||
|
}
|
||||||
|
@ -18,33 +18,33 @@ export const calcLessonProgress = (lesson: Lesson, total: number = 4) => {
|
|||||||
return Math.floor((progress.step / total) * 100);
|
return Math.floor((progress.step / total) * 100);
|
||||||
};
|
};
|
||||||
|
|
||||||
export const getLessonSteps = (lesson: Lesson) => {
|
export const getLessonSteps = (lesson: Lesson, simplify: boolean = false) => {
|
||||||
const dayjs = useDayjs();
|
const dayjs = useDayjs();
|
||||||
const dateFormat = "YYYY-MM-DD HH:mm:ss";
|
const dateFormat = "YYYY-MM-DD HH:mm:ss";
|
||||||
const progress = extractLessonStage(lesson);
|
const progress = extractLessonStage(lesson);
|
||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
title: progress.script_upload ? "脚本文件上传" : undefined,
|
title: progress.script_upload ? "脚本提交" : undefined,
|
||||||
description: progress.script_upload
|
description: progress.script_upload
|
||||||
? `已于 ${dayjs(lesson.script_upload_time * 1000).format(dateFormat)} 完成上传`
|
? (simplify ? '已完成' : `已于 ${dayjs(lesson.script_upload_time * 1000).format(dateFormat)} 完成上传`)
|
||||||
: "脚本文件上传",
|
: "脚本文件提交",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: progress.script_confirm ? "脚本文件确认" : undefined,
|
title: progress.script_confirm ? "脚本确认" : undefined,
|
||||||
description: progress.script_confirm
|
description: progress.script_confirm
|
||||||
? `已于 ${dayjs(lesson.script_confirm_time * 1000).format(dateFormat)} 确认`
|
? (simplify ? '已完成' : `已于 ${dayjs(lesson.script_confirm_time * 1000).format(dateFormat)} 确认`)
|
||||||
: "脚本文件确认",
|
: "脚本文件确认",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: progress.video_capture ? "视频拍摄和上传" : undefined,
|
title: progress.video_capture ? "视频拍摄" : undefined,
|
||||||
description: progress.video_capture
|
description: progress.video_capture
|
||||||
? `已于 ${dayjs(lesson.video_capture_time * 1000).format(dateFormat)} 完成上传`
|
? (simplify ? '已完成' : `已于 ${dayjs(lesson.video_capture_time * 1000).format(dateFormat)} 完成上传`)
|
||||||
: "视频拍摄上传",
|
: "视频拍摄提交",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: progress.post_production ? "视频后期制作" : undefined,
|
title: progress.post_production ? "后期制作" : undefined,
|
||||||
description: progress.post_production
|
description: progress.post_production
|
||||||
? `已于 ${dayjs(lesson.video_confirm_time * 1000).format(dateFormat)} 完成上传`
|
? (simplify ? '已完成' : `已于 ${dayjs(lesson.video_confirm_time * 1000).format(dateFormat)} 完成上传`)
|
||||||
: "视频后期制作",
|
: "视频后期制作",
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
Loading…
Reference in New Issue
Block a user