index.vue 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244
  1. <template>
  2. <a-card :bordered="false">
  3. <a-space>
  4. <a-input-search
  5. v-model:value="searchFormState.postTitle"
  6. placeholder="请输入名称关键词"
  7. enter-button
  8. allowClear
  9. @search="onSearch"
  10. />
  11. <a-select
  12. v-model:value="typeValue"
  13. show-search
  14. placeholder="所有分类"
  15. style="width: 200px"
  16. :options="typeOptions"
  17. :filter-option="filterOption"
  18. @change="handleChange"
  19. ></a-select>
  20. <a-select
  21. v-model:value="typeValueEx"
  22. allowClear
  23. placeholder="请选择"
  24. style="width: 200px"
  25. :options="typeOptionsEx"
  26. @change="handleChangeEx"
  27. ></a-select>
  28. <a-radio-group v-model:value="searchFormState.sortOrder" button-style="solid">
  29. <a-radio-button
  30. v-for="module in moduleTypeList"
  31. :key="module.id"
  32. :value="module.id"
  33. @click="moduleClock(module.id)"
  34. >
  35. {{ module.title }}
  36. </a-radio-button>
  37. </a-radio-group>
  38. <a-button type="primary" @click="formRef.onOpen(undefined, searchFormState.sortOrder)">
  39. <template #icon><plus-outlined /></template>
  40. 创建新主题
  41. </a-button>
  42. </a-space>
  43. <s-table ref="table" :columns="columns" :data="loadData" :row-key="(record) => record.id" :custom-row="customRow">
  44. <template #bodyCell="{ column, record }">
  45. <template v-if="column.dataIndex === 'postTitle'">
  46. <div class="forum-list-title">{{ record.postTitle }}</div>
  47. <div class="forum-list-type">{{ record.typeName }}</div>
  48. <div class="forum-list-content one-line" v-html="record.postContent"></div>
  49. </template>
  50. <template v-if="column.dataIndex === 'lastReplyUserAvatar'">
  51. <a-tooltip :title="record.lastReplyUserNickName" placement="top">
  52. <a-avatar :src="record.lastReplyUserAvatar"></a-avatar>
  53. </a-tooltip>
  54. </template>
  55. <template v-if="column.dataIndex === 'lastReplyTime'">
  56. <div>{{ formatDateTime(record.lastReplyTime) }}</div>
  57. </template>
  58. </template>
  59. </s-table>
  60. </a-card>
  61. <Form ref="formRef" @successful="table.refresh(true)" />
  62. </template>
  63. <script setup name="forumList">
  64. import forumApi from '@/api/forum/forumApi'
  65. import Form from './form.vue'
  66. import { parseTime } from '@/utils/exam'
  67. import { useRoute, useRouter } from 'vue-router'
  68. const route = useRoute()
  69. const router = useRouter()
  70. const formRef = ref()
  71. let searchFormState = reactive({
  72. sortOrder: 0,
  73. postTitle: '',
  74. postType: route.query.postType ?? null
  75. })
  76. const table = ref(null)
  77. const moduleTypeList = ref([
  78. {
  79. title: '最新',
  80. id: 0
  81. },
  82. {
  83. title: '热门',
  84. id: 1
  85. }
  86. ])
  87. const columns = [
  88. {
  89. title: '主题',
  90. dataIndex: 'postTitle'
  91. },
  92. {
  93. title: '最后回复人',
  94. dataIndex: 'lastReplyUserAvatar',
  95. align: 'center',
  96. width: 100
  97. },
  98. {
  99. title: '回复量',
  100. dataIndex: 'replyCount',
  101. align: 'center',
  102. width: 100
  103. },
  104. {
  105. title: '浏览量',
  106. dataIndex: 'viewCount',
  107. align: 'center',
  108. width: 100
  109. },
  110. {
  111. title: '最后回复时间',
  112. dataIndex: 'lastReplyTime',
  113. align: 'center',
  114. width: 120
  115. }
  116. ]
  117. const typeValue = ref('所有分类')
  118. const typeOptions = ref([])
  119. const handleChange = (value) => {
  120. exType.value = false
  121. typeValueEx.value = ''
  122. searchFormState.typeId = value
  123. table.value.refresh(true)
  124. }
  125. const filterOption = (input, option) => {
  126. return option.value.toLowerCase().indexOf(input.toLowerCase()) >= 0
  127. }
  128. function formatDateTime(val) {
  129. if (!val) return ''
  130. return parseTime(val, '{y}-{m}-{d} {h}:{i}:{s}')
  131. }
  132. // 查询
  133. const onSearch = () => {
  134. typeValueEx.value = ''
  135. exType.value = false
  136. table.value.refresh(true)
  137. }
  138. function customRow(record) {
  139. return {
  140. onClick: () => itemSelect(record)
  141. }
  142. }
  143. function itemSelect(record) {
  144. router.push({
  145. path: '/forum/detail',
  146. query: {
  147. postId: record.postId,
  148. postType: route.query.postType ?? ''
  149. }
  150. })
  151. }
  152. function getTypeList() {
  153. forumApi.forumTypeList().then((data) => {
  154. typeOptions.value = data.map((r) => {
  155. return {
  156. label: r.typeName,
  157. value: r.typeId,
  158. ...r
  159. }
  160. })
  161. })
  162. }
  163. getTypeList()
  164. const typeValueEx = ref('')
  165. const exType = ref(false)
  166. const typeOptionsEx = ref([
  167. {
  168. label: '我发布的',
  169. value: 1
  170. },
  171. {
  172. label: '我回复的',
  173. value: 2
  174. },
  175. {
  176. label: '关于我的',
  177. value: 3
  178. },
  179. {
  180. label: '我点赞的',
  181. value: 4
  182. }
  183. ])
  184. const handleChangeEx = (value) => {
  185. if (value) {
  186. exType.value = true
  187. } else {
  188. exType.value = false
  189. typeValueEx.value = ''
  190. }
  191. table.value.refresh(true)
  192. }
  193. const loadData = (parameter) => {
  194. if (exType.value) {
  195. return forumApi.moreList(Object.assign(parameter, {postExtend:typeValueEx.value})).then((data) => {
  196. if (data) {
  197. return data
  198. } else {
  199. return []
  200. }
  201. })
  202. } else {
  203. return forumApi.forumList(Object.assign(parameter, searchFormState)).then((data) => {
  204. if (data) {
  205. return data
  206. } else {
  207. return []
  208. }
  209. })
  210. }
  211. }
  212. // 切换应用标签查询菜单列表
  213. const moduleClock = (value) => {
  214. exType.value = false
  215. typeValueEx.value = ''
  216. searchFormState.sortOrder = value
  217. table.value.refresh(true)
  218. }
  219. </script>
  220. <style scoped>
  221. .forum-list-title {
  222. font-size: 16px;
  223. font-weight: bold;
  224. }
  225. .forum-list-type {
  226. font-size: 12px;
  227. }
  228. .forum-list-content {
  229. font-size: 14px;
  230. color: #696969;
  231. }
  232. .one-line {
  233. display: -webkit-box;
  234. -webkit-box-orient: vertical;
  235. -webkit-line-clamp: 1;
  236. overflow: hidden;
  237. }
  238. </style>