flat: 合并
This commit is contained in:
115
App.vue
115
App.vue
@@ -3,25 +3,31 @@ import { reactive, inject, onMounted } from 'vue';
|
|||||||
import { onLaunch, onShow, onHide } from '@dcloudio/uni-app';
|
import { onLaunch, onShow, onHide } from '@dcloudio/uni-app';
|
||||||
import useUserStore from './stores/useUserStore';
|
import useUserStore from './stores/useUserStore';
|
||||||
import useDictStore from './stores/useDictStore';
|
import useDictStore from './stores/useDictStore';
|
||||||
const { $api, navTo, appendScriptTagElement } = inject('globalFunction');
|
const { $api, navTo, appendScriptTagElement, aes_Decrypt, sm2_Decrypt } = inject('globalFunction');
|
||||||
import config from '@/config.js';
|
import config from '@/config.js';
|
||||||
|
|
||||||
|
const appword = 'aKd20dbGdFvmuwrt'; // 固定值
|
||||||
|
|
||||||
onLaunch((options) => {
|
onLaunch((options) => {
|
||||||
useUserStore().initSeesionId(); //更新
|
// uni.hideTabBar();
|
||||||
useDictStore().getDictData();
|
useDictStore().getDictData();
|
||||||
uni.hideTabBar();
|
try {
|
||||||
// 登录
|
getUserInfo();
|
||||||
let token = uni.getStorageSync('token') || ''; // 同步获取 缓存信息
|
} catch {
|
||||||
if (token) {
|
console.log('不是爱山东平台,使用测试登陆');
|
||||||
useUserStore()
|
useUserStore().initSeesionId(); //更新
|
||||||
.loginSetToken(token)
|
let token = uni.getStorageSync('token') || ''; // 同步获取 缓存信息
|
||||||
.then(() => {
|
if (token) {
|
||||||
$api.msg('登录成功');
|
useUserStore()
|
||||||
|
.loginSetToken(token)
|
||||||
|
.then(() => {
|
||||||
|
$api.msg('登录成功');
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
uni.redirectTo({
|
||||||
|
url: '/pages/login/login',
|
||||||
});
|
});
|
||||||
} else {
|
}
|
||||||
uni.redirectTo({
|
|
||||||
url: '/pages/login/login',
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -34,6 +40,87 @@ onShow(() => {
|
|||||||
onHide(() => {
|
onHide(() => {
|
||||||
console.log('App Hide');
|
console.log('App Hide');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
function getUserInfo() {
|
||||||
|
lightAppJssdk.user.getUserInfoWithEncryptedParamByAppId({
|
||||||
|
appId: 'qdsrgznrgpp', // 接入方在成功创建应用后自动生成
|
||||||
|
success: function (data) {
|
||||||
|
if (data == '未登录') onLoginApp();
|
||||||
|
else {
|
||||||
|
if (typeof data == 'string') data = JSON.parse(data);
|
||||||
|
|
||||||
|
const sm2_privateKey = '7e14966df4ecd4241ed082ef716d82b52113cb5899ebdc704a98844d0a32b0dc';
|
||||||
|
let sm2_encrypt_result = data.data;
|
||||||
|
let sm2_decrypt_result = sm2_Decrypt(sm2_encrypt_result, sm2_privateKey);
|
||||||
|
|
||||||
|
if (typeof sm2_decrypt_result == 'string') sm2_decrypt_result = JSON.parse(sm2_decrypt_result);
|
||||||
|
|
||||||
|
// 其次,对sm2解密后的结果进行 aes解密
|
||||||
|
// aes解密需要用到 appword , 为固定值,使用示例代码中的即可
|
||||||
|
let aes_encrypt_result = sm2_decrypt_result.data;
|
||||||
|
let aes_decrypt_result = aes_Decrypt(aes_encrypt_result, appword);
|
||||||
|
|
||||||
|
// 加密
|
||||||
|
loginCallback(aes_decrypt_result);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
fail: function (data) {
|
||||||
|
console.log('err', data);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 使用jssdk调用登录页面
|
||||||
|
*/
|
||||||
|
function onLoginApp() {
|
||||||
|
lightAppJssdk.user.loginapp({
|
||||||
|
success: function (data) {
|
||||||
|
if (data == '未登录') {
|
||||||
|
//取消登录或登录失败,关闭页面
|
||||||
|
oncloseWindow();
|
||||||
|
} else {
|
||||||
|
getUserInfo();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
fail: function (data) {
|
||||||
|
//关闭页面
|
||||||
|
oncloseWindow();
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 关闭容器
|
||||||
|
*/
|
||||||
|
function oncloseWindow() {
|
||||||
|
lightAppJssdk.navigation.close({
|
||||||
|
success: function (data) {},
|
||||||
|
fail: function (data) {},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function loginCallback(userInfo) {
|
||||||
|
let params = {
|
||||||
|
username: userInfo,
|
||||||
|
};
|
||||||
|
$api.createRequest('/app/login', params, 'post').then((resData) => {
|
||||||
|
useUserStore()
|
||||||
|
.loginSetToken(resData.token)
|
||||||
|
.then((resume) => {
|
||||||
|
if (resume.data.jobTitleId) {
|
||||||
|
useUserStore().initSeesionId();
|
||||||
|
uni.reLaunch({
|
||||||
|
url: '/pages/index/index',
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
uni.redirectTo({
|
||||||
|
url: '/pages/login/login',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
|
|||||||
@@ -554,6 +554,24 @@ function isEmptyObject(obj) {
|
|||||||
return obj && typeof obj === 'object' && !Array.isArray(obj) && Object.keys(obj).length === 0;
|
return obj && typeof obj === 'object' && !Array.isArray(obj) && Object.keys(obj).length === 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function aes_Decrypt(word, key) {
|
||||||
|
var key = CryptoJS.enc.Utf8.parse(key) //转为128bit
|
||||||
|
var srcs = CryptoJS.enc.Hex.parse(word) //转为16进制
|
||||||
|
var str = CryptoJS.enc.Base64.stringify(srcs) //变为Base64编码的字符串
|
||||||
|
var decrypt = CryptoJS.AES.decrypt(str, key, {
|
||||||
|
mode: CryptoJS.mode.ECB,
|
||||||
|
spadding: CryptoJS.pad.Pkcs7
|
||||||
|
})
|
||||||
|
return decrypt.toString(CryptoJS.enc.Utf8)
|
||||||
|
}
|
||||||
|
|
||||||
|
export function sm2_Decrypt(word, key) {
|
||||||
|
return SM.decrypt(word, key);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function sm2_Encrypt(word, key) {
|
||||||
|
return SM.encrypt(word, key);
|
||||||
|
}
|
||||||
|
|
||||||
export function sm4Decrypt(key, value, mode = "hex") {
|
export function sm4Decrypt(key, value, mode = "hex") {
|
||||||
try {
|
try {
|
||||||
@@ -607,7 +625,8 @@ export const $api = {
|
|||||||
uploadFile,
|
uploadFile,
|
||||||
formatFileSize,
|
formatFileSize,
|
||||||
sendingMiniProgramMessage,
|
sendingMiniProgramMessage,
|
||||||
copyText
|
copyText,
|
||||||
|
aes_Decrypt,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -638,4 +657,7 @@ export default {
|
|||||||
isInWechatMiniProgramWebview,
|
isInWechatMiniProgramWebview,
|
||||||
isEmptyObject,
|
isEmptyObject,
|
||||||
sm4Decrypt,
|
sm4Decrypt,
|
||||||
|
aes_Decrypt,
|
||||||
|
sm2_Decrypt,
|
||||||
|
sm2_Encrypt
|
||||||
}
|
}
|
||||||
@@ -1,9 +1,8 @@
|
|||||||
export default {
|
export default {
|
||||||
// baseUrl: 'http://39.98.44.136:8080', // 测试
|
// baseUrl: 'https://fw.rc.qingdao.gov.cn/rgpp-api/api', // 内网
|
||||||
baseUrl: 'https://qd.zhaopinzao8dian.com/api', // 测试
|
baseUrl: 'https://qd.zhaopinzao8dian.com/api', // 测试
|
||||||
// baseUrl: 'http://10.133.17.161:8080/api', // 测试
|
// baseUrl: "http://192.168.98.110:18181",
|
||||||
// baseUrl: 'http://192.168.3.19:8080', // 测试
|
// baseUrl: "http://192.168.3.19:8080",
|
||||||
// baseUrl: 'http://39.98.44.136:6009', // 测试
|
|
||||||
// sseAI+
|
// sseAI+
|
||||||
// StreamBaseURl: 'http://39.98.44.136:8000',
|
// StreamBaseURl: 'http://39.98.44.136:8000',
|
||||||
StreamBaseURl: 'https://qd.zhaopinzao8dian.com/ai',
|
StreamBaseURl: 'https://qd.zhaopinzao8dian.com/ai',
|
||||||
|
|||||||
@@ -49,6 +49,7 @@ export function useTTSPlayer() {
|
|||||||
const newUtterance = new SpeechSynthesisUtterance(filteredText); // Use filtered text
|
const newUtterance = new SpeechSynthesisUtterance(filteredText); // Use filtered text
|
||||||
utteranceRef.value = newUtterance;
|
utteranceRef.value = newUtterance;
|
||||||
|
|
||||||
|
newUtterance.lang = 'zh-CN';
|
||||||
newUtterance.rate = options.rate || 1;
|
newUtterance.rate = options.rate || 1;
|
||||||
newUtterance.pitch = options.pitch || 1;
|
newUtterance.pitch = options.pitch || 1;
|
||||||
if (options.voice) {
|
if (options.voice) {
|
||||||
|
|||||||
19
index.html
19
index.html
@@ -17,14 +17,19 @@
|
|||||||
})();
|
})();
|
||||||
</script>
|
</script>
|
||||||
<title></title>
|
<title></title>
|
||||||
<!-- vconsole -->
|
<!-- eruda -->
|
||||||
<!-- <script src="https://unpkg.com/vconsole@latest/dist/vconsole.min.js"></script>
|
<script src="https://cdn.jsdelivr.net/npm/eruda"></script>
|
||||||
<script>
|
<script>
|
||||||
var vConsole = new window.VConsole();
|
eruda.init();
|
||||||
vConsole.destroy();
|
</script>
|
||||||
</script> -->
|
<!-- 爱山东jssdk 本sdk存在性能问题 -->
|
||||||
<!-- 爱山东jssdk -->
|
<script type="text/javascript" src="https://isdapp.shandong.gov.cn/jmopen/jssdk/index.js"></script>
|
||||||
<!-- <script type="text/javascript" src="https://isdapp.shandong.gov.cn/jmopen/jssdk/index.js"></script> -->
|
|
||||||
|
<script type="text/javascript" src="./static/js/sm4.min.js"></script>
|
||||||
|
|
||||||
|
<script type="text/javascript" src="./static/js/SM.js"></script>
|
||||||
|
|
||||||
|
<script type="text/javascript" src="./static/js/aes.js"></script>
|
||||||
|
|
||||||
<script type="text/javascript" src="./static/js/sm4.min.js"></script>
|
<script type="text/javascript" src="./static/js/sm4.min.js"></script>
|
||||||
|
|
||||||
|
|||||||
@@ -80,7 +80,7 @@
|
|||||||
"locale": "zh-Hans",
|
"locale": "zh-Hans",
|
||||||
"h5": {
|
"h5": {
|
||||||
"router": {
|
"router": {
|
||||||
"base": "/app/",
|
"base": "./",
|
||||||
"mode": "hash"
|
"mode": "hash"
|
||||||
},
|
},
|
||||||
"title": "青岛智慧就业服务",
|
"title": "青岛智慧就业服务",
|
||||||
@@ -97,6 +97,9 @@
|
|||||||
"serviceHost": ""
|
"serviceHost": ""
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"devServer": {
|
||||||
|
"https": false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -7,31 +7,56 @@
|
|||||||
</template>
|
</template>
|
||||||
<view class="mys-container">
|
<view class="mys-container">
|
||||||
<!-- 个人信息 -->
|
<!-- 个人信息 -->
|
||||||
<view class="card-top" style="margin-top: 12rpx; padding: 0; background: none">
|
<view
|
||||||
|
class="card-top"
|
||||||
|
style="margin-top: 12rpx; padding: 0; background: none"
|
||||||
|
>
|
||||||
<view class="mys-tops btn-feel">
|
<view class="mys-tops btn-feel">
|
||||||
<view class="tops-left">
|
<view class="tops-left">
|
||||||
<view class="name">
|
<view class="name">
|
||||||
<text>{{ userInfo.name || "编辑用户名" }}</text>
|
<text>{{ userInfo.name || "编辑用户名" }}</text>
|
||||||
<view class="edit-icon mar_le10">
|
<view class="edit-icon mar_le10">
|
||||||
<image class="button-click" src="@/static/icon/edit1.png" @click="navTo('/packageA/pages/personalInfo/personalInfo')"></image>
|
<image
|
||||||
|
class="button-click"
|
||||||
|
src="@/static/icon/edit1.png"
|
||||||
|
@click="navTo('/packageA/pages/personalInfo/personalInfo')"
|
||||||
|
></image>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
<view class="subName">
|
<view class="subName">
|
||||||
<dict-Label class="mar_ri10" dictType="sex" :value="userInfo.sex"></dict-Label>
|
<dict-Label
|
||||||
|
class="mar_ri10"
|
||||||
|
dictType="sex"
|
||||||
|
:value="userInfo.sex"
|
||||||
|
></dict-Label>
|
||||||
<text class="mar_ri10">{{ userInfo.age }}岁</text>
|
<text class="mar_ri10">{{ userInfo.age }}岁</text>
|
||||||
<dict-Label class="mar_ri10" dictType="education" :value="userInfo.education"></dict-Label>
|
<dict-Label
|
||||||
<dict-Label class="mar_ri10" dictType="affiliation" :value="userInfo.politicalAffiliation"></dict-Label>
|
class="mar_ri10"
|
||||||
|
dictType="education"
|
||||||
|
:value="userInfo.education"
|
||||||
|
></dict-Label>
|
||||||
|
<dict-Label
|
||||||
|
class="mar_ri10"
|
||||||
|
dictType="affiliation"
|
||||||
|
:value="userInfo.politicalAffiliation"
|
||||||
|
></dict-Label>
|
||||||
</view>
|
</view>
|
||||||
<view class="subName">{{ userInfo.phone }}</view>
|
<view class="subName">{{ userInfo.phone }}</view>
|
||||||
</view>
|
</view>
|
||||||
<view class="tops-right">
|
<view class="tops-right">
|
||||||
<view class="right-imghead">
|
<view class="right-imghead">
|
||||||
<image v-if="userInfo.avatar" :src="userInfo.avatar"></image>
|
<image v-if="userInfo.avatar" :src="userInfo.avatar"></image>
|
||||||
<image v-else-if="userInfo.sex == '0'" src="@/static/icon/boy.png"></image>
|
<image
|
||||||
|
v-else-if="userInfo.sex == '0'"
|
||||||
|
src="@/static/icon/boy.png"
|
||||||
|
></image>
|
||||||
<image v-else src="@/static/icon/girl.png"></image>
|
<image v-else src="@/static/icon/girl.png"></image>
|
||||||
</view>
|
</view>
|
||||||
<view class="right-sex">
|
<view class="right-sex">
|
||||||
<image v-if="userInfo.sex === '0'" src="@/static/icon/boy1.png"></image>
|
<image
|
||||||
|
v-if="userInfo.sex === '0'"
|
||||||
|
src="@/static/icon/boy1.png"
|
||||||
|
></image>
|
||||||
<image v-else src="@/static/icon/girl1.png"></image>
|
<image v-else src="@/static/icon/girl1.png"></image>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
@@ -43,19 +68,34 @@
|
|||||||
<view class="mys-info btn-feel">
|
<view class="mys-info btn-feel">
|
||||||
<view class="mys-h4">
|
<view class="mys-h4">
|
||||||
<view>求职期望</view>
|
<view>求职期望</view>
|
||||||
<image class="icon" src="@/static/icon/edit1.png" @click="navTo('/packageA/pages/jobExpect/jobExpect')"></image>
|
<image
|
||||||
|
class="icon"
|
||||||
|
src="@/static/icon/edit1.png"
|
||||||
|
@click="navTo('/packageA/pages/jobExpect/jobExpect')"
|
||||||
|
></image>
|
||||||
</view>
|
</view>
|
||||||
<view class="mys-text">
|
<view class="mys-text">
|
||||||
<text>期望薪资:</text>
|
<text>期望薪资:</text>
|
||||||
<text>{{ userInfo.salaryMin / 1000 }}k-{{ userInfo.salaryMax / 1000 }}k</text>
|
<text
|
||||||
|
>{{ userInfo.salaryMin / 1000 }}k-{{
|
||||||
|
userInfo.salaryMax / 1000
|
||||||
|
}}k</text
|
||||||
|
>
|
||||||
</view>
|
</view>
|
||||||
<view class="mys-text">
|
<view class="mys-text">
|
||||||
<text>期望工作地:</text>
|
<text>期望工作地:</text>
|
||||||
<text>青岛市-</text>
|
<text>青岛市-</text>
|
||||||
<dict-Label dictType="area" :value="Number(userInfo.area)"></dict-Label>
|
<dict-Label
|
||||||
|
dictType="area"
|
||||||
|
:value="Number(userInfo.area)"
|
||||||
|
></dict-Label>
|
||||||
</view>
|
</view>
|
||||||
<view class="mys-list">
|
<view class="mys-list">
|
||||||
<view class="cards button-click" v-for="(title, index) in userInfo.jobTitle" :key="index">
|
<view
|
||||||
|
class="cards button-click"
|
||||||
|
v-for="(title, index) in userInfo.jobTitle"
|
||||||
|
:key="index"
|
||||||
|
>
|
||||||
{{ title }}
|
{{ title }}
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
@@ -65,19 +105,35 @@
|
|||||||
<view class="mys-info" style="padding: 0">
|
<view class="mys-info" style="padding: 0">
|
||||||
<view class="mys-h4 btn-feel">
|
<view class="mys-h4 btn-feel">
|
||||||
<text>工作经历</text>
|
<text>工作经历</text>
|
||||||
<view class="mys-edit-icon btn-feel" @click="navTo('/packageA/pages/workExp/workExp')">
|
<view
|
||||||
<image class="icon button-click btn-feel" src="@/static/icon/plus.png"></image>
|
class="mys-edit-icon btn-feel"
|
||||||
|
@click="navTo('/packageA/pages/workExp/workExp')"
|
||||||
|
>
|
||||||
|
<image
|
||||||
|
class="icon button-click btn-feel"
|
||||||
|
src="@/static/icon/plus.png"
|
||||||
|
></image>
|
||||||
<view class="txt">添加</view>
|
<view class="txt">添加</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
<view class="exp-item btn-feel" v-for="item in userInfo.workExp" :key="item.id">
|
<view
|
||||||
|
class="exp-item btn-feel"
|
||||||
|
v-for="item in userInfo.workExp"
|
||||||
|
:key="item.id"
|
||||||
|
>
|
||||||
<view class="fl_box fl_justbet mar_top15">
|
<view class="fl_box fl_justbet mar_top15">
|
||||||
<view class="fs_16">{{ item.company }}</view>
|
<view class="fs_16">{{ item.company }}</view>
|
||||||
<image class="icon btn-feel" src="@/static/icon/edit1.png" @click="navTo(`/packageA/pages/workExp/workExp?id=${item.id}`)"></image>
|
<image
|
||||||
|
class="icon btn-feel"
|
||||||
|
src="@/static/icon/edit1.png"
|
||||||
|
@click="navTo(`/packageA/pages/workExp/workExp?id=${item.id}`)"
|
||||||
|
></image>
|
||||||
</view>
|
</view>
|
||||||
<view class="mys-text fl_box fl_justbet">
|
<view class="mys-text fl_box fl_justbet">
|
||||||
<text class="color_333333 fs_14">{{ item.position }}</text>
|
<text class="color_333333 fs_14">{{ item.position }}</text>
|
||||||
<text class="datetext">{{ item.startTime }}--{{ item.endTime || "至今" }}</text>
|
<text class="datetext"
|
||||||
|
>{{ item.startTime }}--{{ item.endTime || "至今" }}</text
|
||||||
|
>
|
||||||
</view>
|
</view>
|
||||||
<view class="mys-text">
|
<view class="mys-text">
|
||||||
<text>{{ item.duty }}</text>
|
<text>{{ item.duty }}</text>
|
||||||
@@ -88,7 +144,9 @@
|
|||||||
</view>
|
</view>
|
||||||
<template #footer>
|
<template #footer>
|
||||||
<view class="footer-container">
|
<view class="footer-container">
|
||||||
<view class="footer-button btn-feel">上传简历</view>
|
<view class="footer-button btn-feel" @click="chooseResume"
|
||||||
|
>上传简历</view
|
||||||
|
>
|
||||||
</view>
|
</view>
|
||||||
</template>
|
</template>
|
||||||
</AppLayout>
|
</AppLayout>
|
||||||
@@ -104,6 +162,69 @@ import useDictStore from "@/stores/useDictStore";
|
|||||||
const { userInfo } = storeToRefs(useUserStore());
|
const { userInfo } = storeToRefs(useUserStore());
|
||||||
const { getUserResume } = useUserStore();
|
const { getUserResume } = useUserStore();
|
||||||
const { getDictData, oneDictData } = useDictStore();
|
const { getDictData, oneDictData } = useDictStore();
|
||||||
|
import config from "@/config.js";
|
||||||
|
|
||||||
|
onLoad(() => {
|
||||||
|
getUserResume();
|
||||||
|
});
|
||||||
|
|
||||||
|
function chooseResume() {
|
||||||
|
uni.chooseImage({
|
||||||
|
sizeType: ["original", "compressed"],
|
||||||
|
sourceType: ["album", "camera"],
|
||||||
|
count: 1,
|
||||||
|
success: ({ tempFilePaths, tempFiles }) => {
|
||||||
|
uploadResume(tempFilePaths[0], true)
|
||||||
|
.then((res) => {
|
||||||
|
res = JSON.parse(res);
|
||||||
|
getUserResume();
|
||||||
|
$api.msg("上传成功");
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
$api.msg("上传失败");
|
||||||
|
});
|
||||||
|
},
|
||||||
|
fail: (error) => {},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function uploadResume(tempFilePath, loading) {
|
||||||
|
if (loading) {
|
||||||
|
uni.showLoading({
|
||||||
|
title: "请稍后",
|
||||||
|
mask: true,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
let Authorization = "";
|
||||||
|
if (useUserStore().token) {
|
||||||
|
Authorization = `${useUserStore().token}`;
|
||||||
|
}
|
||||||
|
const header = {};
|
||||||
|
header["Authorization"] = encodeURIComponent(Authorization);
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
uni.uploadFile({
|
||||||
|
url: config.baseUrl + "/app/oss/uploadToObs",
|
||||||
|
filePath: tempFilePath,
|
||||||
|
name: "file",
|
||||||
|
header,
|
||||||
|
success: (uploadFileRes) => {
|
||||||
|
if (uploadFileRes.statusCode === 200) {
|
||||||
|
resolve(uploadFileRes.data);
|
||||||
|
} else {
|
||||||
|
reject();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
fail: (err) => {
|
||||||
|
reject(err);
|
||||||
|
},
|
||||||
|
complete: () => {
|
||||||
|
if (loading) {
|
||||||
|
uni.hideLoading();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="stylus" scoped>
|
<style lang="stylus" scoped>
|
||||||
|
|||||||
@@ -102,9 +102,9 @@
|
|||||||
<text class="title">竞争力分析</text>
|
<text class="title">竞争力分析</text>
|
||||||
</view>
|
</view>
|
||||||
<view class="description">
|
<view class="description">
|
||||||
三个月内共15位求职者申请,你的简历匹配度为{{ raderData.matchScore }}分,排名位于第{{
|
三个月内共{{ raderData.totalApplicants }}位求职者申请,你的简历匹配度为{{
|
||||||
raderData.rank
|
raderData.matchScore
|
||||||
}}位,超过{{ raderData.percentile }}%的竞争者,处在优秀位置。
|
}}分,排名位于第{{ raderData.rank }}位,超过{{ raderData.percentile }}%的竞争者,处在优秀位置。
|
||||||
</view>
|
</view>
|
||||||
<RadarMap :value="raderData"></RadarMap>
|
<RadarMap :value="raderData"></RadarMap>
|
||||||
|
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -69,7 +69,7 @@ onLoad(() => {
|
|||||||
|
|
||||||
onShow(() => {
|
onShow(() => {
|
||||||
// 获取消息列表
|
// 获取消息列表
|
||||||
useReadMsg().fetchMessages();
|
// useReadMsg().fetchMessages();
|
||||||
});
|
});
|
||||||
|
|
||||||
const state = reactive({
|
const state = reactive({
|
||||||
|
|||||||
@@ -126,7 +126,7 @@ const { getDictSelectOption, oneDictData } = useDictStore();
|
|||||||
const openSelectPopup = inject('openSelectPopup');
|
const openSelectPopup = inject('openSelectPopup');
|
||||||
// status
|
// status
|
||||||
const selectJobsModel = ref();
|
const selectJobsModel = ref();
|
||||||
const tabCurrent = ref(0);
|
const tabCurrent = ref(1);
|
||||||
const salay = [2, 5, 10, 15, 20, 25, 30, 50, 80, 100];
|
const salay = [2, 5, 10, 15, 20, 25, 30, 50, 80, 100];
|
||||||
const state = reactive({
|
const state = reactive({
|
||||||
station: [],
|
station: [],
|
||||||
@@ -150,7 +150,7 @@ const fromValue = reactive({
|
|||||||
});
|
});
|
||||||
|
|
||||||
onLoad((parmas) => {
|
onLoad((parmas) => {
|
||||||
// getTreeselect();
|
getTreeselect();
|
||||||
});
|
});
|
||||||
|
|
||||||
onMounted(() => {});
|
onMounted(() => {});
|
||||||
|
|||||||
168
static/js/SM.js
Normal file
168
static/js/SM.js
Normal file
File diff suppressed because one or more lines are too long
234
static/js/aes.js
Normal file
234
static/js/aes.js
Normal file
@@ -0,0 +1,234 @@
|
|||||||
|
;(function (root, factory, undef) {
|
||||||
|
if (typeof exports === "object") {
|
||||||
|
// CommonJS
|
||||||
|
module.exports = exports = factory(require("./core"), require("./enc-base64"), require("./md5"), require("./evpkdf"), require("./cipher-core"));
|
||||||
|
}
|
||||||
|
else if (typeof define === "function" && define.amd) {
|
||||||
|
// AMD
|
||||||
|
define(["./core", "./enc-base64", "./md5", "./evpkdf", "./cipher-core"], factory);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// Global (browser)
|
||||||
|
factory(root.CryptoJS);
|
||||||
|
}
|
||||||
|
}(this, function (CryptoJS) {
|
||||||
|
|
||||||
|
(function () {
|
||||||
|
// Shortcuts
|
||||||
|
var C = CryptoJS;
|
||||||
|
var C_lib = C.lib;
|
||||||
|
var BlockCipher = C_lib.BlockCipher;
|
||||||
|
var C_algo = C.algo;
|
||||||
|
|
||||||
|
// Lookup tables
|
||||||
|
var SBOX = [];
|
||||||
|
var INV_SBOX = [];
|
||||||
|
var SUB_MIX_0 = [];
|
||||||
|
var SUB_MIX_1 = [];
|
||||||
|
var SUB_MIX_2 = [];
|
||||||
|
var SUB_MIX_3 = [];
|
||||||
|
var INV_SUB_MIX_0 = [];
|
||||||
|
var INV_SUB_MIX_1 = [];
|
||||||
|
var INV_SUB_MIX_2 = [];
|
||||||
|
var INV_SUB_MIX_3 = [];
|
||||||
|
|
||||||
|
// Compute lookup tables
|
||||||
|
(function () {
|
||||||
|
// Compute double table
|
||||||
|
var d = [];
|
||||||
|
for (var i = 0; i < 256; i++) {
|
||||||
|
if (i < 128) {
|
||||||
|
d[i] = i << 1;
|
||||||
|
} else {
|
||||||
|
d[i] = (i << 1) ^ 0x11b;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Walk GF(2^8)
|
||||||
|
var x = 0;
|
||||||
|
var xi = 0;
|
||||||
|
for (var i = 0; i < 256; i++) {
|
||||||
|
// Compute sbox
|
||||||
|
var sx = xi ^ (xi << 1) ^ (xi << 2) ^ (xi << 3) ^ (xi << 4);
|
||||||
|
sx = (sx >>> 8) ^ (sx & 0xff) ^ 0x63;
|
||||||
|
SBOX[x] = sx;
|
||||||
|
INV_SBOX[sx] = x;
|
||||||
|
|
||||||
|
// Compute multiplication
|
||||||
|
var x2 = d[x];
|
||||||
|
var x4 = d[x2];
|
||||||
|
var x8 = d[x4];
|
||||||
|
|
||||||
|
// Compute sub bytes, mix columns tables
|
||||||
|
var t = (d[sx] * 0x101) ^ (sx * 0x1010100);
|
||||||
|
SUB_MIX_0[x] = (t << 24) | (t >>> 8);
|
||||||
|
SUB_MIX_1[x] = (t << 16) | (t >>> 16);
|
||||||
|
SUB_MIX_2[x] = (t << 8) | (t >>> 24);
|
||||||
|
SUB_MIX_3[x] = t;
|
||||||
|
|
||||||
|
// Compute inv sub bytes, inv mix columns tables
|
||||||
|
var t = (x8 * 0x1010101) ^ (x4 * 0x10001) ^ (x2 * 0x101) ^ (x * 0x1010100);
|
||||||
|
INV_SUB_MIX_0[sx] = (t << 24) | (t >>> 8);
|
||||||
|
INV_SUB_MIX_1[sx] = (t << 16) | (t >>> 16);
|
||||||
|
INV_SUB_MIX_2[sx] = (t << 8) | (t >>> 24);
|
||||||
|
INV_SUB_MIX_3[sx] = t;
|
||||||
|
|
||||||
|
// Compute next counter
|
||||||
|
if (!x) {
|
||||||
|
x = xi = 1;
|
||||||
|
} else {
|
||||||
|
x = x2 ^ d[d[d[x8 ^ x2]]];
|
||||||
|
xi ^= d[d[xi]];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}());
|
||||||
|
|
||||||
|
// Precomputed Rcon lookup
|
||||||
|
var RCON = [0x00, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* AES block cipher algorithm.
|
||||||
|
*/
|
||||||
|
var AES = C_algo.AES = BlockCipher.extend({
|
||||||
|
_doReset: function () {
|
||||||
|
var t;
|
||||||
|
|
||||||
|
// Skip reset of nRounds has been set before and key did not change
|
||||||
|
if (this._nRounds && this._keyPriorReset === this._key) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Shortcuts
|
||||||
|
var key = this._keyPriorReset = this._key;
|
||||||
|
var keyWords = key.words;
|
||||||
|
var keySize = key.sigBytes / 4;
|
||||||
|
|
||||||
|
// Compute number of rounds
|
||||||
|
var nRounds = this._nRounds = keySize + 6;
|
||||||
|
|
||||||
|
// Compute number of key schedule rows
|
||||||
|
var ksRows = (nRounds + 1) * 4;
|
||||||
|
|
||||||
|
// Compute key schedule
|
||||||
|
var keySchedule = this._keySchedule = [];
|
||||||
|
for (var ksRow = 0; ksRow < ksRows; ksRow++) {
|
||||||
|
if (ksRow < keySize) {
|
||||||
|
keySchedule[ksRow] = keyWords[ksRow];
|
||||||
|
} else {
|
||||||
|
t = keySchedule[ksRow - 1];
|
||||||
|
|
||||||
|
if (!(ksRow % keySize)) {
|
||||||
|
// Rot word
|
||||||
|
t = (t << 8) | (t >>> 24);
|
||||||
|
|
||||||
|
// Sub word
|
||||||
|
t = (SBOX[t >>> 24] << 24) | (SBOX[(t >>> 16) & 0xff] << 16) | (SBOX[(t >>> 8) & 0xff] << 8) | SBOX[t & 0xff];
|
||||||
|
|
||||||
|
// Mix Rcon
|
||||||
|
t ^= RCON[(ksRow / keySize) | 0] << 24;
|
||||||
|
} else if (keySize > 6 && ksRow % keySize == 4) {
|
||||||
|
// Sub word
|
||||||
|
t = (SBOX[t >>> 24] << 24) | (SBOX[(t >>> 16) & 0xff] << 16) | (SBOX[(t >>> 8) & 0xff] << 8) | SBOX[t & 0xff];
|
||||||
|
}
|
||||||
|
|
||||||
|
keySchedule[ksRow] = keySchedule[ksRow - keySize] ^ t;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Compute inv key schedule
|
||||||
|
var invKeySchedule = this._invKeySchedule = [];
|
||||||
|
for (var invKsRow = 0; invKsRow < ksRows; invKsRow++) {
|
||||||
|
var ksRow = ksRows - invKsRow;
|
||||||
|
|
||||||
|
if (invKsRow % 4) {
|
||||||
|
var t = keySchedule[ksRow];
|
||||||
|
} else {
|
||||||
|
var t = keySchedule[ksRow - 4];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (invKsRow < 4 || ksRow <= 4) {
|
||||||
|
invKeySchedule[invKsRow] = t;
|
||||||
|
} else {
|
||||||
|
invKeySchedule[invKsRow] = INV_SUB_MIX_0[SBOX[t >>> 24]] ^ INV_SUB_MIX_1[SBOX[(t >>> 16) & 0xff]] ^
|
||||||
|
INV_SUB_MIX_2[SBOX[(t >>> 8) & 0xff]] ^ INV_SUB_MIX_3[SBOX[t & 0xff]];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
encryptBlock: function (M, offset) {
|
||||||
|
this._doCryptBlock(M, offset, this._keySchedule, SUB_MIX_0, SUB_MIX_1, SUB_MIX_2, SUB_MIX_3, SBOX);
|
||||||
|
},
|
||||||
|
|
||||||
|
decryptBlock: function (M, offset) {
|
||||||
|
// Swap 2nd and 4th rows
|
||||||
|
var t = M[offset + 1];
|
||||||
|
M[offset + 1] = M[offset + 3];
|
||||||
|
M[offset + 3] = t;
|
||||||
|
|
||||||
|
this._doCryptBlock(M, offset, this._invKeySchedule, INV_SUB_MIX_0, INV_SUB_MIX_1, INV_SUB_MIX_2, INV_SUB_MIX_3, INV_SBOX);
|
||||||
|
|
||||||
|
// Inv swap 2nd and 4th rows
|
||||||
|
var t = M[offset + 1];
|
||||||
|
M[offset + 1] = M[offset + 3];
|
||||||
|
M[offset + 3] = t;
|
||||||
|
},
|
||||||
|
|
||||||
|
_doCryptBlock: function (M, offset, keySchedule, SUB_MIX_0, SUB_MIX_1, SUB_MIX_2, SUB_MIX_3, SBOX) {
|
||||||
|
// Shortcut
|
||||||
|
var nRounds = this._nRounds;
|
||||||
|
|
||||||
|
// Get input, add round key
|
||||||
|
var s0 = M[offset] ^ keySchedule[0];
|
||||||
|
var s1 = M[offset + 1] ^ keySchedule[1];
|
||||||
|
var s2 = M[offset + 2] ^ keySchedule[2];
|
||||||
|
var s3 = M[offset + 3] ^ keySchedule[3];
|
||||||
|
|
||||||
|
// Key schedule row counter
|
||||||
|
var ksRow = 4;
|
||||||
|
|
||||||
|
// Rounds
|
||||||
|
for (var round = 1; round < nRounds; round++) {
|
||||||
|
// Shift rows, sub bytes, mix columns, add round key
|
||||||
|
var t0 = SUB_MIX_0[s0 >>> 24] ^ SUB_MIX_1[(s1 >>> 16) & 0xff] ^ SUB_MIX_2[(s2 >>> 8) & 0xff] ^ SUB_MIX_3[s3 & 0xff] ^ keySchedule[ksRow++];
|
||||||
|
var t1 = SUB_MIX_0[s1 >>> 24] ^ SUB_MIX_1[(s2 >>> 16) & 0xff] ^ SUB_MIX_2[(s3 >>> 8) & 0xff] ^ SUB_MIX_3[s0 & 0xff] ^ keySchedule[ksRow++];
|
||||||
|
var t2 = SUB_MIX_0[s2 >>> 24] ^ SUB_MIX_1[(s3 >>> 16) & 0xff] ^ SUB_MIX_2[(s0 >>> 8) & 0xff] ^ SUB_MIX_3[s1 & 0xff] ^ keySchedule[ksRow++];
|
||||||
|
var t3 = SUB_MIX_0[s3 >>> 24] ^ SUB_MIX_1[(s0 >>> 16) & 0xff] ^ SUB_MIX_2[(s1 >>> 8) & 0xff] ^ SUB_MIX_3[s2 & 0xff] ^ keySchedule[ksRow++];
|
||||||
|
|
||||||
|
// Update state
|
||||||
|
s0 = t0;
|
||||||
|
s1 = t1;
|
||||||
|
s2 = t2;
|
||||||
|
s3 = t3;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Shift rows, sub bytes, add round key
|
||||||
|
var t0 = ((SBOX[s0 >>> 24] << 24) | (SBOX[(s1 >>> 16) & 0xff] << 16) | (SBOX[(s2 >>> 8) & 0xff] << 8) | SBOX[s3 & 0xff]) ^ keySchedule[ksRow++];
|
||||||
|
var t1 = ((SBOX[s1 >>> 24] << 24) | (SBOX[(s2 >>> 16) & 0xff] << 16) | (SBOX[(s3 >>> 8) & 0xff] << 8) | SBOX[s0 & 0xff]) ^ keySchedule[ksRow++];
|
||||||
|
var t2 = ((SBOX[s2 >>> 24] << 24) | (SBOX[(s3 >>> 16) & 0xff] << 16) | (SBOX[(s0 >>> 8) & 0xff] << 8) | SBOX[s1 & 0xff]) ^ keySchedule[ksRow++];
|
||||||
|
var t3 = ((SBOX[s3 >>> 24] << 24) | (SBOX[(s0 >>> 16) & 0xff] << 16) | (SBOX[(s1 >>> 8) & 0xff] << 8) | SBOX[s2 & 0xff]) ^ keySchedule[ksRow++];
|
||||||
|
|
||||||
|
// Set output
|
||||||
|
M[offset] = t0;
|
||||||
|
M[offset + 1] = t1;
|
||||||
|
M[offset + 2] = t2;
|
||||||
|
M[offset + 3] = t3;
|
||||||
|
},
|
||||||
|
|
||||||
|
keySize: 256/32
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Shortcut functions to the cipher's object interface.
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
*
|
||||||
|
* var ciphertext = CryptoJS.AES.encrypt(message, key, cfg);
|
||||||
|
* var plaintext = CryptoJS.AES.decrypt(ciphertext, key, cfg);
|
||||||
|
*/
|
||||||
|
C.AES = BlockCipher._createHelper(AES);
|
||||||
|
}());
|
||||||
|
|
||||||
|
|
||||||
|
return CryptoJS.AES;
|
||||||
|
|
||||||
|
}));
|
||||||
@@ -1,4 +1,8 @@
|
|||||||
import config from "@/config.js"
|
import config from "@/config.js"
|
||||||
|
import {
|
||||||
|
sm2_Decrypt,
|
||||||
|
sm2_Encrypt
|
||||||
|
} from '@/common/globalFunction';
|
||||||
import useUserStore from '@/stores/useUserStore';
|
import useUserStore from '@/stores/useUserStore';
|
||||||
import {
|
import {
|
||||||
sm4Decrypt,
|
sm4Decrypt,
|
||||||
|
|||||||
Reference in New Issue
Block a user