初始化项目

This commit is contained in:
18500206848
2024-02-02 14:51:50 +08:00
parent dc7051417b
commit 12664d0204
681 changed files with 1 additions and 142886 deletions

View File

@@ -1,124 +0,0 @@
<template>
<div class="tinymce-container editor-container">
<textarea ref="text" :id="tinymceId" class="tinymce-textarea"/>
</div>
</template>
<script>
import plugins from './plugins'
import toolbar from './toolbar'
import {putFileFun} from '../../api/resource/oss.js'
let id = 0
function getid() {
return `tinymce${id++}`
}
export default {
name: 'Tinymce',
props: {
height: {
type: Number,
required: false,
default: 360
},
value:{type:String,default:""}
},
data() {
return {
ed:null,
hasInit:false,
tinymceId: getid(),
}
},
mounted() {
this.initTinymce()
},
deactivated() {
this.destroyTinymce()
},
destroyed() {
this.ed.off('blur')
this.destroyTinymce()
},
methods: {
initTinymce() {
window.tinymce.init({
selector: `#${this.tinymceId}`,
language:'zh_CN',
plugins: plugins,
toolbar: toolbar,
height: this.height, //编辑器高度
min_height: 400,
fontsize_formats: '12px 14px 16px 18px 24px 36px 48px 56px 72px',
font_formats: '微软雅黑=Microsoft YaHei,Helvetica Neue,PingFang SC,sans-serif;苹果苹方=PingFang SC,Microsoft YaHei,sans-serif;宋体=simsun,serif;仿宋体=FangSong,serif;黑体=SimHei,sans-serif;Arial=arial,helvetica,sans-serif;Arial Black=arial black,avant garde;Book Antiqua=book antiqua,palatino;Comic Sans MS=comic sans ms,sans-serif;Courier New=courier new,courier;Georgia=georgia,palatino;Helvetica=helvetica;Impact=impact,chicago;Symbol=symbol;Tahoma=tahoma,arial,helvetica,sans-serif;Terminal=terminal,monaco;Times New Roman=times new roman,times;Verdana=verdana,geneva;Webdings=webdings;Wingdings=wingdings,zapf dingbats;知乎配置=BlinkMacSystemFont, Helvetica Neue, PingFang SC, Microsoft YaHei, Source Han Sans SC, Noto Sans CJK SC, WenQuanYi Micro Hei, sans-serif;小米配置=Helvetica Neue,Helvetica,Arial,Microsoft Yahei,Hiragino Sans GB,Heiti SC,WenQuanYi Micro Hei,sans-serif',
extended_valid_elements:'script[src]',
template_cdate_format: '[CDATE: %m/%d/%Y : %H:%M:%S]',
template_mdate_format: '[MDATE: %m/%d/%Y : %H:%M:%S]',
autosave_ask_before_unload: false,
toolbar_mode : 'wrap',
images_upload_base_path: '',
images_upload_handler: function (blobInfo, succFun) {
var file = blobInfo.file ? blobInfo.file : blobInfo.blob()
putFileFun(file).then(e => {
succFun(e.data.data.link)
})
},
setup:(ed) => {
this.ed = ed
ed.on("blur", () => {
this.$emit('input',this.getContent())
})
}
}).then(()=>{
this.hasInit = true
this.setContent(this.value)
});
},
destroyTinymce() {
if (window.tinymce.get(this.tinymceId)) {
window.tinymce.get(this.tinymceId).destroy()
}
},
setContent(value) {
if (this.hasInit)
{window.tinyMCE.get(this.tinymceId).setContent(value)}
},
getContent() {
return window.tinymce.get(this.tinymceId).getContent()
},
},
watch:{
value(val){
this.setContent(val)
}
}
}
</script>
<style scoped>
.tinymce-container {
position: relative;
}
.tinymce-container>>>.mce-fullscreen {
z-index: 10000;
}
.tinymce-textarea {
visibility: hidden;
z-index: -1;
}
.editor-custom-btn-container {
position: absolute;
right: 4px;
top: 4px;
z-index: 2005;
}
.fullscreen .editor-custom-btn-container {
z-index: 10000;
position: fixed;
}
.editor-upload-btn {
display: inline-block;
}
</style>

View File

@@ -1,5 +0,0 @@
const plugins = 'print preview searchreplace autolink directionality visualblocks visualchars fullscreen image link media template code codesample table charmap hr pagebreak nonbreaking anchor insertdatetime advlist lists wordcount imagetools textpattern help emoticons autosave indent2em autoresize axupimgs'
export default plugins

View File

@@ -1,6 +0,0 @@
const toolbar = 'code undo redo restoredraft | cut copy paste pastetext | forecolor backcolor bold italic underline strikethrough link anchor | alignleft aligncenter alignright alignjustify outdent indent | \
styleselect formatselect fontselect fontsizeselect | bullist numlist | blockquote subscript superscript removeformat | \
table image media charmap emoticons hr pagebreak insertdatetime print preview | fullscreen | indent2em axupimgs'
export default toolbar

View File

@@ -1,126 +0,0 @@
<template>
<div class="basic-block"
:style="styleName">
<div class="box"
:style="boxStyleName">
<router-link :to="to">
<span v-text="text"></span>
<p v-text="dept"></p>
<i :class="icon"></i>
</router-link>
</div>
</div>
</template>
<script>
export default {
name: 'basicBlock',
props: {
icon: {
type: String,
},
background: {
type: String,
},
to: {
type: Object,
default: () => {
return {}
}
},
text: {
type: String,
},
dept: {
type: String,
},
time: {
type: [Number, String]
},
gutter: {
type: [Number, String],
default: 5,
},
color: {
type: String,
},
width: {
type: [Number, String]
},
height: {
type: [Number, String]
}
},
computed: {
styleName () {
return {
animationDelay: `${this.time / 25}s`,
width: this.setPx(this.width),
height: this.setPx(this.height),
margin: this.setPx(this.gutter)
}
},
boxStyleName () {
return {
backgroundColor: this.color,
backgroundImage: `url('${this.background}')`,
}
}
}
}
</script>
<style lang="scss">
.basic-block {
opacity: 0;
box-sizing: border-box;
color: #fff;
animation: mymove 1s;
animation-fill-mode: forwards;
.box {
position: relative;
box-sizing: border-box;
padding: 15px;
width: 100%;
height: 100%;
transition: all 1s;
background-size: cover;
&:hover {
transform: rotateY(360deg);
}
}
a {
color: #fff;
}
span {
display: block;
font-size: 16px;
}
p {
width: 80%;
font-size: 10px;
color: #eee;
line-height: 22px;
}
i {
position: absolute;
bottom: 15px;
right: 15px;
font-size: 50px !important ;
}
@keyframes mymove {
from {
opacity: 0;
transform: scale(0);
}
to {
opacity: 1;
transform: scale(1);
}
}
}
</style>

View File

@@ -1,54 +0,0 @@
<template>
<div class="basic-container"
:class="{'basic-container--block':block}">
<el-card>
<slot></slot>
</el-card>
</div>
</template>
<script>
export default {
name: "basicContainer",
props: {
radius: {
type: [String, Number],
default: 10
},
background: {
type: String
},
block: {
type: Boolean,
default: false
}
},
computed: {
styleName () {
return {
borderRadius: this.setPx(this.radius),
background: this.background,
}
}
}
};
</script>
<style lang="scss">
.basic-container {
padding: 10px 6px;
box-sizing: border-box;
&--block {
height: 100%;
.el-card {
height: 100%;
}
}
.el-card {
width: 100%;
}
&:first-child {
padding-top: 0;
}
}
</style>

View File

@@ -1,85 +0,0 @@
<template>
<el-cascader
:options="area.data"
:show-all-levels="showAllLevels"
v-model="model"
:filterable="filterable"
:placeholder="placeholder"
:disabled="disabled"
:clearable="clearable"
></el-cascader>
</template>
<script>
import { mapGetters } from "vuex";
function getProv(code) {
return code.substring(0, 2) + "0000";
}
function getCity(code) {
return code.substring(0, 4) + "00";
}
export default {
props: {
value: String,
filterable: Boolean,
placeholder: String,
showAllLevels: { type: Boolean, default: true },
disabled: Boolean,
clearable: Boolean,
},
data() {
return {
options: [],
};
},
created() {
this.$store.dispatch("InitArea");
},
watch: {},
computed: {
...mapGetters(["area"]),
prov() {
if (this.county) {
return getProv(this.county);
} else {
return "";
}
},
city() {
if (this.county) {
return getCity(this.county);
} else {
return "";
}
},
county: {
get() {
return this.value;
},
set(val) {
this.$emit("input", val);
},
},
model: {
set(val) {
if (val.length > 2) {
this.county = val[2];
} else {
this.county = undefined;
}
},
get() {
if (this.county) {
return [this.prov, this.city, this.county];
}
return null;
},
},
},
};
</script>
<style>
</style>

View File

@@ -1,24 +0,0 @@
<template>
<div class="error-page">
<div class="img"
style=" background-image: url('./img/bg/403.svg');"></div>
<div class="content">
<h1>403</h1>
<div class="desc">抱歉你无权访问该页面</div>
<div class="actions">
<router-link :to="{path:'/'}">
<el-button type="primary">返回首页</el-button>
</router-link>
</div>
</div>
</div>
</template>
<script>
export default {
name: "error-403"
};
</script>
<style lang="scss" scoped>
@import "./style.scss";
</style>

View File

@@ -1,24 +0,0 @@
<template>
<div class="error-page">
<div class="img"
style=" background-image: url('./img/bg/404.svg');"></div>
<div class="content">
<h1>404</h1>
<div class="desc">抱歉你访问的页面不存在</div>
<div class="actions">
<router-link :to="{path:'/'}">
<el-button type="primary">返回首页</el-button>
</router-link>
</div>
</div>
</div>
</template>
<script>
export default {
name: "error-404"
};
</script>
<style lang="scss" scoped>
@import "./style.scss";
</style>

View File

@@ -1,24 +0,0 @@
<template>
<div class="error-page">
<div class="img"
style=" background-image: url('./img/bg/500.svg');"></div>
<div class="content">
<h1>500</h1>
<div class="desc">抱歉服务器出错了</div>
<div class="actions">
<router-link :to="{path:'/'}">
<el-button type="primary">返回首页</el-button>
</router-link>
</div>
</div>
</div>
</template>
<script>
export default {
name: "error-500"
};
</script>
<style lang="scss" scoped>
@import "./style.scss";
</style>

View File

@@ -1,32 +0,0 @@
.error-page {
background: #f0f2f5;
margin-top: -30px;
height: 100%;
display: flex;
align-items: center;
justify-content: center;
.img {
margin-right: 80px;
height: 360px;
width: 100%;
max-width: 430px;
background-repeat: no-repeat;
background-position: 50% 50%;
background-size: contain;
}
.content {
h1 {
color: #434e59;
font-size: 72px;
font-weight: 600;
line-height: 72px;
margin-bottom: 24px;
}
.desc {
color: rgba(0, 0, 0, 0.45);
font-size: 20px;
line-height: 28px;
margin-bottom: 16px;
}
}
}

View File

@@ -1,65 +0,0 @@
<template>
<el-upload action="#" class="upload" drag :before-upload="beforeUpload">
<i class="el-icon-upload"></i>
<div class="el-upload__text">
将文件拖到此处
<em>点击上传</em>
</div>
<div class="el-upload__tip" slot="tip">
<span>请上传 .xls,.xlsx 标准格式文件 </span>
<span class="redFont"> 最多可上传1000条Excel数据</span>
</div>
</el-upload>
</template>
<script>
import { isExcel } from "@/util/validate";
import XLSX from "xlsx";
function fixdata(data) {
let o = "";
let l = 0;
let w = 10240;
for (; l < data.byteLength / w; ++l) {
o += String.fromCharCode.apply(
null,
new Uint8Array(data.slice(l * w, l * w + w))
);
}
o += String.fromCharCode.apply(null, new Uint8Array(data.slice(l * w)));
return o;
}
export default {
props: { success: Function },
methods: {
beforeUpload(file) {
if (!isExcel(file)) {
this.$message.error("上传参保信息只能是 .xls,.xlsx 标准格式文件!");
return;
}
let reader = new FileReader();
let self = this;
reader.onload = function(e) {
var data = e.target.result;
var wb = XLSX.read(btoa(fixdata(data)), {
type: "base64"
});
var questions = XLSX.utils.sheet_to_json(wb.Sheets[wb.SheetNames[0]]);
self.success(questions);
};
reader.readAsArrayBuffer(file);
return false;
}
}
};
</script>
<style scoped>
.upload {
display: inline-block;
}
.redFont{
color:#ff0000;
}
</style>

View File

@@ -1,21 +0,0 @@
<template>
<div style="text-align: right;margin: 0 0 5px 0">
<el-button icon="el-icon-close" circle @click="goBack" size="small"></el-button>
</div>
</template>
<script>
export default {
data() {
return {};
},
methods: {
goBack() {
this.$router.go(-1);
}
}
};
</script>
<style>
</style>

View File

@@ -1,129 +0,0 @@
<template>
<basic-container>
<iframe :src="src"
class="iframe"
ref="iframe"></iframe>
</basic-container>
</template>
<script>
import {mapGetters} from "vuex";
import NProgress from "nprogress"; // progress bar
import "nprogress/nprogress.css"; // progress bar style
export default {
name: "AvueIframe",
data() {
return {
urlPath: this.getUrlPath() //iframe src 路径
};
},
created() {
NProgress.configure({showSpinner: false});
},
mounted() {
this.load();
this.resize();
},
props: ["routerPath"],
watch: {
$route: function () {
this.load();
},
routerPath: function () {
// 监听routerPath变化改变src路径
this.urlPath = this.getUrlPath();
}
},
computed: {
...mapGetters(["screen"]),
src() {
return this.$route.query.src
? this.$route.query.src.replace("$", "#")
: this.urlPath;
}
},
methods: {
// 显示等待框
show() {
NProgress.start();
},
// 隐藏等待狂
hide() {
NProgress.done();
},
// 加载浏览器窗口变化自适应
resize() {
window.onresize = () => {
this.iframeInit();
};
},
// 加载组件
load() {
this.show();
var flag = true; //URL是否包含问号
if (this.$route.query.src !== undefined && this.$route.query.src.indexOf("?") === -1) {
flag = false;
}
var list = [];
for (var key in this.$route.query) {
if (key !== "src" && key !== "name" && key !== "i18n") {
list.push(`${key}= this.$route.query[key]`);
}
}
list = list.join("&").toString();
if (flag) {
this.$route.query.src = `${this.$route.query.src}${
list.length > 0 ? `&list` : ""
}`;
} else {
this.$route.query.src = `${this.$route.query.src}${
list.length > 0 ? `?list` : ""
}`;
}
//超时3s自动隐藏等待狂加强用户体验
let time = 3;
const timeFunc = setInterval(() => {
time--;
if (time === 0) {
this.hide();
clearInterval(timeFunc);
}
}, 1000);
this.iframeInit();
},
//iframe窗口初始化
iframeInit() {
const iframe = this.$refs.iframe;
const clientHeight =
document.documentElement.clientHeight - (screen > 1 ? 200 : 130);
if (!iframe) return;
iframe.style.height = `${clientHeight}px`;
if (iframe.attachEvent) {
iframe.attachEvent("onload", () => {
this.hide();
});
} else {
iframe.onload = () => {
this.hide();
};
}
},
getUrlPath: function () {
//获取 iframe src 路径
let url = window.location.href;
url = url.replace("/myiframe", "");
return url;
}
}
};
</script>
<style lang="scss">
.iframe {
width: 100%;
height: 100%;
border: 0;
overflow: hidden;
box-sizing: border-box;
}
</style>

View File

@@ -1,320 +0,0 @@
<template>
<!-- <div v-if="jlHelpShow" class="jl-help" :style="{'height': height, 'width': width +'px'}">-->
<div class="jl-help avue-right-sidebar" :class="{'jl-help-active': jlHelpShow}">
<div v-if="jlHelpShow">
<div class="jl-switch">
{{helpSwitch}}
<el-switch
v-model="switchValue"
@change="switchHelp"
active-text="默认弹出此侧边栏">
</el-switch>
</div>
<!--政策法规 isShowPolicy -->
<div v-if="helpList.isShowPolicy === 1">
<div>
<div class="big-blank"></div>
<p class="jl-help-title">政策法规</p>
<div class="medium-blank"></div>
<div v-if="policyList.length === 0">
暂无内容
</div>
<div class="jl-small-title" v-for="(item, index) in policyList" :key="index" @click="lookNews(item)">
<span>[{{item.secondName}}]</span>
<p>{{item.title}}</p>
</div>
</div>
<div class="small-blank"></div>
<div class="jl-hr"></div>
</div>
<!--常见问题 isShowQuestion -->
<div v-if="helpList.isShowQuestion === 1">
<div>
<div class="big-blank"></div>
<p class="jl-help-title">常见问题</p>
<div class="medium-blank"></div>
<div v-if="questionList.length === 0">
暂无内容
</div>
<div class="jl-small-title" v-for="(item, index) in questionList" :key="index" @click="lookNews(item)">
<span>[{{item.secondName}}]</span>
<p>{{item.title}}</p>
</div>
</div>
<div class="small-blank"></div>
<div class="jl-hr"></div>
</div>
<!-- 广告位 isShowCarousel -->
<div class="jl-advertisement" v-if="helpList.isShowCarousel === 1">
<div class="big-blank"></div>
<div>
<img
v-for="(item, index) in carouselVoList"
:key="index"
:src="item.image"
class="img"
alt="">
</div>
</div>
<!-- 客服 isShowCustservice -->
<div v-if="helpList.isShowCustservice === 1">
<div class="big-blank"></div>
<div class="jl-user">
<div class="jl-head-portrait">
<img src="../../../public/img/help/portrait.png" height="42" width="42"/>
</div>
<div class="jl-userInfo">
<p class="name">您好我是小助手</p>
<p class="tip">您的专属客服顾问</p>
</div>
</div>
<div class="jl-help-code">
<div class="img"></div>
<div class="jl-help-code-tips">
扫码添加您的专属顾问
</div>
</div>
<div class="big-blank"></div>
<div class="jl-hr"></div>
</div>
<!--服务热线-->
<div>
<div class="big-blank"></div>
<p class="jl-help-title">服务热线</p>
<div class="medium-blank"></div>
<div class="jl-help-phone">
<img src="../../../public/img/help/phone.png" height="20" width="20"/>
<p>185-0020-6848</p>
</div>
<div class="jl-help-time">
<p>服务时间周一至周六08:30-18:00</p>
</div>
</div>
<div style="height: 120px;"></div>
</div>
<el-drawer
title="查看"
:with-header="false"
:visible.sync="drawer"
:direction="direction"
:size="drawerSize">
<div v-html="content">
</div>
</el-drawer>
</div>
</template>
<script>
import {mapState, mapGetters} from "vuex";
import {
getStore,
} from '@/util/store'
export default {
name: "index",
props: {
helpShow: {
default: true,
type: Boolean
}
},
data () {
return {
switchValue: true,
drawer: false,
direction: 'rtl',
drawerSize: '1000px',
content: '',
height: 0,
}
},
watch: {},
methods: {
// 每次点击时进行切换;修改状态在整个系统生效;
switchHelp (v) {
var helpSwitch = v ? 1 : 2
this.$store.dispatch('jlHelpSwitch', helpSwitch)
},
lookNews(item){
this.drawer = true
this.content = item.content
}
},
computed: {
...mapState({
helpTag: state => state.common.helpTag,
helpList: state => state.common.helpList,
}),
jlHelpShow () {
return this.helpTag
},
helpSwitch () {
var helpSwitch = this.$store.state.common.helpSwitch
var status = helpSwitch === 1 ? true : false;
this.switchValue = status
return ''
},
policyList () {
return this.helpList.contentListPolicy
},
questionList () {
return this.helpList.contentListQuestion
},
carouselVoList () {
return this.helpList.carouselVoList
}
}
}
</script>
<style scoped>
p {
margin: 0!important;
}
.big-blank{
height:24px;
}
.medium-blank{
height:16px;
}
.small-blank{
height:12px;
}
.jl-switch{
height: 40px;border-bottom:1px solid #f6f6f6;
margin-left: -20px;margin-right: -20px;line-height: 40px;padding-left:20px;
}
.jl-hr{
width: 198px;
height: 1px;
background-color: rgba(0, 0, 0, 0.08);
}
.jl-help-active{
border-top:1px solid #f6f6f6;
border-left:1px solid #f6f6f6;
box-shadow: 0 1px 2px 0 rgba(0, 0, 0, 0.15);
width: 240px !important;
overflow: auto;min-height: 500px;
height: calc(100% - 64px);
background-color: #FFFFFF;
padding: 0 20px 20px 20px;
}
.jl-help{
width: 0;
}
.jl-help-title{
font-weight: bold;
height: 19px;
font-size: 14px;
color: rgba(0, 0, 0, 0.8);
line-height: 19px;
}
.jl-small-title:hover p{
color: rgba(0, 0, 0, 1) !important;
}
.jl-small-title:hover span{
color: rgba(0, 0, 0, 1) !important;
}
.jl-small-title{
display: flex;
font-size: 12px;
margin-bottom: 12px;
cursor: pointer;
}
.jl-small-title span{
color: rgba(0, 0, 0, 0.4);
margin-right:12px;
}
.jl-small-title p{
color: rgba(0, 0, 0, 0.7);
flex: 1;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.jl-advertisement .img{
width: 198px;
height: 120px;
background-color: #e3e3e3;
border-radius: 4px;
}
.jl-user{
display: flex;
align-items: center;
font-size: 12px;
}
.jl-user .jl-head-portrait{
width: 56px;
height: 56px;
border-radius: 50%;
border: 1px solid #fdfef8;
text-align: center;
line-height: 44px;
background-color: #fdfef8;
margin-right: 8px;
}
.jl-userInfo{
font-size: 15px;
line-height: 20px;
}
.jl-userInfo .name{
color: rgba(0, 0, 0, 0.7);
}
.jl-userInfo .tip{
color: #419EFF;
}
.jl-help-code{
display: flex;
align-items: center;
flex-flow: column;
}
.jl-help-code .img{
background: url("/manage/img/kefu.jpg") no-repeat;
background-size: 126px 126px;
width: 126px;
height: 126px;
}
.jl-help-code-tips{
width: 120px;
height: 17px;
font-size: 12px;
font-weight: 400;
color: rgba(0, 0, 0, 0.4);
line-height: 17px;
/*margin-bottom: 20px;*/
margin-top: 16px;
}
.jl-help-phone{
display: flex;
align-items: center;
font-size: 20px;
font-weight: 600;
color: rgba(0, 0, 0, 0.8);
}
.jl-help-phone img{
margin-right: 14px;
}
.jl-help-time{
font-size: 12px;
color: rgba(0, 0, 0, 0.4);
line-height: 16px;
margin-top: 9px;
}
</style>

View File

@@ -1,151 +0,0 @@
<template>
<div>
<div class="jl-tabs" ref="body">
<span
v-for="(value, index) in data"
ref="tab"
:key="index"
:class="{ 'jl-tab': true, active: active === index }"
@click="change(index, $event)"
>{{ value }}</span
>
<div :class="lineClass" :style="lineStyle"></div>
</div>
<div class="jl-tabs float" v-show="fixedShow">
<span
v-for="(value, index) in data"
:key="index"
class="jl-tab"
:class="{ 'jl-tab': true, active: active === index }"
@click="change(index, $event)"
ref="tab"
>{{ value }}</span
>
<div :class="lineClass" :style="lineStyle"></div>
</div>
</div>
</template>
<script>
export default {
props: {
fixedShow: {
type: Boolean,
default: false,
},
maxFixed: { type: Number },
data: {
type: Array,
default() {
return [];
},
},
},
data() {
return {
active: 0,
lineWidth: 0,
lineLeft: 0,
mounted: false,
activeStatus: false
};
},
mounted() {
this.initLine();
},
computed: {
lineStyle() {
return { width: `${this.lineWidth}px`, left: `${this.lineLeft}px` };
},
lineClass() {
return {
line: true,
mounted: this.mounted,
};
},
},
methods: {
initLine() {
if (this.data.length > 0) {
this.$nextTick(() => {
this.lineWidth = this.$refs.tab[0].clientWidth;
this.lineLeft = this.$refs.tab[0].offsetLeft;
setTimeout(() => {
this.mounted = true;
}, 20);
});
}
},
change(val) {
if (val === this.active) {
return;
}
this.active = val;
this.activeStatus = true
setTimeout(() => {
this.activeStatus = false
}, 500)
this.$emit("change", this.data[val]);
if (this.fixed && this.fixedShow) {
this.$refs.body.scrollIntoView(true);
}
},
tabNum(index){
if(this.active === index)return
this.active = index;
}
},
watch: {
data() {
this.initLine();
},
active(val){
const tab = this.$refs.tab[val]
this.lineWidth = tab.clientWidth;
this.lineLeft = tab.offsetLeft;
}
},
};
</script>
<style scoped>
.jl-tabs {
width: 1000px;
background-color: #fff;
text-align: center;
margin-bottom: 20px;
position: relative;
}
.jl-tab {
padding: 20px 21px 18px 21px;
display: inline-block;
font-size: 18px;
letter-spacing: 0;
text-align: center;
color: #333333;
margin-right: 45px;
cursor: pointer;
}
.jl-tab.active {
color: #5aa0fa;
}
.jl-tabs .jl-tab:last-of-type {
margin-right: 0px;
}
.jl-tabs .line {
height: 4px;
background: #5aa0fa;
position: absolute;
bottom: 0;
}
.jl-tabs .line.mounted {
transition: left 0.5s;
}
.jl-tabs.float {
position: fixed;
top: 0;
z-index: 2000;
background: #ffffff;
box-shadow: 0 0 10px 0 rgba(0, 0, 0, 0.15);
}
</style>

View File

@@ -1,220 +0,0 @@
<template>
<div class="app-container">
<el-autocomplete
v-model="addressLocation"
style="width:100%;"
popper-class="autoAddressClass"
:fetch-suggestions="querySearchAsync"
:trigger-on-focus="false"
placeholder="详细地址"
clearable="false"
@select="handleSelect"
:disabled="!isCanEdit"
v-show="type!=='view'"
@input="addressChangeHandle"
>
<template slot-scope="{ item }">
<div style="overflow:hidden;">
<div class="title">{{ item.title }}</div>
<span class="address ellipsis">{{ item.address }}</span>
</div>
</template>
</el-autocomplete>
<div ref="mapContainer" style="width:100%;height:300px;" v-if="isCanEdit" />
<div ref="viewMap" style="width:100%;height:300px;" v-else />
</div>
</template>
<script>
/* eslint-disable */
import { getcoder, querySearch } from "@/api/tenant/map";
export default {
props: {
lat: {
type: "string",
default: 23.1315381,
},
lng: {
type: "string",
default: 113.3324436,
},
address: String,
isCanEdit: Boolean,
type: {
type: "string",
default: "",
},
},
data () {
return {
map: "", // 地图实例
mk: "", // Marker实例
map2: "", // 地图实例
mk2: "", // Marker实例,
addressLocation: this.address,
key: "FW3BZ-6JTK6-GCUS5-MZCRR-3GPR5-HJFEI",
addressTip: [],
};
},
mounted () {
this.initMap();
},
watch: {},
methods: {
addressChangeHandle(val){
if(val == ""){
this.$emit('addressDel',"删除了地址数据")
}
},
// 初始化地图
initMap () {
var that = this;
if (this.isCanEdit) {
var point = new qq.maps.LatLng(this.lat, this.lng);
// 1、挂载第一张地图
this.map = new qq.maps.Map(this.$refs.mapContainer, {
center: point,
zoom: 19,
//启用缩放控件
zoomControl: true,
//地图缩放控件参数
zoomControlOptions: {
position: qq.maps.ControlPosition.TOP_LEFT,
},
//地图比例尺控件若为false则不显示比例尺控件
scaleControl: false,
});
// 3、设置图像标注并绑定拖拽标注结束后事件
this.mk = new qq.maps.Marker({
position: point,
draggable: true,
map: that.map,
});
// 绑定拖拽标注结束后事件
qq.maps.event.addListener(this.mk, "dragend", function (e) {
that.getAddrByPoint(e.latLng);
});
//6、浏览器定位
if (this.type === "add") {
this.geolocation();
}
// 7、绑定点击地图任意点事件
qq.maps.event.addListener(this.map, "click", function (e) {
that.getAddrByPoint(e.latLng);
});
} else {
var point2 = new qq.maps.LatLng(this.lat, this.lng);
// 1、挂载第二张地图
this.map2 = new qq.maps.Map(this.$refs.viewMap, {
center: point2,
zoom: 19,
//地图缩放控件参数
zoomControlOptions: {
position: qq.maps.ControlPosition.TOP_LEFT,
},
//地图比例尺控件若为false则不显示比例尺控件
scaleControl: false,
});
// 2、设置图像标注并绑定拖拽标注结束后事件
this.mk2 = new qq.maps.Marker({
position: point2,
draggable: false,
map: that.map2,
});
}
},
// 浏览器定位函数
geolocation () {
var that = this;
var geolocation = new qq.maps.Geolocation(
"FW3BZ-6JTK6-GCUS5-MZCRR-3GPR5-HJFEI",
"jobslink 企业"
);
geolocation.getLocation(this.showPosition, this.showErr, {
timeout: 20000,
failTipFlag: true,
});
},
showPosition (position) {
this.getAddrByPoint({
lat: position.lat,
lng: position.lng,
});
},
showErr () {
console.log("定位失败!");
},
// // 2、逆地址解析函数
getAddrByPoint (point) {
var currentPoint = new qq.maps.LatLng(point.lat, point.lng);
var that = this;
var location = point.lat + "," + point.lng;
getcoder(location, encodeURI(this.key), 0).then((res) => {
that.mk.setPosition(currentPoint);
that.map.panTo(currentPoint);
let obj = {
address: res.data.result.address,
lng: point.lng,
lat: point.lat,
};
that.addressLocation = obj.address
that.$emit("addAddress", obj);
});
},
async querySearchAsync (queryString, cb) {
await querySearch(queryString, encodeURI(this.key)).then((res) => {
if (res.data.status === 0) {
this.addressTip = res.data.data;
}
});
var results = this.addressTip;
clearTimeout(this.timeout);
this.timeout = setTimeout(() => {
cb(results);
}, 1000 * Math.random());
},
// 8-2、选择地址
handleSelect (item) {
this.addressLocation = item.address;
var point = new qq.maps.LatLng(item.location.lat, item.location.lng);
this.mk.setPosition(point);
this.map.panTo(point);
let obj = {
title: item.title,
address: item.address,
lng: item.location.lng,
lat: item.location.lat,
};
this.$emit("addAddress", obj);
},
},
};
</script>
<style lang="scss" scoped>
.autoAddressClass {
li {
i.el-icon-search {
margin-top: 11px;
}
.mgr10 {
margin-right: 10px;
}
.title {
text-overflow: ellipsis;
overflow: hidden;
}
.address {
line-height: 1;
font-size: 12px;
color: #b4b4b4;
margin-bottom: 5px;
}
}
}
</style>

View File

@@ -1,29 +0,0 @@
<template>
<el-dialog append-to-body title="提示" :visible.sync="dialogVisible" width="30%" :before-close="handleClose">
<span class="noSignText">您还未开通电子签章功能请前往农民工用工管理电子签章管理中申请开通电子签章功能</span>
<span slot="footer" class="dialog-footer">
<el-button type="primary" @click="dialogVisible = false"> </el-button>
</span>
</el-dialog>
</template>
<script>
export default {
data() {
return {
dialogVisible: false,
}
},
methods: {
open() {
this.dialogVisible = true;
}
}
}
</script>
<style>
.noSignText {
text-align: center;
font-size: 15px;
font-weight: 500;
}
</style>

View File

@@ -1,147 +0,0 @@
<template>
<basic-container>
<el-drawer title="个人简历" append-to-body :visible.sync="drawer" size="60%">
<div class="page" v-loading="loading">
<div class="title">
<b style="font-size:16px;">基础信息</b>
</div>
<div class="basic-info">
<div class="avatar">
<img src="/manage/svg/avatar.svg" style="display:inline-block;width:100%;height:auto;" />
<i
class="iconfont iconnan"
style="position:absolute;top:5px;right:5px;"
v-if="data.age===1"
></i>
<i class="iconfont iconnv" style="position:absolute;top:5px;right:5px;" v-else></i>
</div>
<table>
<tr>
<td>{{data.realName}}</td>
<td>{{data.age}}</td>
<td style="padding-left:120px">身份</td>
<td>灵活用工</td>
</tr>
<tr>
<td>联系方式</td>
<td>{{data.telphone}}</td>
<td style="padding-left:120px">期望地点</td>
<td>{{getCity(data.cityId)}}</td>
</tr>
</table>
</div>
<div class="title">
<b>期望行业</b>
</div>
<div class="content">
<el-tag v-for="(item,index) in data.list" :key="index">{{item.trade}}</el-tag>
</div>
<div class="title">
<b>具备技能</b>
</div>
<div class="content">
<el-tag type="success" v-for="(item,index) in data.list" :key="index">{{item.worktypes}}</el-tag>
</div>
<div class="title">
<b>技能水平</b>
</div>
<div class="content">
<el-tag type="danger" v-for="(item,index) in data.list" :key="index">{{item.skills}}</el-tag>
</div>
</div>
</el-drawer>
</basic-container>
</template>
<script>
import { getDetail } from "@/api/tenant/resume";
// import {mapGetters} from "vuex";
export default {
comments: {
},
components: {
},
data () {
return {
userId: '',
loading: false,
drawer: false,
data: {}
}
},
computed: {
},
watch: {
},
methods: {
getCity (val) {
if (val) {
return this.$store.getters.getAreaParents(val)[0].label + this.$store.getters.getAreaParents(val)[1].label
}
},
/*打开drawer*/
openDialog (row) {
this.userId = row.userId;
this.drawer = true;
this.getDetail();
},
/*加载数据*/
getDetail () {
this.loading = true;
getDetail(this.userId).then(res => {
const data = res.data.data;
this.data = data;
this.loading = false;
});
}
}
};
</script>
<style scoped>
.page {
/* padding: 0 30px; */
}
.page .title {
margin-bottom: 20px;
font-size: 16px;
}
.page .basic-info {
display: flex;
flex-direction: row;
justify-content: flex-start;
align-items: center;
flex-wrap: wrap;
margin-bottom: 30px;
}
.page .basic-info .avatar {
position: relative;
width: 120px;
margin-right: 100px;
}
.page .basic-info table {
border-collapse: separate;
border-spacing: 0px 20px;
}
.page .basic-info table tr td {
min-width: 100px;
}
.page .content {
margin-bottom: 30px;
}
.el-tag {
margin-right: 10px;
}
</style>

View File

@@ -1,178 +0,0 @@
<template>
<div>
<el-tag
class="tag-select-tag"
:key="index"
v-for="(tag,index) in value"
:disable-transitions="true"
closable
@close="removeSkill(tag[prop.value], true)"
size="medium"
>{{ tag[prop.label] }}</el-tag
>
<slot name="dialog-btn" v-if="canSelect">
<el-button class="button-new-tag" size="small" @click="showSelect(true)"
>+ 选择{{ name }}</el-button
>
</slot>
<el-dialog
:title="name"
:visible.sync="dialogVisible"
width="30%"
:close-on-click-modal="false"
:close-on-press-escape="false"
:append-to-body="true"
v-loading="loading"
>
<div>
<el-tag
class="tag-select-tag"
:key="key"
v-for="(value, key) in selected"
closable
type="primary"
:disable-transitions="true"
@close="removeSkill(key)"
size="medium"
>{{ value }}</el-tag
>
</div>
<div class="tag-select-tip">请选择您所需的{{ name }}</div>
<div class="tag-select-searchinp">
<el-input
v-model="search"
placeholder="搜索您想要的标签"
clearable=""
></el-input>
</div>
<div>
<el-tag
class="tag-select-tag"
type="info"
:disable-transitions="true"
size="medium"
effect="plain"
v-for="(tag,index) in noSelect"
:key="index"
@click="editSkill(tag)"
>{{ tag[prop.label] }}</el-tag
>
</div>
<span slot="footer" class="dialog-footer">
<el-button
icon="el-icon-circle-plus-outline"
type="primary"
@click="submit"
> </el-button
>
<el-button icon="el-icon-circle-close" @click="dialogVisible = false"
> </el-button
>
</span>
</el-dialog>
</div>
</template>
<script>
import _ from "lodash";
export default {
name: "tagSelect",
props: {
value: {
type: Array,
default() {
return [];
},
},
name: String,
data: {
type: Array,
default() {
return [];
},
},
canSelect: { type: Boolean, default: true },
loading: Boolean,
prop: {
type: Object,
default() {
return {
label: "label",
value: "value",
};
},
},
},
data() {
return {
search: "",
dialogVisible: false,
selected: {},
};
},
computed: {
noSelect() {
let data = this.data.filter((item) => {
return !this.selected.hasOwnProperty(item[this.prop.value]);
});
if (this.search) {
data = this.data.filter((item) => {
return (
item[this.prop.label]
.toLowerCase()
.indexOf(this.search.toLowerCase()) > -1
);
});
}
return data;
},
},
watch: {},
methods: {
/*技能*/
editSkill(tag) {
this.$set(this.selected, tag[this.prop.value], tag[this.prop.label]);
},
removeSkill(key, save) {
this.$delete(this.selected, key);
if (save) {
this.submit();
}
},
submit() {
const res = [];
for (const key in this.selected) {
const item = {};
item[this.prop.label] = this.selected[key];
item[this.prop.value] = key;
res.push(item);
}
this.$emit("input", res);
this.dialogVisible = false;
},
showSelect(flag) {
const value = _.cloneDeep(this.value || []);
let selected = {};
value.forEach((element) => {
selected[element[this.prop.value]] = element[this.prop.label];
});
this.selected = selected;
this.dialogVisible = flag;
},
},
created(){
this.showSelect();
},
};
</script>
<style>
.tag-select-tag {
margin: 0 5px 5px 0;
cursor: pointer;
}
.tag-select-tip,
.tag-select-searchinp {
margin-bottom: 5px;
}
</style>

View File

@@ -1,25 +0,0 @@
<template>
<el-tooltip effect="dark" placement="right">
<div slot="content">
1.选择相应的搜索时间类型
<br/>
2.选择相应的搜索时间范围
<br>
3.点击搜索按钮查看详情
</div>
<img src="./tip.png" height="26" width="26" class="toolTipImg"/>
</el-tooltip>
</template>
<script>
export default {
name: "index"
}
</script>
<style scoped>
.toolTipImg{
margin-bottom: -5px;
margin-right: 10px;
}
</style>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.7 KiB

File diff suppressed because one or more lines are too long

View File

@@ -1,252 +0,0 @@
<template>
<div style="position: relative">
<div class="verify-img-out">
<div
class="verify-img-panel"
:style="{'width': setSize.imgWidth,
'height': setSize.imgHeight,
'background-size' : setSize.imgWidth + ' '+ setSize.imgHeight,
'margin-bottom': vSpace + 'px'}"
>
<div class="verify-refresh" style="z-index:3" @click="refresh" v-show="showRefresh">
<i class="iconfont icon-refresh"></i>
</div>
<img
:src="'data:image/png;base64,'+pointBackImgBase"
ref="canvas"
alt
style="width:100%;height:100%;display:block"
@click="bindingClick?canvasClick($event):undefined"
/>
<div
v-for="(tempPoint, index) in tempPoints"
:key="index"
class="point-area"
:style="{
'background-color':'#1abd6c',
color:'#fff',
'z-index':9999,
width:'20px',
height:'20px',
'text-align':'center',
'line-height':'20px',
'border-radius': '50%',
position:'absolute',
top:parseInt(tempPoint.y-10) + 'px',
left:parseInt(tempPoint.x-10) + 'px'
}"
>{{index + 1}}</div>
</div>
</div>
<!-- 'height': this.barSize.height, -->
<div
class="verify-bar-area"
:style="{'width': setSize.imgWidth,
'color': this.barAreaColor,
'border-color': this.barAreaBorderColor,
'line-height':this.barSize.height}"
>
<span class="verify-msg">{{text}}</span>
</div>
</div>
</template>
<script type="text/babel">
/**
* VerifyPoints
* @description 点选
* */
import { resetSize } from './../utils/util'
import { aesEncrypt } from "./../utils/ase"
import { reqGet, reqCheck } from "./../api/index"
export default {
name: 'VerifyPoints',
props: {
//弹出式pop固定fixed
mode: {
type: String,
default: 'fixed'
},
captchaType: {
type: String,
},
//间隔
vSpace: {
type: Number,
default: 5
},
imgSize: {
type: Object,
default () {
return {
width: '310px',
height: '155px'
}
}
},
barSize: {
type: Object,
default () {
return {
width: '310px',
height: '40px'
}
}
}
},
data () {
return {
secretKey: '', //后端返回的ase加密秘钥
checkNum: 3, //默认需要点击的字数
fontPos: [], //选中的坐标信息
checkPosArr: [], //用户点击的坐标
num: 1, //点击的记数
pointBackImgBase: '', //后端获取到的背景图片
poinTextList: [], //后端返回的点击字体顺序
backToken: '', //后端返回的token值
setSize: {
imgHeight: 0,
imgWidth: 0,
barHeight: 0,
barWidth: 0
},
tempPoints: [],
text: '',
barAreaColor: undefined,
barAreaBorderColor: undefined,
showRefresh: true,
bindingClick: true
}
},
computed: {
resetSize () {
return resetSize
}
},
methods: {
init () {
//加载页面
this.fontPos.splice(0, this.fontPos.length)
this.checkPosArr.splice(0, this.checkPosArr.length)
this.num = 1
this.getPictrue();
this.$nextTick(() => {
this.setSize = this.resetSize(this) //重新设置宽度高度
this.$parent.$emit('ready', this)
})
},
canvasClick (e) {
this.checkPosArr.push(this.getMousePos(this.$refs.canvas, e));
if (this.num == this.checkNum) {
this.num = this.createPoint(this.getMousePos(this.$refs.canvas, e));
//按比例转换坐标值
this.checkPosArr = this.pointTransfrom(this.checkPosArr, this.setSize);
//等创建坐标执行完
setTimeout(() => {
// var flag = this.comparePos(this.fontPos, this.checkPosArr);
//发送后端请求
var captchaVerification = this.secretKey ? aesEncrypt(this.backToken + '---' + JSON.stringify(this.checkPosArr), this.secretKey) : this.backToken + '---' + JSON.stringify(this.checkPosArr)
let data = {
captchaType: this.captchaType,
"pointJson": this.secretKey ? aesEncrypt(JSON.stringify(this.checkPosArr), this.secretKey) : JSON.stringify(this.checkPosArr),
"token": this.backToken
}
reqCheck(data).then(res => {
if (res.repCode == "0000") {
this.barAreaColor = '#4cae4c'
this.barAreaBorderColor = '#5cb85c'
this.text = '验证成功'
this.bindingClick = false
if (this.mode == 'pop') {
setTimeout(() => {
this.$parent.clickShow = false;
this.refresh();
}, 1500)
}
this.$parent.$emit('success', { captchaVerification })
} else {
this.$parent.$emit('error', this)
this.barAreaColor = '#d9534f'
this.barAreaBorderColor = '#d9534f'
this.text = '验证失败'
setTimeout(() => {
this.refresh();
}, 700);
}
})
}, 400);
}
if (this.num < this.checkNum) {
this.num = this.createPoint(this.getMousePos(this.$refs.canvas, e));
}
},
//获取坐标
getMousePos: function (obj, e) {
var x = e.offsetX
var y = e.offsetY
return { x, y }
},
//创建坐标点
createPoint: function (pos) {
this.tempPoints.push(Object.assign({}, pos))
return ++this.num;
},
refresh: function () {
this.tempPoints.splice(0, this.tempPoints.length)
this.barAreaColor = '#000'
this.barAreaBorderColor = '#ddd'
this.bindingClick = true
this.fontPos.splice(0, this.fontPos.length)
this.checkPosArr.splice(0, this.checkPosArr.length)
this.num = 1
this.getPictrue();
this.text = '验证失败'
this.showRefresh = true
},
// 请求背景图片和验证图片
getPictrue () {
let data = {
captchaType: this.captchaType
}
reqGet(data).then(res => {
if (res.repCode == "0000") {
this.pointBackImgBase = res.repData.originalImageBase64
this.backToken = res.repData.token
this.secretKey = res.repData.secretKey
this.poinTextList = res.repData.wordList
this.text = '请依次点击【' + this.poinTextList.join(",") + '】'
} else {
this.text = res.repMsg;
}
})
},
//坐标转换函数
pointTransfrom (pointArr, imgSize) {
var newPointArr = pointArr.map(p => {
let x = Math.round(310 * p.x / parseInt(imgSize.imgWidth))
let y = Math.round(155 * p.y / parseInt(imgSize.imgHeight))
return { x, y }
})
return newPointArr
}
},
watch: {
// type变化则全面刷新
type: {
immediate: true,
handler () {
this.init()
}
}
},
mounted () {
// 禁止拖拽
this.$el.onselectstart = function () {
return false
}
},
}
</script>

View File

@@ -1,375 +0,0 @@
<template>
<div style="position: relative;">
<div
v-if="type === '2'"
class="verify-img-out"
:style="{height: (parseInt(setSize.imgHeight) + vSpace) + 'px'}"
>
<div
class="verify-img-panel"
:style="{width: setSize.imgWidth,
height: setSize.imgHeight,}"
>
<img
:src="'data:image/png;base64,'+backImgBase"
alt
style="width:100%;height:100%;display:block"
/>
<div class="verify-refresh" @click="refresh" v-show="showRefresh">
<i class="iconfont icon-refresh"></i>
</div>
<transition name="tips">
<span
class="verify-tips"
v-if="tipWords"
:class="passFlag ?'suc-bg':'err-bg'"
>{{tipWords}}</span>
</transition>
</div>
</div>
<!-- 公共部分 -->
<div
class="verify-bar-area"
:style="{width: setSize.imgWidth,
height: barSize.height,
'line-height':barSize.height}"
>
<span class="verify-msg" v-text="text"></span>
<div
class="verify-left-bar"
:style="{width: (leftBarWidth!==undefined)?leftBarWidth: barSize.height, height: barSize.height, 'border-color': leftBarBorderColor, transaction: transitionWidth}"
>
<span class="verify-msg" v-text="finishText"></span>
<div
class="verify-move-block"
@touchstart="start"
@mousedown="start"
:style="{width: barSize.height, height: barSize.height, 'background-color': moveBlockBackgroundColor, left: moveBlockLeft, transition: transitionLeft}"
>
<i :class="['verify-icon iconfont', iconClass]" :style="{color: iconColor}"></i>
<div
v-if="type === '2'"
class="verify-sub-block"
:style="{'width':Math.floor(parseInt(setSize.imgWidth)*47/310)+ 'px',
'height': setSize.imgHeight,
'top':'-' + (parseInt(setSize.imgHeight) + vSpace) + 'px',
'background-size': setSize.imgWidth + ' ' + setSize.imgHeight,
}"
>
<img
:src="'data:image/png;base64,'+blockBackImgBase"
alt
style="width:100%;height:100%;display:block"
/>
</div>
</div>
</div>
</div>
</div>
</template>
<script type="text/babel">
/**
* VerifySlide
* @description 滑块
* */
import { aesEncrypt } from "../utils/ase"
import { resetSize } from '../utils/util'
import { reqGet, reqCheck } from "../api/index"
// "captchaType":"blockPuzzle",
/* eslint-disable */
export default {
name: 'VerifySlide',
props: {
captchaType: {
type: String,
},
type: {
type: String,
default: '1'
},
//弹出式pop固定fixed
mode: {
type: String,
default: 'fixed'
},
vSpace: {
type: Number,
default: 5
},
explain: {
type: String,
default: '向右滑动完成验证'
},
imgSize: {
type: Object,
default () {
return {
width: '310px',
height: '155px'
}
}
},
blockSize: {
type: Object,
default () {
return {
width: '50px',
height: '50px'
}
}
},
barSize: {
type: Object,
default () {
return {
width: '310px',
height: '40px'
}
}
}
},
data () {
return {
secretKey: '', //后端返回的加密秘钥 字段
passFlag: '', //是否通过的标识
backImgBase: '', //验证码背景图片
blockBackImgBase: '', //验证滑块的背景图片
backToken: "", //后端返回的唯一token值
startMoveTime: "", //移动开始的时间
endMovetime: '', //移动结束的时间
tipsBackColor: '', //提示词的背景颜色
tipWords: '',
text: '',
finishText: '',
setSize: {
imgHeight: 0,
imgWidth: 0,
barHeight: 0,
barWidth: 0
},
top: 0,
left: 0,
moveBlockLeft: undefined,
leftBarWidth: undefined,
// 移动中样式
moveBlockBackgroundColor: undefined,
leftBarBorderColor: '#ddd',
iconColor: undefined,
iconClass: 'icon-right',
status: false, //鼠标状态
isEnd: false, //是够验证完成
showRefresh: true,
transitionLeft: '',
transitionWidth: ''
}
},
computed: {
barArea () {
return this.$el.querySelector('.verify-bar-area')
},
resetSize () {
return resetSize
}
},
methods: {
init () {
this.text = this.explain
this.getPictrue();
this.$nextTick(() => {
let setSize = this.resetSize(this) //重新设置宽度高度
for (let key in setSize) {
this.$set(this.setSize, key, setSize[key])
}
this.$parent.$emit('ready', this)
})
var _this = this
window.removeEventListener("touchmove", function (e) {
_this.move(e);
});
window.removeEventListener("mousemove", function (e) {
_this.move(e);
});
//鼠标松开
window.removeEventListener("touchend", function () {
_this.end();
});
window.removeEventListener("mouseup", function () {
_this.end();
});
window.addEventListener("touchmove", function (e) {
_this.move(e);
});
window.addEventListener("mousemove", function (e) {
_this.move(e);
});
//鼠标松开
window.addEventListener("touchend", function () {
_this.end();
});
window.addEventListener("mouseup", function () {
_this.end();
});
},
//鼠标按下
start: function (e) {
e = e || window.event
if (!e.touches) { //兼容PC端
var x = e.clientX;
} else { //兼容移动端
var x = e.touches[0].pageX;
}
this.startLeft = Math.floor(x - this.barArea.getBoundingClientRect().left);
this.startMoveTime = +new Date(); //开始滑动的时间
if (this.isEnd == false) {
this.text = ''
this.moveBlockBackgroundColor = '#337ab7'
this.leftBarBorderColor = '#337AB7'
this.iconColor = '#fff'
e.stopPropagation();
this.status = true;
}
},
//鼠标移动
move: function (e) {
e = e || window.event
if (this.status && this.isEnd == false) {
if (!e.touches) { //兼容PC端
var x = e.clientX;
} else { //兼容移动端
var x = e.touches[0].pageX;
}
var bar_area_left = this.barArea.getBoundingClientRect().left;
var move_block_left = x - bar_area_left //小方块相对于父元素的left值
if (move_block_left >= this.barArea.offsetWidth - parseInt(parseInt(this.blockSize.width) / 2) - 2) {
move_block_left = this.barArea.offsetWidth - parseInt(parseInt(this.blockSize.width) / 2) - 2;
}
if (move_block_left <= 0) {
move_block_left = parseInt(parseInt(this.blockSize.width) / 2);
}
//拖动后小方块的left值
this.moveBlockLeft = (move_block_left - this.startLeft) + "px"
this.leftBarWidth = (move_block_left - this.startLeft) + "px"
}
},
//鼠标松开
end: function () {
this.endMovetime = +new Date();
var _this = this;
//判断是否重合
if (this.status && this.isEnd == false) {
var moveLeftDistance = parseInt((this.moveBlockLeft || '').replace('px', ''));
moveLeftDistance = moveLeftDistance * 310 / parseInt(this.setSize.imgWidth)
let data = {
captchaType: this.captchaType,
"pointJson": this.secretKey ? aesEncrypt(JSON.stringify({ x: moveLeftDistance, y: 5.0 }), this.secretKey) : JSON.stringify({ x: moveLeftDistance, y: 5.0 }),
"token": this.backToken
}
reqCheck(data).then(res => {
if (res.repCode == "0000") {
this.moveBlockBackgroundColor = '#5cb85c'
this.leftBarBorderColor = '#5cb85c'
this.iconColor = '#fff'
this.iconClass = 'icon-check'
this.showRefresh = false
this.isEnd = true;
if (this.mode == 'pop') {
setTimeout(() => {
this.$parent.clickShow = false;
this.refresh();
}, 1500)
}
this.passFlag = true
this.tipWords = `${((this.endMovetime - this.startMoveTime) / 1000).toFixed(2)}s验证成功`
var captchaVerification = this.secretKey ? aesEncrypt(this.backToken + '---' + JSON.stringify({ x: moveLeftDistance, y: 5.0 }), this.secretKey) : this.backToken + '---' + JSON.stringify({ x: moveLeftDistance, y: 5.0 })
setTimeout(() => {
this.tipWords = ""
this.$parent.closeBox();
this.$parent.$emit('success', { captchaVerification })
}, 1000)
} else {
this.moveBlockBackgroundColor = '#d9534f'
this.leftBarBorderColor = '#d9534f'
this.iconColor = '#fff'
this.iconClass = 'icon-close'
this.passFlag = false
setTimeout(function () {
_this.refresh();
}, 1000);
this.$parent.$emit('error', this)
this.tipWords = "验证失败"
setTimeout(() => {
this.tipWords = ""
}, 1000)
}
})
this.status = false;
}
},
refresh: function () {
this.showRefresh = true
this.finishText = ''
this.transitionLeft = 'left .3s'
this.moveBlockLeft = 0
this.leftBarWidth = undefined
this.transitionWidth = 'width .3s'
this.leftBarBorderColor = '#ddd'
this.moveBlockBackgroundColor = '#fff'
this.iconColor = '#000'
this.iconClass = 'icon-right'
this.isEnd = false
this.getPictrue()
setTimeout(() => {
this.transitionWidth = ''
this.transitionLeft = ''
this.text = this.explain
}, 300)
},
// 请求背景图片和验证图片
getPictrue () {
let data = {
captchaType: this.captchaType
}
reqGet(data).then(res => {
if (res.repCode == "0000") {
this.backImgBase = res.repData.originalImageBase64
this.blockBackImgBase = res.repData.jigsawImageBase64
this.backToken = res.repData.token
this.secretKey = res.repData.secretKey
} else {
this.tipWords = res.repMsg;
}
})
},
},
watch: {
// type变化则全面刷新
type: {
immediate: true,
handler () {
this.init()
}
}
},
mounted () {
// 禁止拖拽
this.$el.onselectstart = function () {
return false
}
},
}
</script>

View File

@@ -1,27 +0,0 @@
/**
* 此处可直接引用自己项目封装好的 axios 配合后端联调
*/
import request from '@/router/axios';
// import request from "@/api/axios.js" //调用项目封装的axios
//获取验证图片 以及token
export function reqGet (data) {
return request({
url: '/captcha/get',
method: 'post',
data
})
}
//滑动或者点选验证
export function reqCheck (data) {
return request({
url: '/captcha/check',
method: 'post',
data
})
}

View File

@@ -1,11 +0,0 @@
import CryptoJS from 'crypto-js'
/**
* @word 要加密的内容
* @keyWord String 服务器随机返回的关键字
* */
export function aesEncrypt (word, keyWord = "XwKsGlMcdPMEhR1B") {
var key = CryptoJS.enc.Utf8.parse(keyWord);
var srcs = CryptoJS.enc.Utf8.parse(word);
var encrypted = CryptoJS.AES.encrypt(srcs, key, { mode: CryptoJS.mode.ECB, padding: CryptoJS.pad.Pkcs7 });
return encrypted.toString();
}

View File

@@ -1,36 +0,0 @@
export function resetSize(vm) {
var img_width, img_height, bar_width, bar_height; //图片的宽度、高度,移动条的宽度、高度
var parentWidth = vm.$el.parentNode.offsetWidth || window.offsetWidth
var parentHeight = vm.$el.parentNode.offsetHeight || window.offsetHeight
if (vm.imgSize.width.indexOf('%') != -1) {
img_width = parseInt(this.imgSize.width) / 100 * parentWidth + 'px'
} else {
img_width = this.imgSize.width;
}
if (vm.imgSize.height.indexOf('%') != -1) {
img_height = parseInt(this.imgSize.height) / 100 * parentHeight + 'px'
} else {
img_height = this.imgSize.height
}
if (vm.barSize.width.indexOf('%') != -1) {
bar_width = parseInt(this.barSize.width) / 100 * parentWidth + 'px'
} else {
bar_width = this.barSize.width
}
if (vm.barSize.height.indexOf('%') != -1) {
bar_height = parseInt(this.barSize.height) / 100 * parentHeight + 'px'
} else {
bar_height = this.barSize.height
}
return {imgWidth: img_width, imgHeight: img_height, barWidth: bar_width, barHeight: bar_height}
}
export const _code_chars = [1, 2, 3, 4, 5, 6, 7, 8, 9, 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z']
export const _code_color1 = ['#fffff0', '#f0ffff', '#f0fff0', '#fff0f0']
export const _code_color2 = ['#FF0033', '#006699', '#993366', '#FF9900', '#66CC66', '#FF33CC']