master
xy 2 years ago
parent 330917a76f
commit 81dec0fb22

@ -23,12 +23,15 @@
"echarts": "^4.2.1",
"element-ui": "2.15.13",
"file-saver": "^2.0.5",
"html2canvas": "^1.4.1",
"js-cookie": "2.2.0",
"jspdf": "^2.5.1",
"less-loader": "^5.0.0",
"moment": "^2.29.2",
"normalize.css": "7.0.0",
"nprogress": "0.2.0",
"path-to-regexp": "2.4.0",
"print-js": "^1.6.0",
"qrcodejs2": "^0.0.2",
"tinymce": "^5.10.7",
"view-design": "^4.7.0",

@ -1,8 +1,33 @@
import request from "@/utils/request";
export function login () {
export function login (params) {
return request({
url: '/api/mobile/user/login',
method: 'get',
params
})
}
export function userInfo (params) {
return request({
url: '/api/mobile/user/userinfo',
method: 'get',
params
})
}
export function sendSms (params) {
return request({
url: '/api/mobile/user/send_sms',
method: 'get',
params
})
}
export function updateLog (params) {
return request({
url: '/api/mobile/user/update_log',
method: 'get',
params
})
}

@ -18,7 +18,7 @@ router.beforeEach(async(to, from, next) => {
document.title = getPageTitle(to.meta.title)
// determine whether the user has logged in
const hasToken = getToken()
let hasToken = getToken()
if (whiteList.indexOf(to.path) !== -1) {
// in the free login whitelist, go directly
@ -41,18 +41,22 @@ router.beforeEach(async(to, from, next) => {
try {
// get user info
// note: roles must be a object array! such as: ['admin'] or ,['developer','editor']
const { roles } = await store.dispatch('user/getInfo')
if (!/^\/h5.*/.test(to.path)) {
const { roles } = await store.dispatch('user/getInfo')
// generate accessible routes map based on roles
const accessRoutes = await store.dispatch('permission/generateRoutes', roles)
//console.log(accessRoutes)
// dynamically add accessible routes
router.addRoutes(accessRoutes)
// generate accessible routes map based on roles
const accessRoutes = await store.dispatch('permission/generateRoutes', roles)
//console.log(accessRoutes)
// dynamically add accessible routes
router.addRoutes(accessRoutes)
next({ ...to, replace: true })
} else {
next();
}
// hack method to ensure that addRoutes is complete
// set the replace: true, so the navigation will not leave a history record
next({ ...to, replace: true })
} catch (error) {
console.log(error)
// remove token and go to login page to re-login

@ -85,7 +85,7 @@ export const constantRoutes = [
],
},
{
path: "/h5",
path: "/h5/index",
component: () => import("@/views/h5/index.vue"),
meta: {
title: "首页",
@ -99,7 +99,11 @@ export const constantRoutes = [
title: "登录",
},
hidden: true
}
},
{
path: '/h5',
redirect: '/h5/index'
},
];
/**

@ -17,7 +17,8 @@ const getDefaultState = () => {
token: getToken(),
name: '',
avatar: '',
roles: []
roles: [],
user: {},
}
}
@ -38,7 +39,7 @@ const mutations = {
},
SET_ROLES: (state, roles) => {
state.roles = roles
}
},
}
const actions = {

@ -1,18 +1,18 @@
import Cookies from 'js-cookie'
import router from '@/router'
const TokenKey = 'difficult_employee_query_token'
const TokenKsy_h5 = 'difficult_employee_query_token_h5'
const TokenKey = 'difficult_employee_token'
const TokenKsy_h5 = 'difficult_employee_token_h5'
export function getToken() {
let flag = /^\/h5.*/.test(router.currentRoute.path)
let flag = /\/h5.*/.test(window.location.href)
return Cookies.get(flag ? TokenKsy_h5 : TokenKey)
}
export function setToken(token) {
let flag = /^\/h5.*/.test(router.currentRoute.path)
let flag = /\/h5.*/.test(window.location.href)
return Cookies.set(flag ? TokenKsy_h5 : TokenKey, token)
}
export function removeToken() {
let flag = /^\/h5.*/.test(router.currentRoute.path)
let flag = /\/h5.*/.test(window.location.href)
return Cookies.remove(flag ? TokenKsy_h5 : TokenKey)
}

@ -1,17 +1,151 @@
<template>
<div>
<div class="page">
<div class="content-section">
<div class="content-section-title">个人信息</div>
<ul>
<li>
<div class="products">
<!-- <svg viewBox="0 0 52 52" style="border:1px solid #3291b8">-->
<!-- <g xmlns="http://www.w3.org/2000/svg">-->
<!-- <path d="M40.824 52H11.176C5.003 52 0 46.997 0 40.824V11.176C0 5.003 5.003 0 11.176 0h29.649C46.997 0 52 5.003 52 11.176v29.649C52 46.997 46.997 52 40.824 52z" fill="#061e26" data-original="#393687" />-->
<!-- <path d="M12.16 39H9.28V11h9.64c2.613 0 4.553.813 5.82 2.44 1.266 1.626 1.9 3.76 1.9 6.399 0 .934-.027 1.74-.08 2.42-.054.681-.22 1.534-.5 2.561-.28 1.026-.66 1.866-1.14 2.52-.48.654-1.213 1.227-2.2 1.72-.987.494-2.16.74-3.52.74h-7.04V39zm0-12h6.68c.96 0 1.773-.187 2.44-.56.666-.374 1.153-.773 1.46-1.2.306-.427.546-1.04.72-1.84.173-.801.267-1.4.28-1.801.013-.399.02-.973.02-1.72 0-4.053-1.694-6.08-5.08-6.08h-6.52V27zM29.48 33.92l2.8-.12c.106.987.6 1.754 1.48 2.3.88.547 1.893.82 3.04.82s2.14-.26 2.98-.78c.84-.52 1.26-1.266 1.26-2.239s-.36-1.747-1.08-2.32c-.72-.573-1.6-1.026-2.64-1.36-1.04-.333-2.086-.686-3.14-1.06a7.36 7.36 0 01-2.78-1.76c-.987-.934-1.48-2.073-1.48-3.42s.54-2.601 1.62-3.761 2.833-1.739 5.26-1.739c.854 0 1.653.1 2.4.3.746.2 1.28.394 1.6.58l.48.279-.92 2.521c-.854-.666-1.974-1-3.36-1-1.387 0-2.42.26-3.1.78-.68.52-1.02 1.18-1.02 1.979 0 .88.426 1.574 1.28 2.08.853.507 1.813.934 2.88 1.28 1.066.347 2.126.733 3.18 1.16 1.053.427 1.946 1.094 2.68 2s1.1 2.106 1.1 3.6c0 1.494-.6 2.794-1.8 3.9-1.2 1.106-2.954 1.66-5.26 1.66-2.307 0-4.114-.547-5.42-1.64-1.307-1.093-1.987-2.44-2.04-4.04z" fill="#c1dbe6" data-original="#89d3ff" />-->
<!-- </g>-->
<!-- </svg>-->
<svg viewBox="0 0 1024 1024" xmlns="http://www.w3.org/2000/svg"><path d="M1000.342857 877.371429H24.228571c-13.257143 0-24-10.742857-24-24V170.285714c0-13.257143 10.742857-24 24-24h976.114286c13.257143 0 24 10.742857 24 24v49.142857h-45.714286v-27.428571H45.942857v639.771429h932.685714V292.571429h45.714286v560.8c0 13.257143-10.742857 24-24 24z" p-id="4081"></path><path d="M324.8 534.971429c-66.514286 0-120.571429-54.057143-120.571429-120.571429S258.285714 293.714286 324.8 293.714286s120.571429 54.057143 120.571429 120.571428-54.057143 120.685714-120.571429 120.685715z m0-195.542858c-41.257143 0-74.857143 33.6-74.857143 74.857143s33.6 74.857143 74.857143 74.857143 74.857143-33.6 74.857143-74.857143-33.6-74.857143-74.857143-74.857143z" p-id="4082"></path><path d="M480.114286 730.285714h-310.857143c-12.8 0-23.2-10.4-23.2-23.2 0-52.914286 15.314286-106.057143 42.171428-145.828571 31.542857-46.742857 76.914286-72.457143 127.885715-72.457143 12.571429 0 22.857143 10.285714 22.857143 22.857143s-10.285714 22.857143-22.857143 22.857143c-45.142857 0-73.828571 28.457143-89.942857 52.342857-18.057143 26.857143-29.828571 61.485714-33.257143 97.714286h263.542857c-5.142857-50.857143-27.085714-98.4-58.857143-125.257143-9.6-8.114286-10.857143-22.514286-2.742857-32.228572 8.114286-9.6 22.514286-10.857143 32.228571-2.742857 47.085714 39.657143 76.228571 109.714286 76.228572 182.742857 0 12.8-10.4 23.2-23.2 23.2zM585.257143 342.628571h292.571428v45.714286h-292.571428zM585.257143 488.228571h292.571428v45.714286h-292.571428zM585.257143 635.657143h201.142857v45.714286h-201.142857z"></path></svg>
<p>姓名</p>
<p>{{ info.user.name }}</p>
</div>
</li>
<li>
<div class="products">
<svg viewBox="0 0 52 52" style="border:1px solid #b65a0b">
<g xmlns="http://www.w3.org/2000/svg">
<path d="M40.824 52H11.176C5.003 52 0 46.997 0 40.824V11.176C0 5.003 5.003 0 11.176 0h29.649C46.997 0 52 5.003 52 11.176v29.649C52 46.997 46.997 52 40.824 52z" fill="#261400" data-original="#6d4c13" />
<path d="M30.68 39h-3.24l-2.76-9.04h-8.32L13.72 39H10.6l8.24-28h3.32l8.52 28zm-6.72-12l-3.48-11.36L17.12 27h6.84zM37.479 12.24c0 .453-.16.84-.48 1.16-.32.319-.7.479-1.14.479-.44 0-.827-.166-1.16-.5-.334-.333-.5-.713-.5-1.14s.166-.807.5-1.141c.333-.333.72-.5 1.16-.5.44 0 .82.16 1.14.48.321.322.48.709.48 1.162zM37.24 39h-2.88V18.96h2.88V39z" fill="#e6d2c0" data-original="#ffbd2e" />
</g>
</svg>
Illustrator
</div>
</li>
<li>
<div class="products">
<svg viewBox="0 0 52 52" style="border: 1px solid #C75DEB">
<g xmlns="http://www.w3.org/2000/svg">
<path d="M40.824 52H11.176C5.003 52 0 46.997 0 40.824V11.176C0 5.003 5.003 0 11.176 0h29.649C46.997 0 52 5.003 52 11.176v29.649C52 46.997 46.997 52 40.824 52z" fill="#3a3375" data-original="#3a3375" />
<path d="M27.44 39H24.2l-2.76-9.04h-8.32L10.48 39H7.36l8.24-28h3.32l8.52 28zm-6.72-12l-3.48-11.36L13.88 27h6.84zM31.48 33.48c0 2.267 1.333 3.399 4 3.399 1.653 0 3.466-.546 5.44-1.64L42 37.6c-2.054 1.254-4.2 1.881-6.44 1.881-4.64 0-6.96-1.946-6.96-5.841v-8.2c0-2.16.673-3.841 2.02-5.04 1.346-1.2 3.126-1.801 5.34-1.801s3.94.594 5.18 1.78c1.24 1.187 1.86 2.834 1.86 4.94V30.8l-11.52.6v2.08zm8.6-5.24v-3.08c0-1.413-.44-2.42-1.32-3.021-.88-.6-1.907-.899-3.08-.899-1.174 0-2.167.359-2.98 1.08-.814.72-1.22 1.773-1.22 3.16v3.199l8.6-.439z" fill="#e4d1eb" data-original="#e7adfb" />
</g>
</svg>
After Effects
</div>
</li>
</ul>
</div>
<!-- <Card shadow :bordered="false">-->
<!-- <template>-->
<!-- </template>-->
<!-- </Card>-->
</div>
</template>
<script>
import { getToken } from "@/utils/auth";
import { userInfo } from "@/api/h5";
export default {
data() {
return {}
return {
info: {
user: {},
logs: [],
childrens: []
}
}
},
methods: {
async getUserInfo () {
const res = await userInfo({
bianma: getToken()
})
this.info = res;
}
},
methods: {},
computed: {},
created() {
this.getUserInfo();
}
}
</script>
<style scoped lang="scss">
.page {
width: 100%;
height: 100%;
}
.content-section {
margin-top: 30px;
display: flex;
flex-direction: column;
&-title {
color: #999ba5;
margin-bottom: 14px;
}
ul {
display: flex;
flex-direction: column;
width: 100%;
height: 100%;
justify-content: space-around;
background-color: rgb(146 151 179 / 13%);
padding-left: 0;
margin: 0;
border-radius: 14px;
border: 1px solid rgb(255 255 255 / 31%);
cursor: pointer;
li {
list-style: none;
padding: 10px 18px;
display: flex;
align-items: center;
font-size: 16px;
width: 100%;
height: 100%;
white-space: nowrap;
transition: 0.3s;
&:hover {
background-color: rgb(255 255 255 / 31%);
&:first-child {
border-radius: 13px 13px 0 0;
}
&:last-child {
border-radius: 0 0 13px 13px;
}
}
& + li {
border-top: 1px solid rgb(255 255 255 / 35%);
}
}
svg {
width: 28px;
border-radius: 6px;
margin-right: 16px;
flex-shrink: 0;
}
}
}
@media (min-width: 768px) {
.page {
padding: 40px;
}
}
@media (max-width: 768px) {
.page {
padding: 20px;
}
}
</style>

@ -1,7 +1,7 @@
<template>
<div class="panel">
<div class="logo">
<img src="../../../../assets/logo-mini.png" alt="">
<img :src="require('@/assets/logo-mini.png')" alt="">
<h2>苏州总工会</h2>
</div>
@ -26,7 +26,7 @@
</el-input>
</el-form-item>
<el-form-item style="padding-top: 10px;">
<Button :loading="isLoading" long type="primary" @click="login"></Button>
<Button :loading="isLoading" long type="primary" @click="login"></Button>
</el-form-item>
</el-form>
</div>
@ -36,6 +36,8 @@
</template>
<script>
import { setToken } from "@/utils/auth";
import { sendSms,login } from "@/api/h5";
export default {
data() {
return {
@ -43,13 +45,13 @@ export default {
name: '',
idcard: '',
mobile: '',
verify: '',
code: '',
},
formLabel: {
name: '姓名',
idcard: '身份证号',
mobile: '手机号码',
verify: '验证码'
code: '验证码'
},
rules: {
name: [
@ -94,7 +96,7 @@ export default {
}
}
],
verify: [
code: [
{
required: true,
message: '请输入验证码',
@ -113,12 +115,16 @@ export default {
if (this.isVerify) return
this.$refs['elForm'].validateField('mobile',(res) => {
if (!res) {
this.time = 60;
this.isVerify = true;
this.timer = setInterval(() => {
this.time > 0 ? (this.time--) : (clearInterval(this.timer),this.isVerify = false)
},1000)
sendSms({
mobile: this.form.mobile
}).then(res => {
this.time = 60;
this.isVerify = true;
this.timer = setInterval(() => {
this.time > 0 ? (this.time--) : (clearInterval(this.timer),this.isVerify = false)
},1000)
})
}
})
},
@ -128,7 +134,13 @@ export default {
if (res) {
this.isLoading = true;
setTimeout(() => this.isLoading = false,3000)
login(this.form).then(res => {
console.log(res)
setToken(res.user.bianma);
this.isLoading = false;
this.$router.push('/h5')
}).catch(err => this.isLoading = false)
}
})
}

@ -1,33 +1,51 @@
<template>
<div class="page">
<div class="box" ref="box">
<div class="container" ref="container" :style="{ 'transform': `translate(${container.offsetX}px,${container.offsetY}px) scale(${container.scale},${container.scale})` }">
<div class="container" ref="container" :style="transform">
<div class="no">
序列号{{ info.bianma }}
</div>
<div class="qrcode">
<div ref="qrcode"></div>
<div>扫码核验</div>
<div style="padding-top: 2px;">扫码核验</div>
</div>
<div class="title">
<span style="padding-right: 20px;"></span><span></span>
</div>
<div class="text">
兹有 <span>{{ info.name }}</span> 身份证号 <span>{{ info.idcard }}</span> 经苏州州市总工会审核评定为{{ new Date().getFullYear() }}年度苏州市总工会 <span>{{ type.get(info.kunnanleixing) }}家庭</span>
<br>
<p>特此证明</p>
<div class="stay">
<p>苏州市总工会权益保障部</p>
<p>{{ $moment(new Date()).format('YYYY年M月DD日') }}</p>
</div>
</div>
</div>
</div>
<Button v-show="isReduction" class="reduction" size="small" type="info" @click="reduction"></Button>
<div class="bottom-panel">
<Button type="info" icon="md-download">下载</Button>
<Button type="info" icon="md-print">打印</Button>
<Button type="info" icon="md-download" @click="download"></Button>
<Button type="info" icon="md-print" @click="print"></Button>
</div>
</div>
</template>
<script>
import QRCode from 'qrcodejs2';
import html2canvas from "html2canvas";
import Jspdf from "jspdf";
import printJS from "print-js";
import { show } from "@/api/system/baseForm";
import { userInfo } from "@/api/h5";
export default {
data() {
return {
id: '',
info: {},
container: {
w: 0,
@ -37,28 +55,50 @@ export default {
lastX: 0,
lastY: 0,
scale: 1
}
},
isToImg: false,
type: new Map([
[1,'特别困难'],
[2,'深度困难'],
[3,'相对困难'],
[4,'意外至困']
])
}
},
methods: {
reduction () {
this.container.offsetY = 0;
this.container.offsetX = 0;
this.container.scale = 1;
},
creatQrCode() {
let w = this.$refs['box']?.getBoundingClientRect()?.width;
new QRCode(this.$refs.qrcode, {
text: window.location.href, //
width: 74,
height: 74,
width: (w * 0.14) || 74,
height: (w * 0.14) || 74,
colorDark: '#000',
colorLight: '#fff',
correctLevel: QRCode.CorrectLevel.H
});
},
setFontSize () {
const box = this.$refs['box'];
const container = this.$refs['container'];
const baseSize = 15;
const scale = box.getBoundingClientRect().width / 600;
container.style.fontSize = baseSize * Math.min(scale, 2) + "px";
},
init () {
const box = this.$refs['box'];
const container = this.$refs['container'];
const { width,height } = box.getBoundingClientRect();
this.container.w = width;
this.container.h = height;
this.setFontSize();
//
box.ontouchstart = box.onmousedown = event => {
event.preventDefault();
@ -94,24 +134,91 @@ export default {
this.container.scale *= Math.exp(e.deltaY / -100);
}
},
download () {
this.isToImg = true;
html2canvas(this.$refs['container'],{
backgroundColor: null,
allowTaint: false,
taintTest: false,
logging: false,
useCORS: true,
dpi: window.devicePixelRatio || 1,
scale: 3 //
}).then(cnv => {
this.isToImg = false;
const pdf = new Jspdf('p','mm','a4');
const ctx = cnv.getContext('2d');
let a4w = 190;
let a4h = 277; // A4210mm x 297mm10mm190x277
let imgHeight = Math.floor(a4h * cnv.width / a4w); // A4
let renderedHeight = 0;
while (renderedHeight < cnv.height) {
let page = document.createElement('canvas');
page.width = cnv.width;
page.height = Math.min(imgHeight, cnv.height - renderedHeight);//
// getImageDatacanvas
page.getContext('2d').putImageData(ctx.getImageData(0, renderedHeight, cnv.width, Math.min(imgHeight, cnv.height - renderedHeight)), 0, 0);
pdf.addImage(page.toDataURL('image/jpeg', 1.0), 'JPEG', 10, 10, a4w, Math.min(a4h, a4w * page.height / page.width)); // 10mm
renderedHeight += imgHeight;
if (renderedHeight < cnv.height) {
pdf.addPage();//
}
// delete page;
}
//
pdf.save(`困难职工证明-${this.info.name}.pdf`);
}).catch(err => {
this.isToImg = false;
})
},
print () {
this.isToImg = true;
html2canvas(this.$refs['container'],{
backgroundColor: null,
allowTaint: false,
taintTest: false,
logging: false,
useCORS: true,
dpi: window.devicePixelRatio || 1,
scale: 3 //
}).then(cnv => {
this.isToImg = false;
printJS({
printable: cnv.toDataURL(),
type: 'image',
documentTitle: `困难职工证明-${this.info.name}`,
style: '@page{margin: 0 10mm;}'
})
}).catch(err => this.isToImg = true)
}
},
computed: {
transform () {
if (this.isToImg) return {};
return { 'transform': `translate(${this.container.offsetX}px,${this.container.offsetY}px) scale(${this.container.scale},${this.container.scale})` }
},
isReduction () {
return this.container.offsetX !== 0 || this.container.offsetY !== 0 || this.container.scale !== 1
}
},
computed: {},
created() {
if (this.$route.query.d) {
this.id = window.atob(this.$route.query.d).split('=')[1]
show({
table_name: 'records',
id: this.id
},
mounted() {
if (this.$route.query.bm) {
userInfo({
bianma: window.atob(this.$route.query.bm)
}).then(res => {
console.log(res)
this.info = res;
this.info = res.user;
this.init();
this.creatQrCode();
})
}
}
}
</script>
@ -141,18 +248,69 @@ export default {
position: relative;
&-border {
border: .5px solid #333;
}
@mixin h1 {
font-weight: 900;
font-size: 2em;
text-align: center;
}
@mixin h2 {
font-weight: 500;
font-size: 1.2em;
text-align: center;
}
@mixin text {
font-size: 1.1em;
}
& > div {
position: absolute;
}
.no {
@include h2;
transform: translate(20px,20px);
}
.qrcode {
transform: translate(0px,20px);
right: 20px
right: 20px;
text-align: center;
}
.title {
@include h1;
transform: translate(-50%,0);
left: 50%;
top: 23%;
}
.text {
@include text;
word-spacing: 4px;
letter-spacing: 1px;
top: 36%;
padding: 0 5em;
text-indent: 2em;
line-height: 3;
& > span {
text-decoration: underline;
}
}
.stay {
@include text;
line-height: 2;
text-align: right;
padding-top: 2em;
padding-right: 1em;
}
}
}
.reduction {
transform: translateX(-50%);
position: fixed;
left: 50%;
bottom: 60px;
}
.bottom-panel {
height: 50px;
background: rgba(55,55,55,.6);

@ -335,12 +335,13 @@ export default {
};
},
methods: {
toPrint (row) {
toPrint (row,isChild = false) {
console.log(row);
const url = this.$router.resolve({
path: '/print',
query: {
d: window.btoa(`id=${row.id}`)
bm: window.btoa(row.bianma),
isChild
}
})
window.open(url.href)

Loading…
Cancel
Save