| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487 |
- import { computed, defineComponent, onMounted, reactive, ref } from 'vue';
- import styles from './index.module.less';
- import MSticky from '@/components/m-sticky';
- import MHeader from '@/components/m-header';
- import icon_detail_bg from '../images/icon_detail_bg.png';
- import icon_music from '@common/images/icon-music.png';
- import {
- Button,
- Cell,
- CellGroup,
- Checkbox,
- CheckboxGroup,
- Field,
- Grid,
- GridItem,
- Image,
- Picker,
- Popup,
- showToast
- } from 'vant';
- import MStudent from '../component/m-student';
- import { IMusicGroup, IStudentDetail } from '../type';
- import Assignment from '../component/Assignment';
- import Attendance from '../component/Attendance';
- import icon_pen from '@common/images/icon_pen.png';
- import icon_phone from '../images/icon-phone.png';
- import icon_message from '../images/icon-message.png';
- import SkeletionDetail from './skeletion-detail';
- import { useRoute } from 'vue-router';
- import {
- api_organizationGetGradeList,
- api_studentManageQuitMusicGroup,
- api_studentManageUpdateGrade,
- api_studentManageUserDetail,
- api_studentManageUserMusicGroup
- } from '../api';
- export default defineComponent({
- name: 'student-manage-detail',
- setup() {
- const route = useRoute();
- const studentId: string | undefined =
- route.query?.studentId?.toString() || '';
- const musicGroupIds: string[] =
- route.query.musicGroupIds?.toString()?.split(',') || [];
- const detailData = reactive({
- skelet: true,
- /** 加载 */
- loading: false,
- /** 乐团 */
- groupShow: false,
- /** 退团 */
- quitShow: false,
- /** 确定退团 */
- quitConfirmShow: false,
- /** 联系方式 */
- cancelShow: false,
- /** 年级 */
- gradeShow: false,
- gradeOptions: [[], []] as any,
- musicGroup: [] as IMusicGroup[],
- musicGroupTitle: '全部乐团',
- musicGroupId: musicGroupIds[0] || '',
- student: {} as IStudentDetail,
- /** 年级列表 */
- gradeList: null as any,
- /** 退团列表 */
- quitList: [] as any[],
- /** 退团原因 */
- reason: '',
- quitLoading: false
- });
- const checkboxRefs = ref<any[]>([]);
- /** 获取学生乐团 */
- const getMusicGroup = () => {
- api_studentManageUserMusicGroup(studentId).then(res => {
- if (Array.isArray(res.data)) {
- detailData.musicGroup = res.data.map((item: any) => {
- return {
- text: item.name,
- value: item.id,
- gradeType: item.gradeType
- };
- });
- if (detailData.musicGroup.length === 1) {
- detailData.musicGroupTitle = detailData.musicGroup[0].text;
- }
- }
- });
- };
- /** 获取年级分布 */
- const getGradeList = () => {
- if (detailData.student.organId && detailData.musicGroup.length) {
- if (detailData.gradeList) return;
- console.log(detailData.musicGroup);
- const gradeType = Array.from(
- new Set(detailData.musicGroup.map(group => group.gradeType))
- ).join(',');
- console.log('🚀 ~ gradeType:', gradeType);
- api_organizationGetGradeList(
- detailData.student.organId,
- gradeType
- ).then(res => {
- detailData.gradeList = res.data;
- detailData.gradeOptions[0] = Object.entries(res.data).map(
- (value: any) => {
- return {
- text: value[1],
- value: value[0]
- };
- }
- );
- detailData.gradeOptions[1] = new Array(30)
- .fill(1)
- .map((_, index: number) => ({
- text: `${index + 1}班`,
- value: `${index + 1}班`
- }));
- });
- return;
- }
- setTimeout(() => {
- getGradeList();
- }, 30);
- };
- const getDatail = () => {
- detailData.loading = true;
- api_studentManageUserDetail({
- studentId: studentId,
- musicGroupId: detailData.musicGroupId || ''
- })
- .then(res => {
- if (res.data) {
- if (res.data.phone) {
- res.data.phone =
- res.data.phone.slice(0, 3) + '****' + res.data.phone.slice(-4);
- }
- detailData.student = res.data;
- getGradeList();
- }
- })
- .finally(() => {
- setTimeout(() => {
- detailData.loading = false;
- detailData.skelet = false;
- }, 500);
- });
- };
- onMounted(() => {
- getMusicGroup();
- getDatail();
- });
- const quitName = computed(() => {
- const text = detailData.musicGroup
- .filter(group => detailData.quitList.includes(group.value))
- .map(group => {
- return '“' + group.text + '”';
- })
- .join('、');
- return `${detailData.student.studentName}从${text}`;
- });
- /** 设置学生班级 */
- const handleSetGrade = async (selectedOptions: any[]) => {
- const res = await api_studentManageUpdateGrade({
- currentClass: selectedOptions[1].value, // 班级
- currentGrade: selectedOptions[0].text, // 年级
- currentGradeNum: selectedOptions[0].value, // 年级(数字表示)
- musicGroupId: detailData.musicGroupId, // 乐团ID
- studentId: detailData.student.studentId // 学生ID
- });
- console.log(res);
- if (res.code === 200) {
- showToast('修改成功');
- }
- getDatail();
- };
- /** 退团 */
- const handleQuite = async () => {
- if (!detailData.reason) {
- showToast('请填写退团原因');
- return;
- }
- detailData.quitLoading = true;
- try {
- const res = await api_studentManageQuitMusicGroup({
- musicGroupId: detailData.quitList.join(','),
- reason: detailData.reason,
- reasonEnum: 'OTHER',
- userId: detailData.student.studentId
- });
- detailData.quitConfirmShow = false;
- if (res.code === 200) {
- detailData.quitList = [];
- getDatail();
- }
- } catch (error) {}
- detailData.quitLoading = false;
- };
- /** 去聊天 */
- const openIm = () => {
- postMessage({
- api: 'joinChatGroup',
- content: {
- type: 'single', // single 单人 multi 多人
- id: detailData.student.studentId
- }
- });
- };
- /** 打电话 */
- const hanldeCallPhone = () => {
- postMessage({
- api: 'callPhone',
- content: {
- phone: detailData.student.phone
- }
- });
- };
- return () => (
- <div class={styles.studentDetail}>
- <Image class={styles.bg} src={icon_detail_bg} />
- <MSticky position="top">
- <MHeader background="transparent" />
- </MSticky>
- <SkeletionDetail loading={detailData.skelet}>
- <Cell
- class={styles.musicGroup}
- title={detailData.musicGroupTitle}
- isLink={detailData.musicGroup.length > 1 ? true : false}
- clickable={detailData.musicGroup.length > 1 ? true : false}
- center
- border={false}
- onClick={() => {
- if (detailData.musicGroup.length < 2) return;
- detailData.groupShow = true;
- }}>
- {{
- icon: () => <Image class={styles.iconMusic} src={icon_music} />
- }}
- </Cell>
- <div class={styles.box}>
- <MStudent
- item={detailData.student}
- valueType={
- detailData.student.inGroupStatus === 'OUT'
- ? 'statued'
- : detailData.student.inGroupStatus === 'APPLY_OUT'
- ? 'statuing'
- : 'status'
- }
- isLink={false}
- onQuit={() => (detailData.quitShow = true)}
- onContact={() => (detailData.cancelShow = true)}
- />
- </div>
- <div class={styles.infobox}>
- <div class={styles.attendanceTitle}>
- <span>基本信息</span>
- </div>
- <div class={styles.infoItem}>
- <div>性别</div>
- <div>{detailData.student.gender ? '男' : '女'}</div>
- </div>
- <div class={styles.infoItem}>
- <div>联系电话</div>
- <div>{detailData.student.phone}</div>
- </div>
- <div class={styles.infoItem}>
- <div>年级</div>
- <div
- class={styles.edit}
- onClick={() => {
- if (detailData.student.inGroupStatus === 'OUT') return;
- detailData.gradeShow = true;
- }}>
- {detailData.student.currentGrade}年级
- {detailData.student.currentClass}
- {detailData.student.inGroupStatus !== 'OUT' && (
- <Image class={styles.iconPen} src={icon_pen} />
- )}
- </div>
- </div>
- <div class={styles.infoItem}>
- <div>艺术实践</div>
- <div>{detailData.student.artPracticeCount}次</div>
- </div>
- {detailData.student.quitTime && (
- <div class={styles.infoItem}>
- <div>退团时间</div>
- <div style={{ color: '#FF5A56' }}>
- {detailData.student.quitTime}
- </div>
- </div>
- )}
- </div>
- <div class={styles.box}>
- <Assignment item={detailData.student} />
- </div>
- <div class={styles.box}>
- <Attendance item={detailData.student} />
- </div>
- </SkeletionDetail>
- {/* 切换乐团 */}
- <Popup v-model:show={detailData.groupShow} position="bottom" round>
- <Picker
- visibleOptionNum={5}
- columns={detailData.musicGroup}
- onCancel={() => (detailData.groupShow = false)}
- onConfirm={value => {
- const option = value.selectedOptions[0];
- const oldGroupId = detailData.musicGroupId;
- detailData.musicGroupId = option.value;
- detailData.musicGroupTitle = option.text;
- detailData.groupShow = false;
- if (oldGroupId != option.value) {
- getDatail();
- }
- }}
- />
- </Popup>
- {/* 联系方式 */}
- <Popup
- v-model:show={detailData.cancelShow}
- position="bottom"
- round
- closeable>
- <div class={styles.concatBox}>
- <div class={styles.concatTitle}>联系方式</div>
- <div class={styles.concatContent}>
- <Grid columnNum={2} border={false} center>
- <GridItem text="发送消息" onClick={openIm}>
- {{
- icon: () => (
- <Image class={styles.concatIcon} src={icon_message} />
- )
- }}
- </GridItem>
- <GridItem text="拨打电话" onClick={hanldeCallPhone}>
- {{
- icon: () => (
- <Image class={styles.concatIcon} src={icon_phone} />
- )
- }}
- </GridItem>
- </Grid>
- </div>
- </div>
- </Popup>
- {/* 设置班级 */}
- <Popup v-model:show={detailData.gradeShow} position="bottom" round>
- <Picker
- visibleOptionNum={5}
- columns={detailData.gradeOptions}
- onCancel={() => (detailData.gradeShow = false)}
- onConfirm={value => {
- detailData.gradeShow = false;
- handleSetGrade(value.selectedOptions);
- }}
- />
- </Popup>
- {/* 选择退团列表 */}
- <Popup
- v-model:show={detailData.quitShow}
- class={['popup-custom', 'van-scale']}
- transition="van-scale">
- <div class={styles.quitBox}>
- <div class={styles.quitTitle}>选择乐团</div>
- <div class={styles.quitDes}>请选择要退出的乐团:</div>
- <CheckboxGroup
- v-model:modelValue={detailData.quitList}
- class={styles.optionBox}>
- <CellGroup border={false}>
- {detailData.musicGroup.map(
- (group: IMusicGroup, index: number) => {
- return (
- <Cell
- class={[
- detailData.quitList.includes(group.value) &&
- styles.cellActive
- ]}
- title={group.text}
- center
- border={false}
- onClick={() => {
- checkboxRefs.value[index]?.toggle();
- }}>
- {{
- value: () => (
- <Checkbox
- ref={el => (checkboxRefs.value[index] = el)}
- shape="square"
- name={group.value}
- onClick={(e: Event) =>
- e.stopPropagation()
- }></Checkbox>
- )
- }}
- </Cell>
- );
- }
- )}
- </CellGroup>
- </CheckboxGroup>
- <div class={['btnGroupPopup']}>
- <Button round onClick={() => (detailData.quitShow = false)}>
- 取消
- </Button>
- <Button
- type="primary"
- round
- disabled={!detailData.quitList.length}
- onClick={() => {
- // detailData.quitShow = false
- detailData.quitConfirmShow = true;
- }}>
- 下一步
- </Button>
- </div>
- </div>
- </Popup>
- {/* 确定退团 */}
- <Popup
- v-model:show={detailData.quitConfirmShow}
- class={['popup-custom', 'van-scale']}
- transition="van-scale">
- <div class={styles.quitBox}>
- <div class={styles.quitTitle}>学员退团</div>
- <div class={styles.quitDes}>
- 确认要将学员
- <span style={{ color: '#FF5A56' }}>{quitName.value}</span>
- 中退团吗?
- </div>
- <div style={{ color: '#333' }} class={styles.quitLabel}>
- <span style={{ color: '#FF5A56' }}>*</span>退团原因:
- </div>
- <div class={styles.quitLabel}>
- <Field
- style={{ padding: 0 }}
- v-model={detailData.reason}
- type="textarea"
- rows={3}
- required
- placeholder="请填写退团原因"></Field>
- </div>
- <div class={styles.quitLabel}>
- 确认后,我们将在7个工作日内与学生联系退费事宜
- </div>
- <div class={['btnGroupPopup']}>
- <Button
- round
- onClick={() => (detailData.quitConfirmShow = false)}>
- 取消
- </Button>
- <Button
- loading={detailData.quitLoading}
- type="primary"
- round
- onClick={() => handleQuite()}>
- 确定
- </Button>
- </div>
- </div>
- </Popup>
- </div>
- );
- }
- });
|