|
@@ -3,6 +3,8 @@ import OSearch from '@/components/o-search'
|
|
|
import OSticky from '@/components/o-sticky'
|
|
|
import OEmpty from '@/components/o-empty'
|
|
|
import dayjs from 'dayjs'
|
|
|
+import isBetween from 'dayjs/plugin/isBetween'
|
|
|
+dayjs.extend(isBetween)
|
|
|
import {
|
|
|
Cell,
|
|
|
Icon,
|
|
@@ -15,10 +17,13 @@ import {
|
|
|
PullRefresh,
|
|
|
ActionSheet,
|
|
|
showToast,
|
|
|
- Picker
|
|
|
+ Picker,
|
|
|
+ DropdownMenu,
|
|
|
+ DropdownItem,
|
|
|
+ Button,
|
|
|
+ Calendar
|
|
|
} from 'vant'
|
|
|
import OFullRefresh from '@/components/o-full-refresh'
|
|
|
-
|
|
|
import StudentItem from './modals/student-item'
|
|
|
import { defineComponent, reactive, ref, onMounted } from 'vue'
|
|
|
import { state as globalState } from '@/state'
|
|
@@ -33,42 +38,24 @@ export default defineComponent({
|
|
|
const platformApi = ref(globalState.platformApi)
|
|
|
const router = useRouter()
|
|
|
const state = reactive({
|
|
|
+ showSearchStatus: true,
|
|
|
showPopoverTime: false,
|
|
|
- showPopoverOrchestra: false,
|
|
|
- showPopoverSubject: false,
|
|
|
- showPopoverSort: false,
|
|
|
actions: [] as any,
|
|
|
- subjects: [] as any,
|
|
|
- actionSorts: [
|
|
|
- {
|
|
|
- name: '按天数',
|
|
|
- value: 'PRACTICE_DAY',
|
|
|
- selected: true
|
|
|
- },
|
|
|
- {
|
|
|
- name: '按时长',
|
|
|
- value: 'PRACTICE_TIMES'
|
|
|
- }
|
|
|
- // color: forms.sortType == 'PRACTICE_DAY' ? '#FF8057' : '#333'
|
|
|
- ],
|
|
|
- currentDate: [dayjs().format('YYYY'), dayjs().format('MM')]
|
|
|
+ subjects: [] as any
|
|
|
})
|
|
|
const forms = reactive({
|
|
|
- practiceMonth: state.currentDate[0] + '' + state.currentDate[1],
|
|
|
- practiceMonthName: state.currentDate[0] + '年' + state.currentDate[1] + '月',
|
|
|
+ startTime: dayjs().day(1).format('YYYY-MM-DD'),
|
|
|
+ endTime: dayjs().day(7).format('YYYY-MM-DD'),
|
|
|
orchestraId: '',
|
|
|
- orchestraName: '全部乐团',
|
|
|
+ orchestraName: '',
|
|
|
subjectId: '',
|
|
|
- subjectName: '全部声部',
|
|
|
- sortType: 'PRACTICE_DAY',
|
|
|
- sortTypeName: '按天数',
|
|
|
+ subjectName: '',
|
|
|
+ sortType: '',
|
|
|
+ sortTypeName: '',
|
|
|
keyword: '',
|
|
|
page: 1,
|
|
|
rows: 20
|
|
|
})
|
|
|
- const minDate = ref(new Date(dayjs().subtract(10, 'year').format('YYYY-MM-DD')))
|
|
|
- const maxDate = ref(new Date(dayjs().add(10, 'year').format('YYYY-MM-DD')))
|
|
|
- const columnsType = ref<DatePickerColumnType[]>(['year', 'month'])
|
|
|
const refreshing = ref(false)
|
|
|
const loading = ref(false)
|
|
|
const finished = ref(false)
|
|
@@ -82,9 +69,12 @@ export default defineComponent({
|
|
|
list.value = []
|
|
|
refreshing.value = false
|
|
|
}
|
|
|
- const res = await request.post(`${platformApi.value}/student/page`, {
|
|
|
- data: { ...forms }
|
|
|
- })
|
|
|
+ const res = await request.post(
|
|
|
+ `${platformApi.value}/musicPracticeRecord/school/studentPracticeThisWeek`,
|
|
|
+ {
|
|
|
+ data: { ...forms }
|
|
|
+ }
|
|
|
+ )
|
|
|
|
|
|
if (list.value.length > 0 && res.data.pages === 1) {
|
|
|
return
|
|
@@ -118,37 +108,16 @@ export default defineComponent({
|
|
|
const checkSort = (val: any) => {
|
|
|
forms.sortType = val.value
|
|
|
forms.sortTypeName = val.name
|
|
|
- state.actionSorts.forEach((child: any) => {
|
|
|
- child.selected = false
|
|
|
- })
|
|
|
- val.selected = true
|
|
|
- state.showPopoverSort = false
|
|
|
- refreshing.value = true
|
|
|
- getList()
|
|
|
- }
|
|
|
- const checkTimer = (val: any) => {
|
|
|
- forms.practiceMonth = val.selectedValues[0] + val.selectedValues[1]
|
|
|
- forms.practiceMonthName = val.selectedValues[0] + '年' + val.selectedValues[1] + '月'
|
|
|
- state.showPopoverTime = false
|
|
|
- refreshing.value = true
|
|
|
- getList()
|
|
|
}
|
|
|
+
|
|
|
const checkOrchestra = (val: any) => {
|
|
|
- const selectedOptions = val.selectedOptions[0] || {}
|
|
|
- forms.orchestraId = selectedOptions.value
|
|
|
- forms.orchestraName = selectedOptions.name
|
|
|
- state.showPopoverOrchestra = false
|
|
|
- refreshing.value = true
|
|
|
- getList()
|
|
|
+ forms.orchestraId = val.value
|
|
|
+ forms.orchestraName = val.name
|
|
|
}
|
|
|
|
|
|
const checkSubject = (val: any) => {
|
|
|
- const selectedOptions = val.selectedOptions[0] || {}
|
|
|
- forms.subjectId = selectedOptions.value
|
|
|
- forms.subjectName = selectedOptions.name
|
|
|
- state.showPopoverSubject = false
|
|
|
- refreshing.value = true
|
|
|
- getList()
|
|
|
+ forms.subjectId = val.value
|
|
|
+ forms.subjectName = val.name
|
|
|
}
|
|
|
const getOrchestraList = async () => {
|
|
|
try {
|
|
@@ -161,7 +130,6 @@ export default defineComponent({
|
|
|
value: item.id as string
|
|
|
}
|
|
|
})
|
|
|
- state.actions.unshift({ name: '全部乐团', value: '' })
|
|
|
} catch (e: any) {
|
|
|
const message = e.message
|
|
|
showToast(message)
|
|
@@ -179,7 +147,6 @@ export default defineComponent({
|
|
|
value: item.subjectId as string
|
|
|
}
|
|
|
})
|
|
|
- state.subjects.unshift({ name: '全部声部', value: '' })
|
|
|
} catch (e: any) {
|
|
|
const message = e.message
|
|
|
showToast(message)
|
|
@@ -193,11 +160,149 @@ export default defineComponent({
|
|
|
getList()
|
|
|
}
|
|
|
|
|
|
+ // 名称
|
|
|
+ const formatLength = (name: string) => {
|
|
|
+ if (name.length > 9) {
|
|
|
+ const fristName = name.substring(0, 6)
|
|
|
+ const lastName = name.substring(name.length - 6, name.length - 1)
|
|
|
+ return fristName + '...' + lastName
|
|
|
+ } else {
|
|
|
+ return name
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ const dropdownMenuRef = ref()
|
|
|
+ const dropdownItemRef = ref()
|
|
|
+ // 重置
|
|
|
+ const onSearchReset = () => {
|
|
|
+ forms.startTime = dayjs().day(1).format('YYYY-MM-DD')
|
|
|
+ forms.endTime = dayjs().day(7).format('YYYY-MM-DD')
|
|
|
+ forms.orchestraId = ''
|
|
|
+ forms.orchestraName = ''
|
|
|
+ forms.subjectId = ''
|
|
|
+ forms.subjectName = ''
|
|
|
+ forms.sortType = ''
|
|
|
+ forms.sortTypeName = ''
|
|
|
+ state.showSearchStatus = false
|
|
|
+ refreshing.value = true
|
|
|
+ getList()
|
|
|
+ }
|
|
|
+
|
|
|
+ // 搜索
|
|
|
+ const onSearchConfirm = () => {
|
|
|
+ dropdownItemRef.value?.toggle()
|
|
|
+ refreshing.value = true
|
|
|
+ getList()
|
|
|
+ }
|
|
|
+
|
|
|
return () => (
|
|
|
- <div class={!showContact.value && 'emptyRootContainer'}>
|
|
|
+ <div class={[!showContact.value ? 'emptyRootContainer' : '', styles.exerciseRecord]}>
|
|
|
<OSticky position="top" background="#F8F8F8">
|
|
|
- <div>
|
|
|
- {/* <OHeader onHeaderBack={onBack}></OHeader> */}
|
|
|
+ <OHeader border={false}>
|
|
|
+ {{
|
|
|
+ right: () => (
|
|
|
+ <DropdownMenu
|
|
|
+ class={styles.searchMore}
|
|
|
+ closeOnClickOverlay={false}
|
|
|
+ closeOnClickOutside={false}
|
|
|
+ ref={dropdownMenuRef}
|
|
|
+ >
|
|
|
+ <DropdownItem title="筛选" v-model={state.showSearchStatus} ref={dropdownItemRef}>
|
|
|
+ <div class={styles.searchContainer}>
|
|
|
+ {state.actions.length > 0 && (
|
|
|
+ <>
|
|
|
+ <div class={styles.searchTitle}>乐团</div>
|
|
|
+ <div class={[styles.searchTypeGroup, styles.searchTypeFlex]}>
|
|
|
+ {state.actions.map((item: any) => (
|
|
|
+ <div
|
|
|
+ class={[
|
|
|
+ styles.searchTypeItem,
|
|
|
+ item.value === forms.orchestraId && styles['is-active']
|
|
|
+ ]}
|
|
|
+ onClick={() => checkOrchestra(item)}
|
|
|
+ >
|
|
|
+ {formatLength(item.name)}
|
|
|
+ </div>
|
|
|
+ ))}
|
|
|
+ </div>
|
|
|
+ </>
|
|
|
+ )}
|
|
|
+
|
|
|
+ <div class={styles.searchTitle}>时间段</div>
|
|
|
+ <div class={[styles.searchTypeGroup, styles.searchTypeFlex2]}>
|
|
|
+ <div
|
|
|
+ class={styles.searchTypeItem}
|
|
|
+ onClick={() => (state.showPopoverTime = true)}
|
|
|
+ >
|
|
|
+ {forms.startTime}
|
|
|
+ </div>
|
|
|
+ <div
|
|
|
+ class={styles.searchTypeItemLine}
|
|
|
+ onClick={() => (state.showPopoverTime = true)}
|
|
|
+ ></div>
|
|
|
+ <div
|
|
|
+ class={styles.searchTypeItem}
|
|
|
+ onClick={() => (state.showPopoverTime = true)}
|
|
|
+ >
|
|
|
+ {forms.endTime}
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class={styles.searchTitle}>声部</div>
|
|
|
+ <div class={[styles.searchTypeGroup, styles.searchTypeFlex1]}>
|
|
|
+ {state.subjects.map((subject: any) => (
|
|
|
+ <div
|
|
|
+ class={[
|
|
|
+ styles.searchTypeItem,
|
|
|
+ subject.value === forms.subjectId && styles['is-active']
|
|
|
+ ]}
|
|
|
+ onClick={() => checkSubject(subject)}
|
|
|
+ >
|
|
|
+ {subject.name}
|
|
|
+ </div>
|
|
|
+ ))}
|
|
|
+ </div>
|
|
|
+ <div class={styles.searchTitle}>排序方式</div>
|
|
|
+ <div class={[styles.searchTypeGroup, styles.searchTypeFlex]}>
|
|
|
+ {[
|
|
|
+ {
|
|
|
+ name: '按时长',
|
|
|
+ value: 'PRACTICE_TIMES'
|
|
|
+ },
|
|
|
+ {
|
|
|
+ name: '按天数',
|
|
|
+ value: 'PRACTICE_DAY'
|
|
|
+ }
|
|
|
+ ].map((item: any) => (
|
|
|
+ <div
|
|
|
+ class={[
|
|
|
+ styles.searchTypeItem,
|
|
|
+ forms.sortType === item.value && styles['is-active']
|
|
|
+ ]}
|
|
|
+ onClick={() => checkSort(item)}
|
|
|
+ >
|
|
|
+ {item.name}
|
|
|
+ </div>
|
|
|
+ ))}
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class={[styles.searchMoreGroup, 'van-hairline--top']}>
|
|
|
+ <Button type="default" block round size="large" onClick={onSearchReset}>
|
|
|
+ 重置
|
|
|
+ </Button>
|
|
|
+ <Button type="primary" block round size="large" onClick={onSearchConfirm}>
|
|
|
+ 查询
|
|
|
+ </Button>
|
|
|
+ </div>
|
|
|
+ </DropdownItem>
|
|
|
+ </DropdownMenu>
|
|
|
+ )
|
|
|
+ }}
|
|
|
+ </OHeader>
|
|
|
+ <div
|
|
|
+ style={{
|
|
|
+ backgroundColor: '#fff'
|
|
|
+ }}
|
|
|
+ >
|
|
|
<OSearch
|
|
|
placeholder="请输入学员姓名"
|
|
|
class={styles.recordSearch}
|
|
@@ -207,43 +312,65 @@ export default defineComponent({
|
|
|
getList()
|
|
|
}}
|
|
|
></OSearch>
|
|
|
- <div class={'searchGroup'}>
|
|
|
- <div
|
|
|
- class={['searchItem', state.showPopoverTime ? 'searchItem-active' : '']}
|
|
|
- onClick={() => {
|
|
|
- state.showPopoverTime = true
|
|
|
- }}
|
|
|
- >
|
|
|
- <span>{forms.practiceMonthName}</span>
|
|
|
- <i class="arrow"></i>
|
|
|
- </div>
|
|
|
- <div
|
|
|
- class={['searchItem', state.showPopoverOrchestra ? 'searchItem-active' : '']}
|
|
|
- onClick={() => {
|
|
|
- state.showPopoverOrchestra = true
|
|
|
- }}
|
|
|
- >
|
|
|
- <span>{forms.orchestraName}</span>
|
|
|
- <i class="arrow"></i>
|
|
|
- </div>
|
|
|
- <div
|
|
|
- class={['searchItem', state.showPopoverSubject ? 'searchItem-active' : '']}
|
|
|
- onClick={() => {
|
|
|
- state.showPopoverSubject = true
|
|
|
- }}
|
|
|
- >
|
|
|
- <span>{forms.subjectName}</span>
|
|
|
- <i class="arrow"></i>
|
|
|
- </div>
|
|
|
+ <div class={styles.searchPreview}>
|
|
|
<div
|
|
|
- class={['searchItem', state.showPopoverSort ? 'searchItem-active' : '']}
|
|
|
+ class={styles.searchPreviewItem}
|
|
|
onClick={() => {
|
|
|
- state.showPopoverSort = true
|
|
|
+ // console.log(dropdownItemRef.value, dropdownMenuRef.value)
|
|
|
+ // dropdownItemRef.value?.toggle()
|
|
|
+ // dropdownMenuRef.value?.click()
|
|
|
}}
|
|
|
>
|
|
|
- <span>{forms.sortTypeName}</span>
|
|
|
- <i class="arrow"></i>
|
|
|
+ {forms.startTime}~{forms.endTime}
|
|
|
</div>
|
|
|
+ {forms.orchestraId && (
|
|
|
+ <div class={styles.searchPreviewItem}>
|
|
|
+ {formatLength(forms.orchestraName)}
|
|
|
+ <Icon
|
|
|
+ name="cross"
|
|
|
+ class={styles.cross}
|
|
|
+ onClick={(e: any) => {
|
|
|
+ forms.orchestraId = ''
|
|
|
+ forms.orchestraName = ''
|
|
|
+ e.stopPropagation()
|
|
|
+ refreshing.value = true
|
|
|
+ getList()
|
|
|
+ }}
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+ )}
|
|
|
+ {forms.subjectId && (
|
|
|
+ <div class={styles.searchPreviewItem}>
|
|
|
+ {forms.subjectName}
|
|
|
+ <Icon
|
|
|
+ name="cross"
|
|
|
+ class={styles.cross}
|
|
|
+ onClick={(e: any) => {
|
|
|
+ forms.subjectId = ''
|
|
|
+ forms.subjectName = ''
|
|
|
+ e.stopPropagation()
|
|
|
+ refreshing.value = true
|
|
|
+ getList()
|
|
|
+ }}
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+ )}
|
|
|
+ {forms.sortType && (
|
|
|
+ <div class={styles.searchPreviewItem}>
|
|
|
+ {forms.sortTypeName}
|
|
|
+ <Icon
|
|
|
+ name="cross"
|
|
|
+ class={styles.cross}
|
|
|
+ onClick={(e: any) => {
|
|
|
+ forms.sortType = ''
|
|
|
+ forms.sortTypeName = ''
|
|
|
+ e.stopPropagation()
|
|
|
+ refreshing.value = true
|
|
|
+ getList()
|
|
|
+ }}
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+ )}
|
|
|
</div>
|
|
|
</div>
|
|
|
</OSticky>
|
|
@@ -272,58 +399,26 @@ export default defineComponent({
|
|
|
<OEmpty tips="暂无练习记录" />
|
|
|
)}
|
|
|
|
|
|
- <Popup
|
|
|
+ <Calendar
|
|
|
v-model:show={state.showPopoverTime}
|
|
|
- position="bottom"
|
|
|
- round
|
|
|
- class={'popupBottomSearch'}
|
|
|
- >
|
|
|
- <DatePicker
|
|
|
- onCancel={() => {
|
|
|
- state.showPopoverTime = false
|
|
|
- }}
|
|
|
- onConfirm={checkTimer}
|
|
|
- v-model={state.currentDate}
|
|
|
- minDate={minDate.value}
|
|
|
- formatter={formatterDatePicker}
|
|
|
- maxDate={maxDate.value}
|
|
|
- columnsType={columnsType.value}
|
|
|
- />
|
|
|
- </Popup>
|
|
|
-
|
|
|
- <OActionSheet
|
|
|
- v-model:show={state.showPopoverSort}
|
|
|
- actions={state.actionSorts}
|
|
|
- onSelect={checkSort}
|
|
|
+ firstDayOfWeek={1}
|
|
|
+ showConfirm={false}
|
|
|
+ type="range"
|
|
|
+ maxRange={7}
|
|
|
+ minDate={new Date('2023-02-27')}
|
|
|
+ defaultDate={[dayjs(forms.startTime).toDate(), dayjs(forms.endTime).toDate()]}
|
|
|
+ style={{
|
|
|
+ height: '70%'
|
|
|
+ }}
|
|
|
+ onSelect={(item: any) => {
|
|
|
+ forms.startTime = ''
|
|
|
+ forms.endTime = ''
|
|
|
+ if (!dayjs(item[0]).isBetween(dayjs(forms.startTime), dayjs(forms.endTime))) {
|
|
|
+ forms.startTime = dayjs(item[0]).day(1).format('YYYY-MM-DD')
|
|
|
+ forms.endTime = dayjs(item[0]).day(7).format('YYYY-MM-DD')
|
|
|
+ }
|
|
|
+ }}
|
|
|
/>
|
|
|
-
|
|
|
- <Popup
|
|
|
- v-model:show={state.showPopoverOrchestra}
|
|
|
- position="bottom"
|
|
|
- round
|
|
|
- class={'popupBottomSearch'}
|
|
|
- >
|
|
|
- <Picker
|
|
|
- columns={state.actions}
|
|
|
- onCancel={() => (state.showPopoverOrchestra = false)}
|
|
|
- onConfirm={(val: any) => checkOrchestra(val)}
|
|
|
- columnsFieldNames={{ text: 'name', value: 'value' }}
|
|
|
- />
|
|
|
- </Popup>
|
|
|
-
|
|
|
- <Popup
|
|
|
- v-model:show={state.showPopoverSubject}
|
|
|
- position="bottom"
|
|
|
- round
|
|
|
- class={'popupBottomSearch'}
|
|
|
- >
|
|
|
- <Picker
|
|
|
- columns={state.subjects}
|
|
|
- onCancel={() => (state.showPopoverSubject = false)}
|
|
|
- onConfirm={(val: any) => checkSubject(val)}
|
|
|
- columnsFieldNames={{ text: 'name', value: 'value' }}
|
|
|
- />
|
|
|
- </Popup>
|
|
|
</div>
|
|
|
)
|
|
|
}
|