index.vue 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214
  1. <!-- 学校关系管理 -->
  2. <!-- art-full-height 自动计算出页面剩余高度 -->
  3. <!-- art-table-card 一个符合系统样式的 class,同时自动撑满剩余高度 -->
  4. <!-- 更多 useTable 使用示例请移步至 功能示例 下面的 高级表格示例 -->
  5. <template>
  6. <div class="user-page art-full-height">
  7. <!-- 搜索栏 -->
  8. <UserSearch
  9. v-model="searchForm"
  10. @search="handleSearch"
  11. @reset="resetSearchParams"
  12. :selectList="selectList"
  13. ></UserSearch>
  14. <ElCard class="art-table-card" shadow="never">
  15. <!-- 表格头部 -->
  16. <ArtTableHeader v-model:columns="columnChecks" @refresh="refreshData">
  17. <template #left>
  18. <ElButton type="primary" @click="follow()" v-ripple v-auth="130301">新增跟进记录</ElButton>
  19. </template>
  20. </ArtTableHeader>
  21. <!-- 表格 -->
  22. <ArtTable
  23. :loading="loading"
  24. :data="data"
  25. :columns="columns"
  26. :pagination="pagination"
  27. @pagination:size-change="handleSizeChange"
  28. @pagination:current-change="handleCurrentChange"
  29. >
  30. </ArtTable>
  31. <!-- 跟进弹窗 -->
  32. <FollowDialog
  33. v-model:visible="followDialogVisible"
  34. :user-data="currentUserData"
  35. :type="'canteen'"
  36. :first_id="0"
  37. :second_id="0"
  38. :selectList="selectList"
  39. @submit="handleDialogSubmit"
  40. />
  41. </ElCard>
  42. </div>
  43. </template>
  44. <script setup lang="ts">
  45. import ArtButtonTable from '@/components/core/forms/art-button-table/index.vue'
  46. import {ElMessageBox, ElMessage, ElTag, ElImage, ElButton} from 'element-plus'
  47. import { useTable } from '@/composables/useTable'
  48. import UserSearch from './modules/user-search.vue'
  49. import { followApi } from '@/api/followApi'
  50. import {RoutesAlias} from "@/router/routesAlias";
  51. import {router} from "@/router";
  52. import {canteenApi} from "@/api/canteenApi";
  53. import {commonApi} from "@/api/commonApi";
  54. import { detectDeviceType } from '@/utils'
  55. defineOptions({ name: 'CanteenFollow' })
  56. type ListItem = Api.Canteen.ListItem
  57. // 弹窗相关
  58. const dialogVisible = ref(false)
  59. const followDialogVisible = ref(false)
  60. const currentUserData = ref<Partial<ListItem>>({})
  61. // 搜索表单
  62. const searchForm = ref({
  63. name: '',
  64. phone: '',
  65. company_id: parseInt(<string>useRoute().query.company_id) || '',
  66. date: useRoute().query.date || '',
  67. })
  68. const selectList = ref<Api.Common.SelectRelationInfo[]>([])
  69. const getSelectList = async () => {
  70. await commonApi.selectList(['school_canteen']).then(res => {
  71. selectList.value = res.school_canteen || []
  72. })
  73. }
  74. getSelectList()
  75. const {
  76. columns,
  77. columnChecks,
  78. data,
  79. loading,
  80. pagination,
  81. getData,
  82. searchParams,
  83. resetSearchParams,
  84. handleSizeChange,
  85. handleCurrentChange,
  86. refreshData
  87. } = useTable<Api.Follow.FollowInfo>({
  88. // 核心配置
  89. core: {
  90. apiFn: followApi.canteenList,
  91. apiParams: {
  92. current: 1,
  93. size: 20,
  94. ...searchForm.value
  95. },
  96. // 排除 apiParams 中的属性
  97. excludeParams: ['daterange'],
  98. columnsFactory: () => [
  99. { prop:'first_name', label:'校园(园区)' },
  100. { prop:'second_name', label:'食堂' },
  101. { prop:'phone', label:'手机号' },
  102. { prop:'weixin', label:'微信号' },
  103. { prop:'chat_imgs', label:'微信聊天记录', formatter: (row) => {
  104. return h(ElImage, {
  105. src: row.chat_imgs[0] + '!max100',
  106. previewSrcList: row.chat_imgs,
  107. showProgress: true,
  108. fit: "cover",
  109. title: `点击预览全部图片,共${row.chat_imgs.length}张`,
  110. style: {"max-width": "50px", "max-height": "50px"},
  111. // 图片预览是否插入至 body 元素上,用于解决表格内部图片预览样式异常
  112. previewTeleported: true
  113. })
  114. }
  115. },
  116. { prop:'user_name', label:'跟进人员' },
  117. { prop:'create_date', label:'跟进时间' },
  118. {
  119. prop: 'operation',
  120. label: '操作',
  121. width: detectDeviceType() == 'Mobile' ? 60 : 120,
  122. fixed: 'right', // 固定列
  123. formatter: (row) =>
  124. h('div', [
  125. h(ArtButtonTable, {
  126. type: 'view',
  127. onClick: () => view(row.id)
  128. }),
  129. ])
  130. }
  131. ]
  132. }
  133. })
  134. /**
  135. * 查看
  136. */
  137. const view = (id: number): void => {
  138. router.push({
  139. path: RoutesAlias.CanteenFollowInfo,
  140. query: {
  141. id: id
  142. }
  143. })
  144. }
  145. /**
  146. * 搜索处理
  147. * @param params 参数
  148. */
  149. const handleSearch = (params: Record<string, any>) => {
  150. Object.assign(searchParams, { ...params })
  151. getData()
  152. }
  153. /**
  154. * 显示跟进弹窗
  155. */
  156. const follow = (): void => {
  157. nextTick(() => {
  158. followDialogVisible.value = true
  159. })
  160. }
  161. /**
  162. * 处理弹窗提交事件
  163. */
  164. const handleDialogSubmit = async () => {
  165. try {
  166. dialogVisible.value = false
  167. followDialogVisible.value = false
  168. currentUserData.value = {}
  169. // 延迟更新 不然数据可能没更新
  170. setTimeout(() => {
  171. refreshData()
  172. }, 1000)
  173. } catch (error) {
  174. console.error('提交失败:', error)
  175. }
  176. }
  177. </script>
  178. <style lang="scss" scoped>
  179. .user-page {
  180. :deep(.user) {
  181. .avatar {
  182. width: 40px;
  183. height: 40px;
  184. margin-left: 0;
  185. border-radius: 6px;
  186. }
  187. > div {
  188. margin-left: 10px;
  189. .user-name {
  190. font-weight: 500;
  191. color: var(--art-text-gray-800);
  192. }
  193. }
  194. }
  195. }
  196. </style>