|
@@ -1,199 +1,253 @@
|
|
|
-import { PropType, defineComponent, onMounted, reactive, ref } from 'vue';
|
|
|
-import styles from './suggestion-list.module.less';
|
|
|
-import {
|
|
|
- NInput,
|
|
|
- NSelect,
|
|
|
- NScrollbar,
|
|
|
- NSpin,
|
|
|
- NThing,
|
|
|
- NImageGroup,
|
|
|
- NSpace,
|
|
|
- NImage,
|
|
|
- NButton
|
|
|
-} from 'naive-ui';
|
|
|
-import { batchSetRead, getSysSuggestionList } from './api';
|
|
|
-import CDatePicker from '../../CDatePicker';
|
|
|
-import TheEmpty from '../../TheEmpty';
|
|
|
-import { useDebounceFn, useThrottleFn } from '@vueuse/core';
|
|
|
-import { eventGlobal, getTimes } from '/src/utils';
|
|
|
-
|
|
|
-export default defineComponent({
|
|
|
- name: 'suggestion-list',
|
|
|
- props: {
|
|
|
- typeList: {
|
|
|
- type: Array as PropType<any[]>,
|
|
|
- default: () => []
|
|
|
- }
|
|
|
- },
|
|
|
- setup(props) {
|
|
|
- const state = reactive({
|
|
|
- suggestionTypeList: [] as any,
|
|
|
- loading: false,
|
|
|
- finshed: false, // 是否加载完
|
|
|
- pagination: {
|
|
|
- page: 1,
|
|
|
- rows: 20
|
|
|
- },
|
|
|
- searchGroup: {
|
|
|
- suggestionTypeId: null,
|
|
|
- timer: null as any
|
|
|
- },
|
|
|
- tableList: [] as any,
|
|
|
- show: false,
|
|
|
- item: {} as any
|
|
|
- });
|
|
|
-
|
|
|
- const getList = async () => {
|
|
|
- try {
|
|
|
- if (state.pagination.page === 1) {
|
|
|
- state.loading = true;
|
|
|
- }
|
|
|
- const { timer, ...res } = state.searchGroup;
|
|
|
- const { data } = await getSysSuggestionList({
|
|
|
- ...state.searchGroup,
|
|
|
- ...res,
|
|
|
- ...getTimes(timer, ['startTime', 'endTime'])
|
|
|
- });
|
|
|
- state.loading = false;
|
|
|
- const tempRows = data.rows || [];
|
|
|
- tempRows.forEach((row: any) => {
|
|
|
- const imgList =
|
|
|
- (row.attachmentUrls && row.attachmentUrls.split(',')) || [];
|
|
|
- row.imgList = imgList;
|
|
|
- });
|
|
|
- if (state.pagination.page === 1) {
|
|
|
- state.tableList = tempRows;
|
|
|
- } else {
|
|
|
- state.tableList.push(...tempRows);
|
|
|
- }
|
|
|
- state.finshed = data.pages <= data.current ? true : false;
|
|
|
- } catch {
|
|
|
- state.loading = false;
|
|
|
- }
|
|
|
- };
|
|
|
-
|
|
|
- const throttledFnSearch = useDebounceFn(item => {
|
|
|
- state.pagination.page = state.pagination.page + 1;
|
|
|
- state.pagination.page = 1;
|
|
|
- state.tableList = [];
|
|
|
- state.searchGroup = Object.assign(state.searchGroup, item);
|
|
|
- getList();
|
|
|
- }, 100);
|
|
|
-
|
|
|
- const throttledFn = useThrottleFn(() => {
|
|
|
- state.pagination.page = state.pagination.page + 1;
|
|
|
- getList();
|
|
|
- }, 500);
|
|
|
-
|
|
|
- const getBatchSetRead = async () => {
|
|
|
- try {
|
|
|
- await batchSetRead({ messageType: 'SYS_SUGGEST_FEEDBACK_TEACHER' });
|
|
|
-
|
|
|
- eventGlobal.emit('onSuggestionRead');
|
|
|
- } catch {
|
|
|
- //
|
|
|
- }
|
|
|
- };
|
|
|
- onMounted(() => {
|
|
|
- props.typeList.forEach((item: any) => {
|
|
|
- state.suggestionTypeList.push({
|
|
|
- label: item.name,
|
|
|
- value: item.id
|
|
|
- });
|
|
|
- });
|
|
|
- getBatchSetRead();
|
|
|
- getList();
|
|
|
- });
|
|
|
- return () => (
|
|
|
- <div class={styles.suggestionList}>
|
|
|
- <div class={styles.attendClassSearch}>
|
|
|
- <NSelect
|
|
|
- placeholder="反馈类型"
|
|
|
- clearable
|
|
|
- options={
|
|
|
- [
|
|
|
- { label: '反馈类型', value: null },
|
|
|
- ...state.suggestionTypeList
|
|
|
- ] as any
|
|
|
- }
|
|
|
- v-model:value={state.searchGroup.suggestionTypeId}
|
|
|
- />
|
|
|
- <CDatePicker
|
|
|
- v-model:value={state.searchGroup.timer}
|
|
|
- separator={'至'}
|
|
|
- start-placeholder="反馈开始日期"
|
|
|
- end-placeholder="反馈结束日期"
|
|
|
- type="daterange"
|
|
|
- clearable={true}
|
|
|
- timerValue={state.searchGroup.timer}></CDatePicker>
|
|
|
-
|
|
|
- <NButton type="primary" class="searchBtn" onClick={throttledFnSearch}>
|
|
|
- 搜索
|
|
|
- </NButton>
|
|
|
- </div>
|
|
|
- <NScrollbar
|
|
|
- class={styles.classList}
|
|
|
- onScroll={(e: any) => {
|
|
|
- const clientHeight = e.target?.clientHeight;
|
|
|
- const scrollTop = e.target?.scrollTop;
|
|
|
- const scrollHeight = e.target?.scrollHeight;
|
|
|
- // 是否到底,是否加载完
|
|
|
- if (
|
|
|
- clientHeight + scrollTop + 20 >= scrollHeight &&
|
|
|
- !state.finshed &&
|
|
|
- !state.loading
|
|
|
- ) {
|
|
|
- throttledFn();
|
|
|
- }
|
|
|
- }}>
|
|
|
- <NSpin show={state.loading}>
|
|
|
- <div
|
|
|
- class={[
|
|
|
- styles.listSection,
|
|
|
- !state.loading && state.tableList.length <= 0
|
|
|
- ? styles.emptySection
|
|
|
- : ''
|
|
|
- ]}>
|
|
|
- {state.tableList.map((item: any) => (
|
|
|
- <div>
|
|
|
- <NThing class={[styles.thingItem, 'isFull']}>
|
|
|
- <div class={styles.item}>
|
|
|
- <span>反馈类型:</span>
|
|
|
- {item.suggestionTypeName}
|
|
|
- </div>
|
|
|
- <div class={styles.item}>
|
|
|
- <span>反馈内容:</span>
|
|
|
- {item.content}
|
|
|
- </div>
|
|
|
- {item.imgList && item.imgList.length > 0 && (
|
|
|
- <div class={styles.item}>
|
|
|
- <NImageGroup class={styles.IMageWraps}>
|
|
|
- {item.imgList?.map((item: any, index: number) => (
|
|
|
- <NImage
|
|
|
- class={[styles.ShowImg]}
|
|
|
- src={item}
|
|
|
- objectFit="cover"></NImage>
|
|
|
- ))}
|
|
|
- </NImageGroup>
|
|
|
- </div>
|
|
|
- )}
|
|
|
-
|
|
|
- {item.handleStatus && (
|
|
|
- <div class={styles.itemResult}>
|
|
|
- <span>处理结果:</span>
|
|
|
- {item.handleAttitude === 'NO'
|
|
|
- ? '感谢你对音乐数字课堂的关注与支持,我们会认真处理您的反馈,尽快修复和完善相关功能!'
|
|
|
- : item.feedbackContent}
|
|
|
- </div>
|
|
|
- )}
|
|
|
- </NThing>
|
|
|
- </div>
|
|
|
- ))}
|
|
|
- {!state.loading && state.tableList.length <= 0 && <TheEmpty />}
|
|
|
- </div>
|
|
|
- </NSpin>
|
|
|
- </NScrollbar>
|
|
|
- </div>
|
|
|
- );
|
|
|
- }
|
|
|
-});
|
|
|
+import { PropType, defineComponent, onMounted, reactive, ref } from 'vue';
|
|
|
+
|
|
|
+import styles from './suggestion-list.module.less';
|
|
|
+
|
|
|
+import {
|
|
|
+ NInput,
|
|
|
+ NSelect,
|
|
|
+ NScrollbar,
|
|
|
+ NSpin,
|
|
|
+ NThing,
|
|
|
+ NImageGroup,
|
|
|
+ NSpace,
|
|
|
+ NImage,
|
|
|
+ NButton
|
|
|
+} from 'naive-ui';
|
|
|
+
|
|
|
+import { batchSetRead, getSysSuggestionList } from './api';
|
|
|
+
|
|
|
+import CDatePicker from '../../CDatePicker';
|
|
|
+
|
|
|
+import TheEmpty from '../../TheEmpty';
|
|
|
+
|
|
|
+import { useDebounceFn, useThrottleFn } from '@vueuse/core';
|
|
|
+
|
|
|
+import { eventGlobal, getTimes } from '/src/utils';
|
|
|
+
|
|
|
+export default defineComponent({
|
|
|
+ name: 'suggestion-list',
|
|
|
+
|
|
|
+ props: {
|
|
|
+ typeList: {
|
|
|
+ type: Array as PropType<any[]>,
|
|
|
+
|
|
|
+ default: () => []
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+ setup(props) {
|
|
|
+ const state = reactive({
|
|
|
+ suggestionTypeList: [] as any,
|
|
|
+
|
|
|
+ loading: false,
|
|
|
+
|
|
|
+ finshed: false, // 是否加载完
|
|
|
+
|
|
|
+ pagination: {
|
|
|
+ page: 1,
|
|
|
+
|
|
|
+ rows: 20
|
|
|
+ },
|
|
|
+
|
|
|
+ searchGroup: {
|
|
|
+ suggestionTypeId: null,
|
|
|
+
|
|
|
+ timer: null as any
|
|
|
+ },
|
|
|
+
|
|
|
+ tableList: [] as any,
|
|
|
+
|
|
|
+ show: false,
|
|
|
+
|
|
|
+ item: {} as any
|
|
|
+ });
|
|
|
+
|
|
|
+ const getList = async () => {
|
|
|
+ try {
|
|
|
+ if (state.pagination.page === 1) {
|
|
|
+ state.loading = true;
|
|
|
+ }
|
|
|
+
|
|
|
+ const { timer, ...res } = state.searchGroup;
|
|
|
+
|
|
|
+ const { data } = await getSysSuggestionList({
|
|
|
+ ...state.searchGroup,
|
|
|
+
|
|
|
+ ...res,
|
|
|
+
|
|
|
+ ...getTimes(timer, ['startTime', 'endTime'])
|
|
|
+ });
|
|
|
+
|
|
|
+ state.loading = false;
|
|
|
+
|
|
|
+ const tempRows = data.rows || [];
|
|
|
+
|
|
|
+ tempRows.forEach((row: any) => {
|
|
|
+ const imgList =
|
|
|
+ (row.attachmentUrls && row.attachmentUrls.split(',')) || [];
|
|
|
+
|
|
|
+ row.imgList = imgList;
|
|
|
+ });
|
|
|
+
|
|
|
+ if (state.pagination.page === 1) {
|
|
|
+ state.tableList = tempRows;
|
|
|
+ } else {
|
|
|
+ state.tableList.push(...tempRows);
|
|
|
+ }
|
|
|
+
|
|
|
+ state.finshed = data.pages <= data.current ? true : false;
|
|
|
+ } catch {
|
|
|
+ state.loading = false;
|
|
|
+ }
|
|
|
+ };
|
|
|
+
|
|
|
+ const throttledFnSearch = useDebounceFn(item => {
|
|
|
+ state.pagination.page = state.pagination.page + 1;
|
|
|
+
|
|
|
+ state.pagination.page = 1;
|
|
|
+
|
|
|
+ state.tableList = [];
|
|
|
+
|
|
|
+ state.searchGroup = Object.assign(state.searchGroup, item);
|
|
|
+
|
|
|
+ getList();
|
|
|
+ }, 100);
|
|
|
+
|
|
|
+ const throttledFn = useThrottleFn(() => {
|
|
|
+ state.pagination.page = state.pagination.page + 1;
|
|
|
+
|
|
|
+ getList();
|
|
|
+ }, 300);
|
|
|
+
|
|
|
+ const getBatchSetRead = async () => {
|
|
|
+ try {
|
|
|
+ await batchSetRead({ messageType: 'SYS_SUGGEST_FEEDBACK_TEACHER' });
|
|
|
+
|
|
|
+ eventGlobal.emit('onSuggestionRead');
|
|
|
+ } catch {
|
|
|
+ //
|
|
|
+ }
|
|
|
+ };
|
|
|
+
|
|
|
+ onMounted(() => {
|
|
|
+ props.typeList.forEach((item: any) => {
|
|
|
+ state.suggestionTypeList.push({
|
|
|
+ label: item.name,
|
|
|
+
|
|
|
+ value: item.id
|
|
|
+ });
|
|
|
+ });
|
|
|
+
|
|
|
+ getBatchSetRead();
|
|
|
+
|
|
|
+ getList();
|
|
|
+ });
|
|
|
+
|
|
|
+ return () => (
|
|
|
+ <div class={styles.suggestionList}>
|
|
|
+ <div class={styles.attendClassSearch}>
|
|
|
+ <NSelect
|
|
|
+ placeholder="反馈类型"
|
|
|
+ clearable
|
|
|
+ options={
|
|
|
+ [
|
|
|
+ { label: '反馈类型', value: null },
|
|
|
+
|
|
|
+ ...state.suggestionTypeList
|
|
|
+ ] as any
|
|
|
+ }
|
|
|
+ v-model:value={state.searchGroup.suggestionTypeId}
|
|
|
+ />
|
|
|
+
|
|
|
+ <CDatePicker
|
|
|
+ v-model:value={state.searchGroup.timer}
|
|
|
+ separator={'至'}
|
|
|
+ start-placeholder="反馈开始日期"
|
|
|
+ end-placeholder="反馈结束日期"
|
|
|
+ type="daterange"
|
|
|
+ clearable={true}
|
|
|
+ timerValue={state.searchGroup.timer}></CDatePicker>
|
|
|
+
|
|
|
+ <NButton type="primary" class="searchBtn" onClick={throttledFnSearch}>
|
|
|
+ 搜索
|
|
|
+ </NButton>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <NScrollbar
|
|
|
+ class={styles.classList}
|
|
|
+ onScroll={(e: any) => {
|
|
|
+ const clientHeight = e.target?.clientHeight;
|
|
|
+
|
|
|
+ const scrollTop = e.target?.scrollTop;
|
|
|
+
|
|
|
+ const scrollHeight = e.target?.scrollHeight;
|
|
|
+
|
|
|
+ // 是否到底,是否加载完
|
|
|
+
|
|
|
+ if (
|
|
|
+ clientHeight + scrollTop + 20 >= scrollHeight &&
|
|
|
+ !state.finshed &&
|
|
|
+ !state.loading
|
|
|
+ ) {
|
|
|
+ throttledFn();
|
|
|
+ }
|
|
|
+ }}>
|
|
|
+ <NSpin show={state.loading}>
|
|
|
+ <div
|
|
|
+ class={[
|
|
|
+ styles.listSection,
|
|
|
+
|
|
|
+ !state.loading && state.tableList.length <= 0
|
|
|
+ ? styles.emptySection
|
|
|
+ : ''
|
|
|
+ ]}>
|
|
|
+ {state.tableList.map((item: any) => (
|
|
|
+ <div>
|
|
|
+ <NThing class={[styles.thingItem, 'isFull']}>
|
|
|
+ <div class={styles.item}>
|
|
|
+ <span>反馈类型:</span>
|
|
|
+
|
|
|
+ {item.suggestionTypeName}
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div class={styles.item}>
|
|
|
+ <span>反馈内容:</span>
|
|
|
+
|
|
|
+ {item.content}
|
|
|
+ </div>
|
|
|
+
|
|
|
+ {item.imgList && item.imgList.length > 0 && (
|
|
|
+ <div class={styles.item}>
|
|
|
+ <NImageGroup class={styles.IMageWraps}>
|
|
|
+ {item.imgList?.map((item: any, index: number) => (
|
|
|
+ <NImage
|
|
|
+ class={[styles.ShowImg]}
|
|
|
+ src={item}
|
|
|
+ objectFit="cover"></NImage>
|
|
|
+ ))}
|
|
|
+ </NImageGroup>
|
|
|
+ </div>
|
|
|
+ )}
|
|
|
+
|
|
|
+ {item.handleStatus && (
|
|
|
+ <div class={styles.itemResult}>
|
|
|
+ <span>处理结果:</span>
|
|
|
+
|
|
|
+ {item.handleAttitude === 'NO'
|
|
|
+ ? '感谢你对音乐数字课堂的关注与支持,我们会认真处理您的反馈,尽快修复和完善相关功能!'
|
|
|
+ : item.feedbackContent}
|
|
|
+ </div>
|
|
|
+ )}
|
|
|
+ </NThing>
|
|
|
+ </div>
|
|
|
+ ))}
|
|
|
+
|
|
|
+ {!state.loading && state.tableList.length <= 0 && <TheEmpty />}
|
|
|
+ </div>
|
|
|
+ </NSpin>
|
|
|
+ </NScrollbar>
|
|
|
+ </div>
|
|
|
+ );
|
|
|
+ }
|
|
|
+});
|
|
|
+
|