index.vue 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  1. <template>
  2. <CommonPage>
  3. <template #action>
  4. <NButton type="primary" @click="router.push('article/add')">
  5. <i class="i-material-symbols:add mr-4 text-18"/>
  6. 新增文章
  7. </NButton>
  8. </template>
  9. <MeCrud ref="$table" v-model:query-items="queryItems" :scroll-x="1200" :columns="columns" :get-data="api.read">
  10. <MeQueryItem label="标题" :label-width="50">
  11. <n-input v-model:value="queryItems.title" type="text" placeholder="请输入标题名" clearable>
  12. <template #password-visible-icon/>
  13. </n-input>
  14. </MeQueryItem>
  15. <MeQueryItem label="状态" :label-width="50">
  16. <n-select
  17. v-model:value="queryItems.enable" clearable :options="[
  18. { label: '启用', value: 1 },
  19. { label: '停用', value: 0 },
  20. ]"
  21. />
  22. </MeQueryItem>
  23. </MeCrud>
  24. </CommonPage>
  25. </template>
  26. <script setup>
  27. import {MeCrud, MeQueryItem} from '@/components'
  28. import {useCrud} from '@/composables'
  29. import {formatDateTime} from '@/utils'
  30. import {NButton, NSwitch} from 'naive-ui'
  31. import api from './api'
  32. defineOptions({name: 'RoleMgt'})
  33. const router = useRouter()
  34. const $table = ref(null)
  35. /** QueryBar筛选参数(可选) */
  36. const queryItems = ref({})
  37. onMounted(() => {
  38. $table.value?.handleSearch()
  39. })
  40. const {handleDelete}
  41. = useCrud({
  42. name: '文章',
  43. doCreate: api.create,
  44. doDelete: api.delete,
  45. doUpdate: api.update,
  46. initForm: {enable: true},
  47. refresh: (_, keepCurrentPage) => $table.value?.handleSearch(keepCurrentPage),
  48. })
  49. const columns = [
  50. {title: '标题名', key: 'title', width: '200'},
  51. {title: '分类', key: 'category.title'},
  52. {
  53. title: '内容',
  54. key: 'content',
  55. width: '400',
  56. render: row => h('div', htmlspecialchars(row.translations?.length ? row.translations.find(i => i.locale === 'zh').content : row.content)),
  57. },
  58. {
  59. title: '创建时间',
  60. key: 'createTime',
  61. render: row => h('span', formatDateTime(row.createTime)),
  62. },
  63. {
  64. title: '状态',
  65. key: 'enable',
  66. render: row =>
  67. h(
  68. NSwitch,
  69. {
  70. size: 'small',
  71. rubberBand: false,
  72. value: row.enable,
  73. loading: !!row.enableLoading,
  74. disabled: row.code === 'SUPER_ADMIN',
  75. onUpdateValue: () => handleEnable(row),
  76. },
  77. {
  78. checked: () => '启用',
  79. unchecked: () => '停用',
  80. },
  81. ),
  82. },
  83. {
  84. title: '操作',
  85. key: 'actions',
  86. width: 200,
  87. align: 'center',
  88. fixed: 'right',
  89. render(row) {
  90. return [
  91. h(
  92. NButton,
  93. {
  94. size: 'small',
  95. type: 'primary',
  96. style: 'margin-left: 12px;',
  97. disabled: row.code === 'SUPER_ADMIN',
  98. onClick: () => handleEdit(row),
  99. },
  100. {
  101. default: () => '编辑',
  102. icon: () => h('i', {class: 'i-material-symbols:edit-outline text-14'}),
  103. },
  104. ),
  105. h(
  106. NButton,
  107. {
  108. size: 'small',
  109. type: 'error',
  110. style: 'margin-left: 12px;',
  111. disabled: row.code === 'SUPER_ADMIN',
  112. onClick: () => handleDelete(row.id),
  113. },
  114. {
  115. default: () => '删除',
  116. icon: () => h('i', {class: 'i-material-symbols:delete-outline text-14'}),
  117. },
  118. ),
  119. ]
  120. },
  121. },
  122. ]
  123. async function handleEnable(row) {
  124. row.enableLoading = true
  125. try {
  126. await api.update({id: row.id, enable: !row.enable})
  127. row.enableLoading = false
  128. $message.success('操作成功')
  129. $table.value?.handleSearch()
  130. } catch (error) {
  131. console.error(error)
  132. row.enableLoading = false
  133. }
  134. }
  135. function htmlspecialchars(str) {
  136. const div = document.createElement('div')
  137. div.innerHTML = str
  138. const text = div.textContent || ''
  139. return text.length > 150 ? `${text.substring(0, 150)}...` : text
  140. }
  141. function handleEdit(row) {
  142. router.push(`/article/edit/${row.id}`)
  143. }
  144. </script>