<link rel="icon" type="image/svg+xml" href="/logo_1.jpg" /> | <link rel="icon" type="image/svg+xml" href="/logo_1.jpg" /> | ||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> | <meta name="viewport" content="width=device-width, initial-scale=1.0" /> | ||||
<title>菊城人才市场后台管理</title> | <title>菊城人才市场后台管理</title> | ||||
<script type="module" crossorigin src="/assets/index-zplygJt9.js"></script> | |||||
<script type="module" crossorigin src="/assets/index-i0sh_yC6.js"></script> | |||||
<link rel="stylesheet" crossorigin href="/assets/index-EE_SYqet.css"> | <link rel="stylesheet" crossorigin href="/assets/index-EE_SYqet.css"> | ||||
</head> | </head> | ||||
<body> | <body> |
export const Login = postModel(url.userLogin); | export const Login = postModel(url.userLogin); | ||||
export const GetUserMenulist = getModel(url.UserMenulist); | export const GetUserMenulist = getModel(url.UserMenulist); | ||||
export const PostSmsSend = postModel(url.SmsSend); | |||||
export const GetCaptcha = getModel(url.Captcha); | |||||
// 角色 | // 角色 | ||||
export const PostRoleAdd = postModel(url.RoleAdd); | export const PostRoleAdd = postModel(url.RoleAdd); | ||||
export const GetSysconfigDetail = getModel(url.SysconfigDetail); | export const GetSysconfigDetail = getModel(url.SysconfigDetail); | ||||
// 反馈 | // 反馈 | ||||
export const PostFeedbackAdd = postModel(url.FeedbackAdd); | |||||
export const PostFeedbackDel = postModel(url.FeedbackDel); | |||||
export const PostFeedbackUpdate = postModel(url.FeedbackUpdate); | |||||
export const GetFeedbackList = getModel(url.FeedbackList); | |||||
export const GetFeedbackDetail = getModel(url.FeedbackDetail); | |||||
export const PostFeedbackAdd = postModel(url.FeedbackAdd); | |||||
export const PostFeedbackDel = postModel(url.FeedbackDel); | |||||
export const PostFeedbackUpdate = postModel(url.FeedbackUpdate); | |||||
export const GetFeedbackList = getModel(url.FeedbackList); | |||||
export const GetFeedbackDetail = getModel(url.FeedbackDetail); | |||||
// 反馈 | // 反馈 | ||||
export const PostCustomerAdd = postModel(url.CustomerAdd); | |||||
export const PostCustomerDel = postModel(url.CustomerDel); | |||||
export const GetCustomerUpdate = getModel(url.CustomerUpdate); | |||||
export const GetCustomerList = getModel(url.CustomerList); | |||||
export const PostCustomerAdd = postModel(url.CustomerAdd); | |||||
export const PostCustomerDel = postModel(url.CustomerDel); | |||||
export const GetCustomerUpdate = getModel(url.CustomerUpdate); | |||||
export const GetCustomerList = getModel(url.CustomerList); | |||||
export const GetCustomerDetail = getModel(url.CustomerDetail); | export const GetCustomerDetail = getModel(url.CustomerDetail); | ||||
export const PostEsJobseeker = postModel(url.EsJobseeker); | export const PostEsJobseeker = postModel(url.EsJobseeker); | ||||
export const PostTokenizerModify = postModel(url.TokenizerModify); | export const PostTokenizerModify = postModel(url.TokenizerModify); | ||||
export const GetTokenizerGet = getModel(url.TokenizerGet); | |||||
export const GetTokenizerGet = getModel(url.TokenizerGet); |
declare namespace urlType { | declare namespace urlType { | ||||
type url = { | type url = { | ||||
Captcha : String, | |||||
SmsSend : String, | |||||
userLogin : String, | userLogin : String, | ||||
UserMenulist : String, | UserMenulist : String, | ||||
RoleAdd : String, | RoleAdd : String, | ||||
StatsPosition : String, | StatsPosition : String, | ||||
StatsTitleAndSkill : String, | StatsTitleAndSkill : String, | ||||
StatsJobMajor : String, | StatsJobMajor : String, | ||||
'SysconfigAdd':String, | |||||
'SysconfigDel': String, | |||||
'SysconfigUpdate':String, | |||||
'SysconfigList': String, | |||||
'SysconfigDetail': String, | |||||
'SysconfigAdd' : String, | |||||
'SysconfigDel' : String, | |||||
'SysconfigUpdate' : String, | |||||
'SysconfigList' : String, | |||||
'SysconfigDetail' : String, | |||||
// 反馈 | // 反馈 | ||||
FeedbackAdd: String, | |||||
FeedbackDel: String, | |||||
FeedbackUpdate: String, | |||||
FeedbackList: String, | |||||
FeedbackDetail: String, | |||||
FeedbackAdd : String, | |||||
FeedbackDel : String, | |||||
FeedbackUpdate : String, | |||||
FeedbackList : String, | |||||
FeedbackDetail : String, | |||||
// 反馈 | // 反馈 | ||||
CustomerAdd: String, | |||||
CustomerDel: String, | |||||
CustomerUpdate: String, | |||||
CustomerList: String, | |||||
CustomerDetail:String, | |||||
DocUpload: String, | |||||
EsJobseeker: String, | |||||
TokenizerModify: String, | |||||
TokenizerGet:String, | |||||
CustomerAdd : String, | |||||
CustomerDel : String, | |||||
CustomerUpdate : String, | |||||
CustomerList : String, | |||||
CustomerDetail : String, | |||||
DocUpload : String, | |||||
EsJobseeker : String, | |||||
TokenizerModify : String, | |||||
TokenizerGet : String, | |||||
} | } | ||||
} | } |
export const url : urlType.url = { | export const url : urlType.url = { | ||||
userLogin: admin + '/user/login', | userLogin: admin + '/user/login', | ||||
UserMenulist: admin + '/user/menulist', | UserMenulist: admin + '/user/menulist', | ||||
SmsSend: common + '/sms/send', // 短信验证码 | |||||
Captcha: common + '/captcha', // 获取验证码 | |||||
// 角色 | // 角色 | ||||
RoleAdd: admin + '/role/add', | RoleAdd: admin + '/role/add', | ||||
RoleList: admin + '/role/list', | RoleList: admin + '/role/list', |
<template> | |||||
<div v-if="needPre"> | |||||
<img :src="imgObj.src" alt="" | |||||
:style="{width: imgObj.width,height: imgObj.height,'object-fit': imgObj.mode, 'border-radius': 0} " | |||||
@click="preImage(imgObj.src)"> | |||||
<a-modal v-model:open="imageBigOpen" width="50%" centered :footer="null" @cancel="close"> | |||||
<div style="padding: 30px;"> | |||||
<img :src="imgObj.src" style="width: 100%; height: 100%;"> | |||||
</div> | |||||
</a-modal> | |||||
</div> | |||||
<div v-else> | |||||
<img :src="imgObj.src" alt="" | |||||
:style="{width: imgObj.width,height: imgObj.height,'object-fit': imgObj.mode, 'border-radius': 0} "> | |||||
</div> | |||||
</template> | |||||
<script lang="ts" setup> | |||||
import { ref, onMounted, defineProps, watch, computed } from 'vue'; | |||||
const props = defineProps({ | |||||
imgObj: { | |||||
type: Object, | |||||
default: {} | |||||
}, | |||||
need: { | |||||
type: Boolean, | |||||
default: false | |||||
} | |||||
}); | |||||
let needPre = ref<Boolean>(props.need) | |||||
let imageBigOpen = ref<Boolean>(false) | |||||
interface imgType { | |||||
src ?: String, | |||||
width ?: Number, | |||||
height ?: Number, | |||||
mode ?: String, | |||||
} | |||||
const imgObj = ref<imgType>({ | |||||
src: '', | |||||
width: 0, | |||||
height: 0, | |||||
mode: '', | |||||
}) | |||||
// 预览 | |||||
const preImage = (src) => { | |||||
imageBigOpen.value = true | |||||
} | |||||
const close = (src) => { | |||||
imageBigOpen.value = false | |||||
} | |||||
watch(() => [props.imgObj], (newVal : any) => { | |||||
if (newVal[0]) { | |||||
imgObj.value = newVal[0] | |||||
} | |||||
}, { immediate: true }) | |||||
</script> | |||||
<style> | |||||
</style> |
import ACSelectCommon from '@/components/cSelect/common.vue'; | import ACSelectCommon from '@/components/cSelect/common.vue'; | ||||
import UploadOne from '@/components/upload/one.vue'; | import UploadOne from '@/components/upload/one.vue'; | ||||
import UploadFile from '@/components/upload/file.vue'; | import UploadFile from '@/components/upload/file.vue'; | ||||
import ImageContainer from '@/components/form/image-container.vue'; | |||||
import { Model } from 'node_modules/echarts/index'; | import { Model } from 'node_modules/echarts/index'; | ||||
// router.beforeEach(async (to, from, next) => { | // router.beforeEach(async (to, from, next) => { | ||||
app.component('a-xuanze', AXuanze); | app.component('a-xuanze', AXuanze); | ||||
app.component('a-shujilian', AShujilian); | app.component('a-shujilian', AShujilian); | ||||
app.component('search-select', SearchSelect); | app.component('search-select', SearchSelect); | ||||
app.component('image-container', ImageContainer) | |||||
app.component('a-c-select-common', ACSelectCommon); | app.component('a-c-select-common', ACSelectCommon); | ||||
app.component('QuillEditor', QuillEditor) | app.component('QuillEditor', QuillEditor) | ||||
app.component('upload-one', UploadOne) | app.component('upload-one', UploadOne) |
<a-col span="24"> | <a-col span="24"> | ||||
<a-form-item label="上传文件,可将链接放入文章内容"> | <a-form-item label="上传文件,可将链接放入文章内容"> | ||||
<upload-file @uploadSuccess="uploadDocSuccess"></upload-file> | <upload-file @uploadSuccess="uploadDocSuccess"></upload-file> | ||||
<a-typography-paragraph v-if="createForm.doc" :copyable="{ text: imageprefix+createForm.doc}"> | |||||
{{imageprefix+createForm.doc}} | |||||
<a-typography-paragraph v-if="createForm.doc_url" :copyable="{ text: imageprefix+createForm.doc_url}"> | |||||
{{imageprefix+createForm.doc_url}} | |||||
</a-typography-paragraph> | </a-typography-paragraph> | ||||
</a-form-item> | </a-form-item> | ||||
</a-col> | </a-col> | ||||
// 上传文件 | // 上传文件 | ||||
const uploadDocSuccess = (data : Object) => { | const uploadDocSuccess = (data : Object) => { | ||||
createForm.value.doc = data | |||||
createForm.value.doc_url = data | |||||
} | } | ||||
// 选择栏目/频道 | // 选择栏目/频道 |
export let dataForm = { | export let dataForm = { | ||||
title: '', | title: '', | ||||
cover_img: '', | cover_img: '', | ||||
doc: '', | |||||
doc_url: '', | |||||
section_id: 0, | section_id: 0, | ||||
content: '', | content: '', | ||||
stick_top: 0, | stick_top: 0, | ||||
dataForm = { | dataForm = { | ||||
title: '', | title: '', | ||||
cover_img: '', | cover_img: '', | ||||
doc: '', | |||||
doc_url: '', | |||||
section_id: 0, | section_id: 0, | ||||
content: '', | content: '', | ||||
stick_top: 0, | stick_top: 0, |
<h2 class="title">菊城人才市场招聘后台管理系统</h2> | <h2 class="title">菊城人才市场招聘后台管理系统</h2> | ||||
<div class="sub-title">欢迎使用</div> | <div class="sub-title">欢迎使用</div> | ||||
<a-form> | <a-form> | ||||
<a-row> | |||||
<a-col :span="24"><a-form-item> | |||||
<a-input placeholder="账号" v-model:value="createForm.mobile"> | |||||
<template #prefix> | |||||
<user-outlined type="user" /> | |||||
</template> | |||||
</a-input> | |||||
</a-form-item> | |||||
</a-col> | |||||
</a-row> | |||||
<a-row> | |||||
<a-col :span="24"> | |||||
<a-form-item> | |||||
<a-input type="password" placeholder="密码" v-model:value="createForm.password"> | |||||
<template #prefix> | |||||
<LockOutlined /> | |||||
</template> | |||||
<template #suffix> | |||||
<a-tooltip title="Extra information"> | |||||
<EyeInvisibleOutlined style="color: rgba(0, 0, 0, 0.25)" /> | |||||
</a-tooltip> | |||||
</template> | |||||
</a-input> | |||||
</a-form-item> | |||||
</a-col> | |||||
</a-row> | |||||
<a-row :gutter="10"> | |||||
<a-col :span="16"> | |||||
<a-form-item> | |||||
<a-input type="password" placeholder="验证码"> | |||||
<template #prefix> | |||||
<LockOutlined /> | |||||
</template> | |||||
<template #suffix> | |||||
<a-tooltip title="Extra information"> | |||||
<EyeInvisibleOutlined style="color: rgba(0, 0, 0, 0.25)" /> | |||||
</a-tooltip> | |||||
</template> | |||||
</a-input> | |||||
</a-form-item> | |||||
</a-col> | |||||
<a-col :span="8"> | |||||
<a-button style="width: 100%;">验证码</a-button> | |||||
</a-col> | |||||
</a-row> | |||||
<a-row type="flex" justify="end"> | |||||
<a-col :span="6"> | |||||
<a-form-item> | |||||
<div>忘记密码?</div> | |||||
</a-form-item> | |||||
</a-col> | |||||
</a-row> | |||||
<a-row> | |||||
<a-col :span="24"> | |||||
<a-button @click="toLogin" style="width: 100%;" type="primary">登录</a-button> | |||||
</a-col> | |||||
</a-row> | |||||
<a-space direction="vertical"> | |||||
<a-row :gutter="10"> | |||||
<a-col :span="24"> | |||||
<a-form-item> | |||||
<a-input size="large" placeholder="账号" v-model:value="createForm.mobile"> | |||||
<template #prefix> | |||||
<user-outlined type="user" /> | |||||
</template> | |||||
</a-input> | |||||
</a-form-item> | |||||
</a-col> | |||||
</a-row> | |||||
<a-row :gutter="10"> | |||||
<a-col :span="24"> | |||||
<a-form-item> | |||||
<a-input size="large" type="password" placeholder="密码" | |||||
v-model:value="createForm.password"> | |||||
<template #prefix> | |||||
<LockOutlined /> | |||||
</template> | |||||
<template #suffix> | |||||
<a-tooltip title="Extra information"> | |||||
<EyeInvisibleOutlined style="color: rgba(0, 0, 0, 0.25)" /> | |||||
</a-tooltip> | |||||
</template> | |||||
</a-input> | |||||
</a-form-item> | |||||
</a-col> | |||||
</a-row> | |||||
<a-row :gutter="10"> | |||||
<a-col span="12"> | |||||
<a-form-item> | |||||
<a-input v-model:value="createForm.captcha" placeholder="图形验证码" size="large" /> | |||||
</a-form-item> | |||||
</a-col> | |||||
<a-col span="12"> | |||||
<a-form-item> | |||||
<image-container :imgObj="{src: codeImage,width: '100%',height: '40px', mode: 'fill'}" | |||||
@click="getCaptcha"></image-container> | |||||
</a-form-item> | |||||
</a-col> | |||||
</a-row> | |||||
<a-row :gutter="10"> | |||||
<a-col span="16"> | |||||
<a-form-item> | |||||
<a-input v-model:value="createForm.sms_code" placeholder="短信验证码" size="large" /> | |||||
</a-form-item> | |||||
</a-col> | |||||
<a-col span="8"> | |||||
<a-form-item> | |||||
<a-button type="primary" block size="large" @click="sendCode" | |||||
:disabled="state.disabled"> | |||||
{{ state.codeTxt }}</a-button> | |||||
</a-form-item> | |||||
</a-col> | |||||
</a-row> | |||||
<!-- <a-row type="flex" justify="end"> | |||||
<a-col :span="6"> | |||||
<a-form-item> | |||||
<div>忘记密码?</div> | |||||
</a-form-item> | |||||
</a-col> | |||||
</a-row> --> | |||||
<a-row> | |||||
<a-col :span="24"> | |||||
<a-button @click="toLogin" style="width: 100%;" type="primary">登录</a-button> | |||||
</a-col> | |||||
</a-row> | |||||
</a-space> | |||||
</a-form> | </a-form> | ||||
</div> | </div> | ||||
</div> | </div> | ||||
</template> | </template> | ||||
<script lang="ts" setup> | <script lang="ts" setup> | ||||
import { ref } from 'vue'; | |||||
import { Login } from '@/apis/models'; | |||||
import { ref, onMounted, onBeforeUnmount } from 'vue'; | |||||
import { Login, PostSmsSend, GetCaptcha } from '@/apis/models'; | |||||
import { useAsRouter } from '@/hooks/useAsRouter' | import { useAsRouter } from '@/hooks/useAsRouter' | ||||
import { UserOutlined, InfoCircleOutlined, LockOutlined, EyeInvisibleOutlined } from '@ant-design/icons-vue'; | import { UserOutlined, InfoCircleOutlined, LockOutlined, EyeInvisibleOutlined } from '@ant-design/icons-vue'; | ||||
import { useCommon } from '@/hooks/useCommon'; | import { useCommon } from '@/hooks/useCommon'; | ||||
let { message } = useCommon(); | let { message } = useCommon(); | ||||
const { routerTo } = useAsRouter(); | const { routerTo } = useAsRouter(); | ||||
let capt_id = ref<String>('') | |||||
let codeImage = ref<String>('') | |||||
const createForm = ref<Object>({ | const createForm = ref<Object>({ | ||||
mobile: '', | mobile: '', | ||||
password: '' | |||||
password: '', | |||||
// captcha: '', | |||||
// sms_code: '' | |||||
}) | |||||
interface State { | |||||
count : number; | |||||
sending : boolean; | |||||
disabled : boolean; | |||||
} | |||||
const state = ref<State>({ | |||||
count: 60, | |||||
codeTxt: '获取验证码', | |||||
disabled: false, | |||||
}); | |||||
let timer = ref<any>(null) | |||||
const sendCode = () => { | |||||
if (!createForm.value.mobile) { | |||||
message.danger('请输入手机号') | |||||
return false; | |||||
} | |||||
PostSmsSend({ mobile: createForm.mobile, captcha: '', capt_id: capt_id.value }).then(res => { | |||||
message.success('发送验证码成功,验证码有效期为一分钟'); | |||||
timer.value = setInterval(function () { | |||||
if (state.value.count > 1) { | |||||
state.value.count = state.value.count - 1; | |||||
state.value.codeTxt = '剩余' + (state.value.count - 1) + '秒'; | |||||
state.value.disabled = true | |||||
} else { | |||||
clearInterval(timer.value); | |||||
state.value.count = 60; | |||||
state.value.codeTxt = '获取验证码'; | |||||
state.value.disabled = false | |||||
}; | |||||
}, 1000) | |||||
}) | |||||
}; | |||||
onBeforeUnmount(() => { | |||||
clearInterval(timer.value); | |||||
}) | }) | ||||
const toLogin = () => { | const toLogin = () => { | ||||
if (!createForm.value.mobile) { | if (!createForm.value.mobile) { | ||||
if (!createForm.value.password) { | if (!createForm.value.password) { | ||||
message.warning('请输入密码'); | message.warning('请输入密码'); | ||||
return false; | return false; | ||||
} | |||||
} | |||||
Login(createForm.value).then(res => { | Login(createForm.value).then(res => { | ||||
sessionStorage.setItem('token', res.data.jwttoken.accesstoken); | sessionStorage.setItem('token', res.data.jwttoken.accesstoken); | ||||
routerTo('/home'); | routerTo('/home'); | ||||
// sessionStorage.setItem('token', '1321'); | // sessionStorage.setItem('token', '1321'); | ||||
// routerTo('/home'); | // routerTo('/home'); | ||||
} | } | ||||
const getCaptcha = () => { | |||||
capt_id.value = '' | |||||
GetCaptcha().then(res => { | |||||
capt_id.value = res.data.capt_id; | |||||
codeImage.value = res.data.img; | |||||
}) | |||||
} | |||||
onMounted(() => { | |||||
getCaptcha() | |||||
}) | |||||
</script> | </script> | ||||
<style lang="less"> | <style lang="less"> |