Pārlūkot izejas kodu

ts 类型添加优化;退出登录/修改密码接口联调

zhangguohua 1 gadu atpakaļ
vecāks
revīzija
eafd2a0312

+ 4 - 4
src/api/examination.ts

@@ -1,6 +1,6 @@
 import request from '../utils/request.ts'
 // 联考学校列表
-export function getJoinExamList(params: any) {
+export const getJoinExamList = (params: any) => {
   return request({
     url: `/adminApi/v1/listSchoolICh`,
     method: 'get',
@@ -8,7 +8,7 @@ export function getJoinExamList(params: any) {
   })
 }
 // 单考学校列表
-export function getSingleExamList(params: any) {
+export const getSingleExamList = (params: any) => {
   return request({
     url: `/adminApi/v1/schoolOneAll`,
     method: 'get',
@@ -16,7 +16,7 @@ export function getSingleExamList(params: any) {
   })
 }
 // 新增学校
-export function addSingleSchool(data: any) {
+export const addSingleSchool = (data: any) => {
   return request({
     url: `/adminApi/v1/admin-child-schools`,
     method: 'post',
@@ -24,7 +24,7 @@ export function addSingleSchool(data: any) {
   })
 }
 // 删除学校
-export function deleteSchool(data: any) {
+export const deleteSchool = (data: any) => {
   return request({
     url: `/adminApi/v1/admin-child-schools`,
     method: 'delete',

+ 17 - 2
src/api/login.ts

@@ -1,7 +1,7 @@
 // src/api/login.ts
 import request from '../utils/request.ts'
 // 登录接口
-export function login(data:any) {
+export const login = (data:any) => {
   return request({
     url: '/adminApi/v1/auth/login',
     method: 'post',
@@ -10,10 +10,25 @@ export function login(data:any) {
 }
 
 // 获取用户信息
-export function getUserInfo() {
+export const getUserInfo = () => {
   return request({
     url: '/adminApi/v1/sys/users/info',
     method: 'get'
   })
 }
+// 退出登录
+export const loginOut = (userId: any) => {
+  return request({
+    url: `/adminApi/v1/sys/users/${userId}/kickOut`,
+    method: 'post'
+  })
+}
+// 修改密码
+export const changePassWord = (data: any) => {
+  return request({
+    url: `/adminApi/v1/sys/users/updatePassword`,
+    method: 'post',
+    data
+  })
+}
 

+ 5 - 5
src/api/manager.ts

@@ -1,14 +1,14 @@
 import request from '../utils/request.ts'
 
 // 查询运维人员详情
-export function managerDetails(id: any) {
+export const managerDetails = (id: any) => {
   return request({
     url: `/adminApi/v1/sys/users/${id}`,
     method: 'get'
   })
 }
 // 新增运维人员
-export function addManager(data: any) {
+export const addManager = (data: any) => {
   return request({
     url: `/adminApi/v1/sys/users`,
     method: 'post',
@@ -16,7 +16,7 @@ export function addManager(data: any) {
   })
 }
 // 编辑运维人员
-export function editManager(data: any) {
+export const editManager = (data: any): Promise<any> => {
   return request({
     url: `/adminApi/v1/sys/users`,
     method: 'put',
@@ -24,7 +24,7 @@ export function editManager(data: any) {
   })
 }
 // 删除运维人员
-export function deleteManager(data: any) {
+export const deleteManager = (data: any) => {
   return request({
     url: `/adminApi/v1/sys/users`,
     method: 'delete',
@@ -32,7 +32,7 @@ export function deleteManager(data: any) {
   })
 }
 // 重置密码
-export function resetPassWord(id: any, data: any) {
+export const resetPassWord = (id: any, data: any) => {
   return request({
     url: `/adminApi/v1/sys/users/${id}/password`,
     method: 'put',

+ 24 - 16
src/api/school.ts

@@ -1,14 +1,14 @@
 import request from '../utils/request.ts'
 
 // 获取学校数量
-export function getSchoolNumber() {
+export const getSchoolNumber = () => {
   return request({
     url: '/adminApi/v1/adminSchoolNumber',
     method: 'get'
   })
 }
 // 获取学校管理列表
-export function getSchoolList(data: any) {
+export const getSchoolList = (data: any) => {
   return request({
     url: '/adminApi/v1/adminSchoolInfosAll',
     method: 'post',
@@ -16,14 +16,14 @@ export function getSchoolList(data: any) {
   })
 }
 // 获取学校管理筛选列表
-export function getSearchList() {
+export const getSearchList = () => {
   return request({
     url: '/adminApi/v1/provinceCityTree',
     method: 'get'
   })
 }
 // 学校管理--新增用户
-export function addUser(data: any) {
+export const addUser = (data: any) => {
   return request({
     url: '/adminApi/v1/adminSchoolInfos',
     method: 'post',
@@ -31,7 +31,7 @@ export function addUser(data: any) {
   })
 }
 // 学校管理--运维人员列表
-export function getUserList(params: any) {
+export const getUserList = (params: any) => {
   return request({
     url: '/adminApi/v1/sys/userList',
     method: 'get',
@@ -39,7 +39,7 @@ export function getUserList(params: any) {
   })
 }
 // 学校管理--学校logo上传
-export function uploadFile(data: any) {
+export const uploadFile = (data: any) => {
   return request({
     url: '/adminApi/v1/oss/oss/upload_filesSele',
     method: 'post',
@@ -47,21 +47,21 @@ export function uploadFile(data: any) {
   })
 }
 // 学校管理--省市区树列表
-export function provinceTree() {
+export const provinceTree = () => {
   return request({
     url: '/adminApi/v1/provinceTree',
     method: 'get'
   })
 }
 // 学校管理--查看详情
-export function getSchoolInfo(id: any) {
+export const getSchoolInfo = (id: any) => {
   return request({
     url: `/adminApi/v1/admin-school-infos/${id}`,
     method: 'get'
   })
 }
 // 学校管理--编辑
-export function editSchoolInfo(data: any) {
+export const editSchoolInfo = (data: any) => {
   return request({
     url: `/adminApi/v1/adminSchoolInfos`,
     method: 'put',
@@ -69,7 +69,7 @@ export function editSchoolInfo(data: any) {
   })
 }
 // 学校管理--改变状态(冻结/解冻)
-export function changeStatus(data: any) {
+export const changeStatus = (data: any) => {
   return request({
     url: `/adminApi/v1/adminSchoolInfos/status`,
     method: 'post',
@@ -79,14 +79,14 @@ export function changeStatus(data: any) {
 
 
 // 学校管理--查询所有年级
-export function getAllGrade(id: any) {
+export const getAllGrade = (id: any) => {
   return request({
     url: `/adminApi/v1/admin/school/grade/getAllList/${id}`,
     method: 'get'
   })
 }
 // 学校管理--添加年级
-export function addGrade(data: any) {
+export const addGrade = (data: any) => {
   return request({
     url: `/adminApi/v1/admin/school/grade/addSchoolGrade`,
     method: 'post',
@@ -97,7 +97,7 @@ export function addGrade(data: any) {
 
 
 // 学校管理--查询所有科目
-export function getAllSubject(params: any) {
+export const getAllSubject = (params: any) => {
   return request({
     url: `/adminApi/v1/admin/school/course/getAllList`,
     method: 'get',
@@ -105,7 +105,7 @@ export function getAllSubject(params: any) {
   })
 }
 // 学校管理--新增科目
-export function addSubject(data: any) {
+export const addSubject = (data: any) => {
   return request({
     url: `/adminApi/v1/admin/school/course/courses`,
     method: 'post',
@@ -113,7 +113,7 @@ export function addSubject(data: any) {
   })
 }
 // 学校管理--删除科目
-export function deleteSubject(data: any) {
+export const deleteSubject = (data: any) => {
   return request({
     url: `/adminApi/v1/admin/school/course/deleteByIds`,
     method: 'delete',
@@ -121,10 +121,18 @@ export function deleteSubject(data: any) {
   })
 }
 // 免密登录
-export function loginTeach(data: any) {
+export const loginTeach = (data: any) => {
   return request({
     url: `/adminApi/v1/admin_login_teach`,
     method: 'post',
     data
   })
+}
+// 重置密码
+export const resetSchoolPassWord = (data: any) => {
+  return request({
+    url: `/adminApi/v1/resetSchoolInfo`,
+    method: 'post',
+    data
+  })
 }

+ 36 - 16
src/components/resetPassword.vue

@@ -4,16 +4,16 @@
       <el-form-item :label="dialogData.label+ ':'" prop="name" >
         <el-input :value="dialogData.name" disabled/>
       </el-form-item>
-      <el-form-item label="重置方式:">
+      <el-form-item label="重置方式:" v-if="dialogData.type == '2'">
         <el-radio-group v-model="editPassWordData.useDefault">
-          <el-radio value="0">使用新密码</el-radio>
-          <el-radio value="1">重置为默认密码</el-radio>
+          <el-radio :value="0">使用新密码</el-radio>
+          <el-radio :value="1">重置为默认密码</el-radio>
         </el-radio-group>
       </el-form-item>
-      <el-form-item label="新密码:" v-if="editPassWordData.useDefault=='0'" prop="randomPassword">
-        <el-input v-model="editPassWordData.randomPassword" placeholder="请输入密码" />
+      <el-form-item label="新密码:" v-if="editPassWordData.useDefault==0" prop="randomPassword">
+        <el-input v-model="editPassWordData.randomPassword" type="password" placeholder="请输入密码" />
       </el-form-item>
-      <el-form-item label="默认密码:" v-if="editPassWordData.useDefault=='1'">
+      <el-form-item label="默认密码:" v-if="dialogData.type == '2' && editPassWordData.useDefault==1">
         <div class="default_pass">
           <el-input value="******" disabled />
           <p class="default_pass">默认密码:{{ dialogData.remark }}</p>
@@ -33,24 +33,33 @@ export default {
 }
 </script>
 <script lang="ts" setup>
-import { ref, reactive, onMounted, watch, inject } from 'vue'
+import { ref, reactive, onMounted, inject } from 'vue'
 import type { FormInstance, FormRules } from 'element-plus'
 import { ElMessage } from 'element-plus'
 import { resetPassWord } from '@/api/manager'
+import { resetSchoolPassWord } from '@/api/school'
 interface DialogData {
-  dialogShow: boolean
+  dialogShow: boolean,
+  type: string
   name: string,
   label: string,
   id: string
   remark: string
 }
-const dialogData = inject<DialogData>('passwordDialog')
+const dialogData = inject<DialogData>('passwordDialog', {
+  dialogShow: false,
+  type: '',
+  name: '',
+  label: '',
+  id: '',
+  remark: ''
+})
 interface EditPassWordData {
-  useDefault: string
+  useDefault: number
   randomPassword: string
 }
 const editPassWordData = reactive<EditPassWordData>({
-  useDefault: '1',
+  useDefault: 0,
   randomPassword: '',
 })
 const submitLoading = ref(false)
@@ -66,16 +75,27 @@ onMounted(() => {
 })
 const confirmPassWord = async (formEl: FormInstance | undefined) => {
   if (!formEl) return
-  await formEl.validate(async(valid, fields) => {
+  await formEl.validate(async(valid) => {
     if (valid) {
       submitLoading.value = true
       try {
-        const res = await resetPassWord(dialogData.id, { 
-          randomPassword: editPassWordData.useDefault == '1' ? '' : editPassWordData.randomPassword 
-        })
+        let res
+        if(dialogData.type == '1') {
+          res = await resetPassWord(dialogData.id, { 
+            randomPassword: editPassWordData.useDefault == 1 ? '' : editPassWordData.randomPassword 
+          })
+        }else if(dialogData.type == '2')  {
+          res = await resetSchoolPassWord({
+            schoolInfoId: dialogData.id, 
+            useDefault: editPassWordData.useDefault,
+            password: editPassWordData.useDefault == 1 ? '' : editPassWordData.randomPassword 
+          })
+        }
         if (res.code == 200) {
           ElMessage.success(res.msg)
-          editPassWordForm.value.resetFields()
+          if(editPassWordForm.value) {
+            editPassWordForm.value.resetFields()
+          }
           dialogData.dialogShow = false
         } else {
           ElMessage.error(res.msg)

+ 1 - 7
src/layout/components/SiderBar.vue

@@ -4,7 +4,7 @@
       <img v-if="isCollapse" src="@/assets/icon/open.svg" alt="">
       <img v-else src="@/assets/icon/close.svg" alt="">
     </div>
-    <el-menu :collapse="isCollapse" router @handleOpen="handleOpen" @handleClose="handleClose">
+    <el-menu :collapse="isCollapse" router>
       <el-menu-item v-for="item in menuItems" :key="item.route" :index="item.route" :class="activeRoute == item.route ? 'is-active' : ''" >
         <template #default>
           <i class="iconfont" :class="item.icon"></i>
@@ -49,12 +49,6 @@ const menuItems = ref([
     route: '/main/examination',
   }
 ])
-const handleOpen = (key, keyPath) => {
-  console.log(key, keyPath)
-}
-const handleClose = (key, keyPath) => {
-  console.log(key, keyPath)
-}
 const toggleCollapse = () => {
   isCollapse.value = !isCollapse.value
 }

+ 139 - 10
src/layout/components/header.vue

@@ -5,18 +5,139 @@
       <div class="small_head">大数据精准教学平台</div>
     </div>
     <div class="head_content_right">
-      xxxxxx学校
+      <el-dropdown trigger="click" @command="UserCommand" placement="bottom-end">
+        <span class="userName">
+          {{ userInfo.nickname }}
+          <el-icon class="el-icon--right">
+            <arrow-down />
+          </el-icon>
+        </span>
+        <template #dropdown>
+          <el-dropdown-menu>
+            <el-dropdown-item command="setPassWord">修改密码</el-dropdown-item>
+            <el-dropdown-item command="loginOut">退出登录</el-dropdown-item>
+          </el-dropdown-menu>
+        </template>
+      </el-dropdown>
     </div>
+    <el-dialog v-model="dialogShow" title="修改密码" width="450px" :append-to-body="true">
+      <el-form
+        :model="editPassWordData"
+        label-width="80px"
+        :rules="editPassWordDataRules"
+        ref="editPassWordForm"
+      >
+        <el-form-item label="原密码" prop="passWord">
+          <el-input v-model="editPassWordData.passWord" type="password" placeholder="请输入原密码" />
+        </el-form-item>
+        <el-form-item label="新密码" prop="newPassWord">
+          <el-input v-model="editPassWordData.newPassWord" type="password" placeholder="请输入新密码" />
+        </el-form-item>
+        <el-form-item label="确认密码" prop="confirmNewPassWord">
+          <el-input v-model="editPassWordData.confirmNewPassWord" type="password" placeholder="请输入确认新密码" />
+        </el-form-item>
+      </el-form>
+      <template #footer>
+        <el-button class="button_border_grag cancel" @click="dialogShow = false">取 消</el-button>
+        <el-button class="button_background" :loading="submitLoading" @click="confirmPassWord(editPassWordForm)">确 定</el-button>
+      </template>
+    </el-dialog>
   </div>
 </template>
+<script lang="ts">
+export default {
+  name: 'Header'
+}
+</script>
+<script lang="ts" setup>
+import router from '@/router'
+import { ArrowDown } from '@element-plus/icons-vue'
+import { ref, reactive, computed } from 'vue'
+import { loginOut, changePassWord } from '@/api/login'
+import { ElMessage } from 'element-plus'
+import type { FormInstance, FormRules } from 'element-plus'
+import ResetPassword from '@/components/resetPassword.vue'
+const userInfo = computed(() => {
+  const user = localStorage.getItem('userInfo')
+  if (user) {
+    return JSON.parse(user)
+  }
+  return null
+})
+const dialogShow = ref(false)
+interface EditPassWordData {
+  passWord: string
+  newPassWord: string
+  confirmNewPassWord: string
+}
+const editPassWordData = reactive<EditPassWordData>({
+  passWord: '',
+  newPassWord: '',
+  confirmNewPassWord: ''
+}) // 修改密码弹窗数据
+
+const editPassWordForm = ref<FormInstance>()
+const editPassWordDataRules = reactive<FormRules<EditPassWordData>>({
+  passWord: [
+    { required: true, message: '请输入旧密码', trigger: 'blur' }
+  ],
+  newPassWord: [
+    { required: true, message: '请输入新密码', trigger: 'blur' },
+    { min: 6, max: 20, message: '长度在 6 到 20 个字符', trigger: 'blur' },
+  ],
+  confirmNewPassWord: [
+    { required: true, message: '请输入确认新密码', trigger: 'blur' }
+  ]
+})
+const UserCommand = (command: string) => {
+  console.log(command)
+  if(command == 'setPassWord') {
+    setPassWord()
+  }else if(command == 'loginOut') {
+    loginOutFn()
+  }
+}
+const setPassWord = () => {
+  dialogShow.value = true
+}
+const loginOutFn = async () => {
+  console.log(userInfo.value.username)
+  const res = await loginOut(userInfo.value.userid)
+  if(res.code == 200) {
+    localStorage.removeItem('token')
+    localStorage.removeItem('userInfo')
+    router.push('/login')
+  }else {
+    ElMessage.error(res.msg)
+  }
+}
+const submitLoading = ref(false)
+const confirmPassWord = async (formEl: FormInstance | undefined) => {
+  if (!formEl) return
+  await formEl.validate(async(valid) => {
+    if (valid) {
+      submitLoading.value = true
+      try {
+        const res = await changePassWord({
+          oldPassword: editPassWordData.passWord,
+          newPassword: editPassWordData.newPassWord,
+          confirmNewPassword: editPassWordData.confirmNewPassWord,
+        })
+        if(res.code == 200) {
+          ElMessage.success(res.msg)
+          dialogShow.value = false
+        }else {
+          ElMessage.error(res.msg)
+        }
+      }catch {}finally {
+        submitLoading.value = false
+      }
+    }
+  })
+}
+</script>
  
- <script>
- export default {
- 
- }
- </script>
- 
- <style scoped>
+<style lang="scss" scoped>
 .head_content {
   height: 65px;
   padding: 0 50px;
@@ -34,6 +155,14 @@
   color: #fff;
 }
 .head_content_right {
-  color: #fff;
+  .userName {
+    height: 24px;
+    line-height: 24px;
+    color: #fff;
+    cursor: pointer;
+    .el-icon svg {
+      margin-top: 2px;
+    }
+  }
 }
- </style>
+</style>

+ 1 - 1
src/main.ts

@@ -11,7 +11,7 @@ import { setupStore } from './store' // 引入 store 初始化方法
 import './styles/common.scss'
 const app = createApp(App)
 Object.keys(ElIcons).forEach((key) => {
-  app.component(key, ElIcons[key])
+  app.component(key, (ElIcons as Record<string, any>)[key])
 })//ele icon
 
 app.use(ElementPlus)

+ 6 - 6
src/store/index.ts

@@ -1,29 +1,29 @@
-import { createStore } from 'vuex'
-import type { Store } from 'vuex'
+import { createStore } from 'vuex' 
+import type { ActionContext } from 'vuex'
 import type { App } from 'vue'
 
 // 定义 RootState 接口(可扩展)
 interface RootState {
   count: number
 }
-
+type StoreActionContext = ActionContext<RootState, RootState>
 // 创建 store 实例
 const store = createStore<RootState>({
   state: () => ({
     count: 0
   }),
   mutations: {
-    increment(state) {
+    increment(state: RootState) {
       state.count++
     }
   },
   actions: {
-    increment({ commit }) {
+    increment({ commit }: StoreActionContext) {
       commit('increment')
     }
   },
   getters: {
-    count: (state) => state.count
+    count: (state: RootState) => state.count
   }
 })
 

+ 1 - 1
src/utils/request.ts

@@ -1,7 +1,7 @@
 // src/utils/request.ts
 import axios from 'axios'
 import { ElMessage } from 'element-plus'
-import type { AxiosInstance, AxiosRequestConfig, AxiosResponse } from 'axios'
+import type { AxiosInstance, AxiosResponse } from 'axios'
 
 // 创建 axios 实例
 const service: AxiosInstance = axios.create({

+ 32 - 17
src/views/examination/addSchool.vue

@@ -1,5 +1,5 @@
 <template>
-  <el-dialog v-model="schoolData.showDialog" :title="`${schoolData.data.tenantName} 新增学校`" width="680px">
+  <el-dialog v-model="schoolData.showDialog" :title="`${schoolData.tenantName} 新增学校`" width="680px">
     <div class="page_search">
       <div class="search_content">
         <div class="content_left">
@@ -55,7 +55,6 @@
   </el-dialog>
 </template>
 <script lang="ts">
-import Vue from 'vue'
 export default {
   name: 'AddSchool',
 }
@@ -63,7 +62,7 @@ export default {
 <script lang="ts" setup>
 import { Search } from '@element-plus/icons-vue'
 import { ElMessage } from 'element-plus'
-import { ref, inject, reactive, onMounted } from 'vue'
+import { ref, inject, onMounted } from 'vue'
 import { getSingleExamList, addSingleSchool } from '@/api/examination'
 import { provinceTree } from '@/api/school'
 interface SchoolDataItem {
@@ -71,10 +70,20 @@ interface SchoolDataItem {
 }
 interface SchoolData {
   showDialog: boolean
-  data: SchoolDataItem
+  tenantName: string
+  id: string
+}
+const schoolData = inject<SchoolData>('schoolData', {
+  showDialog: false,
+  tenantName: '',
+  id: ''
+})
+interface Province {
+  provinceCode: string
+  provinceName: string
+  children?: any[] // 可选字段
 }
-const schoolData = inject<SchoolData>('schoolData')
-const provincesList = ref([])
+const provincesList = ref<Province[]>([])
 const provinceSelect = ref('')
 const schooltName =  ref('')
 const tableData = ref([])
@@ -93,29 +102,35 @@ const GetProvinceTree = async () => {
     provincesList.value = data
   }
 }
+const tableLoading = ref(false)
 const GetSingleExamList = async () => {
-  const res = await getSingleExamList({
-    queryStr: schooltName.value,
-    provinceCode: provinceSelect.value,
-    // cityCode: '',
-    // areaCode: '',
-  })
-  if (res.code === 200) {
-    tableData.value = res.data
+  try {
+    tableLoading.value = true
+    const res = await getSingleExamList({
+      queryStr: schooltName.value,
+      provinceCode: provinceSelect.value,
+      // cityCode: '',
+      // areaCode: '',
+    })
+    if (res.code === 200) {
+      tableData.value = res.data
+    }
+  }catch {} finally {
+    tableLoading.value = false
   }
 }
 const SearchChange = () => {
   GetSingleExamList()
 }
-const handleSelectionChange = (val) => {
-  selUserList.value = val.map(item => item.id)
+const handleSelectionChange = (val: any) => {
+  selUserList.value = val.map((item: any) => item.id)
 }
 const emit = defineEmits(['RefTable'])
 const AddComfirm = async () => {
   submitLoading.value = true
   try {
     const res = await addSingleSchool({
-      schoolParentId: schoolData.data.id,
+      schoolParentId: schoolData.id,
       schoolChildId: selUserList.value
     })
     if(res.code == 200) {

+ 26 - 5
src/views/examination/index.vue

@@ -113,7 +113,26 @@ import { getJoinExamList, deleteSchool } from '@/api/examination'
 const schooltName = ref('')
 const tableLoading = ref(false)
 const tableData = ref([])
-const selectRow = ref({})
+interface SchoolItem {
+  id: number | string;
+  tenantCode: string;
+  tenantName: string;
+  cityAndAreaName: string;
+  schoolType: number;
+  status: number;
+  childrenCount?: number;
+  children?: SchoolItem[];
+}
+const selectRow = ref<SchoolItem | null>({
+  id: '',
+  tenantCode: '',
+  tenantName: '',
+  cityAndAreaName: '',
+  schoolType: 0,
+  status: 0,
+  childrenCount: 0,
+  children: []
+})
 onMounted(() => {
   GetJoinExamList()
 })
@@ -130,20 +149,22 @@ const GetJoinExamList = () => {
       selectRow.value = tableData.value[0]
     }
     tableLoading.value = false
-  }).catch(err => {
+  }).catch(() => {
     tableLoading.value = false
   })
 }
 const schoolData = reactive({
   showDialog: false,
-  data: {},
+  tenantName: '',
+  id: '' as string | number
 })
 provide('schoolData', schoolData)
 const addSchool = () => {
-  schoolData.data = selectRow.value
+  schoolData.tenantName = selectRow.value.tenantName
+  schoolData.id = selectRow.value.id
   schoolData.showDialog = true
 }
-const DeleteSchool = (row) => {
+const DeleteSchool = (row: any) => {
   ElMessageBox.confirm('确定删除该学校吗?', '提示', {
     confirmButtonText: '确定',
     cancelButtonText: '取消',

+ 8 - 6
src/views/manager/addAdmin.vue

@@ -66,7 +66,7 @@ const userForm = reactive<UserForm>({
   username: '',
   passwordOfNewUser: '',
   phoneNo: '',
-  gender: null,
+  gender: 0,
   status: 1,
 })
 const userFormRef = ref<FormInstance>()
@@ -97,7 +97,7 @@ onMounted(() => {
   }
 })
 const GetManagerDetails = () => {
-  managerDetails(dialogData.id).then(res => {
+  managerDetails(dialogData.id).then((res: any) => {
     if(res.code == 200 && res.data) {
       const { data } = res
       userForm.id = data.id
@@ -113,19 +113,21 @@ const GetManagerDetails = () => {
 const submitLoading = ref(false)
 const SubmitForm = async (formEl: FormInstance | undefined) => {
   if (!formEl) return
-  await formEl.validate(async(valid, fields) => {
+  await formEl.validate(async(valid) => {
     if (valid) {
       submitLoading.value = true
       try {
         let res
-        if(dialogData.pageType == 'add') {
+        if(dialogData?.pageType == 'add') {
           res = await addManager(userForm)
-        }else if(dialogData.pageType == 'edit') {
+        }else if(dialogData?.pageType == 'edit') {
           res = await editManager(userForm)
         }
         if (res.code == 200) {
           ElMessage.success(res.msg)
-          userFormRef.value.resetFields()
+          if(userFormRef.value) {
+            userFormRef.value.resetFields()
+          }
           emit('update', false)
         } else {
           ElMessage.error(res.msg)

+ 15 - 9
src/views/manager/index.vue

@@ -10,7 +10,7 @@
           </el-input>
         </div>
         <div class="content_right">
-          <el-button class="button_border_gray"><img src="@/assets/icon/refresh.svg" alt="" style="margin-right: 5px;">刷新</el-button>
+          <el-button class="button_border_gray" @click="Refresh"><img src="@/assets/icon/refresh.svg" alt="" style="margin-right: 5px;">刷新</el-button>
           <el-button class="button_background" @click="AddManager" >新增用户</el-button>
         </div>
       </div>
@@ -55,7 +55,7 @@
 </template>
 
 <script lang="ts" setup>
-import { ref, reactive, onMounted, onBeforeUnmount, provide} from 'vue'
+import { ref, reactive, onMounted, provide} from 'vue'
 import { Search } from '@element-plus/icons-vue'
 import { ElMessageBox, ElMessage } from 'element-plus'
 import { getUserList } from '@/api/school'
@@ -74,6 +74,7 @@ const dialogData = reactive({
 const passwordDialog = reactive({
   dialogShow: false,
   id: '',
+  type: '',
   name: '',
   label: '',
   remark: ''
@@ -106,23 +107,23 @@ onMounted(() => {
 })
 
 // 表格相关方法
-function GetIndexNumber(index) {
-  return index + 1
-}
+// function GetIndexNumber(index) {
+//   return index + 1
+// }
 const AddManager = () => {
   dialogData.showDialog = true
   dialogData.pageType = 'add'
 }
-const EditManager = (row) => {
+const EditManager = (row: any) => {
   dialogData.showDialog = true
   dialogData.pageType = 'edit'
   dialogData.id = row.id 
 }
-const RefTable = (val) => {
+const RefTable = (val: any) => {
   dialogData.showDialog = val
   GetUserList()
 }
-const DeleteManager = (row) => {
+const DeleteManager = (row: any) => {
   console.log(row)
   ElMessageBox.confirm('确定删除该用户吗?', '提示', {
     confirmButtonText: '确定',
@@ -138,14 +139,19 @@ const DeleteManager = (row) => {
     }
   })
 }
-const EditPassword = (row) => {
+const EditPassword = (row: any) => {
   console.log(row)
   passwordDialog.dialogShow = true
   passwordDialog.id = row.id
+  passwordDialog.type = '1'
   passwordDialog.name = row.nickname
   passwordDialog.label = '用户姓名'
   passwordDialog.remark = '用户账号'
 }
+const Refresh = () => {
+  keyWord.value = ""
+  GetUserList()
+}
 
 </script>
 

+ 37 - 4
src/views/school/SearchMain.vue

@@ -49,15 +49,48 @@ const searchData = ref({
   status: '',
   userId: '',
 })
-const cityNode = ref([])
-const searchList =  ref({
+interface City {
+  cityCode:  string
+  cityName:  string
+}
+const cityNode = ref<City[]>([])
+interface Province {
+  provinceCode: string;
+  provinceName: string;
+  children?: City[]; // 如果有子级城市数据的话
+}
+
+interface City {
+  cityCode: string;
+  cityName: string;
+}
+
+interface StatusNode {
+  status: string;
+  statusName: string;
+}
+
+interface UserInfo {
+  userId: string;
+  nickname: string;
+}
+
+interface SearchList {
+  examTypes: any[]; 
+  provinceNode: Province[];
+  statusNode: StatusNode[];
+  userInfo: UserInfo[];
+}
+const searchList =  ref<SearchList>({
   examTypes: [],
   provinceNode: [],
   statusNode: [],
   userInfo: []
 })
 const emit = defineEmits(['FnSearch'])
-const selectItem = (value, str, item) => {
+
+type SearchDataKey = 'provinceCode' | 'cityCode' | 'status' | 'userId'
+const selectItem = (value: string, str: SearchDataKey, item: any) => {
   searchData.value[str] = value
   let arr = []
   if(str == 'provinceCode') {
@@ -77,7 +110,7 @@ onMounted(() => {
   GetSearchList()
 })
 const GetSearchList = () => {
-  getSearchList().then(res => {
+  getSearchList().then((res: any) => {
     console.log(res)
     if(res.code == 200) {
       const { data } = res

+ 47 - 24
src/views/school/addUser.vue

@@ -104,7 +104,7 @@ export default {
 }
 </script>
 <script lang="ts" setup>
-import { ref, reactive, inject, onMounted, nextTick } from 'vue'
+import { ref, reactive, inject, onMounted } from 'vue'
 import type { FormInstance, FormRules } from 'element-plus'
 import { ElMessage } from 'element-plus'
 import { getUserList, addUser, uploadFile, provinceTree, getSchoolInfo, editSchoolInfo } from '@/api/school'
@@ -113,7 +113,10 @@ interface DialogData {
   id: string
 }
 let showDialog = inject('showDialog')
-let dialogData = inject<DialogData>('dialogData')
+let dialogData = inject<DialogData>('dialogData', {
+  pageType: 'add',
+  id: ''
+})
 const formLabelWidth = '120px'
 // 新增用户表单数据定义
 interface UserForm {
@@ -187,15 +190,34 @@ const rules = reactive<FormRules<UserForm>>({
   //   { required: true, message: '请选择运维人员', trigger: 'change' }
   // ]
 })
+interface Province {
+  provinceCode: string
+  provinceName: string
+  children?: City[] // 可选字段
+}
 
+interface City {
+  cityCode: string
+  cityName: string
+  children?: District[]
+}
+
+interface District {
+  districtCode: string
+  districtName: string
+}
 // 省份列表
-const provinceTreeList = ref([])
+const provinceTreeList = ref<Province[]>([])
 // 市列表
-const cityTreeList = ref([])
+const cityTreeList = ref<City[]>([])
 // 区/县列表
-const areaList = ref([])
+const areaList = ref<District[]>([])
+interface User {
+  id: string
+  nickname: string
+}
 // 运维人员列表
-const userList = ref([])
+const userList = ref<User[]>([])
 // 提交按钮loading
 const submitLoading = ref(false)
 onMounted (async () => {
@@ -207,7 +229,7 @@ onMounted (async () => {
 })
 // 获取用户详情
 const GetUserDetail = () => {
-  getSchoolInfo(dialogData.id).then(res => {
+  getSchoolInfo(dialogData.id).then((res: any) => {
     if(res.code == 200 && res.data) {
       const { data } = res
       if(data.provinceCode) {
@@ -237,7 +259,7 @@ const GetUserDetail = () => {
 }
 // 获取运维人员列表
 const GetUserList = () => {
-  getUserList({}).then(res => {
+  getUserList({}).then((res: any) => {
     if(res.code == 200 && res.data) {
       const { data } = res
       userList.value = data
@@ -246,8 +268,8 @@ const GetUserList = () => {
 }
 // 获取省市区树列表
 const GetProvinceTree = (): Promise<void> => {
-  return new Promise((resolve, reject) => {
-    provinceTree().then(res => {
+  return new Promise((resolve) => {
+    provinceTree().then((res: any) => {
       if(res.code == 200 && res.data) {
         const { data } = res
         provinceTreeList.value = data
@@ -256,33 +278,32 @@ const GetProvinceTree = (): Promise<void> => {
     })
   })
 }
-const fileImageUrl = ref('')
 // 选择省份
-const handleProvinceChange = (val) => {
+const handleProvinceChange = (val: any) => {
   userForm.provinceCode = val
-  userForm.provinceName = provinceTreeList.value.find(item => item.provinceCode == val).provinceName
-  cityTreeList.value = provinceTreeList.value.find(item => item.provinceCode == val).children
+  userForm.provinceName = provinceTreeList.value.find(item => item.provinceCode == val)?.provinceName
+  cityTreeList.value = provinceTreeList.value.find(item => item.provinceCode == val)?.children
   areaList.value = []
   userForm.cityCode = ''
   userForm.areaCode = ''
 }
 // 选择市
-const handleCityChange = (val) => {
+const handleCityChange = (val: any) => {
   userForm.cityCode = val
-  userForm.cityName = cityTreeList.value.find(item => item.cityCode == val).cityName
-  areaList.value = cityTreeList.value.find(item => item.cityCode == val).children
+  userForm.cityName = cityTreeList.value.find(item => item.cityCode == val)?.cityName
+  areaList.value = cityTreeList.value.find(item => item.cityCode == val)?.children
   userForm.areaCode = ''
 }
 // 选择区/县
-const handleAreaChange = (val) => {
+const handleAreaChange = (val: any) => {
   userForm.areaCode = val
-  userForm.areaName = areaList.value.find(item => item.districtCode == val).districtName
+  userForm.areaName = areaList.value.find(item => item.districtCode == val)?.districtName
 }
 // 上传学校logo
-const UploadLogo = (file) => {
+const UploadLogo = (file: any) => {
   let formData = new FormData();
   formData.append("file", file.file);
-  uploadFile(formData).then(res => {
+  uploadFile(formData).then((res: any) => {
     console.log(res)
     if(res.code == 200 && res.data) {
       const { data } = res
@@ -291,7 +312,7 @@ const UploadLogo = (file) => {
   })
 }
 // 选择运维人员
-const handleUserChange = (val) => {
+const handleUserChange = (val: any) => {
   console.log(val)
   let result = userList.value.filter(item => val.includes(item.id)).map(item => {
     return { id: item.id }
@@ -304,7 +325,7 @@ const emit = defineEmits(['AddUser'])
 // 表单提交
 const SubmitForm = async (formEl: FormInstance | undefined) => {
   if (!formEl) return
-  await formEl.validate(async(valid, fields) => {
+  await formEl.validate(async(valid) => {
     if (valid) {
       submitLoading.value = true
       try {
@@ -316,7 +337,9 @@ const SubmitForm = async (formEl: FormInstance | undefined) => {
         }
         if (res.code == 200) {
           ElMessage.success(res.msg)
-          userFormRef.value.resetFields()
+          if(userFormRef.value) {
+            userFormRef.value.resetFields()
+          }
           emit('AddUser', false)
         } else {
           ElMessage.error(res.msg)

+ 28 - 11
src/views/school/authConfig.vue

@@ -11,7 +11,7 @@
       <div v-if="authType == '1'" class="grade_content">
         <div v-for="(grade, index) in gradeList" :key="grade.levelCode" class="grade_level">
           <el-checkbox v-model="checkAll[index]" :indeterminate="!checkAll[index] && selectedGrades[index]?.length > 0" :label="grade.levelName" @click="CheckAllChange(index)" />
-          <el-checkbox-group v-model="selectedGrades[index]" @change="(val) =>handleGradeChange(index, val)">
+          <el-checkbox-group v-model="selectedGrades[index]" @change="val =>handleGradeChange(index, val)">
             <el-checkbox v-for="item in grade.gradeList" :key="item.gradeCode" :label="item.gradeName" :value="item.gradeCode" />
           </el-checkbox-group>
           <!-- <div>
@@ -41,17 +41,31 @@ interface AuthData {
   tenantCode: string
   id: string
 }
-let authData = inject<AuthData>('authData')
-const gradeList = ref([])
+let authData = inject<AuthData>('authData', {
+  showDialog: false,
+  schoolName: '',
+  tenantCode: '',
+  id: ''
+})
+interface GradeData {
+  gradeName: string
+  gradeCode: string
+  schoolId: string
+  gradeList: any[]
+  levelCode: string
+  levelName: string
+  levelNumder?: number 
+}
+const gradeList = ref<GradeData[]>([])
 const authType = ref('1')
 const submitLoading = ref(false)
-const checkAll = ref([])
-const selectedGrades = ref([])
+const checkAll = ref<boolean[]>([])
+const selectedGrades = ref<string[][]>([])
 onMounted (() => {
   GetAllGrade()
 })
 const GetAllGrade = () => {
-  getAllGrade(authData.id).then(res => {
+  getAllGrade(authData.id).then((res: any) => {
     if(res.code == 200 && res.data) {
       const { data } = res
       gradeList.value = data
@@ -70,17 +84,17 @@ const GetAllGrade = () => {
     }
   })
 }
-const ChangeTab = (val) => {
+const ChangeTab = (val: any) => {
   console.log(val)
 }
-const CheckAllChange = (index) => {
+const CheckAllChange = (index: number) => {
   if(!checkAll.value[index]) {
     selectedGrades.value[index] = gradeList.value[index].gradeList.map(item => item.gradeCode)
   }else {
     selectedGrades.value[index] = []
   }
 }
-const handleGradeChange = (index, val) => {
+const handleGradeChange = (index: number, val: string[]) => {
   if(gradeList.value[index].gradeList.length == val.length) {
     checkAll.value[index] = true
   } else if(val.length == 0) {
@@ -90,10 +104,13 @@ const handleGradeChange = (index, val) => {
   }
 }
 const SubmitForm = async () => {
+  if(!authData) {
+    return
+  }
   try {
     submitLoading.value = true
-    let arrList = gradeList.value.map((item, index) => {
-      let arr = item.gradeList.filter(i => selectedGrades.value[index].includes(i.gradeCode))
+    let arrList = gradeList.value.map((item: any, index: number) => {
+      let arr = item.gradeList.filter((i: any) => selectedGrades.value[index].includes(i.gradeCode))
       return {
         levelCode: item.levelCode,
         levelName: item.levelName,

+ 40 - 16
src/views/school/index.vue

@@ -48,7 +48,7 @@
             </el-input>
           </div>
           <div class="content_right">
-            <el-button class="button_border_gray">
+            <el-button class="button_border_gray" @click="Refresh">
               <img src="@/assets/icon/refresh.svg" alt="" style="margin-right: 5px;">刷新
             </el-button>
             <el-button class="button_border" @click="OpenSubject">开通科目</el-button>
@@ -91,9 +91,9 @@
                 </div>
               </template>
             </el-table-column>
-            <el-table-column prop="nicknames" label="运维人员" align="center">
+            <el-table-column prop="sysUserName" label="运维人员" align="center">
               <template #default="{ row }">
-                {{ row.nicknames ||  '-' }}
+                {{ row.sysUserName ||  '-' }}
               </template>
             </el-table-column>
             <el-table-column label="操作" width="280" fixed="right" align="center">
@@ -103,7 +103,7 @@
                   <div v-else class="button_editor text_color_orange" @click="ChangeStatus(row)">冻结</div>
                   <div class="button_editor" @click="EditUser(row)">编辑</div>
                   <div class="button_editor" @click="OpenAuth(row)">权限</div>
-                  <div class="button_editor">重置密码</div>
+                  <div class="button_editor" @click="resetPassWord(row)">重置密码</div>
                   <div class="button_editor" @click="GoTeach(row)">进入学校</div>
                 </div>
               </template>
@@ -116,6 +116,7 @@
       <AddUser v-if="showDialog" @AddUser="RefTable" /> 
       <AuthConfig v-if="authData.showDialog" />
       <SubjectList v-if="subjectShowDialog" />
+      <ResetPassword v-if="passwordDialog.dialogShow" />
     </div>
   </div>
 </template>
@@ -125,8 +126,9 @@ import SearchMain from '@/views/school/SearchMain.vue'
 import AddUser from '@/views/school/addUser.vue'
 import AuthConfig from '@/views/school/authConfig.vue'
 import SubjectList from '@/views/school/subjectList.vue'
+import ResetPassword from '@/components/resetPassword.vue'
 import { Search } from '@element-plus/icons-vue'
-import { getSchoolNumber, getSchoolList, changeStatus, loginTeach } from '@/api/school'
+import { getSchoolNumber, getSchoolList, changeStatus } from '@/api/school'
 import { ref, reactive, provide, onMounted } from 'vue'
 interface UserNumber {
   allUser: number
@@ -151,7 +153,7 @@ interface User {
   startDate:  String;
   endDate:  String;
   sysUserId: String;
-  nicknames:  String;
+  sysUserName:  String;
   cityAndAreaName:  String;
 }
 const tableData = ref<User[]>([])
@@ -172,10 +174,19 @@ const authData = reactive({
   schoolName: '',
   tenantCode: ''
 })
+const passwordDialog = reactive({
+  dialogShow: false,
+  id: '',
+  type: '',
+  name: '',
+  label: '',
+  remark: ''
+}) // 重置密码弹窗数据
 provide('showDialog', showDialog) // 新增用户弹窗是否展示
 provide('dialogData', dialogData) // 新增用户弹窗数据
 provide('authData', authData) // 设置权限弹窗数据
 provide('subjectShowDialog', subjectShowDialog) // 开通科目弹窗数据
+provide('passwordDialog', passwordDialog) // 重置密码弹窗数据
 onMounted(() => {
   GetSchoolNumber()
   GetSchoolList()
@@ -186,7 +197,7 @@ const addUser = () => {
   dialogData.pageType = 'add'
 }
 // 编辑
-const EditUser =  (row) => {
+const EditUser =  (row: any) => {
   console.log(row)
   showDialog.value = true
   dialogData.pageType = 'edit'
@@ -194,7 +205,7 @@ const EditUser =  (row) => {
   dialogData.tenantName = row.tenantName
 }
 // 设置权限
-const OpenAuth = (row) => {
+const OpenAuth = (row: any) => {
   authData.id = row.id
   authData.schoolName = row.tenantName
   authData.tenantCode = row.tenantCode
@@ -213,7 +224,7 @@ const searchData = ref({
   userId: ''
 })
 // 筛选项查询
-const FnSearch = (data) => {
+const FnSearch = (data: any) => {
   searchData.value = data.value
   GetSchoolList()
 }
@@ -223,7 +234,7 @@ const SearchChange = () => {
 }
 // 获取用户数量
 const GetSchoolNumber = () => {
-  getSchoolNumber().then(res => {
+  getSchoolNumber().then((res: any) => {
     if(res.code == 200 && res.data) {
       userNumber.value = res.data
     }
@@ -240,36 +251,49 @@ const GetSchoolList = () => {
     queryStr: schoolNameCode.value
   }
   tableLoading.value = true
-  getSchoolList(params).then(res => {
+  getSchoolList(params).then((res: any) => {
     if(res.code == 200 && res.data) {
       tableData.value = res.data
     }
     tableLoading.value = false
-  }).catch(err => {
+  }).catch(() => {
     tableLoading.value = false
   })
 }
 // 新增/修改学校信息后刷新列表
-const RefTable = (val) => {
+const RefTable = (val: any) => {
   showDialog.value = val
   GetSchoolList()
 }
 // 改变用户状态
-const ChangeStatus = (row) => {
+const ChangeStatus = (row: any) => {
   console.log(row)
   changeStatus({
     id: row.id,
     status: row.status == 0 ? 1 : 0
-  }).then(res => {
+  }).then((res: any) => {
     if(res.code == 200) {
       GetSchoolList()
     }
   })
 }
-const GoTeach = (row) => {
+const GoTeach = (row: any) => {
   let accessToken = localStorage.getItem('token')
   window.open(`https://dev3.k12100.net/#/otherLogin?schoolId=${row.id}&adminToken=${accessToken}`)
 }
+const resetPassWord = (row: any) => {
+  passwordDialog.dialogShow = true
+  passwordDialog.id = row.id
+  passwordDialog.type = '2'
+  passwordDialog.name = row.tenantName
+  passwordDialog.label = '学校名称'
+  passwordDialog.remark = '学校编号'
+}
+const Refresh = () => {
+  schoolTypeSelect.value = " "
+  schoolNameCode.value = ""
+  GetSchoolList()
+}
 </script>
 
 <style lang="scss" scoped>

+ 10 - 6
src/views/school/subjectList.vue

@@ -28,11 +28,15 @@ export default {
 }
 </script>
 <script lang="ts" setup>
-import { ref, inject, reactive, nextTick, onMounted } from 'vue'
+import { ref, inject, nextTick, onMounted } from 'vue'
 import { ElMessage } from 'element-plus'
 import { getAllSubject, deleteSubject, addSubject } from '@/api/school'
 let subjectShowDialog = inject('subjectShowDialog')
-const subjectList = ref([])
+interface subjectList {
+  id: number
+  courseName: string
+}
+const subjectList = ref<subjectList[]>([])
 const inputValue = ref('')
 const inputVisible = ref(false)
 onMounted(() => {
@@ -40,7 +44,7 @@ onMounted(() => {
 })
 // 获取所有科目
 const GetAllSubject = () => {
-  getAllSubject({}).then((res) => {
+  getAllSubject({}).then((res: any) => {
     if (res.code === 200 && res.data) {
       const { data } = res
       subjectList.value = data
@@ -56,7 +60,7 @@ const InputBlur = () => {
 }
 const handleInputConfirm = () => {
   if (inputValue.value) {
-    addSubject({ courseName: inputValue.value }).then((res) => {
+    addSubject({ courseName: inputValue.value }).then((res: any) => {
       if (res.code === 200 && res.data) {
         ElMessage.success(res.msg)
         GetAllSubject()
@@ -83,8 +87,8 @@ const cancelAdd = () => {
   inputVisible.value = false
   inputValue.value = ''
 }
-const delSubject = (id) => {
-  deleteSubject({ ids: [id] }).then((res) => { 
+const delSubject = (id: number) => {
+  deleteSubject({ ids: [id] }).then((res: any) => { 
     if (res.code === 200) {
       ElMessage.success(res.msg)
       GetAllSubject()

+ 1 - 1
tsconfig.json

@@ -6,7 +6,7 @@
   ],
   "compilerOptions": {
     "moduleResolution": "node",
-    
+    "types": ["vite/env", "vuex"],
     "baseUrl": "./",
     "paths": {
       "@/*": ["src/*"]