suggestion-list.tsx 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199
  1. import { PropType, defineComponent, onMounted, reactive, ref } from 'vue';
  2. import styles from './suggestion-list.module.less';
  3. import {
  4. NInput,
  5. NSelect,
  6. NScrollbar,
  7. NSpin,
  8. NThing,
  9. NImageGroup,
  10. NSpace,
  11. NImage,
  12. NButton
  13. } from 'naive-ui';
  14. import { batchSetRead, getSysSuggestionList } from './api';
  15. import CDatePicker from '../../CDatePicker';
  16. import TheEmpty from '../../TheEmpty';
  17. import { useDebounceFn, useThrottleFn } from '@vueuse/core';
  18. import { eventGlobal, getTimes } from '/src/utils';
  19. export default defineComponent({
  20. name: 'suggestion-list',
  21. props: {
  22. typeList: {
  23. type: Array as PropType<any[]>,
  24. default: () => []
  25. }
  26. },
  27. setup(props) {
  28. const state = reactive({
  29. suggestionTypeList: [] as any,
  30. loading: false,
  31. finshed: false, // 是否加载完
  32. pagination: {
  33. page: 1,
  34. rows: 20
  35. },
  36. searchGroup: {
  37. suggestionTypeId: null,
  38. timer: null as any
  39. },
  40. tableList: [] as any,
  41. show: false,
  42. item: {} as any
  43. });
  44. const getList = async () => {
  45. try {
  46. if (state.pagination.page === 1) {
  47. state.loading = true;
  48. }
  49. const { timer, ...res } = state.searchGroup;
  50. const { data } = await getSysSuggestionList({
  51. ...state.searchGroup,
  52. ...res,
  53. ...getTimes(timer, ['startTime', 'endTime'])
  54. });
  55. state.loading = false;
  56. const tempRows = data.rows || [];
  57. tempRows.forEach((row: any) => {
  58. const imgList =
  59. (row.attachmentUrls && row.attachmentUrls.split(',')) || [];
  60. row.imgList = imgList;
  61. });
  62. if (state.pagination.page === 1) {
  63. state.tableList = tempRows;
  64. } else {
  65. state.tableList.push(...tempRows);
  66. }
  67. state.finshed = data.pages <= data.current ? true : false;
  68. } catch {
  69. state.loading = false;
  70. }
  71. };
  72. const throttledFnSearch = useDebounceFn(item => {
  73. state.pagination.page = state.pagination.page + 1;
  74. state.pagination.page = 1;
  75. state.tableList = [];
  76. state.searchGroup = Object.assign(state.searchGroup, item);
  77. getList();
  78. }, 100);
  79. const throttledFn = useThrottleFn(() => {
  80. state.pagination.page = state.pagination.page + 1;
  81. getList();
  82. }, 500);
  83. const getBatchSetRead = async () => {
  84. try {
  85. await batchSetRead({ messageType: 'SYS_SUGGEST_FEEDBACK_TEACHER' });
  86. eventGlobal.emit('onSuggestionRead');
  87. } catch {
  88. //
  89. }
  90. };
  91. onMounted(() => {
  92. props.typeList.forEach((item: any) => {
  93. state.suggestionTypeList.push({
  94. label: item.name,
  95. value: item.id
  96. });
  97. });
  98. getBatchSetRead();
  99. getList();
  100. });
  101. return () => (
  102. <div class={styles.suggestionList}>
  103. <div class={styles.attendClassSearch}>
  104. <NSelect
  105. placeholder="反馈类型"
  106. clearable
  107. options={
  108. [
  109. { label: '反馈类型', value: null },
  110. ...state.suggestionTypeList
  111. ] as any
  112. }
  113. v-model:value={state.searchGroup.suggestionTypeId}
  114. />
  115. <CDatePicker
  116. v-model:value={state.searchGroup.timer}
  117. separator={'至'}
  118. start-placeholder="反馈开始日期"
  119. end-placeholder="反馈结束日期"
  120. type="daterange"
  121. clearable={true}
  122. timerValue={state.searchGroup.timer}></CDatePicker>
  123. <NButton type="primary" class="searchBtn" onClick={throttledFnSearch}>
  124. 搜索
  125. </NButton>
  126. </div>
  127. <NScrollbar
  128. class={styles.classList}
  129. onScroll={(e: any) => {
  130. const clientHeight = e.target?.clientHeight;
  131. const scrollTop = e.target?.scrollTop;
  132. const scrollHeight = e.target?.scrollHeight;
  133. // 是否到底,是否加载完
  134. if (
  135. clientHeight + scrollTop + 20 >= scrollHeight &&
  136. !state.finshed &&
  137. !state.loading
  138. ) {
  139. throttledFn();
  140. }
  141. }}>
  142. <NSpin show={state.loading}>
  143. <div
  144. class={[
  145. styles.listSection,
  146. !state.loading && state.tableList.length <= 0
  147. ? styles.emptySection
  148. : ''
  149. ]}>
  150. {state.tableList.map((item: any) => (
  151. <div>
  152. <NThing class={[styles.thingItem, 'isFull']}>
  153. <div class={styles.item}>
  154. <span>反馈类型:</span>
  155. {item.suggestionTypeName}
  156. </div>
  157. <div class={styles.item}>
  158. <span>反馈内容:</span>
  159. {item.content}
  160. </div>
  161. {item.imgList && item.imgList.length > 0 && (
  162. <div class={styles.item}>
  163. <NImageGroup class={styles.IMageWraps}>
  164. {item.imgList?.map((item: any, index: number) => (
  165. <NImage
  166. class={[styles.ShowImg]}
  167. src={item}
  168. objectFit="cover"></NImage>
  169. ))}
  170. </NImageGroup>
  171. </div>
  172. )}
  173. {item.handleStatus && (
  174. <div class={styles.itemResult}>
  175. <span>处理结果:</span>
  176. {item.handleAttitude === 'NO'
  177. ? '感谢你对音乐数字课堂的关注与支持,我们会认真处理您的反馈,尽快修复和完善相关功能!'
  178. : item.feedbackContent}
  179. </div>
  180. )}
  181. </NThing>
  182. </div>
  183. ))}
  184. {!state.loading && state.tableList.length <= 0 && <TheEmpty />}
  185. </div>
  186. </NSpin>
  187. </NScrollbar>
  188. </div>
  189. );
  190. }
  191. });