Xiao_123 2 månader sedan
förälder
incheckning
0d44d8714b

+ 3 - 0
components.d.ts

@@ -73,4 +73,7 @@ declare module 'vue' {
     VerifySlide: typeof import('./src/components/Verifition/Verify/VerifySlide.vue')['default']
     VerifySlide: typeof import('./src/components/Verifition/Verify/VerifySlide.vue')['default']
     WangEditor: typeof import('./src/components/FormUI/wangEditor/index.vue')['default']
     WangEditor: typeof import('./src/components/FormUI/wangEditor/index.vue')['default']
   }
   }
+  export interface ComponentCustomProperties {
+    vLoading: typeof import('element-plus/es')['ElLoadingDirective']
+  }
 }
 }

+ 39 - 0
src/api/school.js

@@ -94,3 +94,42 @@ export const getSchoolOrganizationList = async (params) => {
 		params
 		params
 	})
 	})
 }
 }
+
+// 获取机构分页
+export const getOrganizationPage = async (params) => {
+	return await request.get({
+		url: '/app-api/menduner/system/teacher/school/organization/page',
+		params
+	})
+}
+
+// 获取机构列表
+export const getOrganizationList = async (params) => {
+	return await request.get({
+		url: '/app-api/menduner/system/teacher/school/organization/list',
+		params
+	})
+}
+
+// 创建机构
+export const createOrganization = async (data) => {
+	return await request.post({
+		url: '/app-api/menduner/system/teacher/school/organization/create',
+		data
+	})
+}
+
+// 更新机构
+export const updateOrganization = async (data) => {
+	return await request.post({
+		url: '/app-api/menduner/system/teacher/school/organization/update',
+		data
+	})
+}
+
+// 删除机构
+export const deleteOrganization = async (id) => {
+	return await request.post({
+		url: '/app-api/menduner/system/teacher/school/delete?id=' + id
+	})
+}

+ 1 - 1
src/components/CtFilter/index.vue

@@ -1,6 +1,6 @@
 <template>
 <template>
 	<v-card style="width:100%; min-height: 80px;" elevation="5">
 	<v-card style="width:100%; min-height: 80px;" elevation="5">
-		<v-form v-model="valid" ref="formRef">
+		<v-form v-model="valid" ref="formRef" @submit.prevent>
 			<div class="flex-horizon d-flex pa-2 flex-wrap">
 			<div class="flex-horizon d-flex pa-2 flex-wrap">
 				<div v-for="(item, index) in items.options" :key="`filter_${item.label}_${index}`" class="pa-3" v-show="!item.hidden">
 				<div v-for="(item, index) in items.options" :key="`filter_${item.label}_${index}`" class="pa-3" v-show="!item.hidden">
 					<textUI
 					<textUI

+ 20 - 0
src/router/modules/components/recruit/teacher.js

@@ -117,6 +117,26 @@ const teacher = [
       },
       },
     ]
     ]
   },
   },
+  {
+    path: '/recruit/teacher/organization',
+    component: Layout,
+    name: '学校机构',
+    icon: 'mdi-file-tree-outline',
+    meta: {
+      enName: 'Teacher Organization'
+    },
+    children: [
+      {
+        path: 'index',
+        name: '学校机构',
+        meta: {
+          enName: 'Teacher Organization',
+        },
+        show: true,
+        component: () => import('@/views/recruit/teacher/organization/index.vue')
+      },
+    ]
+  },
 ]
 ]
 
 
 function traverse(list, type) {
 function traverse(list, type) {

+ 69 - 0
src/views/recruit/teacher/organization/FormPage.vue

@@ -0,0 +1,69 @@
+<template>
+  <CtForm ref="CtFormRef" :items="formItems"></CtForm>
+</template>
+
+<script setup>
+import { ref } from 'vue'
+import { updateOrganization, createOrganization } from '@/api/school'
+import Snackbar from '@/plugins/snackbar'
+
+const props = defineProps({
+  editItem: {
+    type: Object,
+    default: null
+  }
+})
+
+const CtFormRef = ref()
+const formItems = ref({
+  options: [
+    {
+      type: 'text',
+      key: 'name',
+      value: null,
+      label: '院系名称 *',
+      rules: [v => !!v || '请输入院系名称']
+    }
+  ]
+})
+
+if (props.editItem) {
+  formItems.value.options.forEach(e => {
+    e.value = props.editItem[e.key]
+  })
+}
+
+const submit = async () => {
+	const { valid } = await CtFormRef.value.formRef.validate()
+	if (!valid) return
+
+	let obj = {
+		schoolId: JSON.parse(localStorage.getItem('schoolInfo'))?.schoolId,
+		type: '0', // 0院系|1专业|2班级
+		parentId: 0
+	}
+	formItems.value.options.forEach(e => obj[e.key] = e.value)
+
+  if (props.editItem) {
+    obj.id = props.editItem.id
+  }
+
+  const subApi = props.editItem ? updateOrganization : createOrganization
+  return new Promise((resolve, reject) => {
+    subApi(obj).then(data => {
+      resolve(data)
+      Snackbar.success(props.editItem ? '保存成功' : '提交成功' )
+    }).catch(err => {
+      Snackbar.error(err.msg)
+    })
+  })
+}
+
+defineExpose({
+  submit
+})
+</script>
+
+<style lang="scss" scoped>
+
+</style>

+ 147 - 0
src/views/recruit/teacher/organization/index.vue

@@ -0,0 +1,147 @@
+<template>
+  <CtFilter :items="formItems" @reset="handleReset" @search="handleSearch">
+    <template #appendBtn>
+      <v-btn class="ml-3 elevation-5" color="#00897B" @click="handleAdd">
+        <v-icon left>mdi-plus</v-icon>
+        {{ t('common.add') }} 
+      </v-btn>
+    </template>
+  </CtFilter>
+
+  <v-card class="pa-5 card-box mt-3">
+    <CtTable
+      :items="items"
+      :headers="headers"
+      :loading="loading"
+      :showPage="true"
+      :total="total"
+      :page-info="pageInfo"
+      itemKey="id"
+      :isTools="false"
+      @pageHandleChange="handleChangePage"
+    >
+      <template #status="{ item }">
+        <v-chip :color="item.status === '0' ? 'success' : 'error'" size="small" label>{{ item.statusName }}</v-chip>
+      </template>
+      <template #actions="{ item }">
+        <v-btn variant="text" color="primary" @click="handleEdit(item)">编辑</v-btn>
+        <v-btn variant="text" color="error" @click="handleDel(item)">删除</v-btn>
+      </template>
+    </CtTable>
+  </v-card>
+
+  <CtDialog :visible="show" :widthType="2" :title="editItem ? '编辑院系' : '新增院系'" @close="show = false" @submit="handleSubmit">
+    <FormPage ref="formPageRef" :editItem="editItem" />
+  </CtDialog>
+</template>
+
+<script setup>
+defineOptions({ name: 'organization' })
+import { ref } from 'vue'
+
+import { useI18n } from '@/hooks/web/useI18n'
+import Confirm from '@/plugins/confirm'
+import Snackbar from '@/plugins/snackbar'
+import { formatDate } from '@/utils/date'
+import { deleteOrganization, getOrganizationPage } from '@/api/school'
+import FormPage from './FormPage.vue'
+
+
+const { t } = useI18n()
+const total = ref(10)
+const items = ref([])
+const show = ref(false)
+const loading = ref(false)
+const formPageRef = ref()
+const editItem = ref(null)
+
+// 检索框
+const formItems = ref({
+  options: [
+		{
+      type: 'text',
+      key: 'name',
+      value: '',
+      label: '院系名称',
+			clearable: true,
+			hideDetails: true,
+			width: 200
+    }
+  ]
+})
+
+const query = ref({
+  name: null
+})
+const pageInfo = ref({
+  pageNo: 1,
+  pageSize: 10
+})
+
+const headers = [
+  { title: '院系名称', key: 'name', align: 'left', sortable: false },
+  { title: '创建时间', key: 'createTime', value: (e) => formatDate(e.createTime), sortable: false },
+  { title: t('common.actions'), key: 'actions', sortable: false }
+]
+// 列表
+const getPage = async () => {
+  loading.value = true
+  try {
+    const res = await getOrganizationPage({ ...pageInfo.value, ...query.value })
+    items.value = res.list || []
+    total.value = res.total
+  } finally {
+    loading.value = false
+  }
+}
+
+// 检索
+const handleSearch = (obj) => {
+  pageInfo.value.pageNo = 1
+  query.value = obj
+  getPage()
+}
+
+// 重置
+const handleReset = (obj) => {
+  pageInfo.value.pageNo = 1
+  query.value = obj
+  getPage()
+}
+
+// 新增
+const handleAdd = () => {
+  editItem.value = null
+  show.value = true
+}
+
+// 编辑
+const handleEdit = (item) => {
+  editItem.value = item
+  show.value = true
+}
+
+// 新增、编辑提交
+const handleSubmit = async () => {
+	await formPageRef.value.submit()
+	show.value = false
+	getPage()
+}
+
+// 删除
+const handleDel = async (item) => {
+  Confirm(t('common.confirmTitle'), '是否确定删除?').then(async () => {
+    await deleteOrganization(item.id)
+    Snackbar.success('删除成功')
+    getPage()
+  })
+}
+
+// 分页
+const handleChangePage = (index) => {
+  pageInfo.value.pageNo = index
+  getPage()
+}
+
+getPage()
+</script>

+ 18 - 46
src/views/recruit/teacher/teacherCertification/teacherInfo.vue

@@ -17,19 +17,6 @@
         </div>
         </div>
         <div style="font-size: 14px; color: var(--color-999);">只支持JPG、JPEG、PNG类型的图片,大小不超过20M</div>
         <div style="font-size: 14px; color: var(--color-999);">只支持JPG、JPEG、PNG类型的图片,大小不超过20M</div>
       </template>
       </template>
-			<template #organizationList>
-				<div class="pa-5 mb-3" style="width: 100%; border: 1px dashed #ccc; border-radius: 4px;">
-					<p class="color-999 font-size-14 mb-3">
-						<span class="color-error">*</span>
-						负责院系
-					</p>
-					<div v-for="(k, index) in departmentList" :key="index" class="d-flex align-center mb-5">
-						<TextInput v-model="k.name" :item="textItem" />
-						<v-icon v-if="index > 0" class="ml-3 cursor-pointer" @click="handleDeleteDepartment(index)" color="error">mdi-close-circle</v-icon>
-					</div>
-					<v-btn class="mt-3" color="primary" prepend-icon="mdi-plus" size="small" @click="handleAddDepartment">添加院系</v-btn>
-				</div>
-			</template>
 		</CtForm>
 		</CtForm>
 		<v-btn class="buttons my-10" color="primary" @click.stop="handleSubmit">{{ $t('common.save') }}</v-btn>
 		<v-btn class="buttons my-10" color="primary" @click.stop="handleSubmit">{{ $t('common.save') }}</v-btn>
 	</div>
 	</div>
@@ -47,19 +34,10 @@ import { useI18n } from '@/hooks/web/useI18n'
 import { useUserStore } from '@/store/user'
 import { useUserStore } from '@/store/user'
 import { uploadFile } from '@/api/common'
 import { uploadFile } from '@/api/common'
 import Snackbar from '@/plugins/snackbar'
 import Snackbar from '@/plugins/snackbar'
-import { updateTeacherInfo } from '@/api/school'
+import { updateTeacherInfo, getOrganizationList } from '@/api/school'
 
 
 const showIcon = ref(false)
 const showIcon = ref(false)
 const CtFormRef = ref()
 const CtFormRef = ref()
-const departmentList = ref([{ name: '' }])
-const textItem = {
-	type: 'text',
-  key: 'name',
-	width: 450,
-  label: '院系名称 *',
-	hideDetails: true,
-  rules: [v => !!v || '请输入您负责的院系名称']
-}
 const formItems = ref({
 const formItems = ref({
   options: [
   options: [
 		{
 		{
@@ -100,11 +78,16 @@ const formItems = ref({
       label: '电子邮箱'
       label: '电子邮箱'
     },
     },
     {
     {
-			slotName: 'organizationList',
+      type: 'autocomplete',
       key: 'organizationList',
       key: 'organizationList',
-			noParam: true,
+      value: [],
       label: '负责院系 *',
       label: '负责院系 *',
-      rules: [v => !!v || '请填写您在学校负责的院系']
+      itemText: 'name',
+      itemValue: 'id',
+      multiple: true,
+      returnObject: true,
+      rules: [v => !!v || '请选择您在学校负责的院系'],
+      items: []
     }
     }
   ]
   ]
 })
 })
@@ -117,8 +100,15 @@ userStore.$subscribe((mutation, state) => {
   schoolInfo.value = state.schoolInfo
   schoolInfo.value = state.schoolInfo
 })
 })
 
 
+// 院系列表
+const getSchoolOrganizationList = async () => {
+  const data = await getOrganizationList({ schoolId: schoolInfo.value.schoolId })
+  formItems.value.options.find(e => e.key === 'organizationList').items = data || []
+}
+
 onMounted(async () => {
 onMounted(async () => {
 	await userStore.getSchoolInfo()
 	await userStore.getSchoolInfo()
+  await getSchoolOrganizationList()
 
 
 	// 获取性别字典数据
 	// 获取性别字典数据
 	const sexItem = formItems.value.options.find(e => e.key === 'sex')
 	const sexItem = formItems.value.options.find(e => e.key === 'sex')
@@ -127,21 +117,10 @@ onMounted(async () => {
 	sexItem.items = data || []
 	sexItem.items = data || []
 
 
 	formItems.value.options.forEach(item => {
 	formItems.value.options.forEach(item => {
-		if (!item.noParam) item.value = schoolInfo.value[item.key] || item.defaultValue
-		else {
-			departmentList.value = schoolInfo.value?.organizationList && schoolInfo.value.organizationList.length ? schoolInfo.value.organizationList : [{ name: '' }]
-		}
+		item.value = schoolInfo.value[item.key] || item.defaultValue
 	})
 	})
 })
 })
 
 
-// 添加院系
-const handleAddDepartment = () => {
-	departmentList.value.push({ name: '' })
-}
-// 删除院系
-const handleDeleteDepartment = (index) => {
-	departmentList.value.splice(index, 1)
-}
 
 
 // 图片裁剪
 // 图片裁剪
 const overlay = ref(false)
 const overlay = ref(false)
@@ -203,18 +182,11 @@ const handleHideCopper = (data) => {
 const handleSubmit = async () => {
 const handleSubmit = async () => {
   const { valid } = await CtFormRef.value.formRef.validate()
   const { valid } = await CtFormRef.value.formRef.validate()
   if (!valid) return
   if (!valid) return
-
-	const isCheck = departmentList.value.every(item => item.name)
-	if (!isCheck) return Snackbar.warning('请将院系信息填写完整')
-
   overlay.value = true
   overlay.value = true
-
   let obj = {
   let obj = {
-    id: schoolInfo.value.id,
-    organizationList: departmentList.value?.length ? departmentList.value.map(e => { return { name: e.name } }) : []
+    id: schoolInfo.value.id
   }
   }
 	formItems.value.options.forEach(item => {
 	formItems.value.options.forEach(item => {
-		if (item.noParam) return
 		obj[item.key] = item.value
 		obj[item.key] = item.value
 	})
 	})