index.vue 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393
  1. <template>
  2. <div class="main_container">
  3. <div class="page_item end_item hide_scrollbar" ref="scrollDom">
  4. <div v-if="scrollMsg.isScrollTop" :style="{height:scrollMsg.headerHeight || '140px',flexShrink:'0'}"></div>
  5. <div class="search_page" ref="searchDom">
  6. <DefaultSelectSearch v-if="scrollMsg.isScrollTop" @searchChange="HandleSearchChange">
  7. <div v-if="userInfo.roles.includes('Admin')" class="content_right">
  8. <el-button class="button_refresh" @click="OpenBatchImportDialog">批量导入</el-button>
  9. <el-button class="button_background" @click="OpenSchoolFormDialog()">新增学校</el-button>
  10. </div>
  11. </DefaultSelectSearch>
  12. <DefaultBlockSearch v-else @searchChange="HandleSearchChange">
  13. <div v-if="userInfo.roles.includes('Admin')" class="content_right">
  14. <el-button class="button_refresh" @click="OpenBatchImportDialog">批量导入</el-button>
  15. <el-button class="button_background" @click="OpenSchoolFormDialog()">新增学校</el-button>
  16. </div>
  17. </DefaultBlockSearch>
  18. </div>
  19. <Table :tableColumns="publicSeasTableColumns" :tableData="tableData"
  20. :currentPage="currentPage" :pageSize="pageSize" :totalNum="totalNum"
  21. :showPageSize="true" @paginationChange="HandlePaginationChange">
  22. <template #num="{row,currentIndex}">
  23. {{ currentIndex + pageSize * (currentPage - 1) }}
  24. </template>
  25. <template #operation="{row}">
  26. <div class="table_row_option">
  27. <span class="button_editor" @click="ClaimCustomer(row)">认领</span>
  28. <span class="button_editor" @click="OpenSchoolFormDialog(row)">编辑</span>
  29. <span class="button_editor" @click="GoToDetail(row)">详情</span>
  30. <span class="el_button_delete" @click="OpenDeleteDialog(row)">删除</span>
  31. </div>
  32. </template>
  33. <template #paginationDesc>
  34. <span>共 {{ totalNum }} 条数据</span>
  35. </template>
  36. </Table>
  37. </div>
  38. <!-- 新增/修改 学校弹窗 -->
  39. <SchoolFormDialog
  40. :schoolTitle="schoolTitle"
  41. v-model:visible="schoolVisible"
  42. v-model:submitLoading="editFormDialogSubmitLoading"
  43. :defaultFormData="schoolDefaultFormData"
  44. @confirm="HandleSchoolDialogConfirm">
  45. </SchoolFormDialog>
  46. <!-- 批量导入 弹窗 -->
  47. <FormDialog class="batch_import_form" width="548px"
  48. title="批量导入" :visible="batchImportVisible"
  49. :submitLoading="batchImportSubmitLoading"
  50. :defaultFormData="defaultImportFormData"
  51. :formItemList="batchImportFormItemList"
  52. @fileUpload="HandleFileUplaod"
  53. @close="CloseBatchImportDialog"
  54. @confirm="HandleBatchImportComfirm">
  55. <template #templateFile>
  56. <el-button class="button_refresh" @click="HandleDownloadTemplate">下载模板</el-button>
  57. </template>
  58. <template #tableTemplate>
  59. <Table :hidePagination="true" :tableColumns="templateTableColumns" :tableData="[{},{}]" />
  60. <div style="font-size: 12px;">用于分析同一份试卷内不同试卷类型的得分、排名等情况。可下载模块进行填写后导入。</div>
  61. </template>
  62. </FormDialog>
  63. <!-- 删除弹窗 -->
  64. <DeleteCustomerDialog
  65. :currentDeleteRow="currentDeleteRow"
  66. v-model:dialogVisible="deleteDialogVisible"
  67. @confirm="HandleDeleteDialogConfirm">
  68. </DeleteCustomerDialog>
  69. </div>
  70. </template>
  71. <script setup lang="ts">
  72. import { computed, onMounted, ref } from 'vue';
  73. import { useRouter } from 'vue-router';
  74. import {ElMessage} from 'element-plus'
  75. import DefaultBlockSearch from '@/components/HighSeasCustomerHeaderSearch/DefaultBlockSearch/index.vue'
  76. import {stageOptions, regionOptions } from '@/components/HighSeasCustomerHeaderSearch/commonVar'
  77. import {defaultPageSearchParams as searchParams} from '@/components/HighSeasCustomerHeaderSearch/commonVar'
  78. import DefaultSelectSearch from '@/components/HighSeasCustomerHeaderSearch/DefaultSelectSearch/index.vue'
  79. import Table from '@/baseComponents/Table.vue';
  80. import {publicSeasTableColumns,templateTableColumns} from './table'
  81. import SchoolFormDialog from '@/components/SchoolFormDialog/index.vue'
  82. import FormDialog from '@/baseComponents/FormDialog.vue';
  83. import DeleteCustomerDialog from './components/DeleteCustomerDialog.vue';
  84. import {batchImportFormItemList} from './formDialog'
  85. import {HandleExportExcel} from '@/utils/exportExcelData'
  86. import { getHeaderSearchParamsApi,
  87. getHighSeasCustomerListApi,
  88. addHighSeasCustomerApi,
  89. importHighSeasCustomerApi,
  90. updateHighSeasCustomerApi,
  91. claimHighSeasCustomerApi,
  92. } from '@/api/highSeasCustomer'
  93. import { useHeaderFixed } from '@/baseComponents/useHeaderFixed'
  94. const router = useRouter()
  95. const scrollDom = ref()
  96. const searchDom = ref()
  97. const scrollMsg = useHeaderFixed(scrollDom,searchDom,140,'calc(100% - 250px - 20px)','calc(80px)') //搜索栏是否需要在滚动的时候固定到顶部
  98. const userInfo = computed(()=>{
  99. return JSON.parse(localStorage.getItem('userInfo') || '{}')
  100. })
  101. // 获取头部筛选数据
  102. const GetHeaderSearchParams = async ()=>{
  103. let res = await getHeaderSearchParamsApi()
  104. const {regionData,stageData} = res.data || {}
  105. // 学段筛选选项
  106. stageOptions.value = stageData?.map(item=>{
  107. return{
  108. label:item.name,
  109. value:JSON.stringify({
  110. label:item.name,
  111. value:item.id,
  112. }),
  113. }
  114. }) || []
  115. // 省份筛选项
  116. regionOptions.value = regionData?.map(item=>{
  117. return{
  118. label:item.name,
  119. value:JSON.stringify({
  120. label:item.name,
  121. value:item.id
  122. }),
  123. subData:item.subData?.map(sub=>{
  124. return {
  125. label:sub.name,
  126. value:JSON.stringify({
  127. label:sub.name,
  128. value:sub.id
  129. }),
  130. }
  131. }) || [],
  132. }
  133. }) || []
  134. }
  135. /** 头部筛选 变更 */
  136. const HandleSearchChange = async (params:any,key:string)=>{
  137. searchParams.value = {
  138. ...searchParams.value,
  139. ...params
  140. }
  141. if(key === 'province'){
  142. searchParams.value.area = 'all'
  143. }
  144. await GetTableData()
  145. }
  146. /** 2. 表格数据 有关操作 */
  147. const pageSize = ref(20)
  148. const currentPage = ref(1)
  149. const totalNum = ref(0)
  150. // 表格数据
  151. const tableData = ref([])
  152. const HandlePaginationChange = async (params)=>{
  153. const {type,val} = params
  154. if(type == 'currentPage'){
  155. currentPage.value = val
  156. }else if(type == 'pageSize'){
  157. pageSize.value = val
  158. }
  159. await GetTableData()
  160. }
  161. const GetTableData = async ()=>{
  162. let params = {
  163. queryStr: searchParams.value.queryStr,
  164. stageId: searchParams.value.stage === 'all' ? '' : JSON.parse(searchParams.value.stage || '{}')?.value,
  165. provinceId: searchParams.value.province === 'all' ? '' : JSON.parse(searchParams.value.province || '{}')?.value,
  166. cityId: searchParams.value.area === 'all' ? '' : JSON.parse(searchParams.value.area || '{}')?.value,
  167. pageNum: currentPage.value,
  168. pageSize: pageSize.value
  169. }
  170. let res = await getHighSeasCustomerListApi(params)
  171. tableData.value = res?.data?.records || []
  172. totalNum.value = res.data.total || 0
  173. }
  174. /**
  175. * 3. 新增/修改 学校弹窗有关数据
  176. */
  177. const schoolVisible = ref(false)
  178. const schoolTitle = ref('')
  179. const schoolDefaultFormData = ref({})
  180. const editFormDialogSubmitLoading = ref(false)
  181. const OpenSchoolFormDialog = (row?:any)=>{
  182. if(row){
  183. schoolTitle.value = '编辑学校'
  184. schoolDefaultFormData.value = {
  185. ...row,
  186. schoolStage:JSON.stringify({
  187. label:row.stageName,
  188. value:row.stageId
  189. }),
  190. provinceArea:{
  191. province:JSON.stringify({
  192. label:row.provinceName,
  193. value:row.provinceId
  194. }),
  195. district:JSON.stringify({
  196. label:row.cityName,
  197. value:row.cityId
  198. }),
  199. },
  200. }
  201. }else{
  202. schoolTitle.value = '新增学校'
  203. }
  204. schoolVisible.value = true
  205. }
  206. const CloseSchoolFormDialog = ()=>{
  207. editFormDialogSubmitLoading.value = false
  208. schoolVisible.value = false
  209. schoolDefaultFormData.value = {}
  210. }
  211. const HandleSchoolDialogConfirm = async (params:any)=>{
  212. editFormDialogSubmitLoading.value = true
  213. const {formData,formRef} = params
  214. console.log('表单的提交信息',formData)
  215. let transferParams = {
  216. id: formData.id,
  217. name: formData.name,
  218. stageId: JSON.parse(formData.schoolStage || '{}')?.value,
  219. stageName: JSON.parse(formData.schoolStage || '{}')?.label,
  220. provinceId: JSON.parse(formData.provinceArea.province || '{}')?.value,
  221. provinceName: JSON.parse(formData.provinceArea.province || '{}')?.label,
  222. cityId: JSON.parse(formData.provinceArea.district || '{}')?.value,
  223. cityName: JSON.parse(formData.provinceArea.district || '{}')?.label,
  224. address: formData.address,
  225. }
  226. let res = undefined
  227. try{
  228. if(formData.id){
  229. // 修改
  230. res = await updateHighSeasCustomerApi(transferParams)
  231. }else{
  232. // 新增
  233. res = await addHighSeasCustomerApi(transferParams)
  234. }
  235. }catch{}
  236. if(res?.code == 200){
  237. CloseSchoolFormDialog()
  238. await GetTableData()
  239. }else{
  240. editFormDialogSubmitLoading.value = false
  241. }
  242. }
  243. /**
  244. * 4. 批量导入弹窗有关数据
  245. */
  246. const batchImportVisible = ref(false)
  247. const batchImportSubmitLoading = ref(false)
  248. const defaultImportFormData = ref({})
  249. // 打开弹窗
  250. const OpenBatchImportDialog = ()=>{
  251. batchImportVisible.value = true
  252. }
  253. // 关闭弹窗
  254. const CloseBatchImportDialog = ()=>{
  255. batchImportSubmitLoading.value = false
  256. batchImportVisible.value = false
  257. }
  258. // 导入确认
  259. const HandleBatchImportComfirm = async (params:any)=>{
  260. const {formData,formRef} = params
  261. // console.log('表单信息',formData)
  262. if(!formData?.file?.url){
  263. ElMessage.warning('请先上传文件')
  264. return
  265. }
  266. batchImportSubmitLoading.value = true
  267. let fileFormData = new FormData()
  268. fileFormData.append('file',formData.file.url)
  269. let res = await importHighSeasCustomerApi(fileFormData)
  270. if(res?.code == 200){
  271. ElMessage.success(res?.msg)
  272. CloseBatchImportDialog()
  273. await GetTableData()
  274. }else{
  275. batchImportSubmitLoading.value = false
  276. }
  277. }
  278. // 下载模板
  279. const HandleDownloadTemplate = async ()=>{
  280. await HandleExportExcel(templateTableColumns.value,[],'新增学校_批量导入模板')
  281. }
  282. // 获取上传文件
  283. const HandleFileUplaod = (params)=>{
  284. const {key,file} = params
  285. console.log('file',file)
  286. defaultImportFormData.value.file = {
  287. url:file.raw,
  288. name:file.name
  289. }
  290. }
  291. /**
  292. * 5. 删除弹窗 有关数据
  293. */
  294. const deleteDialogVisible = ref(false)
  295. const currentDeleteRow = ref()
  296. const OpenDeleteDialog = (row)=>{
  297. deleteDialogVisible.value = true
  298. currentDeleteRow.value = row
  299. }
  300. // 删除后执行的操作
  301. const HandleDeleteDialogConfirm = async ()=>{
  302. currentDeleteRow.value = {}
  303. await GetTableData()
  304. }
  305. /**
  306. * 6.认领有关接口调用
  307. */
  308. const ClaimCustomer = async (row)=>{
  309. let res = await claimHighSeasCustomerApi(row.id)
  310. if(res?.code == 200){
  311. ElMessage.success(res?.msg)
  312. await GetTableData()
  313. }
  314. }
  315. /** 7.跳转详情 */
  316. const GoToDetail = (row)=>{
  317. sessionStorage.setItem('customerMsg',JSON.stringify(row))
  318. router.push(`highSeasCustomerDetail?id=${row.id}`)
  319. }
  320. onMounted( async()=>{
  321. await GetHeaderSearchParams()
  322. await GetTableData()
  323. })
  324. </script>
  325. <style lang="scss" scoped>
  326. .end_item{
  327. overflow: auto;
  328. :deep(.page_table){
  329. overflow:initial;
  330. }
  331. }
  332. .batch_import_form{
  333. :deep(.el-dialog__body){
  334. min-height: 345px !important;
  335. }
  336. }
  337. </style>