index.vue 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  1. <script setup lang="ts">
  2. import { onMounted, ref, watch } from 'vue'
  3. import type { Article, ArticleSearchFilter } from '@/model/article'
  4. import RegularPage from '@/components/RegularPage.vue'
  5. import {
  6. searchArticlesRequest,
  7. deleteArticlesRequest,
  8. publishArticlesByIdRequest,
  9. closeArticlesByIdRequest
  10. } from '@/api/article'
  11. import { searchCategoryListRequest } from '@/api/category'
  12. import type { Category } from '@/model/category'
  13. import type { BaseTableColumns } from 'tdesign-vue-next'
  14. import { useSearchable } from '@/composables/useSearchable'
  15. import ArticleDialog from '@/pages/article/components/ArticleDialog.vue'
  16. import { MessagePlugin } from 'tdesign-vue-next'
  17. const { data, loading, pagination, onPageChange, fetchData } = useSearchable<
  18. ArticleSearchFilter,
  19. Article
  20. >(searchArticlesRequest)
  21. const statusArticleListMap = {
  22. draft: { label: '草稿', theme: 'default' },
  23. published: { label: '已发布', theme: 'success' },
  24. closed: { label: '已关闭', theme: 'danger' }
  25. }
  26. const columns: BaseTableColumns = [
  27. {
  28. title: '咨询标题',
  29. colKey: 'title',
  30. width: 100
  31. },
  32. {
  33. title: '分类',
  34. colKey: 'categoryName',
  35. width: 100
  36. },
  37. {
  38. title: '状态',
  39. colKey: 'status',
  40. width: 100
  41. },
  42. {
  43. title: '创建时间',
  44. colKey: 'createdTime',
  45. width: 100
  46. },
  47. {
  48. title: '操作',
  49. colKey: 'operation',
  50. width: 100
  51. }
  52. ]
  53. const articleDialogVisble = ref(false)
  54. const isEdit = ref(false)
  55. const currentTableData = ref<Article | {}>({})
  56. const categoryList = ref<Category[]>([])
  57. onMounted(fetchData)
  58. watch(articleDialogVisble, (newValue) => {
  59. if (newValue) {
  60. searchCategoryList()
  61. }
  62. })
  63. const searchCategoryList = async () => {
  64. try {
  65. const res = await searchCategoryListRequest()
  66. categoryList.value = res
  67. } catch (error) {
  68. categoryList.value = []
  69. }
  70. }
  71. const editClick = (article: Article) => {
  72. isEdit.value = true
  73. currentTableData.value = article
  74. articleDialogVisble.value = true
  75. }
  76. const handleArticleDialogSuccess = () => {
  77. fetchData()
  78. articleDialogVisble.value = false
  79. }
  80. const handleArticleDialogClosed = () => {
  81. isEdit.value = false
  82. currentTableData.value = {}
  83. }
  84. const toggleArticleStatus = async (article: Article) => {
  85. if (article.status === 'published') {
  86. await closeArticlesByIdRequest(article.id)
  87. } else {
  88. await publishArticlesByIdRequest(article.id)
  89. }
  90. fetchData()
  91. MessagePlugin.success(`${article.status === 'published' ? '关闭' : '发布'}咨询成功`)
  92. }
  93. const deleteCategoryClick = async (article: Article) => {
  94. await deleteArticlesRequest(article.id)
  95. fetchData()
  96. MessagePlugin.success('删除咨询成功')
  97. }
  98. </script>
  99. <template>
  100. <RegularPage title="咨询管理">
  101. <template #right-area>
  102. <TButton @click="articleDialogVisble = true">创建咨询</TButton>
  103. </template>
  104. <TTable
  105. class="w-full h-full"
  106. row-key="id"
  107. height="92%"
  108. table-layout="auto"
  109. :data="data"
  110. :loading="loading"
  111. :columns="columns"
  112. cell-empty-content="-"
  113. :paginationAffixedBottom="true"
  114. :pagination="{
  115. total: pagination.total,
  116. current: pagination.page,
  117. pageSize: pagination.size,
  118. onChange: onPageChange
  119. }"
  120. >
  121. <template #categoryName="{ row }">
  122. {{ row.category.name }}
  123. </template>
  124. <template #status="{ row }">
  125. <t-tag :theme="statusArticleListMap[row.status as keyof typeof statusArticleListMap].theme">
  126. {{ statusArticleListMap[row.status as keyof typeof statusArticleListMap].label }}
  127. </t-tag>
  128. </template>
  129. <template #operation="{ row }">
  130. <TSpace :size="1">
  131. <TButton variant="text" size="small" theme="primary" @click="editClick(row)"
  132. >编辑</TButton
  133. >
  134. <TButton variant="text" size="small" theme="warning" @click="toggleArticleStatus(row)">{{
  135. row.status === 'published' ? '关闭' : '发布'
  136. }}</TButton>
  137. <t-popconfirm
  138. theme="default"
  139. content="确认删除此项分类吗"
  140. @confirm="deleteCategoryClick(row)"
  141. >
  142. <TButton variant="text" size="small" theme="danger">删除</TButton>
  143. </t-popconfirm>
  144. </TSpace>
  145. </template>
  146. </TTable>
  147. <ArticleDialog
  148. headerTitle="咨询"
  149. :isEdit="isEdit"
  150. :article="currentTableData"
  151. :categoryList="categoryList"
  152. v-model:visible="articleDialogVisble"
  153. @closed="handleArticleDialogClosed"
  154. @success="handleArticleDialogSuccess"
  155. ></ArticleDialog>
  156. </RegularPage>
  157. </template>
  158. <style scoped>
  159. :deep(.t-card__body) {
  160. flex: 1;
  161. min-height: 0;
  162. }
  163. </style>