index.vue 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791
  1. <template>
  2. <div class="main_container" @scroll="OnScroll" ref="scrollContainer">
  3. <div class="user_num_content">
  4. <div class="user_item all">
  5. <div class="item_left">
  6. <img src="@/assets/icon/user_all.svg" alt="">
  7. <p>全部用户</p>
  8. </div>
  9. <div class="item_right">{{ userNumber.allUser }}</div>
  10. </div>
  11. <div class="user_item blue">
  12. <div class="item_left">
  13. <img src="@/assets/icon/user_blue.svg" alt="">
  14. <p>正式用户</p>
  15. </div>
  16. <div class="item_right">{{ userNumber.officialUser }}</div>
  17. </div>
  18. <div class="user_item green">
  19. <div class="item_left">
  20. <img src="@/assets/icon/user_green.svg" alt="">
  21. <p>体验用户</p>
  22. </div>
  23. <div class="item_right">{{ userNumber.experienceUser }}</div>
  24. </div>
  25. <div class="user_item orange">
  26. <div class="item_left">
  27. <img src="@/assets/icon/user_orange.svg" alt="">
  28. <p>冻结用户</p>
  29. </div>
  30. <div class="item_right">{{ userNumber.freezeUser }}</div>
  31. </div>
  32. </div>
  33. <div ref="filterRef" class="filter_area">
  34. <!-- <SearchMain @FnSearch="FnSearch" /> -->
  35. <div class="page_item">
  36. <div class="tag_group" v-if="searchList.provinceNode.length > 1">
  37. <div class="tag_group_title">省份:</div>
  38. <div class="tag_group_content">
  39. <div class="tag_item" v-for="item in searchList.provinceNode" :key="item.provinceCode" @click="selectItem(item.provinceCode, 'provinceCode', item)" :class="item.provinceCode === searchData.provinceCode ? 'active' : ''">
  40. {{ item.provinceName }}
  41. </div>
  42. </div>
  43. </div>
  44. <div class="tag_group" v-if="cityNode.length > 0">
  45. <div class="tag_group_title">城市:</div>
  46. <div class="tag_group_content">
  47. <div class="tag_item" v-for="item in cityNode" :key="item.cityCode" @click="selectItem(item.cityCode, 'cityCode', item)" :class="item.cityCode === searchData.cityCode ? 'active' : ''">
  48. {{ item.cityName }}
  49. </div>
  50. </div>
  51. </div>
  52. <div class="tag_group" v-if="districtNode.length > 0">
  53. <div class="tag_group_title">区/县:</div>
  54. <div class="tag_group_content">
  55. <div class="tag_item" v-for="item in districtNode" :key="item.districtCode" @click="selectItem(item.districtCode, 'districtCode', item)" :class="item.districtCode === searchData.districtCode ? 'active' : ''">
  56. {{ item.districtName }}
  57. </div>
  58. </div>
  59. </div>
  60. <div class="tag_group" v-if="searchList.userInfo.length > 1">
  61. <div class="tag_group_title">运维:</div>
  62. <div class="tag_group_content">
  63. <div class="tag_item" v-for="item in searchList.userInfo" :key="item.userId" @click="selectItem(item.userId, 'userId', item)" :class="item.userId === searchData.userId ? 'active' : ''">
  64. {{ item.nickname }}
  65. </div>
  66. </div>
  67. </div>
  68. <div class="tag_group" v-if="searchList.typeNode.length > 1">
  69. <div class="tag_group_title">类型:</div>
  70. <div class="tag_group_content">
  71. <div class="tag_item" v-for="item in searchList.typeNode" :key="item.type" @click="selectItem(item.type, 'type', item)" :class="item.type === searchData.type ? 'active' : ''">
  72. {{ item.typeName }}
  73. </div>
  74. </div>
  75. </div>
  76. <div class="tag_group" v-if="searchList.statusNodes.length > 1">
  77. <div class="tag_group_title">状态:</div>
  78. <div class="tag_group_content">
  79. <div class="tag_item" v-for="item in searchList.statusNodes" :key="item.status" @click="selectItem(item.status, 'status', item)" :class="item.status === searchData.status ? 'active' : ''">
  80. {{ item.statusName }}
  81. </div>
  82. </div>
  83. </div>
  84. </div>
  85. </div>
  86. <div class="page_jg_20"></div>
  87. <div class="page_item">
  88. <div class="page_search">
  89. <div class="search_content" ref="searchContentRef">
  90. <div class="content_left">
  91. <div class="simple_filter" v-if="isShowSimpleFilter">
  92. <el-select v-model="searchData.provinceCode" @change="ChangeRegion('provinceCode')" v-if="searchList.provinceNode && searchList.provinceNode.length > 1">
  93. <el-option v-for="item in searchList.provinceNode" :key="item.provinceCode" :value="item.provinceCode" :label="item.provinceName == '全部' ? '全部省份' : item.provinceName"></el-option>
  94. </el-select>
  95. <el-select v-model="searchData.cityCode" @change="ChangeRegion('cityCode')" v-if="cityNode && cityNode.length > 1">
  96. <el-option v-for="item in cityNode" :key="item.cityCode" :value="item.cityCode" :label="item.cityName == '全部' ? '全部城市' : item.cityName"></el-option>
  97. </el-select>
  98. <el-select v-model="searchData.districtCode" @change="ChangeRegion('districtCode')" v-if="districtNode && districtNode.length > 1">
  99. <el-option v-for="item in districtNode" :key="item.districtCode" :value="item.districtCode" :label="item.districtName == '全部' ? '全部区县' : item.districtName"></el-option>
  100. </el-select>
  101. <el-select v-model="searchData.userId" @change="SearchChange" v-if="searchList.userInfo && searchList.userInfo.length > 1">
  102. <el-option v-for="item in searchList.userInfo" :key="item.userId" :value="item.userId" :label="item.nickname == '全部' ? '全部运维' : item.nickname"></el-option>
  103. </el-select>
  104. <el-select v-model="searchData.type" @change="SearchChange" v-if="searchList.typeNode && searchList.typeNode.length > 1">
  105. <el-option v-for="item in searchList.typeNode" :key="item.type" :value="item.type" :label="item.typeName == '全部' ? '全部类型' : item.typeName"></el-option>
  106. </el-select>
  107. <el-select v-model="searchData.status" @change="SearchChange" v-if="searchList.statusNodes && searchList.statusNodes.length > 1">
  108. <el-option v-for="item in searchList.statusNodes" :key="item.status" :value="item.status" :label="item.statusName == '全部' ? '全部状态' : item.statusName"></el-option>
  109. </el-select>
  110. </div>
  111. <el-select v-model="schoolTypeSelect" @change="SearchChange">
  112. <el-option label="全部类型" value="all"></el-option>
  113. <el-option label="单校" :value="0"></el-option>
  114. <el-option label="联考" :value="1"></el-option>
  115. </el-select>
  116. <el-input v-model="schoolNameCode" placeholder="请输入学校名称或编号" @input="SearchChange">
  117. <template #append>
  118. <el-button :icon="Search" @click="SearchChange" />
  119. </template>
  120. </el-input>
  121. </div>
  122. <div class="content_right">
  123. <!-- <el-button class="button_refresh" @click="Refresh">
  124. <img src="@/assets/icon/refresh.svg" alt="" style="margin-right: 5px;">刷新
  125. </el-button> -->
  126. <el-button class="button_border" @click="OpenSubject" v-if="permissions.includes('schoolOpenSubjects')">开通科目</el-button>
  127. <el-button class="button_background" @click="addUser" v-if="permissions.includes('schoolCreate')">新增用户</el-button>
  128. </div>
  129. </div>
  130. </div>
  131. <div class="page_jg_20"></div>
  132. <div class="page_table">
  133. <el-table :data="tableData" stripe v-loading="tableLoading" element-loading-text="拼命加载中……" :height="tableHeight"
  134. element-loading-spinner="el-icon-loading" element-loading-background="#ffffff">
  135. <el-table-column prop="index" label="序号" fixed="left" align="center" />
  136. <el-table-column prop="tenantCode" label="学校编号" width="80" fixed="left" align="center" show-overflow-tooltip />
  137. <el-table-column prop="tenantName" label="学校名称" min-width="160" fixed="left" align="center" show-overflow-tooltip>
  138. <template #default="{row}">
  139. <span @click="GoTeach(row)" :class="row.status == 0 || row.dateDiffDayS==0 || !permissions.includes('UserInfo') ? '' : 'text_color_blue'">{{ row.tenantName }}</span>
  140. </template>
  141. </el-table-column>
  142. <el-table-column prop="abbreviation" label="学校简称" width="120" align="center" show-overflow-tooltip>
  143. <template #default="{ row }">
  144. {{ row.abbreviation || '-' }}
  145. </template>
  146. </el-table-column>
  147. <el-table-column prop="cityAndAreaName" label="区域" width="160" align="center" show-overflow-tooltip>
  148. <template #default="{ row }">
  149. {{ row.cityAndAreaName || '-' }}
  150. </template>
  151. </el-table-column>
  152. <el-table-column prop="schoolType" label="账号类型" width="100" align="center">
  153. <template #default="{ row }">
  154. {{ row.schoolType == 0 ? '单校版' : row.schoolType == 1 ? '联考版' : '-' }}
  155. </template>
  156. </el-table-column>
  157. <el-table-column prop="startDate" label="开始时间" width="100" align="center" show-overflow-tooltip />
  158. <el-table-column prop="endDate" label="结束时间" width="100" align="center" show-overflow-tooltip />
  159. <el-table-column prop="dateDiffDayS" label="剩余天数" width="100" align="center" />
  160. <el-table-column prop="type" label="状态" width="80" align="center">
  161. <template #default="{ row }">
  162. <div class="table_row_status">
  163. <!-- 冻结 -->
  164. <div class="no_release_icon" v-if="row.status==0"></div>
  165. <!-- 正式 -->
  166. <div class="need_summary_icon" v-if="row.status==1 && row.type==1"></div>
  167. <!-- 体验 -->
  168. <div class="yes_release_icon" v-if="row.status==1 && row.type==0"></div>
  169. <!-- {{ row.statusLabel }} -->
  170. {{ row.status == 0 ? '冻结' : row.type == 1 ? '正式' : row.type == 0 ? '体验' : '-' }}
  171. </div>
  172. </template>
  173. </el-table-column>
  174. <el-table-column prop="sysUserName" width="120" label="运维人员" align="center" show-overflow-tooltip>
  175. <template #default="{ row }">
  176. {{ row.sysUserName || '-' }}
  177. </template>
  178. </el-table-column>
  179. <el-table-column label="操作" width="280" fixed="right" align="center">
  180. <template #default="{ row }">
  181. <div class="table_row_option">
  182. <span v-if="row.status == 0 && permissions.includes('schoolFreeze')" class="button_delete" @click="ChangeStatus(row, '解冻')">
  183. 解冻
  184. </span>
  185. <span v-if="row.status != 0 && permissions.includes('schoolFreeze')" class="button_editor text_color_orange" @click="ChangeStatus(row, '冻结')">
  186. 冻结
  187. </span>
  188. <span class="button_editor" @click="EditUser(row)" v-if="permissions.includes('schoolUpdate')">编辑</span>
  189. <span class="button_editor" @click="OpenAuth(row)" v-if="permissions.includes('schoolPermission')">权限</span>
  190. <span class="button_editor" @click="resetPassWord(row)" v-if="permissions.includes('schoolPassword')">重置密码</span>
  191. <span class="button_editor" :class="row.status == 0 || row.dateDiffDayS==0 ? 'disabled_text' : ''" @click="GoTeach(row)" v-if="permissions.includes('UserInfo') ">进入学校</span>
  192. </div>
  193. </template>
  194. </el-table-column>
  195. </el-table>
  196. <div class="page_pagination">
  197. <el-pagination v-model:current-page="pageNum" v-model:page-size="pageSize" :page-sizes="[20, 50, 100]" background layout="sizes, prev, pager, next" :total="total"
  198. @current-change="HandleCurrentChange" @size-change="HandleSizeChange" />
  199. </div>
  200. </div>
  201. </div>
  202. <div class="page_dialog">
  203. <AddUser v-if="showDialog" @AddUser="RefTable" />
  204. <AuthConfig v-if="authData.showDialog" />
  205. <SubjectList v-if="subjectShowDialog" />
  206. <ResetPassword v-if="passwordDialog.dialogShow" />
  207. </div>
  208. </div>
  209. </template>
  210. <script lang="ts" setup>
  211. import SearchMain from '@/views/school/SearchMain.vue'
  212. import AddUser from '@/views/school/addUser.vue'
  213. import AuthConfig from '@/views/school/authConfig.vue'
  214. import SubjectList from '@/views/school/subjectList.vue'
  215. import ResetPassword from '@/components/resetPassword.vue'
  216. import { Search } from '@element-plus/icons-vue'
  217. import { ElMessageBox, ElMessage } from 'element-plus'
  218. import { ref, reactive, provide, onMounted, nextTick, onUnmounted } from 'vue'
  219. import { getSchoolNumber, getSchoolList, changeStatus ,getTicket, getSearchList} from '@/api/school'
  220. import { throttle } from 'lodash';
  221. interface UserNumber {
  222. allUser: number
  223. officialUser: number
  224. experienceUser: number
  225. freezeUser: number
  226. }
  227. const userNumber = ref<UserNumber>({
  228. allUser: 0,
  229. officialUser: 0,
  230. experienceUser: 0,
  231. freezeUser: 0
  232. })
  233. const searchData = ref({
  234. provinceCode: 'all',
  235. cityCode: 'all',
  236. districtCode: 'all',
  237. type: 'all',
  238. userId: 'all',
  239. status: 'all',
  240. })
  241. interface Province {
  242. provinceCode: string;
  243. provinceName: string;
  244. children?: City[]; // 如果有子级城市数据的话
  245. }
  246. interface City {
  247. cityCode: string
  248. cityName: string
  249. children?: District[]; // 如果有子级区县数据的话
  250. }
  251. interface District {
  252. districtCode: string
  253. districtName: string
  254. }
  255. const cityNode = ref<City[]>([])
  256. const districtNode = ref<District[]>([])
  257. interface TypeNode {
  258. type: string;
  259. typeName: string;
  260. }
  261. interface UserInfo {
  262. userId: string;
  263. nickname: string;
  264. }
  265. interface StatusNodes {
  266. status: string;
  267. statusName: string;
  268. }
  269. interface SearchList {
  270. examTypes: any[];
  271. provinceNode: Province[];
  272. cityNode: City[];
  273. districtNode: District[];
  274. typeNode: TypeNode[];
  275. userInfo: UserInfo[];
  276. statusNodes: StatusNodes[];
  277. }
  278. const searchList = ref<SearchList>({
  279. examTypes: [],
  280. provinceNode: [],
  281. cityNode: [],
  282. districtNode: [],
  283. typeNode: [],
  284. userInfo: [],
  285. statusNodes: []
  286. })
  287. // const emit = defineEmits(['FnSearch'])
  288. type SearchDataKey = 'provinceCode' | 'cityCode' | 'districtCode' | 'type' | 'userId' | 'status'
  289. const selectItem = (value: string, str: SearchDataKey, item: any) => {
  290. searchData.value[str] = value
  291. let arr = []
  292. if(str == 'provinceCode') {
  293. if(value && value != 'all') {
  294. arr = [...item.children]
  295. arr.splice(0, 0, { cityCode: "all", cityName: "全部" })
  296. cityNode.value = arr
  297. searchData.value.cityCode = 'all'
  298. districtNode.value = []
  299. searchData.value.districtCode = 'all'
  300. }else {
  301. cityNode.value = []
  302. searchData.value.cityCode = 'all'
  303. districtNode.value = []
  304. searchData.value.districtCode = 'all'
  305. }
  306. }
  307. if(str == 'cityCode') {
  308. if(value && value != 'all') {
  309. arr = [...item.children]
  310. arr.splice(0, 0, { districtCode: "all", districtName: "全部" })
  311. districtNode.value = arr
  312. searchData.value.districtCode = 'all'
  313. }else {
  314. districtNode.value = []
  315. searchData.value.districtCode = 'all'
  316. }
  317. }
  318. FnSearch(searchData)
  319. // emit('FnSearch', searchData);
  320. }
  321. const ChangeRegion = (str: SearchDataKey) => {
  322. let arr = []
  323. if(str == 'provinceCode') {
  324. if(searchData.value.provinceCode && searchData.value.provinceCode != 'all') {
  325. arr = [...searchList.value.provinceNode.find(item => item.provinceCode == searchData.value.provinceCode).children]
  326. arr.splice(0, 0, { cityCode: "all", cityName: "全部" })
  327. cityNode.value = arr
  328. console.log(cityNode.value)
  329. searchData.value.cityCode = 'all'
  330. districtNode.value = []
  331. searchData.value.districtCode = 'all'
  332. } else {
  333. cityNode.value = []
  334. searchData.value.cityCode = 'all'
  335. districtNode.value = []
  336. searchData.value.districtCode = 'all'
  337. }
  338. }
  339. if(str == 'cityCode') {
  340. if(searchData.value.cityCode && searchData.value.cityCode != 'all') {
  341. arr = [...cityNode.value.find(item => item.cityCode == searchData.value.cityCode).children]
  342. arr.splice(0, 0, { districtCode: "all", districtName: "全部" })
  343. districtNode.value = arr
  344. searchData.value.districtCode = 'all'
  345. }else {
  346. districtNode.value = []
  347. searchData.value.districtCode = 'all'
  348. }
  349. }
  350. SearchChange()
  351. }
  352. const GetSearchList = () => {
  353. getSearchList().then((res: any) => {
  354. console.log(res)
  355. if(res.code == 200) {
  356. const { data } = res
  357. for(let i in data) {
  358. if(i == 'provinceNode') {
  359. data[i].splice(0, 0, { provinceCode: "all", provinceName: "全部" })
  360. }else if(i == 'cityNode') {
  361. data[i].splice(0, 0, { cityCode: "all", cityName: "全部" })
  362. }else if(i == 'districtNode') {
  363. data[i].splice(0, 0, { districtCode: "all", districtName: "全部" })
  364. }else if( i == 'typeNode') {
  365. data[i].splice(0, 0, { type: "all", typeName: "全部" })
  366. }else if( i == 'userInfo') {
  367. data[i].splice(0, 0, { userId: "all", nickname: "全部" })
  368. }else if( i == 'statusNodes') {
  369. data[i].splice(0, 0, { status: "all", statusName: "全部" })
  370. }
  371. }
  372. searchList.value = data
  373. console.log(searchList.value)
  374. }
  375. })
  376. }
  377. // 定义列表数据类型
  378. interface User {
  379. index: number;
  380. tenantCode: String;
  381. tenantName: String;
  382. status: number;
  383. statusLabel: String;
  384. schoolType: String;
  385. abbreviation: String;
  386. dateDiffDayS: String;
  387. startDate: String;
  388. endDate: String;
  389. sysUserId: String;
  390. sysUserName: String;
  391. cityAndAreaName: String;
  392. }
  393. // 初始化列表数据
  394. const tableData = ref<User[]>([])
  395. const schoolTypeSelect = ref<string>("all")
  396. const schoolNameCode = ref('')
  397. const pageNum = ref(1)
  398. const pageSize = ref(20)
  399. const total = ref(0)
  400. const tableLoading = ref(false)
  401. const showDialog = ref(false)
  402. const dialogData = reactive({
  403. id: '',
  404. pageType: '',
  405. isChild: false,
  406. tenantName: ''
  407. })
  408. const subjectShowDialog = ref(false)
  409. // 编辑权限传递参数
  410. const authData = reactive({
  411. showDialog: false,
  412. id: '',
  413. schoolName: '',
  414. tenantCode: ''
  415. })
  416. // 重置密码弹窗数据
  417. const passwordDialog = reactive({
  418. dialogShow: false,
  419. id: '', // 学校id
  420. type: '', // 学校状态
  421. name: '', // 学校名称
  422. label: '', // 名称label
  423. remark: '' // 提示语
  424. }) // 重置密码弹窗数据
  425. const permissions = ref([]) // 权限列表
  426. provide('showDialog', showDialog) // 新增用户弹窗是否展示
  427. provide('dialogData', dialogData) // 新增用户弹窗数据
  428. provide('authData', authData) // 设置权限弹窗数据
  429. provide('subjectShowDialog', subjectShowDialog) // 开通科目弹窗数据
  430. provide('passwordDialog', passwordDialog) // 重置密码弹窗数据
  431. onMounted(() => {
  432. permissions.value = JSON.parse(localStorage.getItem('permissions'))
  433. GetSearchList()
  434. GetSchoolNumber()
  435. GetSchoolList()
  436. nextTick(() => {
  437. SetTableHeight()
  438. })
  439. window.addEventListener('resize', HandleResize);
  440. })
  441. onUnmounted(() => {
  442. window.removeEventListener('resize', HandleResize);
  443. });
  444. // 新增用户
  445. const addUser = () => {
  446. showDialog.value = true
  447. dialogData.isChild = false
  448. dialogData.pageType = 'add'
  449. }
  450. // 编辑
  451. const EditUser = (row: any) => {
  452. console.log(row)
  453. showDialog.value = true
  454. dialogData.pageType = 'edit'
  455. dialogData.id = row.id
  456. dialogData.isChild = row.isChild
  457. dialogData.tenantName = row.tenantName
  458. }
  459. // 设置权限
  460. const OpenAuth = (row: any) => {
  461. authData.id = row.id
  462. authData.schoolName = row.tenantName
  463. authData.tenantCode = row.tenantCode
  464. authData.showDialog = true
  465. }
  466. // 开通科目
  467. const OpenSubject = () => {
  468. console.log('OpenSubject')
  469. subjectShowDialog.value = true
  470. }
  471. // 筛选项查询
  472. const FnSearch = (data: any) => {
  473. searchData.value = data.value
  474. pageNum.value = 1
  475. GetSchoolList()
  476. }
  477. // 表格上面筛选查询
  478. const SearchChange = () => {
  479. pageNum.value = 1
  480. GetSchoolList()
  481. }
  482. // 获取用户数量
  483. const GetSchoolNumber = () => {
  484. getSchoolNumber().then((res: any) => {
  485. if(res.code == 200 && res.data) {
  486. userNumber.value = res.data
  487. }
  488. })
  489. }
  490. // 获取学校列表
  491. const GetSchoolList = () => {
  492. let params = {
  493. type: searchData.value.type == 'all' ? '' : searchData.value.type,
  494. status: searchData.value.status == 'all' ? '' : searchData.value.status,
  495. userId: searchData.value.userId == 'all' ? '' : searchData.value.userId,
  496. cityCode: searchData.value.cityCode == 'all' ? '' : searchData.value.cityCode,
  497. provinceCode: searchData.value.provinceCode == 'all' ? '' : searchData.value.provinceCode,
  498. schoolType: schoolTypeSelect.value == 'all' ? '' : schoolTypeSelect.value,
  499. queryStr: schoolNameCode.value,
  500. pageNum: pageNum.value,
  501. pageSize: pageSize.value,
  502. }
  503. tableLoading.value = true
  504. getSchoolList(params).then((res: any) => {
  505. if(res.code == 200 && res.data) {
  506. tableData.value = res.data.records
  507. total.value = parseInt(res.data.total)
  508. tableData.value.map((item, index) => {
  509. item.index = (pageNum.value - 1) * pageSize.value + index + 1
  510. })
  511. }
  512. tableLoading.value = false
  513. }).catch(() => {
  514. tableLoading.value = false
  515. })
  516. }
  517. // 切换分页页码
  518. const HandleCurrentChange = (val) => {
  519. pageNum.value = val
  520. GetSchoolList()
  521. }
  522. const HandleSizeChange = (val) => {
  523. pageSize.value = val
  524. pageNum.value = 1
  525. GetSchoolList()
  526. }
  527. // 新增/修改学校信息后刷新列表
  528. const RefTable = (val: any) => {
  529. showDialog.value = val
  530. GetSearchList()
  531. GetSchoolNumber()
  532. GetSchoolList()
  533. }
  534. // 改变用户状态
  535. const ChangeStatus = (row: any, text: String) => {
  536. console.log(row)
  537. ElMessageBox.confirm(`是否${text}${row.tenantName}?`, '提示', {
  538. confirmButtonText: '确定',
  539. cancelButtonText: '取消',
  540. type: 'warning'
  541. }).then(async () => {
  542. changeStatus({
  543. id: row.id,
  544. status: row.status == 0 ? 1 : 0
  545. }).then((res: any) => {
  546. if(res.code == 200) {
  547. ElMessage.success(res.msg)
  548. GetSearchList()
  549. GetSchoolNumber()
  550. GetSchoolList()
  551. }
  552. })
  553. })
  554. }
  555. // 进入学校
  556. const GoTeach = (row: any) => {
  557. //剩余天数为0的禁止进入学校
  558. if(row.status == 0 || row.dateDiffDayS==0)
  559. {
  560. if(row.dateDiffDayS==0)
  561. {
  562. ElMessage.error('该学校已到期,请续费!')
  563. }
  564. return
  565. }
  566. console.log("打印row",row)
  567. let params = {
  568. schoolId: row.id,
  569. }
  570. getTicket(params).then((res: any) => {
  571. console.log("打印获取票据接口返回res",res)
  572. if(res.code == 200 && res.data)
  573. {
  574. let ticket = res.data;
  575. let url=`https://www.k12100.com/#/otherLogin?schoolId=${row.id}&ticket=${ticket}`;//正式环境
  576. // let url=`https://dev3.k12100.net/#/otherLogin?schoolId=${row.id}&ticket=${ticket}`;//测试环境
  577. console.log("打印获取票据接口返回ticket",ticket)
  578. console.log("打印第三方登录地址",url);
  579. // window.open(`https://www.k12100.com/#/otherLogin?schoolId=${row.id}&ticket=${ticket}`)
  580. window.open(url)
  581. }
  582. }).catch(() => {
  583. })
  584. }
  585. // 重置密码
  586. const resetPassWord = (row: any) => {
  587. passwordDialog.dialogShow = true
  588. passwordDialog.id = row.id
  589. passwordDialog.type = '2'
  590. passwordDialog.name = row.tenantName
  591. passwordDialog.label = '学校名称'
  592. passwordDialog.remark = '学校编号'
  593. }
  594. // 刷新
  595. const Refresh = () => {
  596. schoolTypeSelect.value = " "
  597. schoolNameCode.value = ""
  598. GetSchoolList()
  599. }
  600. const filterRef = ref<HTMLDivElement | null>(null)
  601. const scrollContainer = ref<HTMLElement | null>(null);
  602. const isShowSimpleFilter = ref(false);
  603. // 监听页面滚动
  604. const OnScroll = () => {
  605. nextTick(() => {
  606. const filterElement = filterRef.value.$el || filterRef.value // 获取 DOM 元素
  607. if (!filterElement) return
  608. const filterElementHeight = filterElement.getBoundingClientRect().height
  609. const scrollTop = scrollContainer.value?.scrollTop || window.scrollY
  610. // console.log('筛选区域高度', filterElementHeight)
  611. // console.log('scrolltop滑动距离', scrollTop)
  612. // 判断是否滚动到了筛选区域的底部
  613. if (scrollTop > filterElementHeight + 60) {
  614. isShowSimpleFilter.value = true
  615. SetTableHeight()
  616. } else {
  617. isShowSimpleFilter.value = false
  618. }
  619. })
  620. };
  621. const tableHeight = ref(0)
  622. const searchContentRef = ref<HTMLDivElement | null>(null);
  623. const SetTableHeight = () => {
  624. const clientHeight = scrollContainer.value?.clientHeight || document.documentElement.clientHeight;
  625. const searchContentHeight = searchContentRef.value?.clientHeight || document.documentElement.clientHeight;
  626. tableHeight.value = clientHeight - searchContentHeight - 148
  627. }
  628. // 监听窗口大小变化,重新计算表格高度 使用节流防止频繁改变窗口大小导致计算量过大而页面卡顿
  629. const HandleResize = throttle(() => {
  630. SetTableHeight();
  631. }, 500) // 节流 500 毫秒内最多执行一次
  632. </script>
  633. <style lang="scss" scoped>
  634. .simple_filter {
  635. display: flex;
  636. flex-wrap: wrap;
  637. gap: 10px;
  638. }
  639. .search_content {
  640. align-items: flex-start !important;
  641. }
  642. .user_num_content {
  643. width: 100%;
  644. display: flex;
  645. gap: 20px;
  646. justify-content: space-between;
  647. align-items: center;
  648. margin-bottom: 20px;
  649. .user_item {
  650. flex-grow: 1;
  651. height: 80px;
  652. padding: 20px;
  653. display: flex;
  654. justify-content: space-between;
  655. align-items: center;
  656. border-radius: 10px;
  657. font-weight: 500;
  658. .item_left {
  659. display: flex;
  660. align-items: center;
  661. img {
  662. margin-right: 10px;
  663. }
  664. }
  665. &.all {
  666. background: #2E64FA;
  667. color: #fff;
  668. .item_right {
  669. color: #fff;
  670. }
  671. }
  672. &.blue {
  673. border: 1px solid #2E64FA;
  674. background: #EAF0FF;
  675. color: #333;
  676. .item_right {
  677. color: #2E64FA;
  678. }
  679. }
  680. &.green {
  681. border: 1px solid #2BC644;
  682. background: #EAF9EC;
  683. color: #333;
  684. .item_right {
  685. color: #2BC644;
  686. }
  687. }
  688. &.orange {
  689. border: 1px solid #FB9F34;
  690. background: #FFF5EB;
  691. color: #333;
  692. .item_right {
  693. color: #FB9F34;
  694. }
  695. }
  696. .item_right {
  697. font-size: 24px;
  698. font-weight: 700;
  699. }
  700. }
  701. }
  702. .button_editor.text_color_orange {
  703. color: #FB9F34;
  704. }
  705. .button_delete {
  706. margin-right: 5px;
  707. }
  708. .button_editor.text_color_red {
  709. color: #F56C6C;
  710. }
  711. .text_color_blue {
  712. color: #2E64FA;
  713. cursor: pointer;
  714. }
  715. .disabled_text {
  716. color: #ccc;
  717. cursor: not-allowed;
  718. }
  719. .filter_area .page_item {
  720. padding: 10px 20px !important;
  721. }
  722. .tag_group{
  723. padding:8px 0;
  724. display: flex;
  725. justify-content: flex-start;
  726. .tag_group_title {
  727. // width: auto;
  728. width: 50px;
  729. height: auto;
  730. margin-right: 8px;
  731. color: #303133;
  732. font-size: 14px;
  733. text-align: right;
  734. line-height: 30px;
  735. font-weight: 500;
  736. letter-spacing: 0em;
  737. }
  738. .tag_group_content {
  739. width: calc(100% - 80px);
  740. display: flex;
  741. flex-wrap: wrap;
  742. gap: 8px;
  743. .tag_item {
  744. padding: 0 8px;
  745. line-height: 30px;
  746. border-radius: 4px;
  747. font-size: 14px;
  748. background: #fff;
  749. color: #999999;
  750. cursor: pointer;
  751. &.active {
  752. background: rgba(71,113,203,0.1);
  753. color: #2E64FA;
  754. }
  755. &:hover {
  756. color: #2E64FA;
  757. }
  758. }
  759. }
  760. }
  761. </style>