FamilyList.vue 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121
  1. <template>
  2. <div class="family-list admin-page">
  3. <el-card>
  4. <div slot="header" style="display:flex;justify-content:space-between;align-items:center">
  5. <span>我的家庭</span>
  6. <el-input v-model="keyword" placeholder="搜索家庭..." prefix-icon="el-icon-search" style="width:200px" clearable @keyup.enter.native="handleSearch" @clear="handleSearch" />
  7. </div>
  8. <el-table :data="filteredFamilies" v-loading="loading" border stripe :max-height="tableHeight">
  9. <el-table-column prop="id" label="ID" width="80">
  10. <template slot="header">
  11. <span class="sort-header" @click.stop="onSortClick('id', $event)" @dblclick.stop="onSortToggle('id')">ID<span v-if="sortIndex('id') !== null" class="sort-index" :class="sortClass('id') === 'sort-asc' ? 'sort-asc-badge' : 'sort-desc-badge'">{{ sortIndex('id') }}</span>{{ sortIcon('id') }}</span>
  12. </template>
  13. </el-table-column>
  14. <el-table-column prop="familyName" label="家庭名称">
  15. <template slot="header">
  16. <span class="sort-header" @click.stop="onSortClick('familyName', $event)">家庭名称<span v-if="sortIndex('familyName') !== null" class="sort-index" :class="sortClass('familyName') === 'sort-asc' ? 'sort-asc-badge' : 'sort-desc-badge'">{{ sortIndex('familyName') }}</span>{{ sortIcon('familyName') }}</span>
  17. </template>
  18. </el-table-column>
  19. <el-table-column prop="memberCount" label="成员数" width="100">
  20. <template slot="header">
  21. <span class="sort-header" @click.stop="onSortClick('memberCount', $event)">成员数<span v-if="sortIndex('memberCount') !== null" class="sort-index" :class="sortClass('memberCount') === 'sort-asc' ? 'sort-asc-badge' : 'sort-desc-badge'">{{ sortIndex('memberCount') }}</span>{{ sortIcon('memberCount') }}</span>
  22. </template>
  23. </el-table-column>
  24. <el-table-column prop="createdAt" label="绑定时间" width="180">
  25. <template slot="header">
  26. <span class="sort-header" @click.stop="onSortClick('createdAt', $event)" @dblclick.stop="onSortToggle('createdAt')">绑定时间<span v-if="sortIndex('createdAt') !== null" class="sort-index" :class="sortClass('createdAt') === 'sort-asc' ? 'sort-asc-badge' : 'sort-desc-badge'">{{ sortIndex('createdAt') }}</span>{{ sortIcon('createdAt') }}</span>
  27. </template>
  28. </el-table-column>
  29. <el-table-column label="操作" width="200" fixed="right">
  30. <template slot-scope="{ row }">
  31. <el-button size="mini" type="primary" @click="handleEdit(row)">编辑</el-button>
  32. <el-dropdown trigger="hover" @command="(cmd) => handleActionCmd(row, cmd)">
  33. <el-button size="mini">
  34. 更多<i class="el-icon-arrow-down el-icon--right"></i>
  35. </el-button>
  36. <el-dropdown-menu slot="dropdown">
  37. <el-dropdown-item command="view" icon="el-icon-view">查看详情</el-dropdown-item>
  38. <el-dropdown-item command="delete" icon="el-icon-delete">删除</el-dropdown-item>
  39. </el-dropdown-menu>
  40. </el-dropdown>
  41. </template>
  42. </el-table-column>
  43. </el-table>
  44. </el-card>
  45. </div>
  46. </template>
  47. <script>
  48. import SortMixin from '@/mixins/SortMixin'
  49. export default {
  50. mixins: [SortMixin],
  51. name: 'FamilyList',
  52. data() {
  53. return { loading: false, families: [], keyword: '', sortableColumns: { id: 'ID', createdAt: '绑定时间', familyName: '家庭名称', memberCount: '成员数' } }
  54. },
  55. computed: {
  56. tableHeight() {
  57. return window.innerHeight - 320
  58. },
  59. filteredFamilies() {
  60. if (!this.keyword) return this.families
  61. const kw = this.keyword.toLowerCase()
  62. return this.families.filter(f =>
  63. (f.familyName || '').toLowerCase().includes(kw) ||
  64. String(f.id).includes(kw)
  65. )
  66. }
  67. },
  68. created() { this.loadFamilies() },
  69. methods: {
  70. handleSearch() {
  71. },
  72. loadList() {
  73. this.loadFamilies()
  74. },
  75. async loadFamilies() {
  76. this.loading = true
  77. try {
  78. const token = localStorage.getItem('token')
  79. const baseURL = process.env.VUE_APP_BASE_API || ''
  80. const axios = this.$axios || (await import('axios')).default
  81. const params = {}
  82. if (this.sortState.length > 0) params.sort = this.sortState
  83. const res = await axios.post(baseURL + '/api/guide/family/list', params, {
  84. headers: { Authorization: 'Bearer ' + token }
  85. })
  86. this.families = res.data?.data || []
  87. } catch (e) {
  88. this.$message?.error?.('加载家庭列表失败')
  89. } finally {
  90. this.loading = false
  91. }
  92. },
  93. viewFamily(row) {
  94. this.$router.push('/my-families/' + row.id)
  95. },
  96. handleEdit(row) {
  97. this.viewFamily(row)
  98. },
  99. handleActionCmd(row, cmd) {
  100. switch (cmd) {
  101. case 'view': this.viewFamily(row); break
  102. case 'edit': this.handleEdit(row); break
  103. case 'delete': this.$confirm('确认删除该家庭吗?', '提示', { type: 'warning' }).then(() => {}).catch(() => {}); break
  104. }
  105. }
  106. }
  107. }
  108. </script>
  109. <style scoped>
  110. .sort-header {
  111. cursor: pointer;
  112. user-select: none;
  113. font-weight: 500;
  114. font-size: 12px;
  115. }
  116. .sort-header:hover {
  117. color: #409eff;
  118. }
  119. </style>