This commit is contained in:
Unique-Jerry 2024-02-28 15:12:50 +08:00
parent b4cdf86580
commit 327564d769
24 changed files with 761 additions and 146 deletions

View File

@ -13,6 +13,7 @@
"dependencies": { "dependencies": {
"@arco-design/web-vue": "^2.53.0", "@arco-design/web-vue": "^2.53.0",
"@element-plus/icons-vue": "^2.1.0", "@element-plus/icons-vue": "^2.1.0",
"@tinymce/tinymce-vue": "^4.0.1",
"ant-design-vue": "4.x", "ant-design-vue": "4.x",
"axios": "^1.5.1", "axios": "^1.5.1",
"echarts": "^5.4.3", "echarts": "^5.4.3",
@ -20,6 +21,7 @@
"element-plus": "^2.4.0", "element-plus": "^2.4.0",
"less": "^4.2.0", "less": "^4.2.0",
"pinia": "^2.1.6", "pinia": "^2.1.6",
"tinymce": "^5.6.2",
"uuid": "^9.0.1", "uuid": "^9.0.1",
"uuidv1": "^1.6.14", "uuidv1": "^1.6.14",
"vue": "^3.3.4", "vue": "^3.3.4",

View File

@ -11,6 +11,9 @@ dependencies:
'@element-plus/icons-vue': '@element-plus/icons-vue':
specifier: ^2.1.0 specifier: ^2.1.0
version: registry.npmmirror.com/@element-plus/icons-vue@2.1.0(vue@3.3.4) version: registry.npmmirror.com/@element-plus/icons-vue@2.1.0(vue@3.3.4)
'@tinymce/tinymce-vue':
specifier: ^4.0.1
version: registry.npmmirror.com/@tinymce/tinymce-vue@4.0.7(vue@3.3.4)
ant-design-vue: ant-design-vue:
specifier: 4.x specifier: 4.x
version: registry.npmmirror.com/ant-design-vue@4.0.7(vue@3.3.4) version: registry.npmmirror.com/ant-design-vue@4.0.7(vue@3.3.4)
@ -32,6 +35,9 @@ dependencies:
pinia: pinia:
specifier: ^2.1.6 specifier: ^2.1.6
version: registry.npmmirror.com/pinia@2.1.7(vue@3.3.4) version: registry.npmmirror.com/pinia@2.1.7(vue@3.3.4)
tinymce:
specifier: ^5.6.2
version: registry.npmmirror.com/tinymce@5.10.9
uuid: uuid:
specifier: ^9.0.1 specifier: ^9.0.1
version: registry.npmmirror.com/uuid@9.0.1 version: registry.npmmirror.com/uuid@9.0.1
@ -651,6 +657,18 @@ packages:
version: 2.11.7 version: 2.11.7
dev: false dev: false
registry.npmmirror.com/@tinymce/tinymce-vue@4.0.7(vue@3.3.4):
resolution: {integrity: sha512-1esB8wGWrjPCY+rK8vy3QB1cxwXo7HLJWuNrcyPl6LOVR+QJjub0OiV/C+TUEsLN6OpCtRv+QnIqMC5vXz783Q==, registry: http://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/@tinymce/tinymce-vue/-/tinymce-vue-4.0.7.tgz}
id: registry.npmmirror.com/@tinymce/tinymce-vue/4.0.7
name: '@tinymce/tinymce-vue'
version: 4.0.7
peerDependencies:
vue: ^3.0.0
dependencies:
tinymce: registry.npmmirror.com/tinymce@5.10.9
vue: registry.npmmirror.com/vue@3.3.4
dev: false
registry.npmmirror.com/@types/estree@1.0.2: registry.npmmirror.com/@types/estree@1.0.2:
resolution: {integrity: sha512-VeiPZ9MMwXjO32/Xu7+OwflfmeoRwkE/qzndw42gGtgJwZopBnzy2gD//NN1+go1mADzkDcqf/KnFRSjTJ8xJA==, registry: http://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/@types/estree/-/estree-1.0.2.tgz} resolution: {integrity: sha512-VeiPZ9MMwXjO32/Xu7+OwflfmeoRwkE/qzndw42gGtgJwZopBnzy2gD//NN1+go1mADzkDcqf/KnFRSjTJ8xJA==, registry: http://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/@types/estree/-/estree-1.0.2.tgz}
name: '@types/estree' name: '@types/estree'
@ -3135,6 +3153,12 @@ packages:
engines: {node: '>=12.22'} engines: {node: '>=12.22'}
dev: false dev: false
registry.npmmirror.com/tinymce@5.10.9:
resolution: {integrity: sha512-5bkrors87X9LhYX2xq8GgPHrIgJYHl87YNs+kBcjQ5I3CiUgzo/vFcGvT3MZQ9QHsEeYMhYO6a5CLGGffR8hMg==, registry: http://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/tinymce/-/tinymce-5.10.9.tgz}
name: tinymce
version: 5.10.9
dev: false
registry.npmmirror.com/titleize@3.0.0: registry.npmmirror.com/titleize@3.0.0:
resolution: {integrity: sha512-KxVu8EYHDPBdUYdKZdKtU2aj2XfEx9AfjXxE/Aj0vT06w2icA09Vus1rh6eSu1y01akYg6BjIK/hxyLJINoMLQ==, registry: http://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/titleize/-/titleize-3.0.0.tgz} resolution: {integrity: sha512-KxVu8EYHDPBdUYdKZdKtU2aj2XfEx9AfjXxE/Aj0vT06w2icA09Vus1rh6eSu1y01akYg6BjIK/hxyLJINoMLQ==, registry: http://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/titleize/-/titleize-3.0.0.tgz}
name: titleize name: titleize

7
src/api/carouselChart.js Normal file
View File

@ -0,0 +1,7 @@
import request from '@/utils/request'
export const useGetCarouselChart = () =>
request.get('vx_interview/getCarouselChart')
export const useUpdateCarouselChart = ({ submitImages }) =>
request.post('vx_interview/updateCarouselChart', { submitImages })

9
src/api/company.js Normal file
View File

@ -0,0 +1,9 @@
import request from '@/utils/request'
export const useGetApplicationCount = (days, encoding) =>
request.get('company/getApplicationCount', {
params: {
days: days,
encoding: encoding
}
})

View File

@ -86,3 +86,19 @@ export const useUploadUserInfo = ({
export const useAdminEditPassword = ({ userId, updateUserId, password }) => export const useAdminEditPassword = ({ userId, updateUserId, password }) =>
request.post('admin/adminEditPassword', { userId, updateUserId, password }) request.post('admin/adminEditPassword', { userId, updateUserId, password })
//获取反馈列表
export const useGetFeedBackList = (status) =>
request.get('vxUser/getAllFeedBack', {
params: {
status: status
}
})
//修改反馈的状态
export const useChangeFeedBackStatus = (id, userId) =>
request.get('vxUser/changeFeedBackStatus', {
params: {
id: id,
userId: userId
}
})

View File

View File

@ -35,6 +35,23 @@ const router = createRouter({
path: '/manager', path: '/manager',
component: () => import('@/views/manager/ManagerPage.vue') component: () => import('@/views/manager/ManagerPage.vue')
}, },
{
path: '/adminManager',
component: () => import('@/views/manager/AdminMangePage.vue')
},
{
path: '/companyManager',
component: () => import('@/views/manager/CompanyManagePage.vue')
},
{
path: '/carouselChart',
component: () => import('@/views/carouselChart/CarouselChartPage.vue')
},
{
path: '/feedbackmanage',
component: () =>
import('@/views/feedbackmanage/FeedbackManagePage.vue')
},
{ {
path: '/interview/imageManagement', path: '/interview/imageManagement',
component: () => import('@/views/interview/ImageManagement.vue') component: () => import('@/views/interview/ImageManagement.vue')

View File

@ -2,7 +2,7 @@ import { useUserStore } from '@/stores'
import axios from 'axios' import axios from 'axios'
import router from '@/router' import router from '@/router'
const baseURL = 'http://localhost:5380' const baseURL = 'http://localhost:8080'
const instance = axios.create({ const instance = axios.create({
baseURL, baseURL,

View File

@ -0,0 +1,141 @@
<script setup>
import {
useGetCarouselChart,
useUpdateCarouselChart
} from '@/api/carouselChart'
import { ref } from 'vue'
import { useUploadPic, useDeletePic } from '@/api/upload'
import { Plus } from '@element-plus/icons-vue'
const submitForm = ref({
images: [],
submitImages: ''
})
const getCarouselChart = async () => {
const res = await useGetCarouselChart()
if (res.data.data) {
submitForm.value.images = [...JSON.parse(res.data.data)]
submitForm.value.submitImages = res.data.data
} else {
submitForm.value.images = []
}
console.log(res)
console.log(submitForm.value)
}
getCarouselChart()
//
const handleRemove = async (file, fileList) => {
console.log('删除')
await useDeletePic(file.name)
submitForm.value.images = fileList
handleEndit()
}
//
const dialogImageUrl = ref('')
const dialogVisible = ref(false)
const handlePictureCardPreview = (file) => {
dialogVisible.value = true
dialogImageUrl.value = file.url
}
const handleExceed = (files, fileList) => {
ElMessage.warning(
`当前限制选择 5 个文件,本次选择了 ${files.length} 个文件,共选择了 ${
files.length + fileList.length
} 个文件`
)
}
const limit = ref(5)
const hideUpload = ref(false)
const OnChange = async (file, fileList) => {
console.log('改变')
console.log(fileList)
const isType = file.type === 'image/jpeg' || 'image/png'
const isLt5M = file.size / 1024 / 1024 < 5
if (!isType) {
ElMessage.error('上传头像图片只能是 JPG 格式!')
fileList.pop()
}
if (!isLt5M) {
ElMessage.error('上传头像图片大小不能超过 5MB!')
fileList.pop()
}
console.log(submitForm.value.images)
hideUpload.value = submitForm.value.images.length >= limit.value
let fd = new FormData()
fd.append('file', file.raw) // file
const res = await useUploadPic(fd)
var newImageObject = {
name: res.data.data.filename,
url: res.data.data.image
}
file.name = res.data.data.filename
file.url = res.data.data.image
submitForm.value.images.push(newImageObject)
}
const handleEndit = async () => {
console.log('修改')
submitForm.value.submitImages = JSON.stringify(
submitForm.value.images.map((item) => {
return {
name: item.name,
url: item.url
}
})
)
const res = await useUpdateCarouselChart(submitForm.value)
ElMessage.success(res.data.data)
getCarouselChart()
}
</script>
<template>
<el-form
ref="form"
label-width="150px"
style="padding-right: 30px; padding-top: 5%"
:class="hideUpload ? 'hide' : 'display'"
>
<el-form-item label="轮播图图片">
<el-upload
ref="upload"
action="#"
multiple
:limit="limit"
:file-list="submitForm.images"
list-type="picture-card"
:on-preview="handlePictureCardPreview"
:on-change="OnChange"
:on-remove="handleRemove"
:on-exceed="handleExceed"
accept="image/jpeg,image/png"
:auto-upload="false"
>
<i class="el-icon-plus">
<el-icon><Plus /></el-icon
></i>
<template #tip>
<div class="el-upload__tip">
只能上传jpg/png文件,最多上传5张且单张图片不超过5M
</div>
</template>
</el-upload>
<el-dialog v-model="dialogVisible" style="line-height: 0">
<img style="width: 100%; height: 100%" :src="dialogImageUrl" alt="" />
</el-dialog>
</el-form-item>
<div style="text-align: center; padding-top: 20%">
<el-button type="primary" @click="handleEndit">保存修改</el-button>
</div>
</el-form>
</template>

View File

@ -0,0 +1,97 @@
<script setup>
import { ref } from 'vue'
import { useGetFeedBackList, useChangeFeedBackStatus } from '@/api/user'
import { Check } from '@element-plus/icons-vue'
import { useUserStore } from '@/stores'
import ViewImagesDialog from './components/ViewImagesDialog.vue'
const feedbackLoading = ref(false)
const feedBackList = ref([])
const status = ref('1')
const getfeedBackList = async () => {
feedbackLoading.value = true
const res = await useGetFeedBackList(parseInt(status.value))
feedBackList.value = res.data.data
feedbackLoading.value = false
console.log(res.data.data)
}
getfeedBackList()
const handleChangeStatus = async () => {
feedbackLoading.value = true
const res = await useGetFeedBackList(parseInt(status.value))
feedBackList.value = res.data.data
feedbackLoading.value = false
}
const userStore = useUserStore()
const handleEdit = async (row) => {
const res = await useChangeFeedBackStatus(row.id, userStore.userInfo.id)
ElMessage.success(res.data.data)
getfeedBackList()
}
const viewImagesDialog = ref()
const handleView = (row) => {
viewImagesDialog.value.open(row)
}
</script>
<template>
<page-container title="反馈管理" v-loading="feedbackLoading">
<template #filter>
<el-select
v-model="status"
placeholder="筛选"
style="width: 115px"
@change="handleChangeStatus"
>
<el-option label="待处理" value="1" />
<el-option label="已处理" value="2" />
</el-select>
</template>
<el-table :data="feedBackList" stripe style="width: 100%">
<el-table-column type="index" label="序号" width="100" />
<el-table-column prop="content" label="描述" />
<el-table-column label="反馈图片">
<template #default="{ row }">
<el-tooltip
class="box-item"
effect="dark"
content="查看图片"
placement="top-start"
>
<el-button type="warning" @click="handleView(row)" plain
>查看图片</el-button
>
</el-tooltip>
</template>
</el-table-column>
<el-table-column prop="phone" label="联系电话" />
<el-table-column prop="createTime" label="反馈时间" />
<el-table-column prop="status" label="状态">
<template #default="{ row }"
>{{ row.status === 1 ? '待处理' : '已处理' }}
</template>
</el-table-column>
<el-table-column label="操作" width="150">
<template #default="{ row }">
<el-tooltip
class="box-item"
effect="dark"
content="确认"
placement="top-start"
v-if="row.status === 1"
>
<el-button
type="primary"
:icon="Check"
@click="handleEdit(row)"
circle
plain
></el-button>
</el-tooltip>
</template>
</el-table-column>
</el-table>
<ViewImagesDialog ref="viewImagesDialog"></ViewImagesDialog>
</page-container>
</template>

View File

@ -0,0 +1,53 @@
<script setup>
import { ref } from 'vue'
const viewImagesDialogVisible = ref(false)
const imgUrls = ref([])
const open = (row) => {
viewImagesDialogVisible.value = true
imgUrls.value = JSON.parse(row.imgUrl)
}
defineExpose({
open
})
</script>
<template>
<el-dialog
v-model="viewImagesDialogVisible"
title="反馈图片"
width="50%"
align-center
>
<el-carousel :interval="4000" type="card" height="200px">
<el-carousel-item v-for="item in imgUrls" :key="item">
<el-image
style="width: 100px; height: 100px"
:src="item"
:fit="contain"
/>
</el-carousel-item>
</el-carousel>
<template #footer>
<span class="dialog-footer">
<el-button @click="centerDialogVisible = false">关闭</el-button>
</span>
</template>
</el-dialog>
</template>
<style scoped>
.el-carousel__item h3 {
color: #475669;
opacity: 0.75;
line-height: 200px;
margin: 0;
text-align: center;
}
.el-carousel__item:nth-child(2n) {
background-color: #99a9bf;
}
.el-carousel__item:nth-child(2n + 1) {
background-color: #d3dce6;
}
</style>

View File

@ -5,7 +5,7 @@ import { BarChart } from 'echarts/charts'
import { CanvasRenderer } from 'echarts/renderers' import { CanvasRenderer } from 'echarts/renderers'
import VChart, { THEME_KEY } from 'vue-echarts' import VChart, { THEME_KEY } from 'vue-echarts'
import { ref, provide } from 'vue' import { ref, provide, onBeforeMount } from 'vue'
import { useCompanyStore, useUserStore } from '@/stores' import { useCompanyStore, useUserStore } from '@/stores'
import { import {
Search, Search,
@ -14,6 +14,7 @@ import {
ChatDotSquare, ChatDotSquare,
Tickets Tickets
} from '@element-plus/icons-vue' } from '@element-plus/icons-vue'
import { useRouter } from 'vue-router'
import { import {
useGetJobList, useGetJobList,
getApplicationList, getApplicationList,
@ -24,12 +25,21 @@ import {
getInterviewRecordList, getInterviewRecordList,
agreeUsersPassInterview agreeUsersPassInterview
} from '@/api/interview' } from '@/api/interview'
import { useGetApplicationCount } from '@/api/company'
import { ElMessage } from 'element-plus' import { ElMessage } from 'element-plus'
import DisagreeDialog from './components/DisagreeDialog.vue' import DisagreeDialog from './components/DisagreeDialog.vue'
import InviteDialog from './components/InviteDialog.vue' import InviteDialog from './components/InviteDialog.vue'
import ViewResume from './components/ViewResume.vue' import ViewResume from './components/ViewResume.vue'
import ViewInterviewRecord from './components/ViewInterviewRecord.vue'
use([TooltipComponent, GridComponent, BarChart, CanvasRenderer]) use([TooltipComponent, GridComponent, BarChart, CanvasRenderer])
onBeforeMount(() => {
const router = useRouter()
const userStore = useUserStore()
if (userStore.userInfo.role === '1') {
router.replace('/adminManager')
}
})
const companyStore = useCompanyStore() const companyStore = useCompanyStore()
const jobList = ref([]) const jobList = ref([])
@ -62,63 +72,26 @@ getJobList()
provide(THEME_KEY, 'white') provide(THEME_KEY, 'white')
// prettier-ignore // prettier-ignore
const date = ref(Number) const date = ref(Number)
const data7 = ref([])
const setDate = (day) => { const dataValues7 = ref([])
const setDate = async (day) => {
date.value = day date.value = day
const resSeven = await useGetApplicationCount(day, companyStore.encoding)
resSeven.data.data.map((item) => {
data7.value.push(item.createTime)
})
console.log(data7.value)
resSeven.data.data.map((item) => {
dataValues7.value.push(item.count)
})
console.log(dataValues7.value)
} }
setDate(7) setDate(7)
const date30 = [ const option = ref({
'2023-10-01',
'2023-10-02',
'2023-10-03',
'2023-10-04',
'2023-10-05',
'2023-10-06',
'2023-10-07',
'2023-10-08',
'2023-10-09',
'2023-10-10',
'2023-10-11',
'2023-10-12',
'2023-10-13',
'2023-10-14',
'2023-10-15',
'2023-10-16',
'2023-10-17',
'2023-10-18',
'2023-10-19',
'2023-10-20',
'2023-10-21',
'2023-10-22',
'2023-10-23',
'2023-10-24',
'2023-10-25',
'2023-10-26',
'2023-10-27',
'2023-10-28',
'2023-10-29',
'2023-10-30'
]
const data7 = [
'2023-10-24',
'2023-10-25',
'2023-10-26',
'2023-10-27',
'2023-10-28',
'2023-10-29',
'2023-10-30'
]
const dataValues7 = [10, 52, 200, 334, 390, 330, 220]
const dataValue30 = [
10, 52, 200, 334, 390, 330, 220, 10, 52, 200, 334, 390, 330, 220, 10, 52, 200,
334, 390, 330, 220, 10, 52, 200, 334, 390, 330, 220, 10, 52, 200, 334, 390,
330, 220, 10, 52, 200, 334, 390, 330, 220, 10, 52, 200, 334, 390, 330, 220,
400, 500
]
const option1 = ref({
tooltip: { tooltip: {
trigger: 'axis', trigger: 'axis',
axisPointer: { axisPointer: {
@ -134,7 +107,7 @@ const option1 = ref({
xAxis: [ xAxis: [
{ {
type: 'category', type: 'category',
data: data7, data: data7.value,
axisTick: { axisTick: {
alignWithLabel: true alignWithLabel: true
} }
@ -150,43 +123,7 @@ const option1 = ref({
name: '投递人数', name: '投递人数',
type: 'bar', type: 'bar',
barWidth: '50%', barWidth: '50%',
data: dataValues7 data: dataValues7.value
}
]
})
const option2 = ref({
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'shadow'
}
},
grid: {
left: '3%',
right: '4%',
bottom: '3%',
containLabel: true
},
xAxis: [
{
type: 'category',
data: date30,
axisTick: {
alignWithLabel: true
}
}
],
yAxis: [
{
type: 'value'
}
],
series: [
{
name: '投递人数',
type: 'bar',
barWidth: '50%',
data: dataValue30
} }
] ]
}) })
@ -291,7 +228,7 @@ const handleSelectionChange = (val) => {
} }
console.log(selectAgreeUsers.value) console.log(selectAgreeUsers.value)
} }
const userStore = useUserStore()
const PassInterview = async () => { const PassInterview = async () => {
if (filterRecored.value === '2') { if (filterRecored.value === '2') {
ElMessage.error('所勾选的列表已经通过面试啦,请不要重复操作') ElMessage.error('所勾选的列表已经通过面试啦,请不要重复操作')
@ -376,37 +313,18 @@ const handleDisagreeApplication = (row) => {
console.log(row) console.log(row)
} }
const viewInterviewRecord = ref()
const handleViewRecordDetail = (row) => { const handleViewRecordDetail = (row) => {
console.log(row) viewInterviewRecord.value.open(row)
} }
</script> </script>
<template> <template>
<el-dropdown> <h1 style="text-align: center">{{ '近7天' }}投递简历人数</h1>
<el-button type="warning" bg>
{{ date === 7 ? '近7天' : '近30天'
}}<el-icon class="el-icon--right"><arrow-down /></el-icon>
</el-button>
<template #dropdown>
<el-dropdown-menu>
<el-dropdown-item @click="setDate(7)">近7天</el-dropdown-item>
<el-dropdown-item @click="setDate(30)">近30天</el-dropdown-item>
</el-dropdown-menu>
</template>
</el-dropdown>
<h1 style="text-align: center">
{{ date === 7 ? '近7天' : '近30天' }}投递简历人数
</h1>
<v-chart <v-chart
class="chart" class="chart"
v-if="date === 7" v-if="date === 7"
:option="option1" :option="option"
style="width: 90%; height: 80%"
/>
<v-chart
class="chart"
v-else
:option="option2"
style="width: 90%; height: 80%" style="width: 90%; height: 80%"
/> />
<!-- 第一个页面 --> <!-- 第一个页面 -->
@ -683,6 +601,7 @@ const handleViewRecordDetail = (row) => {
></DisagreeDialog> ></DisagreeDialog>
<InviteDialog ref="inviteDialog" @getJobList="getJobList"></InviteDialog> <InviteDialog ref="inviteDialog" @getJobList="getJobList"></InviteDialog>
<ViewResume ref="viewResume"></ViewResume> <ViewResume ref="viewResume"></ViewResume>
<ViewInterviewRecord ref="viewInterviewRecord"></ViewInterviewRecord>
</template> </template>
<style scoped></style> <style scoped></style>

View File

@ -0,0 +1,49 @@
<script setup>
import { ref } from 'vue'
const InterviewRecordDialog = ref(false)
const interviewInfo = ref({})
const open = (row) => {
interviewInfo.value = row
InterviewRecordDialog.value = true
console.log(interviewInfo.value)
}
defineExpose({
open
})
</script>
<template>
<el-drawer
v-model="InterviewRecordDialog"
:title="'面试详情'"
direction="rtl"
size="50%"
>
<el-form ref="form" label-width="150px">
<el-form-item label="面试详情">
<el-input
v-model="interviewInfo.detail"
:autosize="{ minRows: 2, maxRows: 6 }"
type="textarea"
placeholder="请输入面试详情"
id="detail"
disabled="false"
/>
</el-form-item>
<el-form-item label="面试评语">
<el-input
v-model="interviewInfo.comments"
:autosize="{ minRows: 2, maxRows: 4 }"
type="textarea"
placeholder="请输入面试评语"
id="comments"
disabled="false"
/>
</el-form-item>
</el-form>
</el-drawer>
</template>

View File

@ -24,6 +24,7 @@ import { useAdminLogout } from '../../api/user'
import { useRouter } from 'vue-router' import { useRouter } from 'vue-router'
import ChangeAvatarDialog from './components/ChangeAvatarDialog.vue' import ChangeAvatarDialog from './components/ChangeAvatarDialog.vue'
import RestPasswordDialog from './components/ResetPasswordDialog.vue' import RestPasswordDialog from './components/ResetPasswordDialog.vue'
import { ref } from 'vue' import { ref } from 'vue'
import UserInfoDialog from './components/UserInfoDialog.vue' import UserInfoDialog from './components/UserInfoDialog.vue'
@ -66,16 +67,58 @@ const RestPassword = () => {
text-color="#fff" text-color="#fff"
router router
> >
<el-menu-item index="/home"> <el-menu-item
index="/home"
v-if="
userStore.userInfo.role === '2' || userStore.userInfo.role === '3'
"
>
<el-icon><House /></el-icon> <el-icon><House /></el-icon>
<span>首页</span> <span>首页</span>
</el-menu-item> </el-menu-item>
<el-menu-item index="/manager"> <el-menu-item
index="/manager"
v-if="
userStore.userInfo.role === '2' || userStore.userInfo.role === '3'
"
>
<el-icon><User /></el-icon>
<span>人员管理</span>
</el-menu-item>
<el-menu-item
index="/adminManager"
v-if="userStore.userInfo.role === '1'"
>
<el-icon><User /></el-icon> <el-icon><User /></el-icon>
<span>管理员管理</span> <span>管理员管理</span>
</el-menu-item> </el-menu-item>
<el-menu-item
<el-sub-menu index="/interview/imageManagement"> index="/companyManager"
v-if="userStore.userInfo.role === '1'"
>
<el-icon><User /></el-icon>
<span>公司管理</span>
</el-menu-item>
<el-menu-item
index="/carouselChart"
v-if="userStore.userInfo.role === '1'"
>
<el-icon><User /></el-icon>
<span>轮播图管理</span>
</el-menu-item>
<el-menu-item
index="/feedbackmanage"
v-if="userStore.userInfo.role === '1'"
>
<el-icon><User /></el-icon>
<span>反馈管理</span>
</el-menu-item>
<el-sub-menu
index="/interview/imageManagement"
v-if="
userStore.userInfo.role === '2' || userStore.userInfo.role === '3'
"
>
<template #title> <template #title>
<el-icon><VideoCamera /></el-icon> <el-icon><VideoCamera /></el-icon>
<span>个性化面试</span> <span>个性化面试</span>
@ -95,7 +138,12 @@ const RestPassword = () => {
</el-menu-item> </el-menu-item>
</el-sub-menu> </el-sub-menu>
<el-sub-menu index="/question/type"> <el-sub-menu
index="/question/type"
v-if="
userStore.userInfo.role === '2' || userStore.userInfo.role === '3'
"
>
<template #title> <template #title>
<el-icon><Files /></el-icon> <el-icon><Files /></el-icon>
<span>题库设置</span> <span>题库设置</span>
@ -113,7 +161,12 @@ const RestPassword = () => {
<span>题目广场</span> <span>题目广场</span>
</el-menu-item> </el-menu-item>
</el-sub-menu> </el-sub-menu>
<el-sub-menu index="/recruitment/publicManagement"> <el-sub-menu
index="/recruitment/publicManagement"
v-if="
userStore.userInfo.role === '2' || userStore.userInfo.role === '3'
"
>
<template #title> <template #title>
<el-icon><Phone /></el-icon> <el-icon><Phone /></el-icon>
<span>招聘</span> <span>招聘</span>

View File

@ -22,11 +22,11 @@ const open = () => {
submitForm.value = userStore.userInfo submitForm.value = userStore.userInfo
userRole.value = userRole.value =
userStore.userInfo.role === '1' userStore.userInfo.role === '1'
? '超级管理员' ? '系统管理员'
: userStore.userInfo.role === '2' : userStore.userInfo.role === '2'
? 'HR' ? '公司管理员'
: userStore.userInfo.role === '3' : userStore.userInfo.role === '3'
? '员工' ? 'HR'
: '面试者' : '面试者'
submitForm.value.userId = submitForm.value.id submitForm.value.userId = submitForm.value.id
@ -38,7 +38,8 @@ const rules = ref({
role: [{ required: true, message: '请输入权限', trigger: 'blur' }], role: [{ required: true, message: '请输入权限', trigger: 'blur' }],
username: [{ required: true, message: '请输入姓名', trigger: 'blur' }], username: [{ required: true, message: '请输入姓名', trigger: 'blur' }],
age: [{ required: true, message: '请输入年龄', trigger: 'blur' }], age: [{ required: true, message: '请输入年龄', trigger: 'blur' }],
email: [{ required: true, message: '请输入电子邮箱', trigger: 'blur' }] email: [{ required: true, message: '请输入电子邮箱', trigger: 'blur' }],
sex: [{ required: true, message: '请输入选择性别', trigger: 'blur' }]
}) })
// //
@ -146,7 +147,7 @@ defineExpose({
v-model="submitForm.email" v-model="submitForm.email"
></el-input> ></el-input>
</el-form-item> </el-form-item>
<el-form-item label="性别"> <el-form-item label="性别" prop="sex">
<el-radio-group v-model="submitForm.sex"> <el-radio-group v-model="submitForm.sex">
<el-radio label="男"></el-radio> <el-radio label="男"></el-radio>
<el-radio label="女"></el-radio> <el-radio label="女"></el-radio>

View File

@ -0,0 +1,105 @@
<script setup>
import { Search, Edit, Delete } from '@element-plus/icons-vue'
import { useCompanyStore } from '@/stores'
import { useGetAdminList } from '@/api/user'
import { ref } from 'vue'
import AdminDelEndit from './components/AdminDelEndit.vue'
import ResetPasswordDialog from './components/ResetPasswordDialog.vue'
import AdminProAddDialog from './components/AdminProAddDialog.vue'
const searchName = ref('')
const loading = ref(false)
const adminList = ref([])
const searchUserName = () => {}
const companyStore = useCompanyStore()
const getAdminList = async () => {
const res = await useGetAdminList(companyStore.encoding)
adminList.value = res.data.data
}
getAdminList()
const adminDelEndit = ref()
const handleDelete = (row) => {
adminDelEndit.value.open(row)
}
const resetPasswordDialog = ref()
const handleEdit = (row) => {
resetPasswordDialog.value.open(row)
}
const adminProAddDialog = ref()
const onAddEdit = () => {
adminProAddDialog.value.open()
}
</script>
<template>
<page-container title="管理员管理">
<template #filter>
<div class="mt-4">
<el-input
v-model="searchName"
placeholder="请输入姓名"
class="input-with-select"
>
<template #prepend>
<el-button :icon="Search" @click="searchUserName" />
</template>
<template #append>
<el-button @click="getAdminList">重置</el-button>
</template>
</el-input>
</div>
</template>
<template #extra>
<el-button type="primary" @click="onAddEdit">添加管理员 </el-button>
</template>
<el-table v-loading="loading" :data="adminList" stripe style="width: 100%">
<el-table-column type="index" label="序号" width="100" />
<el-table-column prop="username" label="姓名" />
<el-table-column prop="phone" label="账号" />
<el-table-column prop="email" label="电子邮箱" />
<el-table-column label="操作" width="200">
<template #default="{ row }">
<el-tooltip
class="box-item"
effect="dark"
content="修改密码"
placement="top-start"
>
<el-button
type="primary"
:icon="Edit"
@click="handleEdit(row)"
circle
plain
></el-button>
</el-tooltip>
<el-tooltip
class="box-item"
effect="dark"
content="删除"
placement="top-start"
>
<el-button
type="danger"
:icon="Delete"
@click="handleDelete(row)"
circle
plain
></el-button>
</el-tooltip>
</template>
</el-table-column>
<template #empty>
<el-empty description="没有数据" />
</template>
</el-table>
<AdminDelEndit ref="adminDelEndit" @getAdminList="getAdminList">
</AdminDelEndit>
<ResetPasswordDialog ref="resetPasswordDialog"></ResetPasswordDialog>
<AdminProAddDialog
ref="adminProAddDialog"
@getAdminList="getAdminList"
></AdminProAddDialog>
</page-container>
</template>

View File

@ -0,0 +1,38 @@
<script setup>
import { Search } from '@element-plus/icons-vue'
import { ref } from 'vue'
const getCompanyList = () => {}
const searchName = ref('')
const searchCompanyName = () => {}
const onAddEdit = () => {}
</script>
<template>
<page-container title="公司管理">
<template #filter>
<div class="mt-4">
<el-input
v-model="searchName"
placeholder="请输入姓名"
class="input-with-select"
>
<template #prepend>
<el-button :icon="Search" @click="searchCompanyName" />
</template>
<template #append>
<el-button @click="getCompanyList">重置</el-button>
</template>
</el-input>
</div>
</template>
<template #extra>
<el-button type="primary" @click="onAddEdit">公司注册 </el-button>
</template>
<el-table :data="tableData" stripe style="width: 100%">
<el-table-column prop="date" label="Date" width="180" />
<el-table-column prop="name" label="Name" width="180" />
<el-table-column prop="address" label="Address" />
</el-table>
</page-container>
</template>

View File

@ -45,7 +45,7 @@ const handleEdit = (row) => {
</script> </script>
<template> <template>
<page-container title="管理员管理"> <page-container title="员管理">
<template #filter> <template #filter>
<div class="mt-4"> <div class="mt-4">
<el-input <el-input

View File

@ -0,0 +1,94 @@
<script setup>
import { ref } from 'vue'
import { useAddAdmin } from '@/api/user'
import { useUserStore, useCompanyStore } from '@/stores'
const userStore = useUserStore()
const companyStore = useCompanyStore()
const addEnditDialog = ref(false)
const form = ref()
const FormModel = ref({
username: '',
phone: '',
role: '1'
})
const open = () => {
addEnditDialog.value = true
}
const rules = {
username: [{ required: true, message: '请输入姓名!', trigger: 'blur' }],
phone: [
{ required: true, message: '请输入手机号码!', trigger: 'blur' },
{
pattern: /(^((\+86)|(86))?(1[3-9])\d{9}$)|(^(0\d{2,3})-?(\d{7,8})$)/,
message: '输入的手机号码格式不正确,请重新输入',
trigger: 'blur'
}
]
}
const emit = defineEmits(['getAdminList'])
const submitForm = async () => {
await form.value.validate()
await useAddAdmin(
companyStore.encoding,
userStore.userInfo.id,
FormModel.value.username,
FormModel.value.phone,
FormModel.value.role
)
ElMessage.success('添加成功!')
FormModel.value = {
username: '',
phone: '',
role: '1'
}
addEnditDialog.value = false
emit('getAdminList')
}
defineExpose({
open
})
</script>
<template>
<el-dialog v-model="addEnditDialog" title="添加管理员" width="30%">
<el-form
ref="form"
label-width="150px"
style="padding-right: 30px"
:model="FormModel"
:rules="rules"
>
<el-form-item label="姓名" prop="username">
<el-input
v-model="FormModel.username"
placeholder="请输入管理员姓名"
></el-input>
</el-form-item>
<el-form-item label="账号/手机号码" prop="phone">
<el-input v-model="FormModel.phone" placeholder="请输入账号/手机号码" />
</el-form-item>
</el-form>
<div><span class="fontstyle">:初始化密码就是账号的后六位</span></div>
<template #footer>
<span class="dialog-footer">
<el-button @click="dialogVisible = false">取消</el-button>
<el-button type="primary" @click="submitForm"> 确认 </el-button>
</span>
</template>
</el-dialog>
</template>
<style scoped>
.fontstyle {
font-weight: bold;
color: red;
}
</style>

View File

@ -124,7 +124,7 @@ defineExpose({
<el-table-column property="title" label="标题" width="200" /> <el-table-column property="title" label="标题" width="200" />
<el-table-column property="typeName" label="题库名称" /> <el-table-column property="typeName" label="题库名称" />
<el-table-column property="details" label="内容" show-overflow-tooltip /> <el-table-column property="details" label="内容" show-overflow-tooltip />
<el-table-column property="promote" label="promote" /> <el-table-column property="answer" label="题目预设答案" />
<el-table-column property="createUserName" label="创建人" /> <el-table-column property="createUserName" label="创建人" />
<el-table-column property="updateTime" label="更新时间" /> <el-table-column property="updateTime" label="更新时间" />
</el-table> </el-table>

View File

@ -19,7 +19,9 @@ const open = (SharedBankIds) => {
submitForm.value.userId = userStore.userInfo.id submitForm.value.userId = userStore.userInfo.id
} }
const addEndit = async () => { const addEndit = async () => {
console.log(submitForm.value)
const res = await useAddQuestionTypeFromShare(submitForm.value) const res = await useAddQuestionTypeFromShare(submitForm.value)
ElMessage.success(res.data.data) ElMessage.success(res.data.data)
submitForm.value = { submitForm.value = {
SharedBankIds: [], SharedBankIds: [],

View File

@ -31,7 +31,7 @@ const rules = {
title: [{ required: true, message: '请输入标题', trigger: 'blur' }], title: [{ required: true, message: '请输入标题', trigger: 'blur' }],
typeName: [{ required: true, message: '请选择题库类型', trigger: 'blur' }], typeName: [{ required: true, message: '请选择题库类型', trigger: 'blur' }],
details: [{ required: true, message: '请输入题目详情', trigger: 'blur' }], details: [{ required: true, message: '请输入题目详情', trigger: 'blur' }],
promote: [{ required: true, message: '请输入题目的promote', trigger: 'blur' }] answer: [{ required: true, message: '请输入题目的预设答案', trigger: 'blur' }]
} }
const form = ref() const form = ref()
const update = async () => { const update = async () => {
@ -91,9 +91,9 @@ defineExpose({
placeholder="请输入题目详情" placeholder="请输入题目详情"
/> />
</el-form-item> </el-form-item>
<el-form-item label="题目promote" prop="promote"> <el-form-item label="题目预设答案" prop="answer">
<el-input <el-input
v-model="updateForm.promote" v-model="updateForm.answer"
:autosize="{ minRows: 2, maxRows: 4 }" :autosize="{ minRows: 2, maxRows: 4 }"
type="textarea" type="textarea"
placeholder="请输入题目的promote" placeholder="请输入题目的promote"

View File

@ -68,13 +68,6 @@ const getCompanyDetail = async () => {
submitForm.value.userId = userStore.userInfo.id submitForm.value.userId = userStore.userInfo.id
// submitForm.value.address = submitForm.value.address.slice(1, -1).split(', ')
// submitForm.value.treatment = submitForm.value.treatment
// .slice(1, -1)
// .split(', ')
// submitForm.value.images = submitForm.value.images.slice(1, -1).split(', ')
if (res.data.data.images === '') { if (res.data.data.images === '') {
submitForm.value.images = [] submitForm.value.images = []
@ -140,10 +133,7 @@ const UploadImage = async (file) => {
} }
// //
const handleRemove = async (file) => { const handleRemove = async (file) => {
console.log('删除')
console.log(file.name)
await useDeletePic(file.name) await useDeletePic(file.name)
handleEndit() handleEndit()
} }
// //
@ -204,7 +194,6 @@ const handleEndit = async () => {
} }
}) })
) )
console.log(submitForm.value.companyLogo)
submitForm.value.subLogo = JSON.stringify( submitForm.value.subLogo = JSON.stringify(
submitForm.value.companyLogo.map((item) => { submitForm.value.companyLogo.map((item) => {
return { return {
@ -214,7 +203,6 @@ const handleEndit = async () => {
}) })
) )
submitForm.value.treatment = JSON.stringify(submitForm.value.treatment) submitForm.value.treatment = JSON.stringify(submitForm.value.treatment)
console.log(submitForm.value)
const res = await useUploadCompanyDetail(submitForm.value) const res = await useUploadCompanyDetail(submitForm.value)
ElMessage.success(res.data.data) ElMessage.success(res.data.data)

View File

@ -26,7 +26,7 @@ export default defineConfig({
//代理设置 //代理设置
server: { server: {
port: 5173, port: 5174,
host: '0.0.0.0', host: '0.0.0.0',
base: './', base: './',
cors: true, // 默认启用并允许任何源 cors: true, // 默认启用并允许任何源