Browse Source

fix style

add validate
old
wangqing 5 years ago
parent
commit
ca26c85881
  1. 1
      package.json
  2. 2
      public/index.html
  3. 2
      src/api/index.js
  4. 0
      src/api/project.js
  5. BIN
      src/assets/images/example.png
  6. BIN
      src/assets/images/official/offcial-bg01.png
  7. BIN
      src/assets/images/official/offcial-bg02.png
  8. 0
      src/assets/images/official/v2_q2woer.png
  9. BIN
      src/assets/images/official/v2_q2wstp.png
  10. BIN
      src/assets/images/official/v2_q2wxu6.gif
  11. 3
      src/assets/styles/form/home.scss
  12. 1
      src/assets/styles/index.scss
  13. 191
      src/assets/styles/sidebar.scss
  14. 21
      src/components/ExampleNotice/index.js
  15. 42
      src/components/ExampleNotice/main.vue
  16. 7
      src/components/autoRegister.js
  17. 465
      src/components/verifition/Verify.vue
  18. 245
      src/components/verifition/Verify/VerifyPoints.vue
  19. 347
      src/components/verifition/Verify/VerifySlide.vue
  20. 25
      src/components/verifition/api/verifition-api.js
  21. 11
      src/components/verifition/utils/ase.js
  22. 36
      src/components/verifition/utils/util.js
  23. 5
      src/router/modules/root.js
  24. 101
      src/views/account/ForgetPwd.vue
  25. 8
      src/views/account/login.vue
  26. 7
      src/views/form/PreView.vue
  27. 139
      src/views/form/PreView1.vue
  28. 13
      src/views/form/ProjectForm.vue
  29. 2
      src/views/form/editor.vue
  30. 14
      src/views/form/index.vue
  31. 25
      src/views/form/statistics.vue
  32. 5
      src/views/form/theme.vue
  33. 7
      src/views/form/write.vue
  34. 2
      src/views/home/HomButton.vue
  35. 18
      src/views/home/index.vue
  36. 11
      src/views/official/index.vue
  37. 130
      src/views/official/introduction.vue
  38. 100
      src/views/project/MyProject.vue
  39. 8
      src/views/project/create.vue
  40. 33
      src/views/test.vue
  41. 5
      yarn.lock

1
package.json

@ -14,6 +14,7 @@
"dependencies": { "dependencies": {
"axios": "^0.21.0", "axios": "^0.21.0",
"core-js": "^3.6.4", "core-js": "^3.6.4",
"crypto-js": "^4.0.0",
"dayjs": "^1.9.4", "dayjs": "^1.9.4",
"element-ui": "^2.14.0", "element-ui": "^2.14.0",
"file-saver": "^2.0.2", "file-saver": "^2.0.2",

2
public/index.html

@ -3,7 +3,7 @@
<head> <head>
<meta charset="utf-8"> <meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no"/> <!-- <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no"/>-->
<link rel="icon" href="<%= BASE_URL %>favicon.ico"> <link rel="icon" href="<%= BASE_URL %>favicon.ico">
<title><%= htmlWebpackPlugin.options.title %></title> <title><%= htmlWebpackPlugin.options.title %></title>
<% for (var i in htmlWebpackPlugin.options.cdn && htmlWebpackPlugin.options.cdn.css) { %> <% for (var i in htmlWebpackPlugin.options.cdn && htmlWebpackPlugin.options.cdn.css) { %>

2
src/api/index.js

@ -112,7 +112,7 @@ api.interceptors.response.use(
}) })
} }
} }
return Promise.reject(res) return Promise.resolve(res)
}, },
error => { error => {
return Promise.reject(error) return Promise.reject(error)

0
src/api/project.js

BIN
src/assets/images/example.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

BIN
src/assets/images/official/offcial-bg01.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 116 KiB

BIN
src/assets/images/official/offcial-bg02.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 138 KiB

0
src/assets/images/bodyRight.png → src/assets/images/official/v2_q2woer.png

Before

Width:  |  Height:  |  Size: 87 KiB

After

Width:  |  Height:  |  Size: 87 KiB

BIN
src/assets/images/official/v2_q2wstp.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 90 KiB

BIN
src/assets/images/official/v2_q2wxu6.gif

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 MiB

3
src/assets/styles/form/home.scss

@ -1,11 +1,10 @@
$selectedColor: #f5f8ff; $selectedColor: #f5f8ff;
$lighterBlue: #4aa0fa; $lighterBlue: #4aa0fa;
.container { .form-edit-container {
position: relative; position: relative;
width: 100%; width: 100%;
height: 100%; height: 100%;
overflow-y: hidden; overflow-y: hidden;
background-color: #f7f7f7;
font-family: "Helvetica Neue", Helvetica, "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "微软雅黑", Arial, sans-serif; font-family: "Helvetica Neue", Helvetica, "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "微软雅黑", Arial, sans-serif;
} }
.components-list { .components-list {

1
src/assets/styles/index.scss

@ -2,7 +2,6 @@
@import './mixin.scss'; @import './mixin.scss';
@import './transition.scss'; @import './transition.scss';
@import './element-ui.scss'; @import './element-ui.scss';
@import './sidebar.scss';
@import './btn.scss'; @import './btn.scss';
body { body {
height: 100%; height: 100%;

191
src/assets/styles/sidebar.scss

@ -1,191 +0,0 @@
#app {
.main-container {
min-height: 100%;
transition: margin-left 0.28s;
margin-left: $sideBarWidth;
position: relative;
}
.sidebar-container {
transition: width 0.28s;
width: $sideBarWidth !important;
background-color: $menuBg;
height: 100%;
position: fixed;
font-size: 0;
top: 0;
bottom: 0;
left: 0;
z-index: 1001;
overflow: hidden;
// reset element-ui css
.horizontal-collapse-transition {
transition: 0s width ease-in-out, 0s padding-left ease-in-out, 0s padding-right ease-in-out;
}
.scrollbar-wrapper {
overflow-x: hidden !important;
}
.el-scrollbar__bar.is-vertical {
right: 0;
}
.el-scrollbar {
height: 100%;
}
&.has-logo {
.el-scrollbar {
height: calc(100% - 50px);
}
}
.is-horizontal {
display: none;
}
a {
display: inline-block;
width: 100%;
overflow: hidden;
}
.svg-icon {
margin-right: 16px;
}
.sub-el-icon {
margin-right: 12px;
margin-left: -2px;
}
.el-menu {
border: none;
height: 100%;
width: 100% !important;
}
// menu hover
.submenu-title-noDropdown,
.el-submenu__title {
&:hover {
background-color: $menuHover !important;
}
}
.is-active > .el-submenu__title {
color: $subMenuActiveText !important;
}
& .nest-menu .el-submenu > .el-submenu__title,
& .el-submenu .el-menu-item {
min-width: $sideBarWidth !important;
background-color: $subMenuBg !important;
&:hover {
background-color: $subMenuHover !important;
}
}
}
.hideSidebar {
.sidebar-container {
width: 54px !important;
}
.main-container {
margin-left: 54px;
}
.submenu-title-noDropdown {
padding: 0 !important;
position: relative;
.el-tooltip {
padding: 0 !important;
.svg-icon {
margin-left: 20px;
}
.sub-el-icon {
margin-left: 19px;
}
}
}
.el-submenu {
overflow: hidden;
& > .el-submenu__title {
padding: 0 !important;
.svg-icon {
margin-left: 20px;
}
.sub-el-icon {
margin-left: 19px;
}
.el-submenu__icon-arrow {
display: none;
}
}
}
.el-menu--collapse {
.el-submenu {
& > .el-submenu__title {
& > span {
height: 0;
width: 0;
overflow: hidden;
visibility: hidden;
display: inline-block;
}
}
}
}
}
.el-menu--collapse .el-menu .el-submenu {
min-width: $sideBarWidth !important;
}
// mobile responsive
.mobile {
.main-container {
margin-left: 0;
}
.sidebar-container {
transition: transform 0.28s;
width: $sideBarWidth !important;
}
&.hideSidebar {
.sidebar-container {
pointer-events: none;
transition-duration: 0.3s;
transform: translate3d(-$sideBarWidth, 0, 0);
}
}
}
.withoutAnimation {
.main-container,
.sidebar-container {
transition: none;
}
}
}
// when menu collapsed
.el-menu--vertical {
& > .el-menu {
.svg-icon {
margin-right: 16px;
}
.sub-el-icon {
margin-right: 12px;
margin-left: -2px;
}
}
.nest-menu .el-submenu > .el-submenu__title,
.el-menu-item {
&:hover {
// you can use $subMenuHover
background-color: $menuHover !important;
}
}
// the scroll bar appears when the subMenu is too long
>.el-menu--popup {
max-height: 100vh;
overflow-y: auto;
&::-webkit-scrollbar-track-piece {
background: #d3dce6;
}
&::-webkit-scrollbar {
width: 6px;
}
&::-webkit-scrollbar-thumb {
background: #99a9bf;
border-radius: 20px;
}
}
}

21
src/components/ExampleNotice/index.js

@ -1,21 +0,0 @@
import Vue from 'vue'
const component = require('./main.vue').default
const constructor = Vue.extend(component)
const exampleNotice = options => {
options = options || {}
let instance = new constructor({
data: options
})
instance.vm = instance.$mount()
instance.dom = instance.vm.$el
document.body.appendChild(instance.dom)
return instance.vm
}
export default {
install: Vue => {
Vue.prototype[`$${component.name}`] = exampleNotice
}
}

42
src/components/ExampleNotice/main.vue

@ -1,42 +0,0 @@
<template>
<transition name="notice">
<div v-if="show" class="notice">
{{ content }}
</div>
</transition>
</template>
<script>
export default {
name: 'ExampleNotice',
data() {
return {
show: false,
content: ''
}
},
mounted() {
this.show = true
setTimeout(() => {
this.show = false
}, 2000)
}
}
</script>
<style lang="scss" scoped>
.notice {
padding: 10px;
background-color: #eee;
border-radius: 10px;
@include position-center(xy);
}
.notice-leave-active,
.notice-enter-active {
transition: all 0.3s;
}
.notice-enter,
.notice-leave-to {
opacity: 0;
}
</style>

7
src/components/autoRegister.js

@ -2,9 +2,10 @@
* 全局组件自动注册 * 全局组件自动注册
* *
* 全局组件各个组件按文件夹区分文件夹名称与组件名无关联但建议与组件名保持一致 * 全局组件各个组件按文件夹区分文件夹名称与组件名无关联但建议与组件名保持一致
* 文件夹内至少保留一个文件名为 index 的组件入口例如 index.vue * 文件夹内至少保留一个文件名为 index 的组件入口例如 Verify.vue
* 普通组件必须设置 name 并保证其唯一自动注册会将组件的 name 设为组件名可参考 SvgIcon 组件写法 * 普通组件必须设置 name 并保证其唯一自动注册会将组件的 name 设为组件名可参考 SvgIcon 组件写法
* 如果组件是通过 js 进行调用则确保组件入口文件为 index.js可参考 ExampleNotice 组件 * 如果组件是通过 js 进行调用则确保组件入口文件为 verifition-api.js可参考 ExampleNotice 组件
* 不自动注册 则名字为其他的
*/ */
import Vue from 'vue' import Vue from 'vue'
@ -15,7 +16,7 @@ componentsContext.keys().forEach(file_name => {
const componentConfig = componentsContext(file_name).default const componentConfig = componentsContext(file_name).default
if (/.vue$/.test(file_name)) { if (/.vue$/.test(file_name)) {
Vue.component(componentConfig.name, componentConfig) Vue.component(componentConfig.name, componentConfig)
} else { } else if (/.js/.test(file_name)) {
Vue.use(componentConfig) Vue.use(componentConfig)
} }
}) })

465
src/components/verifition/Verify.vue

File diff suppressed because one or more lines are too long

245
src/components/verifition/Verify/VerifyPoints.vue

@ -0,0 +1,245 @@
<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, _code_chars, _code_color1, _code_color2} from './../utils/util'
import {aesEncrypt} from "./../utils/ase"
import {reqGet,reqCheck} from "../api/verifition-api"
export default {
name: 'VerifyPoints',
props: {
//popfixed
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}
})
// console.log(newPointArr,"newPointArr");
return newPointArr
}
},
watch: {
// type
type: {
immediate: true,
handler() {
this.init()
}
}
},
mounted() {
//
this.$el.onselectstart = function () {
return false
}
},
}
</script>

347
src/components/verifition/Verify/VerifySlide.vue

@ -0,0 +1,347 @@
<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/verifition-api"
// "captchaType":"blockPuzzle",
export default {
name: 'VerifySlide',
props: {
captchaType:{
type:String,
},
type: {
type: String,
default: '1'
},
//popfixed
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>

25
src/components/verifition/api/verifition-api.js

@ -0,0 +1,25 @@
/**
* 此处可直接引用自己项目封装好的 axios 配合后端联调
*/
import request from "@/api/index.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
})
}

11
src/components/verifition/utils/ase.js

@ -0,0 +1,11 @@
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();
}

36
src/components/verifition/utils/util.js

@ -0,0 +1,36 @@
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']

5
src/router/modules/root.js

@ -24,6 +24,11 @@ export default [
meta: {requireLogin: false}, meta: {requireLogin: false},
component: () => import(/* webpackChunkName: 'root' */ '@/views/account/login.vue') component: () => import(/* webpackChunkName: 'root' */ '@/views/account/login.vue')
}, },
{
path: '/forget/password',
meta: {requireLogin: false},
component: () => import(/* webpackChunkName: 'root' */ '@/views/account/ForgetPwd')
},
{ {
path: '/enterprise', path: '/enterprise',
meta: {requireLogin: false}, meta: {requireLogin: false},

101
src/views/account/ForgetPwd.vue

@ -0,0 +1,101 @@
<template>
<div class="app-container">
<div class="pwd-container">
<label>找回密码</label>
<el-tabs
v-model="retrieveType" class="login-form" style="width: 300px;"
>
<el-tab-pane label="手机号找回" name="phone">
<el-form ref="form" :model="retrieveAccountForm" label-width="0px">
<el-form-item label="">
<el-input v-model="retrieveAccountForm.username" placeholder="请输入手机号" autocomplete="off" />
</el-form-item>
<el-form-item label="">
<el-input v-model="retrieveAccountForm.password" show-password placeholder="请输入密码"
autocomplete="off"
/>
</el-form-item>
<el-form-item label="">
<el-input v-model="retrieveAccountForm.code" style="width: 150px;" placeholder="请输入验证码"
autocomplete="off"
/>
<el-button style="margin-left: 20px;" type="primary">发送验证码</el-button>
</el-form-item>
<el-form-item>
<el-button type="primary" style="width: 100%;">登录</el-button>
</el-form-item>
</el-form>
</el-tab-pane>
<el-tab-pane label="邮箱注册" name="email">
<el-form ref="emailRegForm" status-icon :rules="emailRetrieveRules" :model="retrieveAccountForm"
label-width="0px"
>
<el-form-item label="" prop="email">
<el-input v-model="retrieveAccountForm.email" placeholder="请输入邮箱" autocomplete="off" />
</el-form-item>
<el-form-item label="" prop="password">
<el-input v-model="retrieveAccountForm.password" show-password placeholder="请输入密码"
autocomplete="off"
/>
</el-form-item>
<el-form-item label="" prop="code">
<el-input v-model="retrieveAccountForm.code" oninput="value=value.replace(/[^\d]/g,'')"
style="width: 150px;" maxlength="4" placeholder="请输入验证码"
autocomplete="off"
/>
<el-button style="margin-left: 20px;" :disabled="validateCodeBtn" type="primary"
@click="sendEmailCodeHandle"
>
{{ validateCodeBtnText }}
</el-button>
</el-form-item>
<el-form-item>
<el-button type="primary" style="width: 100%;" @click="emailRegHandle">确定</el-button>
</el-form-item>
</el-form>
</el-tab-pane>
</el-tabs>
</div>
</div>
</template>
<script>
export default {
name: 'RetrievePwd',
data() {
return {
retrieveType: 'phone',
retrieveAccountForm: {
email: '',
password: ''
},
emailRetrieveRules: {
email: [
{required: true, trigger: 'blur', message: '请输入邮箱'},
{
pattern: /^[a-zA-Z0-9_.-]+@[a-zA-Z0-9-]+(\.[a-zA-Z0-9-]+)*\.[a-zA-Z0-9]{2,6}$/,
message: '请输入正确的邮箱,多个使用;分隔'
}
],
// password: [{required: true, trigger: 'blur', validator: validatePassword}],
code: {required: true, trigger: 'blur', message: '请输入验证码'}
}
}
}
}
</script>
<style scoped>
.app-container {
height: 100%;
width: 100%;
display: flex;
justify-content: center;
align-content: center;
}
.pwd-container {
width: 20%;
height: 50%;
border: 1px red solid;
}
</style>

8
src/views/account/login.vue

@ -32,7 +32,7 @@
<el-divider style="width: 100px;" /> <el-divider style="width: 100px;" />
<el-row> <el-row>
<el-col :span="6"> <el-col :span="6">
<el-link class="login-tip">忘记密码</el-link> <el-link class="login-tip" @click="toForgetPwdHandle">忘记密码</el-link>
</el-col> </el-col>
<el-col :span="6"> <el-col :span="6">
<el-link class="login-tip"> <el-link class="login-tip">
@ -176,7 +176,7 @@
</el-form> </el-form>
</el-tab-pane> </el-tab-pane>
<div style="display: flex; flex-direction: row;"> <div style="display: flex; flex-direction: row;">
<el-link style="margin-left: 20px;">忘记密码</el-link> <el-link style="margin-left: 20px;" @click="toForgetPwdHandle">忘记密码</el-link>
<el-link style="margin-left: 20px;" @click="registerHandleClick">立即注册</el-link> <el-link style="margin-left: 20px;" @click="registerHandleClick">立即注册</el-link>
<div class="other-login"> <div class="other-login">
<span @click="redirectUrl(qqLoginAuthorizeUrl)"> <span @click="redirectUrl(qqLoginAuthorizeUrl)">
@ -277,6 +277,10 @@ export default {
this.wxLoginId = res.data.loginId this.wxLoginId = res.data.loginId
}) })
}, },
//
toForgetPwdHandle() {
this.$router.push({path: '/forget/password'})
},
// qq // qq
getQQLoginAuthorizeUrl() { getQQLoginAuthorizeUrl() {
let reUrl = getCurrentDomain() + '/redirect' let reUrl = getCurrentDomain() + '/redirect'

7
src/views/form/PreView.vue

@ -21,9 +21,11 @@
<span slot="label"><i class="el-icon-monitor"></i> <span slot="label"><i class="el-icon-monitor"></i>
电脑 电脑
</span> </span>
<el-scrollbar style="height: 77vh">
<project-form <project-form
:projectConfig="projectConfig" :projectConfig="projectConfig"
v-if="projectConfig.projectKey"/> v-if="projectConfig.projectKey"/>
</el-scrollbar>
</el-tab-pane> </el-tab-pane>
</el-tabs> </el-tabs>
</div> </div>
@ -64,7 +66,6 @@ export default {
margin: 0; margin: 0;
padding: 0; padding: 0;
background-color: #f7f7f7; background-color: #f7f7f7;
overflow-y: hidden !important;
} }
/deep/ .el-tabs__header { /deep/ .el-tabs__header {
@ -84,7 +85,6 @@ div.preview-layer {
margin: 10px auto; margin: 10px auto;
right: 0; right: 0;
text-align: center; text-align: center;
overflow-y: hidden !important;
} }
div.preview-layer .preview-bg { div.preview-layer .preview-bg {
@ -93,7 +93,6 @@ div.preview-layer .preview-bg {
margin: 20px auto; margin: 20px auto;
z-index: 999; z-index: 999;
opacity: 0.7; opacity: 0.7;
overflow-y: hidden !important;
} }
div.preview-layer .preview-phone { div.preview-layer .preview-phone {
@ -102,13 +101,11 @@ div.preview-layer .preview-phone {
background: url('~@/assets/images/appearset_bgc_big.png'); background: url('~@/assets/images/appearset_bgc_big.png');
background-size: 372px 744px; background-size: 372px 744px;
z-index: 1000; z-index: 1000;
overflow-y: hidden !important;
} }
.preview-html { .preview-html {
width: 345px !important; width: 345px !important;
height: 568px !important; height: 568px !important;
overflow-y: hidden !important;
margin: 74px 0 0; margin: 74px 0 0;
border-radius: 5px; border-radius: 5px;
outline: none; outline: none;

139
src/views/form/PreView1.vue

@ -1,139 +0,0 @@
<template>
<div class="preview-form">
<div class="" v-if="!formState">
<el-row type="flex" justify="center" align="middle">
<el-col :sm="{span:20}" :xs="{span:24,offset:0}" style="text-align: center">
<h4 class="form-name-text">
{{formConf.title}}</h4>
</el-col>
</el-row>
<el-row type="flex" justify="center" align="middle">
<el-col :sm="{span:20}" :xs="{span:24,offset:0}" style="text-align: center">
<p class="form-name-text">
{{formConf.description}}
</p>
</el-col>
</el-row>
<el-divider></el-divider>
<parser v-if="formConf.fields.length" :form-conf="formConf" @submit="submitForm"/>
</div>
<div v-if="formState">
<p style="text-align: center">
<i class="el-icon-check"/>您已完成本次问卷感谢您的帮助与支持</p>
</div>
</div>
</template>
<script>
import Parser from '@/components/parser/Parser'
import {dbDataConvertForItemJson} from '@/utils/convert'
// parsernpm使
// import Parser from 'form-gen-parser'
window.onload = function() {
document.addEventListener('touchstart', function(event) {
if (event.touches.length > 1) {
event.preventDefault()
}
})
document.addEventListener('gesturestart', function(event) {
event.preventDefault()
})
}
export default {
components: {
Parser
},
props: {
projectKey: ''
},
data() {
return {
key2: +new Date(),
projectKey: '',
formState: false,//
formConf: {
fields: [],
__methods__: {
clickTestButton1() {
console.log(
`%c【测试按钮1】点击事件里可以访问当前表单:
1) formModel='formData', 所以this.formData可以拿到当前表单的model
2) formRef='elForm', 所以this.$refs.elForm可以拿到当前表单的ref(vue组件)
`,
'color:#409EFF;font-size: 15px'
)
console.log('表单的Model:', this.formData)
console.log('表单的ref:', this.$refs.elForm)
}
},
formRef: 'elForm',
formModel: 'formData',
size: 'small',
labelPosition: 'top',
labelWidth: 100,
formRules: 'rules',
gutter: 15,
disabled: false,
span: 24,
formBtns: true,
resetBtn: true,
unFocusedComponentBorder: true
}
}
},
computed: {},
watch: {},
created() {
this.formConf.size = window.innerWidth < 480 ? 'medium' : 'small'
},
mounted() {
this.$api.get(`/user/project/details/${this.$route.query.key}`).then(res => {
if (res.data) {
let fields = res.data.projectItems.map(item => {
return dbDataConvertForItemJson(item)
})
this.formConf.fields = fields
this.formConf.title = res.data.project.name
this.formConf.description = res.data.project.describe
}
})
this.projectKey = this.$route.query.key
},
methods: {
fillFormData(form, data) {
form.fields.forEach(item => {
const val = data[item.__vModel__]
if (val) {
item.__config__.defaultValue = val
}
})
},
submitForm(data) {
this.$api.post('/user/project/result/create', {
'projectKey': this.projectKey,
'collectData': data
}).then(res => {
this.formState = true
})
}
}
}
</script>
<style lang="scss" scoped>
.preview-form {
margin: 15px auto;
width: 800px;
padding: 15px;
background-repeat: repeat;
background-color: rgba(229, 239, 247, 0.87);
}
@media screen and (max-width: 750px) {
.preview-form {
margin: 0px;
width: 93% !important;
background-color: white;
}
}
</style>

13
src/views/form/ProjectForm.vue

@ -10,6 +10,7 @@
<el-image <el-image
v-if="projectTheme.headImgUrl" v-if="projectTheme.headImgUrl"
:src="projectTheme.headImgUrl" :src="projectTheme.headImgUrl"
style="width: 100%"
fit="scale-down"></el-image> fit="scale-down"></el-image>
<el-row v-if="projectTheme.showTitle" type="flex" justify="center" align="middle"> <el-row v-if="projectTheme.showTitle" type="flex" justify="center" align="middle">
<el-col style="text-align: center"> <el-col style="text-align: center">
@ -145,7 +146,6 @@ export default {
padding: 15px; padding: 15px;
background-repeat: repeat; background-repeat: repeat;
background-color: rgba(229, 239, 247, 0.87); background-color: rgba(229, 239, 247, 0.87);
overflow: hidden;
} }
.project-body::-webkit-scrollbar { .project-body::-webkit-scrollbar {
@ -155,12 +155,10 @@ export default {
.project-body { .project-body {
-ms-overflow-style: none; -ms-overflow-style: none;
}
.project-body {
overflow: -moz-scrollbars-none; overflow: -moz-scrollbars-none;
} }
.logo-img { .logo-img {
max-height: 120px; max-height: 120px;
} }
@ -176,14 +174,11 @@ export default {
@media screen and (max-width: 750px) { @media screen and (max-width: 750px) {
.project-form { .project-form {
margin: 0px; margin: 0px;
width: 93% !important; height: 100%;
width: 100% !important;
background-color: white; background-color: white;
} }
.project-form {
height: 100%;
width: 60vw;
}
.logo-img { .logo-img {
max-height: 2.94rem; max-height: 2.94rem;
} }

2
src/views/form/editor.vue

@ -1,5 +1,5 @@
<template> <template>
<div class="container"> <div class="form-edit-container">
<div class="left-board"> <div class="left-board">
<el-scrollbar class="left-scrollbar"> <el-scrollbar class="left-scrollbar">
<div class="components-list"> <div class="components-list">

14
src/views/form/index.vue

@ -1,5 +1,5 @@
<template> <template>
<div class="container"> <div class="container" style="overflow-y: hidden!important;">
<el-row type="flex" align="middle" justify="justify"> <el-row type="flex" align="middle" justify="justify">
<el-col :offset="1" :span="4"> <el-col :offset="1" :span="4">
<el-button size="mini" round @click="$router.back(-1)"> <el-button size="mini" round @click="$router.back(-1)">
@ -18,7 +18,7 @@
</el-menu> </el-menu>
</el-col> </el-col>
</el-row> </el-row>
<div v-if="projectKey"> <div v-if="projectKey" style="overflow-y: hidden">
<editor :projectKey="projectKey" :is-edit="isEdit" v-if="activeIndex==1"/> <editor :projectKey="projectKey" :is-edit="isEdit" v-if="activeIndex==1"/>
<theme :projectKey="projectKey" v-if="activeIndex==2"/> <theme :projectKey="projectKey" v-if="activeIndex==2"/>
<setting :projectKey="projectKey" v-if="activeIndex==3"/> <setting :projectKey="projectKey" v-if="activeIndex==3"/>
@ -45,7 +45,7 @@ export default {
}, },
data() { data() {
return { return {
activeIndex: '5', activeIndex: '1',
isEdit: false, isEdit: false,
projectKey: '' projectKey: ''
} }
@ -55,7 +55,9 @@ export default {
mounted() { mounted() {
this.projectKey = this.$route.query.key this.projectKey = this.$route.query.key
this.isEdit = !!this.$route.query.active this.isEdit = !!this.$route.query.active
if (this.$route.query.active) {
this.activeIndex = this.$route.query.active this.activeIndex = this.$route.query.active
}
}, },
methods: { methods: {
handleSelect(key, keyPath) { handleSelect(key, keyPath) {
@ -68,4 +70,10 @@ export default {
</script> </script>
<style lang='scss' > <style lang='scss' >
.container{
position: relative;
width: 100%;
height: 100%;
overflow-y: hidden;
}
</style> </style>

25
src/views/form/statistics.vue

@ -1,7 +1,7 @@
<template> <template>
<div class="statistics-container"> <div class="statistics-container">
<div class="filter-table-view"> <div class="filter-table-view">
<el-form :inline="true" class="demo-form-inline" ref="filterForm"> <el-form :inline="true" ref="filterForm">
<el-form-item label="提交时间" prop="endDateTime"> <el-form-item label="提交时间" prop="endDateTime">
<el-date-picker <el-date-picker
v-model="queryConditions.beginDateTime" v-model="queryConditions.beginDateTime"
@ -49,8 +49,19 @@
:render-header="renderHeader"> :render-header="renderHeader">
</el-table-column> </el-table-column>
</el-table> </el-table>
<div style="display: flex;justify-content: center;margin-top: 10px">
<el-pagination
v-if="total>10"
background
:page-size.sync="queryConditions.size"
:current-page.sync="queryConditions.current"
layout="total, prev, pager, next"
:total="total"
@current-change="queryProjectResult"
/>
</div> </div>
<div class=""> </div>
<div >
<el-dialog center title="自定义显示列" :visible.sync="customColumnDialogVisible"> <el-dialog center title="自定义显示列" :visible.sync="customColumnDialogVisible">
<el-row> <el-row>
<el-col :span="3"> <el-col :span="3">
@ -115,8 +126,11 @@ export default {
projectResultList: [], projectResultList: [],
projectItemList: [], projectItemList: [],
projectItemColumns: {}, projectItemColumns: {},
total: 0,
// //
queryConditions: { queryConditions: {
current: 1,
size: 10,
projectKey: '', projectKey: '',
beginDateTime: '', beginDateTime: '',
endDateTime: '' endDateTime: ''
@ -129,8 +143,11 @@ export default {
) )
}, },
queryProjectResult() { queryProjectResult() {
this.$api.post(`/user/project/result/page`, this.queryConditions).then(res => { this.$api.get(`/user/project/result/page`, {params: this.queryConditions}).then(res => {
this.projectResultList = res.data.records let {records, total, size} = res.data
this.projectResultList = records
this.total = total
this.queryConditions.size = size
}) })
}, },
saveStatisticsCheckedColumns() { saveStatisticsCheckedColumns() {

5
src/views/form/theme.vue

@ -179,7 +179,7 @@
</el-row> </el-row>
<el-row v-if="showSettings.btnSetting"> <el-row v-if="showSettings.btnSetting">
<el-row type="flex" align="middle"> <el-row type="flex" align="middle">
<el-col :span="10"> <el-col :span="12">
<span class="option-line-sub-title">按钮提示文字</span> <span class="option-line-sub-title">按钮提示文字</span>
</el-col> </el-col>
<el-col :spvan="10"> <el-col :spvan="10">
@ -383,12 +383,9 @@ export default {
background-color: #f7f7f7; background-color: #f7f7f7;
font-family: "Helvetica Neue", Helvetica, "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "微软雅黑", Arial, sans-serif; font-family: "Helvetica Neue", Helvetica, "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "微软雅黑", Arial, sans-serif;
overflow: hidden; overflow: hidden;
} }
.left-container { .left-container {
width: 341px;
height: 70vh;
line-height: 20px; line-height: 20px;
border-radius: 7px; border-radius: 7px;
text-align: center; text-align: center;

7
src/views/form/write.vue

@ -50,7 +50,7 @@ export default {
preview: false, preview: false,
showBtns: true showBtns: true
}, },
writeStatus: 2, writeStatus: 1,
writeNotStartPrompt: '', writeNotStartPrompt: '',
userProjectSetting: { userProjectSetting: {
submitPromptText: '' submitPromptText: ''
@ -64,7 +64,10 @@ export default {
} }
}, },
beforeCreate() { beforeCreate() {
let meta = document.createElement('meta')
meta.content = 'width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no'
meta.name = 'viewport'
document.getElementsByTagName('head')[0].appendChild(meta)
}, },
created() { created() {
let key = this.$route.query.key let key = this.$route.query.key

2
src/views/home/HomButton.vue

@ -26,7 +26,7 @@ export default {
</script> </script>
<style scoped> <style scoped>
.home-fun-btn { .home-fun-btn {
width: 285px; width: 70%;
height: 145px; height: 145px;
line-height: 20px; line-height: 20px;
border-radius: 15px; border-radius: 15px;

18
src/views/home/index.vue

@ -1,7 +1,7 @@
<template> <template>
<div> <div>
<el-container> <el-container>
<el-header height="80" class="home-header-view"> <el-header height="92" class="home-header-view">
<el-row type="flex" align="middle"> <el-row type="flex" align="middle">
<el-col :span="4" :offset="1"> <el-col :span="4" :offset="1">
<img src="@/assets/images/indexLogo.png" class="header-logo-img" <img src="@/assets/images/indexLogo.png" class="header-logo-img"
@ -106,7 +106,11 @@ export default {
return store return store
}, },
getUserInfo() { getUserInfo() {
return JSON.parse(this.getStore.getters['user/userInfo']) let user = JSON.parse(this.getStore.getters['user/userInfo'])
if (!user) {
this.logoutHandle()
}
return user
} }
}, },
watch: { watch: {
@ -151,8 +155,8 @@ export default {
border-bottom: none; border-bottom: none;
} }
.home-header-view { .home-header-view {
line-height: 90px; line-height: 92px;
height: 80px; height: 92px;
background-color: rgba(255, 255, 255, 100); background-color: rgba(255, 255, 255, 100);
color: rgba(16, 16, 16, 100); color: rgba(16, 16, 16, 100);
font-size: 14px; font-size: 14px;
@ -190,5 +194,9 @@ export default {
border-radius: 100px; border-radius: 100px;
cursor: pointer; cursor: pointer;
} }
.home-main-view {
height: calc(100vh - 92px);
background-color: #f7f7f7;
padding: 0;
}
</style> </style>

11
src/views/official/index.vue

@ -1,5 +1,5 @@
<template> <template>
<div id="welcome"> <div>
<div class="header-container"> <div class="header-container">
<el-row type="flex" align="middle"> <el-row type="flex" align="middle">
<el-col class="header-col" :span="3" :offset="3"> <el-col class="header-col" :span="3" :offset="3">
@ -78,10 +78,6 @@ export default {
} }
</script> </script>
<style scoped> <style scoped>
.header-col,
.body-col {
border: solid thin white;
}
.header-container { .header-container {
background-color: white; background-color: white;
width: 100%; width: 100%;
@ -95,11 +91,10 @@ export default {
float: left; float: left;
cursor: pointer; cursor: pointer;
height: 60px; height: 60px;
padding: 25px 0 20px 0;
} }
.menu-item { .menu-item {
line-height: 110px; line-height: 90px;
height: 110px; height: 90px;
font-size: 18px; font-size: 18px;
font-weight: 900; font-weight: 900;
float: right; float: right;

130
src/views/official/introduction.vue

@ -1,14 +1,11 @@
<template> <template>
<div id="introduction"> <div class="introduction">
<div class="introduction-body"> <div class="introduction-body">
<div class="view_container"> <div class="view-container">
<el-row> <div class="view-container-content">
<el-col class="body-col" :span="3" /> <el-row type="flex" justify="center" align="middle">
<el-col class="body-col" :span="18"> <el-col :span="10" :offset="1">
<div> <div class="view-container-content">
<el-row>
<el-col :span="14">
<div class="view_container_content">
<p class="body-title">TDuck - 填鸭表单</p> <p class="body-title">TDuck - 填鸭表单</p>
<p class="body-slogan">有你所想有你所得</p> <p class="body-slogan">有你所想有你所得</p>
<p class="body-sloganEn">TDuck - Have what you want, get you income.</p> <p class="body-sloganEn">TDuck - Have what you want, get you income.</p>
@ -25,33 +22,28 @@
</div> </div>
</el-col> </el-col>
<el-col :span="10"> <el-col :span="10">
<div class="bodyRight"> <div>
<img class="body-right-img" <img class="body-right-img"
src="https://freebrio.oss-cn-shanghai.aliyuncs.com/t/v2_q2woer.png" src="@/assets/images/official/v2_q2woer.png"
> >
</div> </div>
</el-col> </el-col>
</el-row> </el-row>
</div> </div>
</el-col>
<el-col class="body-col" :span="3" />
</el-row>
</div> </div>
<el-divider /> <el-divider />
<div class="view_container"> <div class="view-container">
<el-row> <div class="view-container-content">
<el-col class="body-col" :span="24"> <el-row type="flex" justify="center" align="middle">
<el-col :span="10" :offset="1">
<div> <div>
<el-row>
<el-col :span="5" :offset="1">
<div class="bodyRight">
<img class="body-right-img" <img class="body-right-img"
src="https://freebrio.oss-cn-shanghai.aliyuncs.com/t/v2_q2wstp.png" src="@/assets/images/official/v2_q2wstp.png"
> >
</div> </div>
</el-col> </el-col>
<el-col :offset="5" :span="13"> <el-col :offset="1" :span="12">
<div class="view_container_content"> <div>
<p style="font-size: 28px;">杂乱的工作界面也会影响心情鸭</p> <p style="font-size: 28px;">杂乱的工作界面也会影响心情鸭</p>
<p class="body-title">TDuck化繁为简给你最好的体验</p> <p class="body-title">TDuck化繁为简给你最好的体验</p>
<p class="body-sloganEn">TDuck -So Easy</p> <p class="body-sloganEn">TDuck -So Easy</p>
@ -64,13 +56,10 @@
</el-col> </el-col>
</el-row> </el-row>
</div> </div>
<el-divider />
</el-col>
<el-col class="body-col" :span="3" />
</el-row>
</div> </div>
<div class="view_container"> <el-divider />
<div class="view_container_content" style="padding: 100px 0;"> <div class="view-container">
<div class="view-container-content" style="width: 80%;">
<el-row type="flex" align="middle"> <el-row type="flex" align="middle">
<el-col :span="10" :offset="5"> <el-col :span="10" :offset="5">
<p style="font-size: 28px;">TDuck - 填鸭表单</p> <p style="font-size: 28px;">TDuck - 填鸭表单</p>
@ -86,13 +75,12 @@
<p style="font-size: 20px; font-weight: 550;">联系我们</p> <p style="font-size: 20px; font-weight: 550;">联系我们</p>
</el-col> </el-col>
</el-row> </el-row>
<el-row> </div>
<el-col :span="10" :offset="5"> <div>
<img style="height: 478px;" <img style="height: 478px;"
src="https://freebrio.oss-cn-shanghai.aliyuncs.com/t/v2_q2wxu6.gif" src="@/assets/images/official/v2_q2wxu6.gif"
>
> >
</el-col>
</el-row>
</div> </div>
</div> </div>
<div class="introduction-footer"> <div class="introduction-footer">
@ -130,7 +118,10 @@
<el-col :span="3"> <el-col :span="3">
<p class="title"> 友情地址</p> <p class="title"> 友情地址</p>
<p class="subtitle"> <p class="subtitle">
Element UI <a href="https://element.eleme.cn/#/zh-CN/" target="_blank">Element UI</a>
</p>
<p class="subtitle">
<a href="https://gitee.com/mrhj/form-generator" target="_blank"> form-generator</a>
</p> </p>
</el-col> </el-col>
<el-col :span="3" :offset="3"> <el-col :span="3" :offset="3">
@ -152,50 +143,15 @@
export default { export default {
data() { data() {
return { return {}
}
},
computed: {
},
watch: {
}, },
computed: {},
watch: {},
mounted() { mounted() {
} }
} }
</script> </script>
<style scoped> <style scoped>
.header-col,
.body-col {
border: solid thin white;
}
.header-container {
background-color: white;
position: fixed;
width: 100%;
top: 0;
z-index: 100;
}
.header-container .header-col .el-menu--horizontal {
border: none;
}
.header-logo {
float: left;
cursor: pointer;
height: 60px;
}
.menu-item {
line-height: 110px;
height: 110px;
font-size: 18px;
font-weight: 900;
float: right;
}
.header-btn {
margin: 35px 0 35px 20px;
float: right;
}
.body-btn { .body-btn {
margin: 30px 20px 0 0; margin: 30px 20px 0 0;
font-size: 20px; font-size: 20px;
@ -223,16 +179,25 @@ export default {
border-color: #205bb5; border-color: #205bb5;
color: #fff; color: #fff;
} }
.introduction {
background: url('~@/assets/images/official/offcial-bg01.png') repeat-x;
}
.introduction-body { .introduction-body {
padding-top: 112px; /* padding-top: 112px; */
} }
.view_container { .view-container {
margin: 0; height: 800px;
display: flex;
justify-content: center;
align-content: center;
align-items: center;
justify-items: center;
flex-direction: column;
} }
.view_container_content { .view-container-content {
padding: 200px 110px; background-color: transparent;
} }
.view_container_content p { .view-container-content p {
color: #205bb5; color: #205bb5;
} }
.body-title { .body-title {
@ -260,8 +225,9 @@ export default {
font-size: 15px; font-size: 15px;
} }
.body-right-img { .body-right-img {
height: 665px; /* height: 665px; */
display: block; width: 100%;
height: 100%;
} }
.title-divider-line { .title-divider-line {
height: 3px; height: 3px;
@ -271,7 +237,7 @@ export default {
border: 1px solid rgba(255, 255, 255, 100); border: 1px solid rgba(255, 255, 255, 100);
} }
.introduction-footer { .introduction-footer {
height: 300px; height: 350px;
line-height: 20px; line-height: 20px;
background-color: rgba(32, 91, 181, 100); background-color: rgba(32, 91, 181, 100);
text-align: center; text-align: center;

100
src/views/project/MyProject.vue

@ -60,23 +60,37 @@
<div <div
class="project-grid-view" class="project-grid-view"
> >
<div v-for="p in projectList" :key="p.id" class="project-grid-item-view" :span="4"> <div v-for="p in projectList" :key="p.id" class="project-grid-item-view pointer" :span="4">
<span v-for="status in projectStatusList" :key="status.code"> <el-row type="flex" align="middle" justify="center">
<el-col :span="5">
<span <span
v-if="status.code==p.status" :style="getStatusColorStyle(p.status)"
:style="{backgroundColor:status.color,borderColor:status.color}"
class="project-grid-view-status" class="project-grid-view-status"
/> />
</span> </el-col>
<p> <el-col :span="19">
<el-tooltip :content="p.name" placement="top">
<p class="project-title">
{{ p.name }} {{ p.name }}
</p> </p>
</el-tooltip>
</el-col>
</el-row>
<img class="project-grid-view-preimg" <img class="project-grid-view-preimg"
src="https://freebrio.oss-cn-shanghai.aliyuncs.com/t/pic%20(1).png" src="https://freebrio.oss-cn-shanghai.aliyuncs.com/t/pic%20(1).png"
> >
<p class="project-grid-view-time">创建时间2020/12/8</p> <p class="project-grid-view-time">创建时间2020/12/8</p>
<div class="gird-operating-btns">
<el-button type="text" @click="toEditHandle(p.key)">
<i class="el-icon-edit" />
编辑
</el-button>
</div>
</div> </div>
</div> </div>
<div v-if="!projectList||projectList.length==0" class="project-grid-container">
<div />
</div>
</div> </div>
<div v-if="dataShowType=='table'" class="project-table-view"> <div v-if="dataShowType=='table'" class="project-table-view">
<el-table <el-table
@ -90,6 +104,7 @@
> >
<el-table-column <el-table-column
prop="name" prop="name"
show-overflow-tooltip
align="center" align="center"
label="标题" label="标题"
/> />
@ -127,7 +142,7 @@
<template slot-scope="scope"> <template slot-scope="scope">
<el-link type="primary" <el-link type="primary"
style="margin: 2px;" style="margin: 2px;"
@click="$router.push({path: '/project/form', query: {key: scope.row.key,active:1}})" @click="toEditHandle(scope.row.key)"
> >
编辑 编辑
</el-link> </el-link>
@ -144,7 +159,7 @@
background background
:page-size.sync="queryParams.size" :page-size.sync="queryParams.size"
:current-page.sync="queryParams.current" :current-page.sync="queryParams.current"
layout="prev, pager, next" layout="total, prev, pager, next"
:total="total" :total="total"
@current-change="queryProjectPage" @current-change="queryProjectPage"
/> />
@ -177,22 +192,26 @@ export default {
projectList: [] projectList: []
} }
}, },
computed: {}, computed: {
getStatusColorStyle() {
return function(code) {
let color = this.projectStatusList.find(item => item.code == code).color
return {
backgroundColor: color,
borderColor: color
}
}
}
},
created() { created() {
this.queryProjectPage() this.queryProjectPage()
}, },
methods: { methods: {
switchDataShowTypeHandle(type) { switchDataShowTypeHandle(type) {
this.dataShowType = type this.dataShowType = type
}, },
getStatusColorClass(code) { toEditHandle(key) {
let color = this.projectStatusList.find(item => item.code = code).color this.$router.push({path: '/project/form', query: {key: key, active: 1}})
return {
backgroundColor: color,
borderColor: color
}
}, },
queryProjectPage() { queryProjectPage() {
this.$api.get('/user/project/page', { this.$api.get('/user/project/page', {
@ -208,7 +227,7 @@ export default {
} }
</script> </script>
<style scoped> <style lang="scss" scoped>
.my-project-container { .my-project-container {
display: flex; display: flex;
width: 100%; width: 100%;
@ -222,22 +241,16 @@ export default {
display: flex; display: flex;
flex-direction: row; flex-direction: row;
} }
.title {
color: rgba(16, 16, 16, 100);
font-size: 14px;
text-align: left;
line-height: 20px;
}
.show-view-type-icon { .show-view-type-icon {
width: 17px; color: white;
height: 17px; font-size: 18px;
color: #a8a8a8; -webkit-text-stroke: 0.5px #a8a8a8;
font-size: 20px;
margin: 5px; margin: 5px;
cursor: pointer; cursor: pointer;
} }
.show-view-type-icon-active { .show-view-type-icon-active {
color: rgba(92, 155, 249, 100); color: rgba(92, 155, 249, 100);
-webkit-text-stroke: 0.5px rgba(92, 155, 249, 100);
} }
.project-grid-container { .project-grid-container {
margin-top: 20px; margin-top: 20px;
@ -247,10 +260,9 @@ export default {
} }
.project-grid-view { .project-grid-view {
display: flex; display: flex;
width: 60%; width: 950px;
flex-direction: row; flex-direction: row;
flex-wrap: wrap; flex-wrap: wrap;
justify-content: center;
} }
.project-table-view { .project-table-view {
margin-top: 20px; margin-top: 20px;
@ -264,9 +276,18 @@ export default {
background-color: rgba(255, 255, 255, 100); background-color: rgba(255, 255, 255, 100);
text-align: center; text-align: center;
box-shadow: 0 3px 6px 3px rgba(0, 0, 0, 0.12); box-shadow: 0 3px 6px 3px rgba(0, 0, 0, 0.12);
border: 1px solid rgba(255, 255, 255, 100);
margin: 10px; margin: 10px;
position: relative; position: relative;
.project-title {
color: rgba(16, 16, 16, 100);
font-size: 14px;
text-align: left;
line-height: 20px;
max-height: 20px;
-webkit-box-orient: vertical;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
} }
.project-grid-view-status { .project-grid-view-status {
display: inline-block; display: inline-block;
@ -277,9 +298,20 @@ export default {
text-align: center; text-align: center;
border: 1px solid rgba(0, 110, 255, 100); border: 1px solid rgba(0, 110, 255, 100);
border-radius: 20px; border-radius: 20px;
}
}
.gird-operating-btns {
position: absolute; position: absolute;
left: 10px; width: 100%;
top: 20px; margin: 0;
padding: 0;
background-color: #f0f0f0;
bottom: 0;
display: none;
border: none;
}
.project-grid-item-view:hover .gird-operating-btns {
display: block;
} }
.project-grid-view-preimg { .project-grid-view-preimg {
width: 143px; width: 143px;
@ -289,7 +321,7 @@ export default {
color: rgba(144, 147, 153, 100); color: rgba(144, 147, 153, 100);
font-size: 12px; font-size: 12px;
line-height: 20px; line-height: 20px;
text-align: left; text-align: center;
margin: 0; margin: 0;
} }
.project-page-view { .project-page-view {

8
src/views/project/create.vue

@ -26,7 +26,7 @@
</el-row> </el-row>
<el-row> <el-row>
<el-col :offset="6" :span="10"> <el-col :offset="6" :span="10">
<el-menu default-active="1" class="el-menu-demo" mode="horizontal"> <el-menu default-active="1" style="background-color: transparent;" mode="horizontal">
<el-menu-item index="1">全部</el-menu-item> <el-menu-item index="1">全部</el-menu-item>
<el-menu-item index="2">问卷调查</el-menu-item> <el-menu-item index="2">问卷调查</el-menu-item>
<el-menu-item index="3">满意度调查</el-menu-item> <el-menu-item index="3">满意度调查</el-menu-item>
@ -70,6 +70,7 @@
<el-row type="flex" justify="center"> <el-row type="flex" justify="center">
<el-col :span="5"> <el-col :span="5">
<el-pagination <el-pagination
background
:hide-on-single-page="true" :hide-on-single-page="true"
:total="50" :total="50"
layout="prev, pager, next" layout="prev, pager, next"
@ -188,7 +189,10 @@ export default {
return 0 return 0
}, },
createBlankTemplate() { createBlankTemplate() {
this.$api.post('/user/project/create', {'describe': formConf.description, 'name': formConf.title}).then(res => { this.$api.post('/user/project/create', {
'describe': formConf.description,
'name': formConf.title
}).then(res => {
console.log(res) console.log(res)
this.$router.push({path: '/project/form', query: {key: res.data}}) this.$router.push({path: '/project/form', query: {key: res.data}})
}) })

33
src/views/test.vue

@ -0,0 +1,33 @@
<template>
<div>
<Verify
ref="verify"
:mode="'pop'"
:captcha-type="'blockPuzzle'"
:img-size="{ width: '330px', height: '155px' }"
@success="'success'"
/>
<button @click="useVerify">调用验证组件</button>
</div>
</template>
<script>
//
import Verify from '@/components/verifition/Verify'
export default {
name: 'App',
components: {
Verify
},
methods: {
success(params) {
// params , 便
console.log(params)
},
useVerify() {
this.$refs.verify.show()
}
}
}
</script>

5
yarn.lock

@ -3517,6 +3517,11 @@ crypto-browserify@^3.11.0:
randombytes "^2.0.0" randombytes "^2.0.0"
randomfill "^1.0.3" randomfill "^1.0.3"
crypto-js@^4.0.0:
version "4.0.0"
resolved "https://registry.npm.taobao.org/crypto-js/download/crypto-js-4.0.0.tgz#2904ab2677a9d042856a2ea2ef80de92e4a36dcc"
integrity sha1-KQSrJnep0EKFai6i74DekuSjbcw=
css-color-names@0.0.4, css-color-names@^0.0.4: css-color-names@0.0.4, css-color-names@^0.0.4:
version "0.0.4" version "0.0.4"
resolved "https://registry.npm.taobao.org/css-color-names/download/css-color-names-0.0.4.tgz#808adc2e79cf84738069b646cb20ec27beb629e0" resolved "https://registry.npm.taobao.org/css-color-names/download/css-color-names-0.0.4.tgz#808adc2e79cf84738069b646cb20ec27beb629e0"

Loading…
Cancel
Save