提交 de9196db authored 作者: haodaking's avatar haodaking

chore: 校友管理

上级 d72c2d94
......@@ -9,6 +9,7 @@
"version": "0.0.0",
"dependencies": {
"@tinymce/tinymce-vue": "^5.0.0",
"@vant/area-data": "^1.3.1",
"axios": "^0.27.2",
"blueimp-md5": "^2.19.0",
"countup.js": "^2.2.0",
......@@ -538,6 +539,11 @@
"url": "https://opencollective.com/typescript-eslint"
}
},
"node_modules/@vant/area-data": {
"version": "1.3.1",
"resolved": "https://registry.npmjs.org/@vant/area-data/-/area-data-1.3.1.tgz",
"integrity": "sha512-xji2kfVBXzFYmHAJNbhYjiRJ4GnN+enbTmtx6FnpTyxs9sUcFtS11BZ23hYCGuj4s02gXyrzUBTXGqhX5IKHIw=="
},
"node_modules/@vitejs/plugin-vue": {
"version": "2.3.3",
"resolved": "https://registry.npmjs.org/@vitejs/plugin-vue/-/plugin-vue-2.3.3.tgz",
......@@ -5101,6 +5107,11 @@
"eslint-visitor-keys": "^3.3.0"
}
},
"@vant/area-data": {
"version": "1.3.1",
"resolved": "https://registry.npmjs.org/@vant/area-data/-/area-data-1.3.1.tgz",
"integrity": "sha512-xji2kfVBXzFYmHAJNbhYjiRJ4GnN+enbTmtx6FnpTyxs9sUcFtS11BZ23hYCGuj4s02gXyrzUBTXGqhX5IKHIw=="
},
"@vitejs/plugin-vue": {
"version": "2.3.3",
"resolved": "https://registry.npmjs.org/@vitejs/plugin-vue/-/plugin-vue-2.3.3.tgz",
......
......@@ -14,6 +14,7 @@
},
"dependencies": {
"@tinymce/tinymce-vue": "^5.0.0",
"@vant/area-data": "^1.3.1",
"axios": "^0.27.2",
"blueimp-md5": "^2.19.0",
"countup.js": "^2.2.0",
......
import { areaList } from '@vant/area-data'
// json to array
const json2Array = function (data: Record<string, string>) {
return Object.keys(data).map(code => ({ code, label: data[code], value: data[code] }))
}
export function useArea() {
const provinceValue = ref('')
const cityValue = ref('')
watch(provinceValue, () => {
cityValue.value = ''
})
const provinceList = ref(json2Array(areaList.province_list))
const cityList = computed(() => {
return json2Array(areaList.city_list).filter(item => {
const provinceValueCode = provinceList.value.find(province => province.label === provinceValue.value)?.code || ''
return item.code.slice(0, 2) === provinceValueCode.slice(0, 2)
})
})
const treeList = json2Array(areaList.province_list).map(item => {
const children = json2Array(areaList.city_list).filter(item2 => {
return item2.code.slice(0, 2) === item.code.slice(0, 2)
})
return { ...item, children }
})
return { provinceValue, cityValue, provinceList, cityList, treeList }
}
......@@ -13,5 +13,10 @@ export function getAlumniList(params: {
// 获取校友详情
export function getAlumniDetail(params: { id: string }) {
return httpRequest.get(`/api/hr/admin/v1/alumni-tenant/${params.id}`, { params })
return httpRequest.get(`/api/hr/api/v1/alumni-talent/${params.id}`, { params })
}
// 获取当前登录的校友信息
export function getAlumniUserInfo() {
return httpRequest.get('/api/hr/api/v1/alumni-talent/login-user-info')
}
......@@ -2,19 +2,37 @@ export interface AlumniType {
id: string
sso_id: string
username: string
sex: string
sex: '0' | '1' | '2'
birthday: string
graduating_institution: string
specialty: string
highest_qualification: string
class_id: string
project_prefix: string
class: ClassType[]
project_prefix:
| 'sofia'
| 'kelley'
| 'marywood'
| 'marywood_plus'
| 'sbu_plus'
| 'cbu_plus'
| 'seg'
| 'x1'
| 'ciis'
| 'campbellsvile'
| 'classes'
| 'prp'
| 'wmp'
| 'financial'
province: string
city: string
industry: string
workplace: string
department: string
position: string
created_at: string
updated_at: string
}
export interface ClassType {
class_id: string
name: string
project_prefix: string
}
<script setup lang="ts">
import { sex } from '@/utils/dictionary'
import { getAlumniList } from '../api'
import { useArea } from '@/composables/useArea'
import { sex, projectPrefix, industryCategoryList } from '@/utils/dictionary'
import { getAlumniList, getAlumniUserInfo } from '../api'
import type { AlumniType } from '../types'
const loaded = ref(false)
const projects = ref()
getAlumniUserInfo()
.then(res => {
projects.value = res.data.projects
})
.finally(() => {
loaded.value = true
})
const appList = ref()
// 省市
const { provinceList, cityList, provinceValue, cityValue } = useArea()
const listOptions = {
remote: {
httpRequest: getAlumniList,
params: {
project_prefix_arr: ['sofia']
workplace: '',
industry: '',
province: '',
city: '',
project_prefix_arr: projects.value
},
beforeRequest(params: any, isReset: boolean) {
if (isReset) {
provinceValue.value = ''
cityValue.value = ''
}
params.province = provinceValue.value
params.city = cityValue.value
params.project_prefix_arr = projects.value
return params
}
},
filters: [
{ type: 'input', label: '工作单位', prop: 'workplace' },
{ type: 'select', label: '所在行业', prop: 'industry' },
{ type: 'select', label: '省份', prop: 'province' },
{ type: 'select', label: '城市', prop: 'city' }
{ type: 'select', label: '所在行业', prop: 'industry', options: industryCategoryList },
{ type: 'select', label: '省份', prop: 'province', slots: 'filter-province' },
{ type: 'select', label: '城市', prop: 'city', slots: 'filter-city' }
],
columns: [
{ label: '姓名', prop: 'username', align: 'center' },
......@@ -23,26 +53,47 @@ const listOptions = {
prop: 'sex',
align: 'center',
computed({ row }: { row: AlumniType }) {
console.log(row.sex)
return sex[row.sex] || row.sex
}
},
{ label: '班级', prop: 'class.name', align: 'center' },
{ label: '项目', prop: 'project_prefix', align: 'center' },
{
label: '项目',
prop: 'project_prefix',
align: 'center',
computed({ row }: { row: AlumniType }) {
return projectPrefix[row.project_prefix] || row.project_prefix
}
},
{ label: '省份', prop: 'province', align: 'center' },
{ label: '城市', prop: 'city', align: 'center' },
{ label: '所在行业', prop: 'industry', align: 'center' },
{ label: '工作单位', prop: 'workplace', align: 'center' },
{ label: '操作', slots: 'table-actions', align: 'center' }
],
data: [{ username: '哈哈哈' }, { username: '哈哈哈' }]
]
}
function handleUpdateList() {
nextTick(() => {
appList.value?.refetch()
})
}
</script>
<template>
<AppList v-bind="listOptions">
<AppList v-bind="listOptions" ref="appList" v-if="loaded">
<template #table-actions="{ row }">
<router-link :to="`/hr/alumni/view/${row.id}`">查看</router-link>
<router-link :to="`/hr/alumni/view/${row.id}`" target="_blank" style="color: #399ee8">查看</router-link>
</template>
<template #filter-province>
<el-select clearable v-model="provinceValue" @change="handleUpdateList">
<el-option v-for="item in provinceList" :value="item.label" :key="item.code"></el-option>
</el-select>
</template>
<template #filter-city>
<el-select clearable v-model="cityValue" @change="handleUpdateList">
<el-option v-for="item in cityList" :value="item.label" :key="item.code"></el-option>
</el-select>
</template>
</AppList>
</template>
......@@ -52,5 +103,8 @@ const listOptions = {
padding: 30px 30px 10px;
background: #f8f8f8;
border-radius: 20px;
.el-form-item__label {
width: 78px;
}
}
</style>
<script setup lang="ts">
import { getAlumniDetail } from '../api'
// import type { AlumniType } from '../types'
import type { AlumniType, ClassType } from '../types'
import { projectPrefix } from '@/utils/dictionary'
const props = defineProps<{ id: string }>()
const data: any = reactive({
const data: AlumniType = reactive({
id: '',
sso_id: '',
username: '',
sex: '',
sex: '0',
birthday: '',
graduating_institution: '',
specialty: '',
graduating_institution: '',
highest_qualification: '',
class_id: '',
project_prefix: '',
class: [],
project_prefix: 'sofia',
province: '',
city: '',
industry: '',
workplace: '',
department: '',
position: '',
created_at: '',
updated_at: ''
position: ''
})
const classNames = computed(() => {
return (data.class?.map((item: ClassType) => item.name) || []).join('、')
})
const projectName = computed(() => {
return projectPrefix[data.project_prefix] || data.project_prefix
})
onMounted(() => {
getAlumniDetail({ id: props.id }).then(res => {
Object.assign(data, res.data.detail)
const { detail } = res.data
const classList = Array.isArray(detail.class) ? detail.class : []
Object.assign(data, detail, { class: classList })
})
})
</script>
......@@ -34,21 +44,21 @@ onMounted(() => {
<template>
<AppCard>
<div class="alumni-info">
<dl>
<!-- <dl>
<dt>编号</dt>
<dd></dd>
</dl>
</dl> -->
<dl>
<dt>姓名</dt>
<dd>{{ data.username }}</dd>
</dl>
<dl>
<dt>所在项目</dt>
<dd>{{ data.project_prefix }}</dd>
<dd>{{ projectName }}</dd>
</dl>
<dl>
<dt>所在班级</dt>
<dd>{{ data.class?.name }}</dd>
<dd>{{ classNames }}</dd>
</dl>
<dl>
<dt>省份</dt>
......@@ -80,9 +90,10 @@ onMounted(() => {
display: grid;
grid-template-columns: repeat(5, 1fr);
dl {
padding: 10px;
margin: 10px;
text-align: center;
height: 38px;
min-height: 38px;
border-left: 1px dashed #c9c9c9;
}
dl:nth-child(5n + 1) {
......
......@@ -27,11 +27,11 @@ httpRequest.interceptors.request.use(
signature: 'UG7wBenexQhiuD2wpCwuxkU0jqcj006d'
}
// config.headers = Object.assign(config.headers, defaultHeaders)
config.params = Object.assign(config.params, defaultHeaders)
config.params = Object.assign(config.params || {}, defaultHeaders)
}
if (config.headers?.['Content-Type'] === 'application/x-www-form-urlencoded') {
config.data = qs.stringify(config.data, { skipNulls: true })
config.data = qs.stringify(config.data)
}
if (config.headers?.['Content-Type'] === 'multipart/form-data') {
const formData = new window.FormData()
......@@ -56,7 +56,10 @@ httpRequest.interceptors.response.use(
location.href = `${import.meta.env.VITE_LOGIN_URL}?rd=${encodeURIComponent(location.href)}`
return Promise.reject(data)
}
if (data.code === 1 || data.code === 404) {
if (data.code === 1) {
return Promise.reject(data)
}
if (data.code === 4008) {
ElMessage.error(data.message || data.msg)
return Promise.reject(data)
}
......
......@@ -67,3 +67,74 @@ export const sex = {
}
// 性别
export const sexList = json2Array(sex)
export const industryCategory = [
'互联网/电子商务',
'基金/证券/期货/投资',
'保险',
'银行',
'信托/担保/拍卖/典当',
'计算机软件',
'IT服务(系统/数据/维护)',
'电子技术/半导体/集成电路',
'计算机硬件',
'通信/电信/网络设备',
'通信/电信运营、增值服务',
'网络游戏',
'房地产/建筑/建材/工程',
'家居/室内设计/装饰装潢',
'物业管理/商业中心',
'专业服务/咨询(财会/法律/人力资源等)',
'广告/会展/公关',
'中介服务',
'检验/检测/认证',
'外包服务',
'快速消费品(食品/饮料/烟酒/日化)',
'耐用消费品(服饰/纺织/皮革/家具/家电)',
'贸易/进出口',
'零售/批发',
'租赁服务',
'教育/培训/院校',
'礼品/玩具/工艺美术/收藏品/奢侈品',
'汽车/摩托车',
'大型设备/机电设备/重工业',
'加工制造(原料加工/模具)',
'仪器仪表及工业自动化',
'印刷/包装/造纸',
'办公用品及设备',
'医药/生物工程',
'医疗设备/器械',
'航空/航天研究与制造',
'交通/运输,物流/仓储',
'医疗/护理/美容/保健/卫生服务',
'酒店/餐饮,旅游/度假,媒体/出版/影视/文化传播',
'娱乐/体育/休闲',
'能源/矿产/采掘/冶炼',
'石油/石化/化工,电气/电力/水利',
'环保',
'政府/公共事业/非盈利机构',
'学术/科研,农/林/牧/渔跨领域经营',
'其他'
]
export const industryCategoryList = industryCategory.map(item => ({ label: item, value: item }))
// 项目
export const projectPrefix = {
sofia: '索菲亚',
kelley: '凯丽',
marywood: '玛丽伍德',
marywood_plus: '玛丽伍德大学1+1',
sbu_plus: '纽约大学石溪分校1+1',
cbu_plus: '加州浸会大学1+1',
seg: '酒店及旅游业工商管理硕士',
x1: '1+X',
ciis: '加州整合大学',
campbellsvile: '康博斯威尔大学',
classes: 'Classes',
prp: 'PRP',
wmp: 'WMP',
financial: '金融数据合格'
}
export const projectPrefixList = json2Array(projectPrefix, false)
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论