初始化
@@ -0,0 +1,51 @@
|
||||
|
||||
|
||||
<template>
|
||||
<router-view></router-view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { useRouter, useRoute } from 'vue-router'
|
||||
|
||||
const router = useRouter()
|
||||
const route = useRoute()
|
||||
console.log(route)
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
@import url('./assets/style/base.css');
|
||||
html,body{
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
color: #222222;
|
||||
|
||||
}
|
||||
#app {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
font-family: Avenir, Helvetica, Arial, sans-serif;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
.box{
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
font-size: $size26;
|
||||
}
|
||||
.no-have{
|
||||
line-height: 1.3333rem /* 100/75 */;
|
||||
font-size: .4rem /* 30/75 */;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
.controls-fixed{
|
||||
position: fixed;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
width: 100%;
|
||||
height: .8rem /* 60/75 */;
|
||||
font-size: .4rem /* 30/75 */;
|
||||
color: $main-color;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,32 @@
|
||||
import request from "./adminRequest.js";
|
||||
// 登录
|
||||
export function getToken(authCode){
|
||||
return request({
|
||||
method: "get",
|
||||
url: "/user/getToken?code="+authCode,
|
||||
data: {
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// 获取访客记录
|
||||
export function getVisitorRecord(params ){
|
||||
return request({
|
||||
method: "get",
|
||||
url: "/visitor/getVisitorRecordList",
|
||||
params,
|
||||
headers:{
|
||||
'Authorization': localStorage.getItem('token')
|
||||
}
|
||||
})
|
||||
}
|
||||
// 获取二维码
|
||||
export function getWhiteCode( ){
|
||||
return request({
|
||||
method: "get",
|
||||
url: "/qr/getCommonBlackWhiteCode",
|
||||
headers:{
|
||||
'Authorization': localStorage.getItem('token')
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,96 @@
|
||||
import axios from 'axios'
|
||||
import { useRoute, useRouter } from 'vue-router'
|
||||
import { useStore } from 'vuex';
|
||||
import { Toast, Dialog } from 'vant';
|
||||
// import { getItem, setItem, removeItem, dalert } from '@/com/index'
|
||||
const errorCode = {
|
||||
'401': '登录状态已过期,即将返回首页重新登录。',
|
||||
'403': '当前操作没有权限',
|
||||
'404': '访问资源不存在',
|
||||
'default': '系统未知错误,请反馈给管理员'
|
||||
}
|
||||
const route = useRoute()
|
||||
const router = useRouter()
|
||||
const store = useStore()
|
||||
const loadNoCloseArr = ['/upload/face', ]
|
||||
// 判断当前的运行环境 process.env.NODE_ENV
|
||||
// isDev 为真 开发环境 --- npm run serve
|
||||
// isDev 为假 非开发环境(测试环境,生产环境)- npm run build
|
||||
const isDev = process.env.NODE_ENV === 'development'
|
||||
const request = axios.create({
|
||||
// 根据环境 设置不同的baseURL
|
||||
// 如果配置了单个的反向代理 --- 字符串模式
|
||||
// 如果配置了多个的反向代理 --- 对象模式
|
||||
// baseURL: isDev ? 'http://visitor.scdswj.cn/prod-api' : 'http://visitor.scdswj.cn/prod-api'
|
||||
baseURL: isDev ? 'http://192.168.31.118:8195' : 'http://visitor.scdswj.cn/prod-api'
|
||||
})
|
||||
// 'http://rap2api.taobao.org/app/mock/297766/example/1643070528065'
|
||||
|
||||
// 请求拦截器 - 所有的请求开始之前先到此处
|
||||
request.interceptors.request.use((config) => {
|
||||
// 可以设置 加载的动画效果 的展示
|
||||
// 在必要的路由设置一些额外的参数 ---- token信息携带放在此处
|
||||
console.log(config)
|
||||
return config
|
||||
}, (error) => {
|
||||
return Promise.reject(error)
|
||||
})
|
||||
|
||||
// 响应拦截器 --- 所有请求的相应先到此处
|
||||
request.interceptors.response.use((response) => {
|
||||
// 可以设置 加载的动画效果 的隐藏
|
||||
const code = response.data.code || 200;
|
||||
const message = errorCode[code] || response.data.msg || errorCode['default']
|
||||
if(code == 200){
|
||||
if(loadNoCloseArr.includes(response.config.url)){ // 设置请求不关闭加载动画接口
|
||||
}else{
|
||||
Toast.clear()
|
||||
}
|
||||
}else{
|
||||
Toast.clear()
|
||||
}
|
||||
if (code === 401) {
|
||||
Toast.fail(message)
|
||||
setTimeout(()=>{
|
||||
localStorage.removeItem('token');
|
||||
localStorage.removeItem('user');
|
||||
const redirectUrl = localStorage.getItem('redirect')
|
||||
if(redirectUrl){
|
||||
window.location.href = redirectUrl
|
||||
}else{
|
||||
window.location.href = '/userHome'
|
||||
}
|
||||
},2000)
|
||||
return Promise.reject('登录状态已过期,即将返回首页重新登录。')
|
||||
} else if (code === 500) {
|
||||
// Message({ message: msg, type: 'error' })
|
||||
Toast.fail(message)
|
||||
return Promise.reject(response.data)
|
||||
} else if (code === 601) {
|
||||
// Message({ message: msg, type: 'warning' })
|
||||
Toast.fail(message)
|
||||
return Promise.reject('error')
|
||||
} else if (code != 200) {
|
||||
Toast.fail(message)
|
||||
return Promise.reject('error')
|
||||
} else {
|
||||
return response.data
|
||||
}
|
||||
}, error => {
|
||||
Toast.clear()
|
||||
console.log(error.message)
|
||||
let { message } = error;
|
||||
if (message == "Network Error") {
|
||||
message = "后端接口连接异常";
|
||||
} else if (message.includes("timeout")) {
|
||||
message = "系统接口请求超时";
|
||||
} else if (message.includes("Request failed with status code")) {
|
||||
message = "系统接口" + message.substr(message.length - 3) + "异常";
|
||||
}
|
||||
console.log(message)
|
||||
Toast.fail(message)
|
||||
return Promise.reject(error.response)
|
||||
|
||||
})
|
||||
|
||||
export default request
|
||||
@@ -0,0 +1,97 @@
|
||||
import request from "./adminRequest.js";
|
||||
// 登录
|
||||
export function getToken(authCode){
|
||||
return request({
|
||||
method: "get",
|
||||
url: "/user/getToken?code="+authCode,
|
||||
data: {
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// 获取部门列表
|
||||
export function getDept( ){
|
||||
return request({
|
||||
method: "get",
|
||||
url: "/dept/getList",
|
||||
headers:{
|
||||
'Authorization': localStorage.getItem('token')
|
||||
}
|
||||
})
|
||||
}
|
||||
// 获取部门员工
|
||||
export function getUserListByDept( deptId){
|
||||
return request({
|
||||
method: "get",
|
||||
url: "/user/getUserListByDept",
|
||||
params:{
|
||||
deptId
|
||||
},
|
||||
headers:{
|
||||
'Authorization': localStorage.getItem('token')
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// 内部员工上传照片后,提交url
|
||||
export function putUserId( data){
|
||||
return request({
|
||||
method: "put",
|
||||
url: "/user/updateByUserId",
|
||||
data,
|
||||
headers:{
|
||||
'Authorization': localStorage.getItem('token')
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// http://localhost:8190/special/getList
|
||||
// 获取特殊人员
|
||||
export function getSpecial( params){
|
||||
return request({
|
||||
method: "get",
|
||||
url: "/special/getList",
|
||||
params,
|
||||
headers:{
|
||||
'Authorization': localStorage.getItem('token')
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// 删除特殊人员
|
||||
export function putSpecial( id){
|
||||
return request({
|
||||
method: "put",
|
||||
url: "/special/remove",
|
||||
params: {
|
||||
id
|
||||
},
|
||||
headers:{
|
||||
'Authorization': localStorage.getItem('token')
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// 特殊人员新增
|
||||
export function postSpecial( data){
|
||||
return request({
|
||||
method: "post",
|
||||
url: "/special/add",
|
||||
data,
|
||||
headers:{
|
||||
'Authorization': localStorage.getItem('token')
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// 修改特殊人员相片
|
||||
export function putSpecialFace( data){
|
||||
return request({
|
||||
method: "put",
|
||||
url: "/special/update",
|
||||
data,
|
||||
headers:{
|
||||
'Authorization': localStorage.getItem('token')
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,98 @@
|
||||
import axios from 'axios'
|
||||
import { useRoute, useRouter } from 'vue-router'
|
||||
import { useStore } from 'vuex';
|
||||
import { Toast, Dialog } from 'vant';
|
||||
// import { getItem, setItem, removeItem, dalert } from '@/com/index'
|
||||
const errorCode = {
|
||||
'401': '登录状态已过期,即将返回首页重新登录。',
|
||||
'403': '当前操作没有权限',
|
||||
'404': '访问资源不存在',
|
||||
'default': '系统未知错误,请反馈给管理员'
|
||||
}
|
||||
const route = useRoute()
|
||||
const router = useRouter()
|
||||
const store = useStore()
|
||||
const loadNoCloseArr = ['/upload/face', ]
|
||||
// 判断当前的运行环境 process.env.NODE_ENV
|
||||
// isDev 为真 开发环境 --- npm run serve
|
||||
// isDev 为假 非开发环境(测试环境,生产环境)- npm run build
|
||||
const isDev = process.env.NODE_ENV === 'development'
|
||||
const request = axios.create({
|
||||
// 根据环境 设置不同的baseURL
|
||||
// 如果配置了单个的反向代理 --- 字符串模式
|
||||
// 如果配置了多个的反向代理 --- 对象模式
|
||||
// baseURL: isDev ? 'http://visitor.scdswj.cn/prod-api' : 'http://visitor.scdswj.cn/prod-api'
|
||||
baseURL: isDev ? 'http://visitor.scdswj.cn/prod-api' : 'http://visitor.scdswj.cn/prod-api'
|
||||
})
|
||||
// 'http://rap2api.taobao.org/app/mock/297766/example/1643070528065'
|
||||
|
||||
// 请求拦截器 - 所有的请求开始之前先到此处
|
||||
request.interceptors.request.use((config) => {
|
||||
// 可以设置 加载的动画效果 的展示
|
||||
// 在必要的路由设置一些额外的参数 ---- token信息携带放在此处
|
||||
console.log(config)
|
||||
return config
|
||||
}, (error) => {
|
||||
return Promise.reject(error)
|
||||
})
|
||||
|
||||
// 响应拦截器 --- 所有请求的相应先到此处
|
||||
request.interceptors.response.use((response) => {
|
||||
// 可以设置 加载的动画效果 的隐藏
|
||||
const code = response.data.code || 200;
|
||||
const message = errorCode[code] || response.data.msg || errorCode['default']
|
||||
if(code == 200){
|
||||
if(loadNoCloseArr.includes(response.config.url)){ // 设置请求不关闭加载动画接口
|
||||
}else{
|
||||
Toast.clear()
|
||||
}
|
||||
}else{
|
||||
Toast.clear()
|
||||
}
|
||||
if (code === 401) {
|
||||
Toast.fail(message)
|
||||
setTimeout(()=>{
|
||||
localStorage.removeItem('token');
|
||||
localStorage.removeItem('user');
|
||||
localStorage.removeItem('userToken');
|
||||
|
||||
const redirectUrl = localStorage.getItem('redirect')
|
||||
if(redirectUrl){
|
||||
window.location.href = redirectUrl
|
||||
}else{
|
||||
window.location.href = '/userHome'
|
||||
}
|
||||
},2000)
|
||||
return Promise.reject('登录状态已过期,即将返回首页重新登录。')
|
||||
} else if (code === 500) {
|
||||
// Message({ message: msg, type: 'error' })
|
||||
Toast.fail(message)
|
||||
return Promise.reject(response.data)
|
||||
} else if (code === 601) {
|
||||
// Message({ message: msg, type: 'warning' })
|
||||
Toast.fail(message)
|
||||
return Promise.reject('error')
|
||||
} else if (code != 200) {
|
||||
Toast.fail(message)
|
||||
return Promise.reject('error')
|
||||
} else {
|
||||
return response.data
|
||||
}
|
||||
}, error => {
|
||||
Toast.clear()
|
||||
console.log(error.message)
|
||||
let { message } = error;
|
||||
if (message == "Network Error") {
|
||||
message = "后端接口连接异常";
|
||||
} else if (message.includes("timeout")) {
|
||||
message = "系统接口请求超时";
|
||||
} else if (message.includes("Request failed with status code")) {
|
||||
message = "系统接口" + message.substr(message.length - 3) + "异常";
|
||||
}
|
||||
console.log(message)
|
||||
Toast.fail(message)
|
||||
return Promise.reject(error.response)
|
||||
|
||||
})
|
||||
|
||||
export default request
|
||||
@@ -0,0 +1,14 @@
|
||||
import request from "./index";
|
||||
|
||||
export function getShop(){
|
||||
return request({
|
||||
url: '/shop',
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
export function getKind(){
|
||||
return request({
|
||||
url: '/hotkind',
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
import request from "./index";
|
||||
// 来访预约接口
|
||||
export function uploadApi(data){
|
||||
return request({
|
||||
url: '/upload/face',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
|
||||
import request from "./index";
|
||||
|
||||
// 来访预约接口
|
||||
export function postApply(data){
|
||||
return request({
|
||||
url: '/visitor/add',
|
||||
method: 'post',
|
||||
data,
|
||||
headers:{
|
||||
'Authorization': localStorage.getItem('userToken')
|
||||
}
|
||||
})
|
||||
}
|
||||
// 拜访人列表
|
||||
export function getVisitor(){
|
||||
return request({
|
||||
url: '/visitor/getVisitingInfo',
|
||||
method: 'get',
|
||||
headers:{
|
||||
'Authorization': localStorage.getItem('userToken')
|
||||
}
|
||||
})
|
||||
}
|
||||
// 手机号查询预约记录
|
||||
export function getByPhone(data){
|
||||
return request({
|
||||
url: '/visitor/getByPhone',
|
||||
method: 'get',
|
||||
params: data,
|
||||
headers:{
|
||||
'Authorization': localStorage.getItem('userToken')
|
||||
}
|
||||
})
|
||||
}
|
||||
// 手机号拜访人姓名
|
||||
export function getUserNameByTel(phone){
|
||||
return request({
|
||||
url: '/user/getUserNameByTel',
|
||||
method: 'get',
|
||||
params: {
|
||||
phone
|
||||
},
|
||||
headers:{
|
||||
'Authorization': localStorage.getItem('userToken')
|
||||
}
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
// 微信授权获得code
|
||||
export function getWeChatCode(){
|
||||
return request({
|
||||
url: '/user/getWxLogin',
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
// 微信登录
|
||||
export function login(code){
|
||||
return request({
|
||||
url: '/user/getWxToken',
|
||||
method: 'get',
|
||||
params:{
|
||||
code
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
|
After Width: | Height: | Size: 2.2 KiB |
|
After Width: | Height: | Size: 6.6 KiB |
|
After Width: | Height: | Size: 37 KiB |
|
After Width: | Height: | Size: 350 KiB |
|
After Width: | Height: | Size: 562 B |
|
After Width: | Height: | Size: 1.3 KiB |
|
After Width: | Height: | Size: 1.5 KiB |
|
After Width: | Height: | Size: 1.2 KiB |
|
After Width: | Height: | Size: 20 KiB |
|
After Width: | Height: | Size: 527 KiB |
|
After Width: | Height: | Size: 1.2 KiB |
|
After Width: | Height: | Size: 48 KiB |
|
After Width: | Height: | Size: 1.0 KiB |
|
After Width: | Height: | Size: 1.5 KiB |
|
After Width: | Height: | Size: 665 B |
|
After Width: | Height: | Size: 2.5 KiB |
|
After Width: | Height: | Size: 67 KiB |
|
After Width: | Height: | Size: 577 B |
|
After Width: | Height: | Size: 60 KiB |
|
After Width: | Height: | Size: 6.7 KiB |
|
After Width: | Height: | Size: 646 B |
|
After Width: | Height: | Size: 52 KiB |
|
After Width: | Height: | Size: 2.4 KiB |
|
After Width: | Height: | Size: 2.4 KiB |
@@ -0,0 +1,62 @@
|
||||
html,
|
||||
body,
|
||||
ul,
|
||||
li,
|
||||
ol,
|
||||
dl,
|
||||
dd,
|
||||
dt,
|
||||
p,
|
||||
h1,
|
||||
h2,
|
||||
h3,
|
||||
h4,
|
||||
h5,
|
||||
h6,
|
||||
form,
|
||||
fieldset,
|
||||
legend,
|
||||
img,input{
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
fieldset,
|
||||
img {
|
||||
border: none;
|
||||
}
|
||||
|
||||
img {
|
||||
display: block;
|
||||
}
|
||||
|
||||
|
||||
|
||||
ul,
|
||||
ol {
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
body {
|
||||
color: #333;
|
||||
font: 12px/20px "SimSun", "宋体", "Arial Narrow", HELVETICA;
|
||||
background: #fff;
|
||||
/* overflow-y:scroll;*/
|
||||
/* overflow-x: hidden; */
|
||||
}
|
||||
|
||||
a {
|
||||
color: #666;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
a:visited {
|
||||
color: #666;
|
||||
}
|
||||
|
||||
a:hover,
|
||||
a:active,
|
||||
a:focus {
|
||||
color: #ff8400;
|
||||
text-decoration: underline;
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
$main-color: #30BF78; // 用户端主题色
|
||||
|
||||
// 字号大小
|
||||
$sm-size: .32rem /* 24/75 */;
|
||||
$size26: .3467rem /* 26/75 */;
|
||||
$md-size: .3733rem /* 28/75 */;
|
||||
$size30: .4rem /* 30/75 */;
|
||||
$lg-size: .4267rem /* 32/75 */;
|
||||
// 颜色
|
||||
$white: #ffffff;
|
||||
|
After Width: | Height: | Size: 270 KiB |
|
After Width: | Height: | Size: 1.6 KiB |
|
After Width: | Height: | Size: 8.3 KiB |
|
After Width: | Height: | Size: 1.7 KiB |
|
After Width: | Height: | Size: 116 KiB |
|
After Width: | Height: | Size: 12 KiB |
|
After Width: | Height: | Size: 13 KiB |
|
After Width: | Height: | Size: 44 KiB |
|
After Width: | Height: | Size: 1.3 KiB |
|
After Width: | Height: | Size: 5.3 KiB |
|
After Width: | Height: | Size: 22 KiB |
|
After Width: | Height: | Size: 1.1 KiB |
|
After Width: | Height: | Size: 31 KiB |
|
After Width: | Height: | Size: 547 KiB |
|
After Width: | Height: | Size: 3.7 KiB |
|
After Width: | Height: | Size: 432 B |
|
After Width: | Height: | Size: 276 KiB |
|
After Width: | Height: | Size: 16 KiB |
|
After Width: | Height: | Size: 16 KiB |
|
After Width: | Height: | Size: 14 KiB |
@@ -0,0 +1,341 @@
|
||||
import { Dialog } from 'vant';
|
||||
|
||||
/*
|
||||
表单对象验证、 rulesForm
|
||||
重置表单对象、resetForm
|
||||
手机号验证、 rulesPhone
|
||||
身份证验证、 rulesIdCard
|
||||
计算器、 calculator
|
||||
时间格式化、formatDate
|
||||
获取星期几、weekDate
|
||||
检查数据类型、checkType
|
||||
表单去除空格、trimFrom
|
||||
数组是否包含数组、isIncludeArray
|
||||
根据id递归查询对象、recursion
|
||||
计算两个时间戳相差的时间、timeDiff
|
||||
判断开始时间是否大于结束时间 compareTime
|
||||
*/
|
||||
|
||||
/*
|
||||
表单验证
|
||||
@param { Object } form(必填) 验证的表单
|
||||
@param { Object } rules(选填) 需要验证的字段 试例rules:{ name: '请输入名称' } name为需要验证的字段
|
||||
@return { Boolean } true 通过 false 失败
|
||||
*/
|
||||
export function rulesForm ( form, rules ) {
|
||||
let flage = true
|
||||
let JSONrules = JSON.stringify(rules)
|
||||
if(JSONrules !== JSON.stringify({})){
|
||||
for( let key in rules){
|
||||
if(Array.isArray( form[key] ) && form[key].length == 0 ){
|
||||
// uni.showToast({
|
||||
// title: rules[key],
|
||||
// })
|
||||
|
||||
Dialog.alert({
|
||||
message: rules[key],
|
||||
})
|
||||
flage = false
|
||||
return
|
||||
break;
|
||||
}else if( !form[key] && form[key] !== 0 ){
|
||||
// uni.showToast({
|
||||
// title: rules[key],
|
||||
// })
|
||||
// Dialog(rules[key])
|
||||
Dialog.alert({
|
||||
message: rules[key],
|
||||
})
|
||||
flage = false
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return flage
|
||||
}
|
||||
export function rulesFormFBoolean ( form ) {
|
||||
let flage = true
|
||||
let JSONform = JSON.stringify(form)
|
||||
if(JSONform !== JSON.stringify({})){
|
||||
for( let key in form){
|
||||
if(Array.isArray( form[key] ) && form[key].length == 0 ){
|
||||
flage = false
|
||||
return
|
||||
break;
|
||||
}else if( !form[key] && form[key] !== 0 ){
|
||||
flage = false
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return flage
|
||||
}
|
||||
/*
|
||||
重置表单对象
|
||||
@param { Object } form(必填) 需要重置的表单
|
||||
@param { Object } rules(选填) 指定需要重置的值默认设为null 试例rules:{ name: 1 } name字段重置为1
|
||||
@return { Object } 重置后的值
|
||||
*/
|
||||
export function resetForm(form, rules = {}) {
|
||||
for( let key in form){
|
||||
if(checkType(form[key]) == "Array"){
|
||||
if(rules.hasOwnProperty(key)){ // 是否包含需要更改的
|
||||
form[key] = rules[key]
|
||||
}else{
|
||||
form[key] = []
|
||||
}
|
||||
}else if(checkType(form[key]) == "Object"){
|
||||
if(rules.hasOwnProperty(key)){ // 是否包含需要更改的
|
||||
form[key] = rules[key]
|
||||
}else{
|
||||
form[key] = {}
|
||||
}
|
||||
}else if(checkType(form[key]) == "Boolean"){
|
||||
if(rules.hasOwnProperty(key)){ // 是否包含需要更改的
|
||||
form[key] = rules[key]
|
||||
}else{
|
||||
form[key] = false
|
||||
}
|
||||
}else{
|
||||
if(rules.hasOwnProperty(key)){ // 是否包含需要更改的
|
||||
form[key] = rules[key]
|
||||
}else{
|
||||
form[key] = null
|
||||
}
|
||||
}
|
||||
}
|
||||
return form
|
||||
}
|
||||
|
||||
|
||||
/* 手机号验证
|
||||
@param { Number } IdcardVal(必填) 手机号
|
||||
@return { Boolean } true 通过 false 失败
|
||||
*/
|
||||
export function rulesPhone ( phoneVal ) {
|
||||
let phoneReg = /(^1\d{10}$)|(^[0-9]\d{7}$)/;
|
||||
if(!phoneReg.test(phoneVal)) {
|
||||
Dialog.alert({
|
||||
message: '请输入正确的手机号!',
|
||||
})
|
||||
return false;
|
||||
}else{
|
||||
return true
|
||||
}
|
||||
}
|
||||
/*
|
||||
@param { Number } email(必填) 邮箱地址
|
||||
@return { Boolean } true 通过 false 失败
|
||||
*/
|
||||
export function rulesEmail(email) {
|
||||
var reg = /^([\w+\.])+@\w+([.]\w+)+$/
|
||||
return reg.test(email)
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
身份证验证
|
||||
@param { String } IdcardVal(必填) 需要检查的参数
|
||||
@return { Boolean } true 通过 false 失败
|
||||
*/
|
||||
export function rulesIdCard ( IdcardVal ) {
|
||||
var idCardReg = /^(\d{15}$|^\d{18}$|^\d{17}(\d|X|x))$/;
|
||||
if(!idCardReg.test(IdcardVal)) {
|
||||
// uni.showToast({
|
||||
// title: '身份证号码格式错误!',
|
||||
// })
|
||||
Dialog.alert({ message: '身份证号码格式错误!' })
|
||||
return false;
|
||||
} else{
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
计算器
|
||||
startNum 类型 Number||String 开始的参数
|
||||
endNum 类型 Number||String 结束参数
|
||||
operator 类型 String 计算方式 + - * ÷
|
||||
返回值 为数值类型计算结果
|
||||
*/
|
||||
export function calculator ( startNum, endNum, operator = '+'){
|
||||
if(operator == '+'){
|
||||
return (Number(startNum * 1000) + Number(endNum * 1000)) / 1000
|
||||
}else if( operator == '-' ){
|
||||
return (Number(startNum * 1000) - Number(endNum * 1000)) / 1000
|
||||
}else if( operator == '/' ){
|
||||
return (Number(startNum * 1000) / Number(endNum * 1000)) / 1000000
|
||||
}else if( operator == '*' ){
|
||||
return (Number(startNum * 1000) * Number(endNum * 1000)) / 1000000
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
时间日期格式化
|
||||
@param { Date||String } timeStr(必填) 默认值当前时间 传入时间
|
||||
@param { String } separator(必填) 默认值 '-' 分隔符号 chinese返回中文汉字
|
||||
@param { String } type(选填) 是否返回时分秒 yaer表示只返回年月日
|
||||
@return { String } 日期
|
||||
*/
|
||||
export function formatDate (timeStr = (new Date()), separator = '-', type){
|
||||
const date = new Date(timeStr)
|
||||
let yaer = date.getFullYear()
|
||||
let month = date.getMonth() + 1
|
||||
let day = date.getDate()
|
||||
let hour = date.getHours()
|
||||
let minute = date.getMinutes()
|
||||
let second = date.getSeconds()
|
||||
if(separator == '-'){
|
||||
if(type == 'year'){
|
||||
return yaer + separator + (month >= 10 ? month : ('0' + month)) + separator + (day >= 10 ? day : ('0' + day))
|
||||
}else {
|
||||
return yaer + separator + (month >= 10 ? month : ('0' + month)) + separator + (day >= 10 ? day : ('0' + day)) + ' ' + (hour >= 10 ? hour : ('0' + hour)) + ':' + (minute >= 10 ? minute : ('0' + minute)) + ':' + (second >= 10 ? second : ('0' + second))
|
||||
}
|
||||
}else if (separator == 'chinese') {
|
||||
if(type == 'year'){
|
||||
return yaer + '年' + month+ '月' + day+ '日'
|
||||
}else {
|
||||
return yaer + '年' + month+ '月' + day+ '日' + hour + '时' + minute + '分' + second + '秒'
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
/*
|
||||
获取星期几
|
||||
@param { Date||String } time(必填) 默认值当前时间 传入时间
|
||||
@return { String } 星期几
|
||||
*/
|
||||
export function weekDate (time = (new Date())){
|
||||
const date = new Date(time)
|
||||
let arr = ['星期天', '星期一', '星期二', '星期三', '星期四', '星期五', '星期六']
|
||||
return arr[date.getDay()]
|
||||
}
|
||||
|
||||
/*
|
||||
判断数据类型值
|
||||
@param { any } value(必填) 需要检查的参数
|
||||
@return { String } 'Number', 'String', 'Boolean', 'Array', 'Object', 'Function', 'Undefined', 'null'
|
||||
*/
|
||||
export function checkType(value) {
|
||||
const toString = Object.prototype.toString;
|
||||
if(toString.call(value) === '[object Number]'){
|
||||
return 'Number'
|
||||
}else if(toString.call(value) === '[object String]') {
|
||||
return 'String'
|
||||
}else if(toString.call(value) === '[object Boolean]') {
|
||||
return 'Boolean'
|
||||
}else if(toString.call(value) === '[object Array]') {
|
||||
return 'Array'
|
||||
}else if(toString.call(value) === '[object Object]') {
|
||||
return 'Object'
|
||||
}else if(toString.call(value) === '[object Function]') {
|
||||
return 'Function'
|
||||
}else if(toString.call(value) === '[object Undefined]') {
|
||||
return 'Undefined'
|
||||
}else if(toString.call(value) === '[object Null]') {
|
||||
return 'null'
|
||||
}else if(toString.call(value) === '[object Date]') {
|
||||
return 'Date'
|
||||
}else if(toString.call(value) === '[object Error]') {
|
||||
return 'Error'
|
||||
}
|
||||
}
|
||||
/*
|
||||
表单去除二端空格
|
||||
该方法需要依赖checkType方法
|
||||
@param { Object || Array } form(必填) 需要去除空格的表单
|
||||
@return { Object || Array } 为去空后的数据对象数组
|
||||
*/
|
||||
export function trimFrom ( form ) {
|
||||
let newForm = null
|
||||
if(checkType(form)== 'Object'){
|
||||
newForm = { ...form }
|
||||
}else if(checkType(form)== 'Array') {
|
||||
newForm = [...form ]
|
||||
}
|
||||
for( let key in form){
|
||||
if( checkType(form[key] ) == 'String' ){
|
||||
console.log(newForm[key])
|
||||
newForm[key] = form[key].trim()
|
||||
}else if( checkType(form[key] ) == 'Object' ){
|
||||
newForm[key] = trim(form[key])
|
||||
}else if( checkType(form[key]) == 'Array' ) {
|
||||
newForm[key] = trim(form[key])
|
||||
}
|
||||
}
|
||||
return newForm
|
||||
}
|
||||
/*
|
||||
数组是否包含数组
|
||||
@param { Array } arr(必填) 包含数组
|
||||
@param { Array } arr2(必填) 被包含数组
|
||||
@return { Boolean } 包含true 不包含false
|
||||
*/
|
||||
export function isIncludeArray(arr1, arr2) {
|
||||
return arr2.every((item) => {
|
||||
return arr1.includes(item)
|
||||
})
|
||||
}
|
||||
|
||||
/*
|
||||
根据id递归查询对象
|
||||
@param { Array } arr(必填) 查询的数组
|
||||
@param { Number||String } value(必填) 查询的数组
|
||||
@param { Number||String } unique(选填) 默认值'id' 查询的字段名
|
||||
@param { Array } children(选填) 默认值'children' 查询递归数组
|
||||
@return { Object||null } 查询到的值
|
||||
*/
|
||||
export function recursion (arr, value, unique = 'id', children = 'children' ) {
|
||||
let obj = null
|
||||
arr.forEach(( item, index ) => {
|
||||
if(item[unique] == value){
|
||||
obj = item
|
||||
}else {
|
||||
if(item[children] && item[children].length != 0){
|
||||
if(recursion(item[children], value, unique, children)){
|
||||
obj = recursion(item[children], value, unique, children)
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
return obj
|
||||
}
|
||||
/*
|
||||
计算两个时间戳相差的时间
|
||||
@param { startTime, endTime } 一个时间,另一个时间
|
||||
@return { Object } 比较后对象返回 天时分秒对象集合
|
||||
*/
|
||||
export function timeDiff (startTime, endTime) {
|
||||
const time2 = new Date(endTime)
|
||||
const time1 = new Date(startTime)
|
||||
const diffTime = {
|
||||
day: 0,
|
||||
hour: 0,
|
||||
min: 0,
|
||||
sec: 0
|
||||
}
|
||||
const diff = Math.abs(time2.getTime() - time1.getTime());
|
||||
const remain_hour = diff % (24 * 60 * 60 * 1000);
|
||||
const remain_min = remain_hour % ( 60 * 60 * 1000);
|
||||
diffTime.day = Math.floor(diff / (24 * 60 * 60 * 1000));
|
||||
diffTime.hour = Math.floor(remain_hour / (60 * 60 * 1000));
|
||||
diffTime.min = Math.floor(remain_min / (60* 1000));
|
||||
diffTime.sec = remain_min % (60 * 1000) / 1000;
|
||||
return diffTime;
|
||||
}
|
||||
|
||||
/*
|
||||
判断开始时间是否大于结束时间 compareTime
|
||||
@param { startTime, endTime } 一个时间,另一个时间
|
||||
@return { boolean } 结束时间大于开始时间 返回true 否者false
|
||||
|
||||
*/
|
||||
export function compareTime (startTime, endTime) {
|
||||
const time1 = new Date(startTime)
|
||||
const time2 = new Date(endTime)
|
||||
if(time2.getTime() - time1.getTime() > 0){
|
||||
return true
|
||||
}else{
|
||||
return false
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
<script setup>
|
||||
import { ref } from 'vue'
|
||||
|
||||
defineProps({
|
||||
msg: String
|
||||
})
|
||||
|
||||
const count = ref(0)
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<h1>{{ msg }}</h1>
|
||||
|
||||
<p>
|
||||
Recommended IDE setup:
|
||||
<a href="https://code.visualstudio.com/" target="_blank">VSCode</a>
|
||||
+
|
||||
<a href="https://github.com/johnsoncodehk/volar" target="_blank">Volar</a>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<a href="https://vitejs.dev/guide/features.html" target="_blank">
|
||||
Vite Documentation
|
||||
</a>
|
||||
|
|
||||
<a href="https://v3.vuejs.org/" target="_blank">Vue 3 Documentation</a>
|
||||
</p>
|
||||
|
||||
<button type="button" @click="count++">count is: {{ count }}</button>
|
||||
<p>
|
||||
Edit
|
||||
<code>components/HelloWorld.vue</code> to test hot module replacement.
|
||||
</p>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
a {
|
||||
color: #42b983;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,191 @@
|
||||
<template>
|
||||
<div @click.self="onClickCancel" class='fixed-model'>
|
||||
<div class="model">
|
||||
<header>
|
||||
<h3>新增特殊人员</h3>
|
||||
</header>
|
||||
<div class="content">
|
||||
<input v-model="form.name" class="name-input" type="text" placeholder="请输入人员姓名" />
|
||||
<input v-model="form.userId" class="tel-input" type="text" placeholder="请输入人员联系方式" />
|
||||
<p>人脸上传:请上传正脸无遮挡照片</p>
|
||||
<div class="upload-box">
|
||||
<img v-if="!faceImg" class="icon-img" src="../assets/img/xiangji.png" alt="">
|
||||
<img v-else class="photo" :src="faceImg" alt="">
|
||||
<input @change="onChangeFile" type="file">
|
||||
</div>
|
||||
<div class="button-box">
|
||||
<div @click="onClickCancel" class="cancel-button">取消</div>
|
||||
<div @click="onClickSave" class="save-button">保存</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, reactive } from 'vue'
|
||||
import { useRouter } from 'vue-router'
|
||||
import { useStore } from 'vuex'
|
||||
import { rulesForm, resetForm, rulesPhone } from '@/com/index'
|
||||
/* @data */
|
||||
const router = useRouter()
|
||||
const store = useStore()
|
||||
const emits = defineEmits(['change', 'cancel', 'save'])
|
||||
const form = reactive({
|
||||
face: '',
|
||||
userId: '',
|
||||
name: '',
|
||||
})
|
||||
const faceImg = ref('')
|
||||
|
||||
/* @setup */
|
||||
|
||||
/* @method */
|
||||
// 上传图片
|
||||
const onChangeFile = (e) =>{
|
||||
if(e.target.files[0]){
|
||||
form.face = e.target.files[0]
|
||||
let reader = new FileReader()
|
||||
reader.readAsDataURL(e.target.files[0]) // 转base64
|
||||
reader.onload = () =>{ // 简化代码 - 转换完成
|
||||
faceImg.value = reader.result
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
const onClickCancel = () =>{
|
||||
emits('cancel')
|
||||
}
|
||||
const onClickSave = () =>{
|
||||
emits('save', form)
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<style lang='scss' scoped>
|
||||
.fixed-model{
|
||||
position: fixed;
|
||||
left: 0;
|
||||
top: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: rgba(60,60,67,0.6);
|
||||
.model{
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
top: 50%;
|
||||
transform: translateX(-50%) translateY(-60%) ;
|
||||
width: 8.1867rem /* 614/75 */;
|
||||
// height: 11.7333rem /* 880/75 */;
|
||||
background: #FFFFFF;
|
||||
border-radius: .5333rem /* 40/75 */;
|
||||
|
||||
header{
|
||||
width: 100%;
|
||||
height: 3.7333rem /* 280/75 */;
|
||||
background: url('../assets/img/xinzengbeijing.png') left top/100% 100% no-repeat;
|
||||
padding: .8267rem /* 62/75 */ 0 0;
|
||||
box-sizing: border-box;
|
||||
h3{
|
||||
line-height: .8rem /* 60/75 */;
|
||||
font-size: .5333rem /* 40/75 */;
|
||||
font-family: Source Han Sans CN, Source Han Sans CN;
|
||||
font-weight: 500;
|
||||
color: #222222;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
.content{
|
||||
width: 100%;
|
||||
padding: 0 .72rem /* 54/75 */ .8rem /* 60/75 */ .8rem /* 60/75 */;
|
||||
box-sizing: border-box;
|
||||
margin-top: -1.6267rem /* 122/75 */;
|
||||
.name-input, .tel-input{
|
||||
width: 100%;
|
||||
height: 1.1467rem /* 86/75 */;
|
||||
background: #F5F5F5;
|
||||
border-radius: 1.3333rem /* 100/75 */;
|
||||
opacity: 1;
|
||||
border: none;
|
||||
outline: none;
|
||||
padding: 0 .4533rem /* 34/75 */ 0;
|
||||
box-sizing: border-box;
|
||||
font-size: $md-size;
|
||||
font-family: Source Han Sans CN, Source Han Sans CN;
|
||||
font-weight: 400;
|
||||
margin-bottom: .48rem /* 36/75 */;
|
||||
}
|
||||
.tel-input{
|
||||
margin-bottom: .3733rem /* 28/75 */;
|
||||
}
|
||||
.name-input::-webkit-input-placeholder{
|
||||
color: #B6B7B8;
|
||||
}
|
||||
.tel-input::-webkit-input-placeholder{
|
||||
color: #B6B7B8;
|
||||
}
|
||||
p{
|
||||
line-height: .5333rem /* 40/75 */;
|
||||
font-size: $size26;
|
||||
font-family: Source Han Sans CN, Source Han Sans CN;
|
||||
font-weight: 400;
|
||||
color: #000000;
|
||||
padding: 0 0 0 .2667rem /* 20/75 */;
|
||||
box-sizing: border-box;
|
||||
margin-bottom: .2667rem /* 20/75 */;
|
||||
}
|
||||
.upload-box{
|
||||
position: relative;
|
||||
width: 3.28rem /* 246/75 */;
|
||||
height: 2.6667rem /* 200/75 */;
|
||||
background: #F5F5F5;
|
||||
border-radius: .2667rem /* 20/75 */;
|
||||
opacity: 1;
|
||||
border: .0267rem /* 2/75 */ solid #D1D1D6;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
.icon-img{
|
||||
width: 1.0667rem /* 80/75 */;
|
||||
height: 1.0667rem /* 80/75 */;
|
||||
}
|
||||
.photo{
|
||||
display: block;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border-radius: .2667rem /* 20/75 */;
|
||||
}
|
||||
input{
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
.button-box{
|
||||
margin-top: 1.1467rem /* 86/75 */;
|
||||
display: flex;
|
||||
div{
|
||||
// width: 240px;
|
||||
flex: 1;
|
||||
height: 1.0667rem /* 80/75 */;
|
||||
line-height: 1.0667rem /* 80/75 */;
|
||||
background: #448CF7;
|
||||
border-radius: 1.3333rem /* 100/75 */;
|
||||
text-align: center;
|
||||
font-size: $md-size;
|
||||
color: #FFFFFF;
|
||||
}
|
||||
.cancel-button{
|
||||
margin-right: .2667rem /* 20/75 */;
|
||||
background: #D9D9D9;
|
||||
color: #999999;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,162 @@
|
||||
<template>
|
||||
<div @click.self="onClickCancel" class='fixed-model'>
|
||||
<div class="model">
|
||||
<header>
|
||||
<h3>员工人脸照片</h3>
|
||||
<div class="upload-box">
|
||||
<div class="span">点击上传</div>
|
||||
<img v-if="faceImg" class="face-img" :src="props.faceImg" alt="">
|
||||
|
||||
<input @change="onChangeFile" type="file" accept="image/*"/>
|
||||
</div>
|
||||
</header>
|
||||
<p class="tips">注:点击照片框进行人脸照片上传</p>
|
||||
<div class="button-box">
|
||||
<div @click="onClickCancel" class="cancel-button">取消</div>
|
||||
<div @click="onClickSave" class="save-button">保存</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref } from 'vue'
|
||||
import { useRouter } from 'vue-router'
|
||||
import { useStore } from 'vuex'
|
||||
import { rulesForm, resetForm, rulesPhone } from '@/com/index'
|
||||
|
||||
/* @data */
|
||||
const router = useRouter()
|
||||
const store = useStore()
|
||||
const emits = defineEmits(['change', 'cancel', 'save'])
|
||||
|
||||
const props = defineProps({
|
||||
faceImg: {
|
||||
default: ''
|
||||
},
|
||||
})
|
||||
const file = ref()
|
||||
|
||||
/* @setup */
|
||||
|
||||
/* @method */
|
||||
// 上传图片
|
||||
const onChangeFile = (e) =>{
|
||||
file.value = e.target.files[0]
|
||||
emits('change', e.target.files[0])
|
||||
}
|
||||
const onClickCancel = () =>{
|
||||
emits('cancel')
|
||||
}
|
||||
const onClickSave = () =>{
|
||||
emits('save', file.value)
|
||||
}
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
<style lang='scss' scoped>
|
||||
.fixed-model{
|
||||
position: fixed;
|
||||
left: 0;
|
||||
top: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: rgba(60,60,67,0.6);
|
||||
.model{
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
top: 50%;
|
||||
transform: translateX(-50%) translateY(-65%) ;
|
||||
width: 8.1867rem /* 614/75 */;
|
||||
// height: 394px;
|
||||
background: #FFFFFF;
|
||||
border-radius: .5333rem /* 40/75 */;
|
||||
padding: 0 0 .7733rem /* 58/75 */;
|
||||
box-sizing: border-box;
|
||||
header{
|
||||
width: 100%;
|
||||
height: 10.5333rem /* 790/75 */;
|
||||
background: #FFFFFF;
|
||||
border-radius: .5333rem /* 40/75 */;
|
||||
background: url('../assets/img/renlianbeijing.png') left top/100% 100% no-repeat;
|
||||
h3{
|
||||
line-height: .7733rem /* 58/75 */;
|
||||
font-size: .5333rem /* 40/75 */;
|
||||
font-family: Source Han Sans CN, Source Han Sans CN;
|
||||
font-weight: 500;
|
||||
color: #222222;
|
||||
padding: .8533rem /* 64/75 */ 0 0 ;
|
||||
text-align: center;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
.upload-box{
|
||||
position: relative;
|
||||
width: 4.4rem /* 330/75 */;
|
||||
height: 4.4rem /* 330/75 */;
|
||||
background: #FFFFFF;
|
||||
box-shadow: 0px .1067rem /* 8/75 */ .8rem /* 60/75 */ .2667rem /* 20/75 */ rgba(68,140,247,0.4);
|
||||
border-radius: .2667rem /* 20/75 */;
|
||||
margin: 1.28rem /* 96/75 */ auto 0;
|
||||
overflow: hidden;
|
||||
.span{
|
||||
text-align: center;
|
||||
line-height: 4.4rem /* 330/75 */;
|
||||
font-size: $size30;
|
||||
font-family: Source Han Sans CN, Source Han Sans CN;
|
||||
font-weight: 400;
|
||||
color: #999999;
|
||||
|
||||
}
|
||||
// display: flex;
|
||||
.face-img, input{
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border-radius: .2667rem /* 20/75 */;
|
||||
opacity: 0;
|
||||
}
|
||||
.face-img{
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
.tips{
|
||||
line-height: .5333rem /* 40/75 */;
|
||||
font-size: $md-size;
|
||||
font-family: Source Han Sans CN, Source Han Sans CN;
|
||||
font-weight: 400;
|
||||
color: #5F6583;
|
||||
text-align: center;
|
||||
margin-top: -1.6rem /* 120/75 */;
|
||||
}
|
||||
.button-box{
|
||||
// margin-top: 1.1467rem /* 86/75 */;
|
||||
display: flex;
|
||||
padding: 0 .7733rem /* 58/75 */;
|
||||
box-sizing: border-box;
|
||||
margin-top: .6133rem /* 46/75 */;
|
||||
div{
|
||||
// width: 240px;
|
||||
flex: 1;
|
||||
height: 1.0667rem /* 80/75 */;
|
||||
line-height: 1.0667rem /* 80/75 */;
|
||||
background: #448CF7;
|
||||
border-radius: 1.3333rem /* 100/75 */;
|
||||
text-align: center;
|
||||
font-size: $md-size;
|
||||
color: #FFFFFF;
|
||||
}
|
||||
.cancel-button{
|
||||
margin-right: .2667rem /* 20/75 */;
|
||||
background: #D9D9D9;
|
||||
color: #999999;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,115 @@
|
||||
<!-- label 为字段名 -->
|
||||
<!-- type 为输入框类型 默认text -->
|
||||
<!-- isMust 为是否存在* 默认有 -->
|
||||
<!-- disabled 是否禁用 -->
|
||||
<template>
|
||||
<div class="input-box" :class=" isline ? 'select-active' : ''">
|
||||
<div class="label"> <span v-if="props.isMust && props.isMustPosition == 'left'">* </span>{{ props.label }} <span v-if="props.isMust && props.isMustPosition == 'right'">*</span></div>
|
||||
<input @blur="onClickBlur" @touchstart="onClickInput" :type="props.type" v-model="sea" @input="valChange(sea)" :disabled="props.disabled" :placeholder="'请输入'+props.label">
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang='ts' setup>
|
||||
import { ref, watch } from 'vue'
|
||||
import { useRouter } from 'vue-router'
|
||||
/* props */
|
||||
const props = defineProps({
|
||||
modelValue:{
|
||||
default: '' as any,
|
||||
},
|
||||
type:{
|
||||
type: String,
|
||||
default: 'text'
|
||||
},
|
||||
label: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
isline: {
|
||||
default: false,
|
||||
},
|
||||
isMust: {
|
||||
type: Boolean,
|
||||
default: true,
|
||||
},
|
||||
isMustPosition: {
|
||||
type: String,
|
||||
default: 'right',
|
||||
},
|
||||
disabled: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
|
||||
})
|
||||
/* emits */
|
||||
const emits = defineEmits(['update:modelValue', 'click', 'input', 'blur'])
|
||||
|
||||
|
||||
/* watch */
|
||||
// 因为props.modelValue是非引用类型,改变时,需要监听,对sea重新赋值
|
||||
watch(() => props.modelValue, () => { sea.value = props.modelValue })
|
||||
|
||||
// 数据双向绑定
|
||||
const valChange = (e: string) =>{
|
||||
emits('update:modelValue', e)
|
||||
emits('input', e)
|
||||
}
|
||||
|
||||
|
||||
/* @data */
|
||||
const router = useRouter()
|
||||
const sea = ref(props.modelValue)
|
||||
|
||||
/* @method */
|
||||
const onClickInput = () =>{
|
||||
emits('click')
|
||||
}
|
||||
const onClickBlur = () =>{
|
||||
emits('blur', sea.value)
|
||||
}
|
||||
|
||||
/* setup */
|
||||
// console.log(props.modelValue)
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
<style lang='scss' scoped>
|
||||
.input-box{
|
||||
width: 100%;
|
||||
height: 1.5733rem /* 118/75 */;
|
||||
// background: #F9F9F9;
|
||||
// border-radius: .2667rem /* 20/75 */;
|
||||
padding: 0 .0267rem /* 2/75 */ 0;
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
// margin: 0 auto .2667rem /* 20/75 */;
|
||||
.label{
|
||||
flex: 1;
|
||||
font-size: $size26;
|
||||
color: #333333;
|
||||
line-height: 1.5733rem /* 118/75 */;
|
||||
span{
|
||||
color: #FF0000;
|
||||
}
|
||||
}
|
||||
input{
|
||||
flex: 1;
|
||||
border: none;
|
||||
outline: none;
|
||||
text-align: right;
|
||||
font-size: $size26;
|
||||
color: #333333;
|
||||
// background: #F9F9F9;
|
||||
padding-right: 0.3733rem;
|
||||
}
|
||||
input::-webkit-input-placeholder {
|
||||
font-size: $size26;
|
||||
color: #999999;
|
||||
}
|
||||
}
|
||||
.select-active{
|
||||
border-bottom: .0267rem /* 2/75 */ dashed #D9D9D9;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,98 @@
|
||||
<template>
|
||||
<div class='fixed-model'>
|
||||
<div class="model">
|
||||
<h3>删除事件提醒</h3>
|
||||
<p>确认删除此员工人脸信息?</p>
|
||||
<div class="button-box">
|
||||
<div @click="onClickCancel" class="cancel-button">取消</div>
|
||||
<div @click="onClickSave" class="save-button">删除</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref } from 'vue'
|
||||
import { useRouter } from 'vue-router'
|
||||
import { useStore } from 'vuex'
|
||||
import { rulesForm, resetForm, rulesPhone } from '@/com/index'
|
||||
|
||||
const emits = defineEmits(['change', 'cancel', 'delete'])
|
||||
/* @data */
|
||||
const router = useRouter()
|
||||
const store = useStore()
|
||||
|
||||
|
||||
/* @setup */
|
||||
|
||||
/* @method */
|
||||
const onClickCancel = () =>{
|
||||
emits('cancel')
|
||||
}
|
||||
const onClickSave = () =>{
|
||||
emits('delete')
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang='scss' scoped>
|
||||
.fixed-model{
|
||||
position: fixed;
|
||||
left: 0;
|
||||
top: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: rgba(60,60,67,0.6);
|
||||
.model{
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
top: 50%;
|
||||
transform: translateX(-50%) translateY(-65%) ;
|
||||
width: 8.1867rem /* 614/75 */;
|
||||
// height: 394px;
|
||||
background: #FFFFFF;
|
||||
border-radius: .5333rem /* 40/75 */;
|
||||
padding: .48rem /* 36/75 */ 0 .7733rem /* 58/75 */;
|
||||
box-sizing: border-box;
|
||||
h3{
|
||||
line-height: .6667rem /* 50/75 */;
|
||||
font-size: .4533rem /* 34/75 */;
|
||||
font-family: Source Han Sans CN, Source Han Sans CN;
|
||||
font-weight: 500;
|
||||
text-align: center;
|
||||
color: #222222;
|
||||
}
|
||||
p{
|
||||
line-height: .5867rem /* 44/75 */;
|
||||
font-size: $size30;
|
||||
font-family: Source Han Sans CN, Source Han Sans CN;
|
||||
font-weight: 400;
|
||||
color: #5F6583;
|
||||
margin: .6933rem /* 52/75 */ 0 .9867rem /* 74/75 */;
|
||||
text-align: center;
|
||||
}
|
||||
.button-box{
|
||||
// margin-top: 1.1467rem /* 86/75 */;
|
||||
display: flex;
|
||||
padding: 0 .7733rem /* 58/75 */;
|
||||
box-sizing: border-box;
|
||||
div{
|
||||
// width: 240px;
|
||||
flex: 1;
|
||||
height: 1.0667rem /* 80/75 */;
|
||||
line-height: 1.0667rem /* 80/75 */;
|
||||
background: #FF6643;
|
||||
border-radius: 1.3333rem /* 100/75 */;
|
||||
text-align: center;
|
||||
font-size: $md-size;
|
||||
color: #FFFFFF;
|
||||
}
|
||||
.cancel-button{
|
||||
margin-right: .2667rem /* 20/75 */;
|
||||
background: #D9D9D9;
|
||||
color: #999999;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,84 @@
|
||||
<template>
|
||||
<div class='success-model-fixed'>
|
||||
<div class="success-model">
|
||||
<img src="../assets/chenggong.png" alt="">
|
||||
<div class="title">保存成功</div>
|
||||
<p>请在手机相册查看访客邀约海报</p>
|
||||
<button class="affirm-button">确定</button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref } from 'vue'
|
||||
import { useRouter } from 'vue-router'
|
||||
import { useStore } from 'vuex'
|
||||
import { rulesForm, resetForm, rulesPhone } from '@/com/index'
|
||||
/* @data */
|
||||
const router = useRouter()
|
||||
const store = useStore()
|
||||
|
||||
/* @setup */
|
||||
|
||||
/* @method */
|
||||
|
||||
</script>
|
||||
|
||||
<style lang='scss' scoped>
|
||||
.success-model-fixed{
|
||||
position: fixed;
|
||||
left: 0;
|
||||
top: 0;
|
||||
width: 100vw;
|
||||
height: 100vh;
|
||||
background: rgba(60,60,67,0.6);
|
||||
.success-model{
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
top: 24%;
|
||||
transform: translateX(-50%);
|
||||
width: 7.1467rem /* 536/75 */;
|
||||
height: 7.6267rem /* 572/75 */;
|
||||
padding: .56rem /* 42/75 */ .9333rem /* 70/75 */;
|
||||
box-sizing: border-box;
|
||||
background: #FFFFFF;
|
||||
border-radius: .2667rem /* 20/75 */ .2667rem /* 20/75 */ .2667rem /* 20/75 */ .2667rem /* 20/75 */;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
img{
|
||||
width: 2.6667rem /* 200/75 */;
|
||||
height: 2.6667rem;
|
||||
}
|
||||
.title{
|
||||
text-align: center;
|
||||
font-size: $md-size;
|
||||
font-family: Source Han Sans CN, Source Han Sans CN;
|
||||
font-weight: 500;
|
||||
color: #222222;
|
||||
line-height: .56rem /* 42/75 */;
|
||||
margin: .3467rem /* 26/75 */ auto .4533rem /* 34/75 */;
|
||||
}
|
||||
p{
|
||||
// width: 5.2rem /* 390/75 */;
|
||||
font-size: $sm-size;
|
||||
font-family: Source Han Sans CN, Source Han Sans CN;
|
||||
font-weight: 400;
|
||||
color: #999999;
|
||||
line-height: .48rem /* 36/75 */;
|
||||
}
|
||||
.affirm-button{
|
||||
width: 2.24rem /* 168/75 */;
|
||||
height: .9867rem /* 74/75 */;
|
||||
background: #30BF78;
|
||||
border-radius: .1333rem /* 10/75 */ ;
|
||||
outline: none;
|
||||
border: none;
|
||||
font-size: $size30;
|
||||
color: #FFFFFF;
|
||||
margin-top: 1.04rem /* 78/75 */;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,84 @@
|
||||
<template>
|
||||
<div class='success-model-fixed'>
|
||||
<div class="success-model">
|
||||
<img src="../assets/chenggong.png" alt="">
|
||||
<div class="title">保存成功</div>
|
||||
<p>请在手机相册查看访客邀约海报</p>
|
||||
<button class="affirm-button">确定</button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref } from 'vue'
|
||||
import { useRouter } from 'vue-router'
|
||||
import { useStore } from 'vuex'
|
||||
import { rulesForm, resetForm, rulesPhone } from '@/com/index'
|
||||
/* @data */
|
||||
const router = useRouter()
|
||||
const store = useStore()
|
||||
|
||||
/* @setup */
|
||||
|
||||
/* @method */
|
||||
|
||||
</script>
|
||||
|
||||
<style lang='scss' scoped>
|
||||
.success-model-fixed{
|
||||
position: fixed;
|
||||
left: 0;
|
||||
top: 0;
|
||||
width: 100vw;
|
||||
height: 100vh;
|
||||
background: rgba(60,60,67,0.6);
|
||||
.success-model{
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
top: 24%;
|
||||
transform: translateX(-50%);
|
||||
width: 7.1467rem /* 536/75 */;
|
||||
height: 7.6267rem /* 572/75 */;
|
||||
padding: .56rem /* 42/75 */ .9333rem /* 70/75 */;
|
||||
box-sizing: border-box;
|
||||
background: #FFFFFF;
|
||||
border-radius: .2667rem /* 20/75 */ .2667rem /* 20/75 */ .2667rem /* 20/75 */ .2667rem /* 20/75 */;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
img{
|
||||
width: 2.6667rem /* 200/75 */;
|
||||
height: 2.6667rem;
|
||||
}
|
||||
.title{
|
||||
text-align: center;
|
||||
font-size: $md-size;
|
||||
font-family: Source Han Sans CN, Source Han Sans CN;
|
||||
font-weight: 500;
|
||||
color: #222222;
|
||||
line-height: .56rem /* 42/75 */;
|
||||
margin: .3467rem /* 26/75 */ auto .4533rem /* 34/75 */;
|
||||
}
|
||||
p{
|
||||
// width: 5.2rem /* 390/75 */;
|
||||
font-size: $sm-size;
|
||||
font-family: Source Han Sans CN, Source Han Sans CN;
|
||||
font-weight: 400;
|
||||
color: #999999;
|
||||
line-height: .48rem /* 36/75 */;
|
||||
}
|
||||
.affirm-button{
|
||||
width: 2.24rem /* 168/75 */;
|
||||
height: .9867rem /* 74/75 */;
|
||||
background: #30BF78;
|
||||
border-radius: .1333rem /* 10/75 */ ;
|
||||
outline: none;
|
||||
border: none;
|
||||
font-size: $size30;
|
||||
color: #FFFFFF;
|
||||
margin-top: 1.04rem /* 78/75 */;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,127 @@
|
||||
<!-- label 为字段名 -->
|
||||
<!-- isMust 为是否存在* 默认无 -->
|
||||
<template>
|
||||
<div class="select-box" :class=" isline ? 'select-active' : ''">
|
||||
<div class="label"><span v-if="props.isMust">* </span>{{ props.label }} </div>
|
||||
<div class="select-button">
|
||||
<span v-if="date" style="color: #333333;">{{ date }}</span>
|
||||
<span v-else>请选择{{ props.label }}</span>
|
||||
<input @change="onConfirm" class="date" type="datetime-local" v-model="date" :min="minDate" >
|
||||
</div>
|
||||
<!-- <img src="../../assets/employment/youjiantou.png" alt=""> -->
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { useRouter } from 'vue-router'
|
||||
import { ref, watch } from 'vue'
|
||||
import { formatDate } from '../com/index.js'
|
||||
|
||||
/* props */
|
||||
const props = defineProps({
|
||||
isMust:{
|
||||
default: false
|
||||
},
|
||||
label:{
|
||||
default: ''
|
||||
},
|
||||
modelValue:{
|
||||
},
|
||||
isline: {
|
||||
default: false,
|
||||
},
|
||||
minDate: {
|
||||
default: '2023-01-01 08:00:00'
|
||||
}
|
||||
})
|
||||
/* emits */
|
||||
const emits = defineEmits(['update:modelValue'])
|
||||
|
||||
|
||||
/* @data */
|
||||
let date = ref(props.modelValue)
|
||||
const router = useRouter()
|
||||
/* watch */
|
||||
// 因为props.modelValue是非引用类型,改变时,需要监听,对sea重新赋值
|
||||
watch(() => props.modelValue, () => {
|
||||
if(props.modelValue == null){
|
||||
date.value = ''
|
||||
}else{
|
||||
date.value = props.modelValue
|
||||
}
|
||||
})
|
||||
/* @setup */
|
||||
// console.log(props.modelValue)
|
||||
|
||||
|
||||
/* @method */
|
||||
const onConfirm = () => {
|
||||
// console.log(date.value)
|
||||
date.value = formatDate(date.value, '-')
|
||||
emits('update:modelValue', date.value)
|
||||
console.log(date.value)
|
||||
};
|
||||
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
<style lang='scss' scoped>
|
||||
.select-box{
|
||||
position: relative;
|
||||
width: 9.2rem /* 690/75 */;
|
||||
width: 100%;
|
||||
height: 1.5733rem /* 118/75 */;
|
||||
// background: #F9F9F9;
|
||||
// border-radius: .2667rem /* 20/75 */;
|
||||
padding: 0 .0267rem /* 2/75 */ 0;
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
margin-bottom: .2667rem /* 20/75 */;
|
||||
.label{
|
||||
flex: 1;
|
||||
font-size: $size26;
|
||||
color: #333333;
|
||||
line-height: 1.5733rem /* 118/75 */;
|
||||
span{
|
||||
color: #FF0000;
|
||||
margin-right: .0267rem /* 2/75 */;
|
||||
|
||||
}
|
||||
}
|
||||
.select-button{
|
||||
position: relative;
|
||||
width: 5.2rem /* 390/75 */;
|
||||
text-align: right;
|
||||
font-size: $size26;
|
||||
color: #999999;
|
||||
line-height: 1.5733rem /* 118/75 */;
|
||||
padding-right: .3733rem /* 28/75 */;
|
||||
box-sizing: border-box;
|
||||
overflow: hidden;
|
||||
.date{
|
||||
position: absolute;
|
||||
right: 0;
|
||||
top: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
.active{
|
||||
color: #333333;
|
||||
}
|
||||
img{
|
||||
position: absolute;
|
||||
right: .4rem /* 30/75 */;
|
||||
top: 50%;
|
||||
width: .1467rem /* 11/75 */;
|
||||
height: .2667rem /* 20/75 */;
|
||||
margin-top: -.16rem /* 12/75 */;
|
||||
}
|
||||
}
|
||||
.select-active{
|
||||
border-bottom: .0267rem /* 2/75 */ dashed #D9D9D9;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,163 @@
|
||||
<!-- label 为字段名 -->
|
||||
<!-- isMust 为是否存在* 默认无 -->
|
||||
<!-- isline 是否有下虚线 -->
|
||||
<template>
|
||||
<div class="select-box" :class=" isline ? 'select-active' : ''">
|
||||
<div class="label"> <span v-if="props.isMust">* </span>{{ props.label }}</div>
|
||||
<div class="select-button" @click="showPicker = true">
|
||||
<span v-if="selectVal" style="color: #333333;">{{ selectVal }}</span>
|
||||
<span v-else>请选择{{ props.label }}</span>
|
||||
</div>
|
||||
<!-- <div class="select-line"></div> -->
|
||||
<!-- <img src="../../assets/employment/youjiantou.png" alt=""> -->
|
||||
<Popup v-model:show="showPicker" round position="bottom">
|
||||
<!-- title="标题" -->
|
||||
<Picker
|
||||
:columns="props.columns"
|
||||
:columns-field-names="customFieldName"
|
||||
:default-index="defaultIndex"
|
||||
@confirm="onConfirm"
|
||||
@cancel="showPicker = false"
|
||||
/>
|
||||
</Popup>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { useRouter } from 'vue-router'
|
||||
import { ref, watch } from 'vue'
|
||||
import { Picker, Popup } from 'vant';
|
||||
|
||||
/* props */
|
||||
const props = defineProps({
|
||||
isMust:{
|
||||
default: false
|
||||
},
|
||||
label:{
|
||||
default: ''
|
||||
},
|
||||
isline: {
|
||||
default: false,
|
||||
},
|
||||
columns:{
|
||||
default: []
|
||||
},
|
||||
modelValue: {
|
||||
},
|
||||
name: {
|
||||
default: 'title'
|
||||
},
|
||||
nameId: {
|
||||
default: 'id'
|
||||
}
|
||||
})
|
||||
/* emits */
|
||||
const emits = defineEmits(['update:modelValue'])
|
||||
|
||||
/* @data */
|
||||
const customFieldName = {
|
||||
text: props.name,
|
||||
children: 'cities',
|
||||
};
|
||||
let selectVal = ref('')
|
||||
const router = useRouter()
|
||||
let showPicker = ref(false)
|
||||
let defaultIndex = ref(0)
|
||||
|
||||
/* @setup */
|
||||
|
||||
/* watch */
|
||||
// 因为props.modelValue是非引用类型,改变时,需要监听,对sea重新赋值
|
||||
watch(() => props.modelValue, () => {
|
||||
if(props.modelValue == null){
|
||||
// console.log('props.modelValue')
|
||||
// console.log(props.modelValue)
|
||||
selectVal.value = ''
|
||||
}
|
||||
})
|
||||
// 根据数据赋值
|
||||
watch(() => props.columns, () => {
|
||||
if(props.modelValue != undefined || props.modelValue != null){
|
||||
props.columns.forEach(( item ,index ) => {
|
||||
// console.log('知悉了'+ item[props.name] + item[props.nameId])
|
||||
if(item[props.nameId] == props.modelValue){
|
||||
selectVal.value = item[props.name]
|
||||
defaultIndex.value = index
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
/* @method */
|
||||
|
||||
const onConfirm = (value , index) => {
|
||||
let str = ''
|
||||
let ids = []
|
||||
if(value.length){
|
||||
value.forEach((item) => {
|
||||
str = str + item[props.name]
|
||||
ids.push(item[props.nameId])
|
||||
});
|
||||
|
||||
}else{
|
||||
str = value[props.name]
|
||||
ids = value[props.nameId]
|
||||
}
|
||||
selectVal.value = str
|
||||
emits('update:modelValue', ids)
|
||||
showPicker.value = false
|
||||
};
|
||||
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
<style lang='scss' scoped>
|
||||
.select-box{
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 1.5733rem /* 118/75 */;
|
||||
// background: #F9F9F9;
|
||||
// border-radius: .2667rem /* 20/75 */;
|
||||
padding: 0 .0267rem /* 2/75 */ 0;
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
// margin-bottom: .2667rem /* 20/75 */;
|
||||
|
||||
.label{
|
||||
flex: 1;
|
||||
font-size: $size26;
|
||||
color: #333333;
|
||||
line-height: 1.5733rem /* 118/75 */;
|
||||
span{
|
||||
color: #FF0000;
|
||||
margin-right: .0267rem /* 2/75 */;
|
||||
}
|
||||
}
|
||||
.select-button{
|
||||
width: 4.8rem /* 360/75 */;
|
||||
text-align: right;
|
||||
font-size: $size26;
|
||||
color: #999999;
|
||||
line-height: 1.5733rem /* 118/75 */;
|
||||
padding-right: .3733rem /* 28/75 */;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
.active{
|
||||
color: #333333;
|
||||
}
|
||||
img{
|
||||
position: absolute;
|
||||
right: .4rem /* 30/75 */;
|
||||
top: 50%;
|
||||
width: .1467rem /* 11/75 */;
|
||||
height: .2667rem /* 20/75 */;
|
||||
margin-top: -.16rem /* 12/75 */;
|
||||
}
|
||||
}
|
||||
.select-active{
|
||||
border-bottom: .0267rem /* 2/75 */ dashed #D9D9D9;
|
||||
}
|
||||
|
||||
</style>
|
||||
@@ -0,0 +1,88 @@
|
||||
<template>
|
||||
<div class='success-model-fixed'>
|
||||
<div class="success-model">
|
||||
<img src="../assets/chenggong.png" alt="">
|
||||
<div class="title">登记成功,等待审核</div>
|
||||
<p>请在预约记录里面输入联系方式查看审核进度及结果反馈</p>
|
||||
<button @click="onClickAffirm" class="affirm-button">确定</button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref } from 'vue'
|
||||
import { useRouter } from 'vue-router'
|
||||
import { useStore } from 'vuex'
|
||||
import { rulesForm, resetForm, rulesPhone } from '@/com/index'
|
||||
/* @data */
|
||||
const router = useRouter()
|
||||
const store = useStore()
|
||||
const emits = defineEmits(['click'])
|
||||
|
||||
/* @setup */
|
||||
|
||||
/* @method */
|
||||
const onClickAffirm = () =>{
|
||||
emits('click')
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang='scss' scoped>
|
||||
.success-model-fixed{
|
||||
position: fixed;
|
||||
left: 0;
|
||||
top: 0;
|
||||
width: 100vw;
|
||||
height: 100vh;
|
||||
background: rgba(60,60,67,0.6);
|
||||
.success-model{
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
top: 24%;
|
||||
transform: translateX(-50%);
|
||||
width: 7.1467rem /* 536/75 */;
|
||||
height: 7.6267rem /* 572/75 */;
|
||||
padding: .56rem /* 42/75 */ .9333rem /* 70/75 */;
|
||||
box-sizing: border-box;
|
||||
background: #FFFFFF;
|
||||
border-radius: .2667rem /* 20/75 */ .2667rem /* 20/75 */ .2667rem /* 20/75 */ .2667rem /* 20/75 */;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
img{
|
||||
width: 2.6667rem /* 200/75 */;
|
||||
height: 2.6667rem;
|
||||
}
|
||||
.title{
|
||||
text-align: center;
|
||||
font-size: $md-size;
|
||||
font-family: Source Han Sans CN, Source Han Sans CN;
|
||||
font-weight: 500;
|
||||
color: #222222;
|
||||
line-height: .56rem /* 42/75 */;
|
||||
margin: .3467rem /* 26/75 */ auto .4533rem /* 34/75 */;
|
||||
}
|
||||
p{
|
||||
// width: 5.2rem /* 390/75 */;
|
||||
font-size: $sm-size;
|
||||
font-family: Source Han Sans CN, Source Han Sans CN;
|
||||
font-weight: 400;
|
||||
color: #999999;
|
||||
line-height: .48rem /* 36/75 */;
|
||||
text-align: center;
|
||||
}
|
||||
.affirm-button{
|
||||
width: 2.24rem /* 168/75 */;
|
||||
height: .9867rem /* 74/75 */;
|
||||
background: #30BF78;
|
||||
border-radius: .1333rem /* 10/75 */ ;
|
||||
outline: none;
|
||||
border: none;
|
||||
font-size: $size30;
|
||||
color: #FFFFFF;
|
||||
margin-top: .56rem /* 42/75 */;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,9 @@
|
||||
import { createApp } from 'vue'
|
||||
import router from './router'
|
||||
import store from './store'
|
||||
|
||||
import App from './App.vue'
|
||||
const app = createApp(App)
|
||||
|
||||
app.use(router).use(store).mount('#app')
|
||||
|
||||
@@ -0,0 +1,110 @@
|
||||
import { createRouter, createWebHistory } from 'vue-router'
|
||||
import register from "../views/register.vue";
|
||||
|
||||
const routerHistory = createWebHistory()
|
||||
|
||||
const routes = [
|
||||
{
|
||||
path: '/login',
|
||||
name:'login',
|
||||
// redirect: '/login',
|
||||
component: () => import('../views/login.vue')
|
||||
},
|
||||
{
|
||||
path: '/visitorApply',
|
||||
name:'visitorApply',
|
||||
// redirect: '/login',
|
||||
component: () => import('../views/visitorApply.vue'),
|
||||
meta: { title: '我要预约' }
|
||||
},
|
||||
{
|
||||
path: '/applyInquire',
|
||||
name:'applyInquire',
|
||||
component: () => import('../views/applyInquire.vue'),
|
||||
meta: { title: '预约查询' }
|
||||
},
|
||||
{
|
||||
path: '/applyRecord',
|
||||
name:'applyRecord',
|
||||
// redirect: '/login',
|
||||
component: () => import('../views/applyRecord.vue'),
|
||||
meta: { title: '预约记录' }
|
||||
},
|
||||
|
||||
{
|
||||
path: '/apply',
|
||||
name:'apply',
|
||||
// redirect: '/login',
|
||||
component: () => import('../views/apply.vue'),
|
||||
meta: { title: '我要预约' }
|
||||
},
|
||||
{
|
||||
path: '/adminHome',
|
||||
name:'adminHome',
|
||||
// redirect: '/login',
|
||||
component: () => import('../views/adminHome.vue'),
|
||||
meta: { title: '智能访客' }
|
||||
},
|
||||
{
|
||||
path: '/visitorRecord',
|
||||
name:'visitorRecord',
|
||||
// redirect: '/login',
|
||||
component: () => import('../views/visitorRecord.vue'),
|
||||
meta: { title: '访客记录' }
|
||||
},
|
||||
{
|
||||
path: '/Invitation',
|
||||
name:'Invitation',
|
||||
// redirect: '/login',
|
||||
component: () => import('../views/Invitation.vue'),
|
||||
meta: { title: '我要邀约' }
|
||||
},
|
||||
{
|
||||
path: '/userHome',
|
||||
name:'userHome',
|
||||
// redirect: '/login',
|
||||
component: () => import('../views/userHome.vue'),
|
||||
meta: { title: '智能访客' }
|
||||
},
|
||||
|
||||
{
|
||||
path: '/register',
|
||||
name:'register',
|
||||
component: register
|
||||
},
|
||||
{
|
||||
path: '/home',
|
||||
name:'home',
|
||||
// redirect: '/login',
|
||||
component: () => import('../views/home.vue'),
|
||||
meta: { title: '员工信息' }
|
||||
|
||||
},
|
||||
{
|
||||
path: '/specialCrowd',
|
||||
name:'specialCrowd',
|
||||
// redirect: '/login',
|
||||
component: () => import('../views/specialCrowd.vue'),
|
||||
meta: { title: '特殊人员录入' }
|
||||
},
|
||||
{
|
||||
path:'/',
|
||||
name:'',
|
||||
component:()=>import('../views/userHome.vue'),
|
||||
meta: { title: '智能访客' }
|
||||
|
||||
},
|
||||
{ path: '/:pathMatch(.*)',
|
||||
redirect: '/userHome',
|
||||
}
|
||||
]
|
||||
const router = createRouter({
|
||||
history: routerHistory,
|
||||
routes
|
||||
})
|
||||
const title = document.querySelector('title')
|
||||
router.beforeEach((to, from, next) => {
|
||||
title.innerText = to.meta.title
|
||||
next()
|
||||
})
|
||||
export default router
|
||||
@@ -0,0 +1,42 @@
|
||||
import { createStore } from 'vuex'
|
||||
|
||||
|
||||
const store = createStore({
|
||||
state: {
|
||||
name: '访客预约系统',
|
||||
stateEnum: {
|
||||
0: {
|
||||
statusName:'待审核',
|
||||
className: 'status',
|
||||
statusText: '您的来访预约还未审核,请耐心等待',
|
||||
status: 0
|
||||
},
|
||||
1: {
|
||||
statusName: '已通过',
|
||||
className: 'pass',
|
||||
statusText: '预约审核通过',
|
||||
status: 1
|
||||
|
||||
},
|
||||
2: {
|
||||
statusName:'未通过',
|
||||
className: 'refuse',
|
||||
statusText: '预约审核已拒绝',
|
||||
status: 2
|
||||
}
|
||||
}
|
||||
},
|
||||
getters: {
|
||||
|
||||
},
|
||||
mutations: {
|
||||
|
||||
},
|
||||
actions: {
|
||||
|
||||
},
|
||||
modules: {
|
||||
}
|
||||
})
|
||||
|
||||
export default store
|
||||
@@ -0,0 +1,310 @@
|
||||
<template>
|
||||
<div class='invitation-model-fixed' id="canvas">
|
||||
<div class="invitation-model">
|
||||
<img class="english-title" src="../assets/yinwen.png" alt="">
|
||||
<div class="ewm-box">
|
||||
<!-- <img :src=" 'data:image/png;base64,'+imgEncode" alt=""> -->
|
||||
<img src="https://www.baidu.com/s?wd=%E7%99%BE%E5%BA%A6%E7%83%AD%E6%90%9C&sa=ire_dl_gh_logo_texing&rsv_dl=igh_logo_pcs" alt="">
|
||||
|
||||
<b class="ewm-box-one"></b>
|
||||
<b class="ewm-box-two"></b>
|
||||
<b class="ewm-box-three"></b>
|
||||
<b class="ewm-box-four"></b>
|
||||
</div>
|
||||
<div class="tips">快来保存您的专属邀约二维码吧</div>
|
||||
<button @click="onClickDown" class="save-button">保存图片</button>
|
||||
<span @click="onClickA" :href="canvasUrl" download="下载">下载</span>
|
||||
</div>
|
||||
<!-- {{ raw }} -->
|
||||
</div>
|
||||
<Savesuccessmodel v-if="false" />
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref } from 'vue'
|
||||
import { useRouter } from 'vue-router'
|
||||
import { useStore } from 'vuex'
|
||||
import { rulesForm, resetForm, rulesPhone } from '@/com/index'
|
||||
import dd from 'dingtalk-jsapi'
|
||||
import html2canvas from 'html2canvas'
|
||||
import Savesuccessmodel from '@/components/save-success.vue'
|
||||
import { getToken, getVisitorRecord, getWhiteCode } from '@/api/admin.js'
|
||||
|
||||
|
||||
/* @data */
|
||||
const router = useRouter()
|
||||
const store = useStore()
|
||||
const imgEncode = ref('')
|
||||
const raw = ref('')
|
||||
const canvasUrl = ref('')
|
||||
|
||||
/* @setup */
|
||||
getWhiteCode().then(res =>{
|
||||
console.log(res)
|
||||
imgEncode.value = res.imgEncode
|
||||
// raw.value = window.atob(res.imgEncode);
|
||||
|
||||
})
|
||||
/* @method */
|
||||
const onClickDown1 = () =>{
|
||||
// const byteCharacters = atob(imgEncode.value);
|
||||
// const byteNumbers = new Array(byteCharacters.length);
|
||||
// for (let i = 0; i < byteCharacters.length; i++) {
|
||||
// byteNumbers[i] = byteCharacters.charCodeAt(i);
|
||||
// }
|
||||
// const byteArray = new Uint8Array(byteNumbers);
|
||||
// const blob = new Blob([byteArray], { type: 'image/jpeg' });
|
||||
// raw.value = byteArray
|
||||
// // 创建可下载链接
|
||||
// const url = URL.createObjectURL(blob);
|
||||
|
||||
// // 创建隐藏的<a>标签
|
||||
// const link = document.createElement('a');
|
||||
// link.href = url;
|
||||
// link.download = 'fileName';
|
||||
|
||||
// // 模拟点击隐藏的<a>标签来触发下载
|
||||
// link.click();
|
||||
|
||||
// // 清理URL对象
|
||||
// URL.revokeObjectURL(url);
|
||||
}
|
||||
const onClickA =() =>{
|
||||
const canvas = document.getElementById('canvas')
|
||||
console.log(canvas.offsetHeight)
|
||||
console.log(canvas.scrollHeight)
|
||||
// alert('asjfjafj1')
|
||||
// // window.location.href = canvasUrl.value
|
||||
// dd.previewImage({
|
||||
// urls: [
|
||||
// canvasUrl.value,
|
||||
// ],
|
||||
// current: 1,
|
||||
// success: () => {},
|
||||
// fail: () => {},
|
||||
// complete: () => {},
|
||||
// });
|
||||
// dd.openLink({
|
||||
// url: 'https://www.baidu.com/img/PCtm_d9c8750bed0b3c7d089fa7d55720d6cf.png',
|
||||
// success: () => {},
|
||||
// fail: () => {},
|
||||
// complete: () => {},
|
||||
// });
|
||||
// dd.saveImage({
|
||||
// url: 'https://img.alicdn.com/tps/TB1sXGYIFXXXXc5XpXXXXXXXXXX.jpg',
|
||||
// success: () => {},
|
||||
// fail: () => {},
|
||||
// complete: () => {},
|
||||
// });
|
||||
}
|
||||
const onClickDown = () =>{
|
||||
let options = { scale: 1, allowTaint: false, useCORS: true, width: '375', height: '649', backgroundColor: null }
|
||||
autoPicture('canvas')
|
||||
}
|
||||
const autoPicture = async (el, options) => {
|
||||
// let { scale = 1, allowTaint = false, useCORS = true, width = '375', height = '649', backgroundColor = null } = options
|
||||
const id = document.getElementById(el)
|
||||
const canvas = await html2canvas(id, {
|
||||
scale: 1, //缩放比例,默认为1
|
||||
allowTaint: false, //是否允许跨域图像污染画布
|
||||
useCORS: true, //是否尝试使用CORS从服务器加载图像
|
||||
width: id.offsetWidth, //画布的宽度
|
||||
height: id.offsetHeight, //画布的高度
|
||||
backgroundColor: null //画布的背景色,默认为透明
|
||||
})
|
||||
// canvas.toDataURL('image/png')
|
||||
console.log(canvas.toDataURL('image/png'))
|
||||
canvasUrl.value = canvas.toDataURL('image/png')
|
||||
|
||||
}
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
<style lang='scss' scoped>
|
||||
.invitation-model-fixed{
|
||||
position: fixed;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: rgba(60,60,67,0.6);
|
||||
.invitation-model{
|
||||
position: absolute;
|
||||
top: 20%;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
width: 7.2267rem /* 542/75 */;
|
||||
height: 9.3067rem /* 698/75 */;
|
||||
background: #FFFFFF;
|
||||
border-radius: .5333rem /* 40/75 */.5333rem /* 40/75 */ .5333rem /* 40/75 */ .5333rem /* 40/75 */;
|
||||
// overflow: hidden;
|
||||
opacity: 1;
|
||||
background: url('../assets/yaoqingbeijing.png') left top/100% 100% no-repeat;
|
||||
|
||||
.english-title{
|
||||
margin: 1.1733rem /* 88/75 */ auto 0;
|
||||
width: 4.9867rem /* 374/75 */;
|
||||
height: .6133rem /* 46/75 */;
|
||||
}
|
||||
.ewm-box{
|
||||
position: relative;
|
||||
border-radius: .1333rem /* 10/75 */;
|
||||
// border: .1333rem /* 10/75 */ solid #30BF78;
|
||||
width: 4.64rem /* 348/75 */;
|
||||
height: 4.64rem /* 348/75 */;
|
||||
margin: .5067rem /* 38/75 */ auto 0;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
img{
|
||||
width: 4rem /* 300/75 */;
|
||||
height: 4rem;
|
||||
}
|
||||
}
|
||||
@mixin border-basics {
|
||||
position: absolute;
|
||||
width: 1.1733rem /* 88/75 */;
|
||||
height: 1.1733rem /* 88/75 */;
|
||||
// border-radius: .1333rem /* 10/75 */;
|
||||
opacity: 1;
|
||||
border: .1333rem /* 10/75 */ solid #30BF78;
|
||||
}
|
||||
.ewm-box-one::after{
|
||||
content: '';
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
// border: .1333rem /* 10/75 */ solid #30BF78;
|
||||
width: .1333rem /* 10/75 */;
|
||||
height: 1.3067rem /* 98/75 */;
|
||||
background-color: #30BF78;
|
||||
border-radius: .2667rem /* 20/75 */ 0 .1333rem /* 10/75 */ .1333rem /* 10/75 */;
|
||||
}
|
||||
.ewm-box-one::before{
|
||||
content: '';
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
// border: .1333rem /* 10/75 */ solid #30BF78;
|
||||
width: 1.3067rem /* 98/75 */;
|
||||
height: .1333rem /* 10/75 */;
|
||||
background-color: #30BF78;
|
||||
border-radius: .2667rem /* 20/75 */ .1333rem /* 10/75 */ .1333rem /* 10/75 */ 0 ;
|
||||
}
|
||||
.ewm-box-two::after{
|
||||
content: '';
|
||||
position: absolute;
|
||||
right: 0;
|
||||
top: 0;
|
||||
// border: .1333rem /* 10/75 */ solid #30BF78;
|
||||
width: .1333rem /* 10/75 */;
|
||||
height: 1.3067rem /* 98/75 */;
|
||||
background-color: #30BF78;
|
||||
border-radius: 0 .2667rem /* 20/75 */ .1333rem /* 10/75 */ .1333rem /* 10/75 */;
|
||||
}
|
||||
.ewm-box-two::before{
|
||||
content: '';
|
||||
position: absolute;
|
||||
right: 0;
|
||||
top: 0;
|
||||
// border: .1333rem /* 10/75 */ solid #30BF78;
|
||||
width: 1.3067rem /* 98/75 */;
|
||||
height: .1333rem /* 10/75 */;
|
||||
background-color: #30BF78;
|
||||
border-radius: .1333rem /* 10/75 */ .2667rem /* 20/75 */ 0 .1333rem /* 10/75 */ ;
|
||||
}
|
||||
// .ewm-box-three{
|
||||
// @include border-basics;
|
||||
// left: 0;
|
||||
// bottom: 0;
|
||||
// border-top: none;
|
||||
// border-right: none;
|
||||
// border-radius: 0 0 0 .1333rem /* 10/75 */ ;
|
||||
|
||||
// }
|
||||
.ewm-box-three::after{
|
||||
content: '';
|
||||
position: absolute;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
// border: .1333rem /* 10/75 */ solid #30BF78;
|
||||
width: .1333rem /* 10/75 */;
|
||||
height: 1.3067rem /* 98/75 */;
|
||||
background-color: #30BF78;
|
||||
border-radius: .1333rem /* 10/75 */ .1333rem /* 10/75 */ 0 .2667rem /* 20/75 */ ;
|
||||
}
|
||||
.ewm-box-three::before{
|
||||
content: '';
|
||||
position: absolute;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
// border: .1333rem /* 10/75 */ solid #30BF78;
|
||||
width: 1.3067rem /* 98/75 */;
|
||||
height: .1333rem /* 10/75 */;
|
||||
background-color: #30BF78;
|
||||
border-radius: 0 .1333rem /* 10/75 */ .1333rem /* 10/75 */ .2667rem /* 20/75 */ ;
|
||||
}
|
||||
// .ewm-box-four{
|
||||
// @include border-basics;
|
||||
// bottom: 0;
|
||||
// right: 0;
|
||||
// border-top: none;
|
||||
// border-left: none;
|
||||
// border-radius: 0 0 .1333rem /* 10/75 */ 0;
|
||||
|
||||
// }
|
||||
.ewm-box-four::after{
|
||||
content: '';
|
||||
position: absolute;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
// border: .1333rem /* 10/75 */ solid #30BF78;
|
||||
width: .1333rem /* 10/75 */;
|
||||
height: 1.3067rem /* 98/75 */;
|
||||
background-color: #30BF78;
|
||||
border-radius: .1333rem /* 10/75 */ .1333rem /* 10/75 */ .2667rem /* 20/75 */ 0 ;
|
||||
}
|
||||
.ewm-box-four::before{
|
||||
content: '';
|
||||
position: absolute;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
// border: .1333rem /* 10/75 */ solid #30BF78;
|
||||
width: 1.3067rem /* 98/75 */;
|
||||
height: .1333rem /* 10/75 */;
|
||||
background-color: #30BF78;
|
||||
border-radius: .1333rem /* 10/75 */ 0 .2667rem /* 20/75 */ .1333rem /* 10/75 */ ;
|
||||
}
|
||||
.tips{
|
||||
font-size: $size30;
|
||||
font-family: Source Han Sans CN, Source Han Sans CN;
|
||||
font-weight: 400;
|
||||
color: #999999;
|
||||
margin-top: .72rem /* 54/75 */;
|
||||
text-align: center;
|
||||
line-height: .6133rem /* 46/75 */;
|
||||
}
|
||||
|
||||
.save-button{
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
left: 50%;
|
||||
z-index: 10;
|
||||
transform: translateY(50% ) translateX(-50% );
|
||||
width: 3.76rem /* 282/75 */;
|
||||
height: 1.1467rem /* 86/75 */;
|
||||
line-height: 1.1467rem /* 86/75 */;
|
||||
background: #30BF78;
|
||||
border-radius: 1.3333rem /* 100/75 */;
|
||||
opacity: 1;
|
||||
font-size: $lg-size;
|
||||
font-family: Source Han Sans CN, Source Han Sans CN;
|
||||
font-weight: 400;
|
||||
color: #FFFFFF;
|
||||
text-align: center;
|
||||
border: none;
|
||||
outline: none;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,143 @@
|
||||
<template>
|
||||
<div v-if="!canvasUrl" class='invitation-model-fixed' id="canvas">
|
||||
<img src="../assets/yaoqingbeijingtu.png" alt="" class="big-img">
|
||||
<img class="ewm" :src="'data:image/png;base64,'+imgEncode" alt="">
|
||||
<!-- <img src="" alt=""> -->
|
||||
</div>
|
||||
<div v-if="canvasUrl" class="img-fixed">
|
||||
<img :src="canvasUrl" alt="">
|
||||
</div>
|
||||
|
||||
<!-- <img src="" alt=""> -->
|
||||
<Savesuccessmodel v-if="false" />
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref } from 'vue'
|
||||
import { useRouter } from 'vue-router'
|
||||
import { useStore } from 'vuex'
|
||||
import { rulesForm, resetForm, rulesPhone } from '@/com/index'
|
||||
import dd from 'dingtalk-jsapi'
|
||||
import html2canvas from 'html2canvas'
|
||||
import Savesuccessmodel from '@/components/save-success.vue'
|
||||
import { getToken, getVisitorRecord, getWhiteCode } from '@/api/admin.js'
|
||||
|
||||
|
||||
/* @data */
|
||||
const router = useRouter()
|
||||
const store = useStore()
|
||||
const imgEncode = ref('')
|
||||
const raw = ref('')
|
||||
const canvasUrl = ref('')
|
||||
|
||||
/* @setup */
|
||||
|
||||
/* @method */
|
||||
|
||||
const onClickDown1 = () =>{
|
||||
// const byteCharacters = atob(imgEncode.value);
|
||||
// const byteNumbers = new Array(byteCharacters.length);
|
||||
// for (let i = 0; i < byteCharacters.length; i++) {
|
||||
// byteNumbers[i] = byteCharacters.charCodeAt(i);
|
||||
// }
|
||||
// const byteArray = new Uint8Array(byteNumbers);
|
||||
// const blob = new Blob([byteArray], { type: 'image/jpeg' });
|
||||
// raw.value = byteArray
|
||||
// // 创建可下载链接
|
||||
// const url = URL.createObjectURL(blob);
|
||||
|
||||
// // 创建隐藏的<a>标签
|
||||
// const link = document.createElement('a');
|
||||
// link.href = url;
|
||||
// link.download = 'fileName';
|
||||
|
||||
// // 模拟点击隐藏的<a>标签来触发下载
|
||||
// link.click();
|
||||
|
||||
// // 清理URL对象
|
||||
// URL.revokeObjectURL(url);
|
||||
}
|
||||
const onClickA =() =>{
|
||||
const canvas = document.getElementById('canvas')
|
||||
console.log(canvas.offsetHeight)
|
||||
console.log(canvas.scrollHeight)
|
||||
dd.previewImage({
|
||||
urls: [
|
||||
canvasUrl.value,
|
||||
],
|
||||
current: 1,
|
||||
success: () => {},
|
||||
fail: () => {},
|
||||
complete: () => {},
|
||||
});
|
||||
|
||||
}
|
||||
const onClickDown = () =>{
|
||||
// let options = { scale: 1, allowTaint: false, useCORS: true, width: '375', height: '649', backgroundColor: null }
|
||||
autoPicture('canvas')
|
||||
}
|
||||
const autoPicture = async (el, options) => {
|
||||
// let { scale = 1, allowTaint = false, useCORS = true, width = '375', height = '649', backgroundColor = null } = options
|
||||
const id = document.getElementById(el)
|
||||
// alert(document.getElementById('canvas').offsetWidth
|
||||
const canvas = await html2canvas(id, {
|
||||
scale: 2, //缩放比例,默认为1
|
||||
allowTaint: false, //是否允许跨域图像污染画布
|
||||
useCORS: true, //是否尝试使用CORS从服务器加载图像
|
||||
// width: document.getElementById('canvas').offsetWidth, //画布的宽度
|
||||
// height: document.getElementById('canvas').offsetHeight, //画布的高度
|
||||
width: document.getElementById('canvas').offsetWidth, //画布的宽度
|
||||
height: document.getElementById('canvas').offsetHeight, //画布的高度
|
||||
backgroundColor: null //画布的背景色,默认为透明
|
||||
})
|
||||
// canvas.toDataURL('image/png')
|
||||
// console.log(canvas.toDataURL('image/png'))
|
||||
canvasUrl.value = canvas.toDataURL('image/png')
|
||||
|
||||
|
||||
}
|
||||
// localStorage.setItem('token', 123456)
|
||||
getWhiteCode().then(res =>{
|
||||
console.log(res)
|
||||
imgEncode.value = res.imgEncode
|
||||
// autoPicture(canvas)
|
||||
// raw.value = window.atob(res.imgEncode);
|
||||
setTimeout(()=>{
|
||||
onClickDown()
|
||||
}, 100)
|
||||
|
||||
})
|
||||
|
||||
</script>
|
||||
|
||||
<style lang='scss' scoped>
|
||||
.invitation-model-fixed{
|
||||
position: fixed;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
// background: url('../assets/yaoqingbeijingtu.png') left top/100% auto no-repeat;
|
||||
background: #fff;
|
||||
.big-img{
|
||||
width: 100%;
|
||||
}
|
||||
.ewm{
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
top: 4rem /* 300/75 */;
|
||||
transform: translateX(-50%);
|
||||
width:4.5333rem /* 340/75 */;
|
||||
height: 4.5333rem /* 340/75 */;
|
||||
}
|
||||
|
||||
}
|
||||
.img-fixed{
|
||||
position: fixed;
|
||||
left: 0;
|
||||
top: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
img{
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,321 @@
|
||||
<template>
|
||||
<div v-if="true" class='box'>
|
||||
<header>
|
||||
<h3>Hello~{{userName}}</h3>
|
||||
<h4>呀 你又来审批预约了啊ㄟ( ▔, ▔ )ㄏ</h4>
|
||||
<div class="plate-box">
|
||||
|
||||
<div @click="onClickGo('/Invitation')" class="plate-button">
|
||||
<img src="../assets/ren.png" alt="">
|
||||
<div class="right">
|
||||
<div>我要邀约</div>
|
||||
<p>保存专属二维码</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div @click="onClickGo('/visitorRecord')" class="plate-button">
|
||||
<img src="../assets/shuben.png" alt="">
|
||||
<div class="right">
|
||||
<div>访客记录</div>
|
||||
<p>查看历史来访记录</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="position-img">
|
||||
<img src="../assets/fangzi.png" alt="">
|
||||
</div>
|
||||
</header>
|
||||
<div class="content">
|
||||
<h2>
|
||||
<div>待审批列表</div>
|
||||
<span @click="onClickGo('/visitorRecord')">查看全部</span>
|
||||
</h2>
|
||||
<div class="content-ul">
|
||||
<div v-for="item in recordArr" class="wait-list" :key="item.id">
|
||||
<h5>被拜访人:{{ item.visitingName }}</h5>
|
||||
<h5>拜访时间:{{ item.hours }}</h5>
|
||||
<div class="apply-box">
|
||||
<p><span>访客姓名:</span><span>{{ item.name }}</span></p>
|
||||
<p><span>联系方式:</span><span>{{ item.phone }}</span></p>
|
||||
<p><span>随行人数:</span><span>{{ item.visitingNum }} </span></p>
|
||||
<p><span>来访事由:</span><span>{{ item.reason }}</span></p>
|
||||
</div>
|
||||
<div class="status" :class="stateEnum[item.status].className">{{ stateEnum[item.status].statusName }}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="isLoading && recordArr.length == 0" class="no-have">
|
||||
<img class="" src="../assets/nodata.png" alt="">
|
||||
<p>暂无待审批数据</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { reactive, ref } from 'vue'
|
||||
import { useRouter } from 'vue-router'
|
||||
import { useStore } from 'vuex'
|
||||
import { Toast, ImagePreview } from 'vant';
|
||||
import dd from 'dingtalk-jsapi'
|
||||
import { rulesForm, resetForm, rulesPhone } from '@/com/index'
|
||||
import { getToken, getVisitorRecord, getWhiteCode } from '@/api/admin.js'
|
||||
|
||||
/* @data */
|
||||
const router = useRouter()
|
||||
const store = useStore()
|
||||
const isLoading = ref(false)
|
||||
|
||||
const token = ref('')
|
||||
const userName = ref('')
|
||||
|
||||
const query = reactive({
|
||||
status: 0,
|
||||
size: 2,
|
||||
current: 1,
|
||||
})
|
||||
const recordArr = ref([])
|
||||
const stateEnum = store.state.stateEnum
|
||||
token.value = localStorage.getItem('token')
|
||||
localStorage.setItem('redirect', '/adminHome')
|
||||
|
||||
/* @setup */
|
||||
const login = () =>{
|
||||
Toast.loading({ duration: 0, forbidClick: true, message: '登录中', });
|
||||
dd.getAuthCode({
|
||||
corpId: 'ding03f8e88dde9b426835c2f4657eb6378f',
|
||||
success: (res) => {
|
||||
const { code } = res;
|
||||
localStorage.removeItem('token');
|
||||
localStorage.removeItem('user');
|
||||
getToken(code).then(data =>{
|
||||
localStorage.setItem('user', JSON.stringify(data.data) )
|
||||
localStorage.setItem('token', data.data.authorization)
|
||||
userName.value = data.data.name
|
||||
|
||||
Toast.clear()
|
||||
Toast.success('登录成功')
|
||||
visitorList()
|
||||
})
|
||||
|
||||
},
|
||||
fail: (err) => {
|
||||
|
||||
},
|
||||
complete: () => {},
|
||||
});
|
||||
}
|
||||
// login()
|
||||
|
||||
const visitorList = () =>{
|
||||
Toast.loading({ duration: 0, forbidClick: true, message: '加载中', });
|
||||
getVisitorRecord(query).then(res =>{
|
||||
isLoading.value = true
|
||||
recordArr.value = res.data
|
||||
}).catch(err=>{
|
||||
isLoading.value = true
|
||||
})
|
||||
}
|
||||
// visitorList()
|
||||
if(token.value){
|
||||
visitorList()
|
||||
console.log((JSON.parse(localStorage.getItem('user'))).name )
|
||||
userName.value = JSON.parse(localStorage.getItem('user')).name
|
||||
}else{
|
||||
login()
|
||||
}
|
||||
|
||||
/* @method */
|
||||
const onClickGo = (url = '/adminHome') =>{
|
||||
router.push(url)
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<style lang='scss' scoped>
|
||||
.box{
|
||||
background-color: #F9FBFC;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
header{
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 10.4rem /* 780/75 */;
|
||||
background: url('../assets/guanlibeijing.png') left top/100% 100% no-repeat;
|
||||
box-sizing: border-box;
|
||||
h3{
|
||||
padding: 1.0933rem /* 82/75 */ .6933rem /* 52/75 */ .1067rem /* 8/75 */;
|
||||
box-sizing: border-box;
|
||||
line-height: .72rem /* 54/75 */;
|
||||
font-size: .48rem /* 36/75 */;
|
||||
font-family: Source Han Sans CN, Source Han Sans CN;
|
||||
font-weight: 500;
|
||||
color: #222222;
|
||||
}
|
||||
h4{
|
||||
line-height: .48rem /* 36/75 */;
|
||||
font-size: $sm-size;
|
||||
font-family: Source Han Sans CN, Source Han Sans CN;
|
||||
font-weight: 400;
|
||||
color: #FFFFFF;
|
||||
padding: 0 .6933rem /* 52/75 */ 1.12rem /* 84/75 */;
|
||||
box-sizing: border-box;
|
||||
|
||||
}
|
||||
.position-img{
|
||||
position: absolute;
|
||||
right: .4267rem /* 32/75 */;
|
||||
top: .2933rem /* 22/75 */;
|
||||
width: 3.6267rem /* 272/75 */;
|
||||
height: 2.96rem /* 222/75 */;
|
||||
img{
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
.plate-box{
|
||||
width: 100%;
|
||||
padding: 0 .4rem /* 30/75 */;
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
.plate-button{
|
||||
width: 4.4rem /* 330/75 */;
|
||||
height: 1.92rem /* 144/75 */;
|
||||
background: linear-gradient(180deg, rgba(255,255,255,0.3) 0%, rgba(255,255,255,0.6) 48%);
|
||||
border-radius: .2667rem /* 20/75 */;
|
||||
border: .0267rem /* 2/75 */ solid #FFFFFF;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
img{
|
||||
width: .9867rem /* 74/75 */;
|
||||
height: .9867rem /* 74/75 */;
|
||||
margin-left: .32rem /* 24/75 */;
|
||||
}
|
||||
.right{
|
||||
margin-left: .3467rem /* 26/75 */;
|
||||
div{
|
||||
line-height: .64rem /* 48/75 */;
|
||||
font-size: $lg-size;
|
||||
font-family: Source Han Sans CN, Source Han Sans CN;
|
||||
font-weight: 500;
|
||||
color: #222222;
|
||||
}
|
||||
P{
|
||||
line-height: .4rem /* 30/75 */;
|
||||
font-size: .2667rem /* 20/75 */;
|
||||
font-family: Source Han Sans CN, Source Han Sans CN;
|
||||
font-weight: 400;
|
||||
color: #5F6583;
|
||||
margin-top: .1067rem /* 8/75 */;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.content{
|
||||
flex: 1;
|
||||
overflow: auto;
|
||||
|
||||
position: relative;
|
||||
// top: 5.8667rem /* 440/75 */;
|
||||
margin-top: -4.5333rem /* 340/75 */;
|
||||
width: 100%;
|
||||
padding: 0 .4rem /* 30/75 */;
|
||||
box-sizing: border-box;
|
||||
h2{
|
||||
width: 100%;
|
||||
padding: .2667rem /* 20/75 */ .32rem /* 24/75 */;
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
line-height: .72rem /* 54/75 */;
|
||||
font-size: .48rem /* 36/75 */;
|
||||
font-family: Source Han Sans CN, Source Han Sans CN;
|
||||
font-weight: 500;
|
||||
color: #222222;
|
||||
span{
|
||||
// line-height: 36px;
|
||||
font-size: $sm-size;
|
||||
font-family: Source Han Sans CN, Source Han Sans CN;
|
||||
font-weight: 400;
|
||||
color: #999999;
|
||||
}
|
||||
}
|
||||
.content-ul{
|
||||
.wait-list{
|
||||
position: relative;
|
||||
width: 9.2rem /* 690/75 */;
|
||||
// height: 470px;
|
||||
background: #FFFFFF;
|
||||
border-radius: .2667rem /* 20/75 */;
|
||||
padding: .48rem /* 36/75 */;
|
||||
box-sizing: border-box;
|
||||
margin-bottom: .2667rem /* 20/75 */;
|
||||
h5{
|
||||
height: .6667rem /* 50/75 */;
|
||||
font-size: $md-size;
|
||||
font-family: Source Han Sans CN, Source Han Sans CN;
|
||||
font-weight: 400;
|
||||
color: #222222;
|
||||
}
|
||||
.apply-box{
|
||||
|
||||
width: 100%;
|
||||
padding: .4rem /* 30/75 */ .3733rem /* 28/75 */ .5067rem /* 38/75 */;
|
||||
box-sizing: border-box;
|
||||
border-radius: .1333rem /* 10/75 */;
|
||||
font-size: $md-size;
|
||||
font-family: Source Han Sans CN, Source Han Sans CN;
|
||||
font-weight: 400;
|
||||
color: #999999;
|
||||
line-height: .72rem /* 54/75 */;
|
||||
background: #F5F7F9;
|
||||
span:last-child{
|
||||
color: #5F6583;
|
||||
}
|
||||
}
|
||||
.status{
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
width: 1.52rem /* 114/75 */;
|
||||
height: .6667rem /* 50/75 */;
|
||||
line-height: .6667rem /* 50/75 */;
|
||||
background: #FFE9E4;
|
||||
border-radius: 0px .2667rem /* 20/75 */ 0px .1333rem /* 10/75 */;
|
||||
color: #FF6643;
|
||||
font-size: $sm-size;
|
||||
font-family: Source Han Sans CN, Source Han Sans CN;
|
||||
font-weight: 400;
|
||||
color: #FF6643;
|
||||
text-align: center;
|
||||
|
||||
}
|
||||
.refuse{
|
||||
color: #5F6583;
|
||||
background: #EAEEF6;
|
||||
}
|
||||
.pass{
|
||||
color: #30BF78;
|
||||
background: #E7F8F5;
|
||||
}
|
||||
}
|
||||
}
|
||||
.no-have{
|
||||
// display: block;
|
||||
width: 7.4667rem /* 560/75 */;
|
||||
height: 5.3867rem /* 404/75 */;
|
||||
margin: .8rem /* 60/75 */ auto;
|
||||
img{
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
// font-size: 15px;
|
||||
font-family: Source Han Sans CN, Source Han Sans CN;
|
||||
font-weight: 400;
|
||||
color: #999999;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,720 @@
|
||||
<template>
|
||||
<div v-if="true" class='box'>
|
||||
<div class="apply-box">
|
||||
<img class="text" src="../assets/zhinengfangke.png" alt="">
|
||||
<p>来访提前约 拜访开门无需按铃</p>
|
||||
<div class="apply-content">
|
||||
<h3>
|
||||
<img src="../assets/icon-shenfenzheng.png" alt="">
|
||||
<span>拜访信息<span>(我找谁)</span></span>
|
||||
</h3>
|
||||
<div class="apply-content-form">
|
||||
<!-- <Selectli label="被拜访对象" v-model="form.visitingTel" :columns="visitDict" :isMust="true" :isline="true" name="name" nameId="userId"/> -->
|
||||
<!-- <div class="search-select-box">
|
||||
<label class="label"><span>* </span>被拜访人</label>
|
||||
<div class="search-select-input">
|
||||
<input @click.stop="onClickVisitor" @input="onInputVisior" :value="visitorName" type="text" placeholder="可填写选择">
|
||||
<div v-if="isSelect && visitDict.length" class="select-box">
|
||||
<b></b>
|
||||
<div class="select-sroll-box">
|
||||
<div @click.self="onClickSelect(item)" v-for="item in visitDict" :class="item.userId == form.visitingTel ? 'select-active' : ''" class="select-li" :key="item.userId">{{ item.name }}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="isSelect && !visitDict.length" class="select-box">
|
||||
<b></b>
|
||||
<div class="select-li" >查无此人</div>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
</div> -->
|
||||
|
||||
<Inputli v-if="telName" v-model="telName" @input="onInputName" label="被访人" :isMust="true" :isline="true" isMustPosition="left"/>
|
||||
<Inputli v-else v-model="form.visitingTel" @blur="onBlurTel" @input="onInputTel" label="被访人电话" :isMust="true" :isline="true" isMustPosition="left"/>
|
||||
<Selectdate v-model="form.hours" label="来访时间" :isMust="true" :isline="false" :minDate="minDate"/>
|
||||
</div>
|
||||
</div>
|
||||
<img class="absolute-img" src="../assets/woyaoyuyue.png" alt="">
|
||||
</div>
|
||||
<p class="tips">
|
||||
说明:拜访时间前后一小时都可刷脸通过门禁
|
||||
</p>
|
||||
<div class="visitor-content">
|
||||
<h3>
|
||||
<img src="../assets/icon-shenfenzheng.png" alt="">
|
||||
<span>访客信息<span>(我是谁)</span></span>
|
||||
</h3>
|
||||
<div class="visitor-content-form">
|
||||
<Inputli v-model="form.name" label="访客姓名" :isMust="true" :isline="true" isMustPosition="left"/>
|
||||
<Inputli v-model="form.phone" label="联系方式" :isMust="true" :isline="true" isMustPosition="left"/>
|
||||
<Inputli v-model="form.visitingNum" label="随行人数" :isMust="true" :isline="true" isMustPosition="left"/>
|
||||
<Inputli v-model="form.reason" label="来访事由" :isMust="true" :isline="true" isMustPosition="left"/>
|
||||
<div class="upload-box">
|
||||
<label for=""><span>* </span>人脸照片</label>
|
||||
<div v-if="!form.img" class="upload-button">
|
||||
<img @click="onClickUpload" src="../assets/xiangji.png" alt="">
|
||||
<input v-if="isDisabled" @change="onChangeFile" type="file" accept="image/*">
|
||||
</div>
|
||||
<div v-else class="face-img">
|
||||
<img :src="form.img" alt="">
|
||||
<input v-if="true" @change="onChangeFile" type="file" accept="image/*">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<p class="tips">
|
||||
说明:人脸照片用于通过门禁系统,请上传正脸无遮挡照片
|
||||
</p>
|
||||
<p class="tel-tips">
|
||||
如果您在使用中遇到问题请联系:<span @click="onClickCall">400040-1573</span>
|
||||
</p>
|
||||
|
||||
<!-- <div class="disclaimer-box">
|
||||
<input type="checkbox">
|
||||
<p>勾选表示同意《<span>用户协议</span>》</p>
|
||||
</div> -->
|
||||
<button @click="onClcikSubmit" class="submit-button " :class="isSubmit ? 'active-button' : ''">提交</button>
|
||||
<Successmodel v-if="isSuccess" @click="onClickAffirm" />
|
||||
<div v-if="false" class="disclaimer-model-fixed">
|
||||
<h3>用户协议</h3>
|
||||
<div class="disclaimer-model">
|
||||
阿哈撒发哈师范哈撒发哈很舒服哈哈
|
||||
阿哈撒发哈师范哈撒发哈很舒服哈哈
|
||||
阿哈撒发哈师范哈撒发哈很舒服哈哈
|
||||
阿哈撒发哈师范哈撒发哈很舒服哈哈
|
||||
阿哈撒发哈师范哈撒发哈很舒服哈哈
|
||||
阿哈撒发哈师范哈撒发哈很舒服哈哈
|
||||
阿哈撒发哈师范哈撒发哈很舒服哈哈
|
||||
阿哈撒发哈师范哈撒发哈很舒服哈哈
|
||||
阿哈撒发哈师范哈撒发哈很舒服哈哈
|
||||
阿哈撒发哈师范哈撒发哈很舒服哈哈
|
||||
阿哈撒发哈师范哈撒发哈很舒服哈哈
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { reactive, ref, watch } from 'vue'
|
||||
import { useRouter, useRoute } from 'vue-router'
|
||||
import { useStore } from 'vuex'
|
||||
import { Toast, ImagePreview , Uploader, Dialog } from 'vant';
|
||||
import { rulesForm, resetForm, rulesPhone, rulesFormFBoolean, formatDate } from '@/com/index'
|
||||
import Inputli from '@/components/input-li.vue'
|
||||
import Selectli from '@/components/select-li.vue'
|
||||
import Selectdate from '@/components/select-li-date.vue'
|
||||
import Successmodel from '../components/success.vue'
|
||||
|
||||
import { postApply, getVisitor, getUserNameByTel } from '@/api/user.js'
|
||||
import { uploadApi } from '@/api/upload'
|
||||
/* @data */
|
||||
const router = useRouter()
|
||||
const route = useRoute()
|
||||
|
||||
const store = useStore()
|
||||
const phoneReg = /(^1\d{10}$)|(^[0-9]\d{7}$)/;
|
||||
let form = reactive({
|
||||
name: "",
|
||||
phone: "",
|
||||
hours: "",
|
||||
reason: "",
|
||||
img: "",
|
||||
visitingTel: "",
|
||||
visitingNum: '',
|
||||
})
|
||||
const isSubmit = ref(false)
|
||||
const visitDict = ref([]) // 被访客数据
|
||||
const visitAllDict = ref([]) // 被访客数据
|
||||
const isDisabled = ref(false) // 是否能提交
|
||||
const isSuccess = ref(false) // 是否提交成功
|
||||
const isSelect = ref( false) // 是否显示下拉选择
|
||||
const visitorName = ref( '') // 是否显示下拉选择的名字
|
||||
const telName = ref( '') // 电话查询姓名
|
||||
|
||||
|
||||
/* watch */
|
||||
watch(() => form, (v1, v2) => {
|
||||
isSubmit.value = rulesFormFBoolean(v2)
|
||||
if(v2.name && v2.phone){
|
||||
if(!phoneReg.test(v2.phone)){
|
||||
isDisabled.value = false
|
||||
}else{
|
||||
isDisabled.value = true
|
||||
}
|
||||
}else{
|
||||
isDisabled.value = false
|
||||
}
|
||||
|
||||
},{ deep: true }
|
||||
) // 深度监听 ) // 监听单个
|
||||
/* @method */
|
||||
const onInputTel = (e) =>{
|
||||
}
|
||||
const onInputName = (e) =>{
|
||||
form.visitingTel = ''
|
||||
telName.value = ''
|
||||
}
|
||||
|
||||
const onBlurTel = (phone) =>{
|
||||
console.log(phone)
|
||||
if(rulesPhone(phone)){
|
||||
getUserNameByTel(phone).then(res =>{
|
||||
console.log(res)
|
||||
if(res.data){
|
||||
telName.value = res.data
|
||||
}
|
||||
}).catch(err =>{
|
||||
console.log(err)
|
||||
Dialog.alert({
|
||||
message: err.msg,
|
||||
}).then(() => {
|
||||
// on close
|
||||
});
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
// const onBlurVisitor = () =>{
|
||||
// isSelect.value = false
|
||||
// let item = visitAllDict.value.find(item =>{ return item.userId == form.visitingTel })
|
||||
// if(item){
|
||||
// visitorName.value = item.name
|
||||
// visitDict.value = visitAllDict.value
|
||||
// }else{
|
||||
// visitorName.value = '' // 是否显示下拉选择的名字
|
||||
// visitDict.value = visitAllDict.value
|
||||
|
||||
// }
|
||||
// }
|
||||
// 输入框
|
||||
// const onInputVisior = (e) =>{
|
||||
// visitorName.value = e.target.value
|
||||
// let arr = []
|
||||
// visitAllDict.value.map( item =>{
|
||||
// if(item.name.search(e.target.value) != -1){
|
||||
// arr.push(item)
|
||||
// }
|
||||
// })
|
||||
// visitDict.value = [ ...arr ]
|
||||
// }
|
||||
// 点击选择了拜访对象
|
||||
// const onClickSelect = (item) =>{
|
||||
// form.visitingTel = item.userId
|
||||
// visitorName.value = item.name
|
||||
// isSelect.value = false
|
||||
|
||||
// }
|
||||
// const onClickVisitor = () =>{
|
||||
// isSelect.value = true
|
||||
// }
|
||||
// 点击确认模态框
|
||||
const onClickAffirm = () =>{
|
||||
router.go(-1)
|
||||
}
|
||||
const onClickUpload = () =>{
|
||||
if(isDisabled.value){
|
||||
|
||||
}else{
|
||||
Toast.fail('请填写访客姓名和正确的联系方式!')
|
||||
}
|
||||
}
|
||||
const onClcikSubmit = () =>{
|
||||
if(isSubmit.value){
|
||||
if(rulesPhone(form.phone) && rulesPhone(form.visitingTel)){
|
||||
Toast.loading({ duration: 0, forbidClick: true, message: '提交中', });
|
||||
postApply(form).then(res =>{
|
||||
Toast.clear();
|
||||
isSuccess.value = true
|
||||
})
|
||||
}
|
||||
|
||||
}else{
|
||||
Toast.fail('请先填写完整信息后提交!')
|
||||
}
|
||||
|
||||
}
|
||||
// 上传照片
|
||||
const onChangeFile = (e) =>{
|
||||
console.log(e.target.files[0].size)
|
||||
if(e.target.files[0]){
|
||||
newcompressImg(e.target.files[0], 0.5).then(res =>{
|
||||
let formData = new FormData()
|
||||
// formData.append('file', e.target.files[0])
|
||||
formData.append('file', res.file)
|
||||
formData.append('userId', form.phone)
|
||||
formData.append('name', form.name)
|
||||
Toast.loading({ duration: 0, forbidClick: true, message: '上传中', });
|
||||
uploadApi(formData).then(res =>{
|
||||
Toast.success(res.msg);
|
||||
form.img = res.data
|
||||
})
|
||||
}).catch(err =>{
|
||||
Toast.fail('图片上传失败,请重新上传')
|
||||
})
|
||||
}
|
||||
}
|
||||
const onClickCall = () =>{
|
||||
window.location.href = 'tel:400-040-1573'
|
||||
}
|
||||
const newcompressImg = (file, quality) =>{
|
||||
var qualitys = 0.52
|
||||
if (parseInt((file.size / 1024).toFixed(2)) < 1024) {
|
||||
qualitys = 0.85
|
||||
}
|
||||
if (5 * 1024 < parseInt((file.size / 1024).toFixed(2))) {
|
||||
qualitys = 0.92
|
||||
}
|
||||
if (quality) {
|
||||
qualitys = quality
|
||||
}
|
||||
if (file[0]) {
|
||||
return Promise.all(Array.from(file).map(e => this.compressImg(e,
|
||||
qualitys))) // 如果是 file 数组返回 Promise 数组
|
||||
} else {
|
||||
return new Promise((resolve) => {
|
||||
if ((file.size / 1024).toFixed(2) < 300) {
|
||||
resolve({
|
||||
file: file
|
||||
})
|
||||
} else {
|
||||
const reader = new FileReader() // 创建 FileReader
|
||||
reader.onload = ({
|
||||
target: {
|
||||
result: src
|
||||
}
|
||||
}) => {
|
||||
const image = new Image() // 创建 img 元素
|
||||
image.onload = async() => {
|
||||
const canvas = document.createElement('canvas') // 创建 canvas 元素
|
||||
const context = canvas.getContext('2d')
|
||||
var targetWidth = image.width
|
||||
var targetHeight = image.height
|
||||
var originWidth = image.width
|
||||
var originHeight = image.height
|
||||
if (1 * 1024 <= parseInt((file.size / 1024).toFixed(2)) && parseInt((file.size / 1024).toFixed(2)) <= 10 * 1024) {
|
||||
var maxWidth = 1600
|
||||
var maxHeight = 1600
|
||||
targetWidth = originWidth
|
||||
targetHeight = originHeight
|
||||
// 图片尺寸超过的限制
|
||||
if (originWidth > maxWidth || originHeight > maxHeight) {
|
||||
if (originWidth / originHeight > maxWidth / maxHeight) {
|
||||
// 更宽,按照宽度限定尺寸
|
||||
targetWidth = maxWidth
|
||||
targetHeight = Math.round(maxWidth * (originHeight / originWidth))
|
||||
} else {
|
||||
targetHeight = maxHeight
|
||||
targetWidth = Math.round(maxHeight * (originWidth / originHeight))
|
||||
}
|
||||
}
|
||||
}
|
||||
if (10 * 1024 <= parseInt((file.size / 1024).toFixed(2)) && parseInt((file.size / 1024).toFixed(2)) <= 20 * 1024) {
|
||||
maxWidth = 1400
|
||||
maxHeight = 1400
|
||||
targetWidth = originWidth
|
||||
targetHeight = originHeight
|
||||
// 图片尺寸超过的限制
|
||||
if (originWidth > maxWidth || originHeight > maxHeight) {
|
||||
if (originWidth / originHeight > maxWidth / maxHeight) {
|
||||
// 更宽,按照宽度限定尺寸
|
||||
targetWidth = maxWidth
|
||||
targetHeight = Math.round(maxWidth * (originHeight / originWidth))
|
||||
} else {
|
||||
targetHeight = maxHeight
|
||||
targetWidth = Math.round(maxHeight * (originWidth / originHeight))
|
||||
}
|
||||
}
|
||||
}
|
||||
canvas.width = targetWidth
|
||||
canvas.height = targetHeight
|
||||
context.clearRect(0, 0, targetWidth, targetHeight)
|
||||
context.drawImage(image, 0, 0, targetWidth, targetHeight) // 绘制 canvas
|
||||
const canvasURL = canvas.toDataURL('image/jpeg', qualitys)
|
||||
const buffer = atob(canvasURL.split(',')[1])
|
||||
let length = buffer.length
|
||||
const bufferArray = new Uint8Array(new ArrayBuffer(length))
|
||||
while (length--) {
|
||||
bufferArray[length] = buffer.charCodeAt(length)
|
||||
}
|
||||
const miniFile = new File([bufferArray], file.name, {
|
||||
type: 'image/jpeg'
|
||||
})
|
||||
resolve({
|
||||
file: miniFile,
|
||||
origin: file,
|
||||
beforeSrc: src,
|
||||
afterSrc: canvasURL,
|
||||
beforeKB: Number((file.size / 1024).toFixed(2)),
|
||||
afterKB: Number((miniFile.size / 1024).toFixed(2))
|
||||
})
|
||||
}
|
||||
image.src = src
|
||||
}
|
||||
reader.readAsDataURL(file)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* @setup */
|
||||
const minDate = ref( formatDate(new Date()))
|
||||
console.log(route.query.tel)
|
||||
if(route.query.tel){
|
||||
form.visitingTel = route.query.tel
|
||||
onBlurTel(route.query.tel)
|
||||
}
|
||||
getVisitor().then( res=>{
|
||||
visitDict.value = res.data
|
||||
visitAllDict.value = res.data
|
||||
})
|
||||
|
||||
</script>
|
||||
|
||||
<style lang='scss' scoped>
|
||||
.box{
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: #F5F5F5;
|
||||
padding: 0 0 1.08rem /* 81/75 */;
|
||||
box-sizing: border-box;
|
||||
overflow: auto;
|
||||
.apply-box{
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 8.0267rem /* 602/75 */;
|
||||
background: url('../assets/yuyuebeijing.png') left top/ 100% 100% no-repeat;
|
||||
padding: 1.04rem /* 78/75 */ 0 0;
|
||||
box-sizing: border-box;
|
||||
.text{
|
||||
width: 3.5467rem /* 266/75 */;
|
||||
height: 1.1467rem /* 86/75 */;
|
||||
margin-left: .6133rem /* 46/75 */;
|
||||
}
|
||||
p{
|
||||
line-height: .48rem /* 36/75 */;
|
||||
font-size: $sm-size;
|
||||
font-family: Source Han Sans CN, Source Han Sans CN;
|
||||
font-weight: 400;
|
||||
color: #999999;
|
||||
padding: .1067rem /* 8/75 */ 0 0 .7467rem /* 56/75 */;
|
||||
}
|
||||
.apply-content{
|
||||
width: 9.2rem /* 690/75 */;
|
||||
height: 4.32rem /* 324/75 */;
|
||||
background: #FFFFFF;
|
||||
border-radius: .2667rem /* 20/75 */;
|
||||
margin: 1.0133rem /* 76/75 */ auto 0;
|
||||
|
||||
h3{
|
||||
padding: .5067rem /* 38/75 */ .3467rem /* 26/75 */ 0 .4533rem /* 34/75 */;
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
color: #222222;
|
||||
font-size: $size30;
|
||||
|
||||
img{
|
||||
width: .5867rem /* 44/75 */;
|
||||
height: .5333rem /* 40/75 */;
|
||||
margin-right: .16rem /* 12/75 */;
|
||||
}
|
||||
span{
|
||||
span{
|
||||
font-size: .32rem /* 24/75 */;
|
||||
color: #666;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
.apply-content-form{
|
||||
width: 100%;
|
||||
padding: 0 .3467rem /* 26/75 */ 0 .4533rem /* 34/75 */;
|
||||
box-sizing: border-box;
|
||||
.search-select-box{
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 1.5733rem /* 118/75 */;
|
||||
// background: #F9F9F9;
|
||||
// border-radius: .2667rem /* 20/75 */;
|
||||
padding: 0 .0267rem /* 2/75 */ 0;
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
// margin-bottom: .2667rem /* 20/75 */;
|
||||
border-bottom: 0.0267rem dashed #D9D9D9;
|
||||
.label{
|
||||
flex: 1;
|
||||
font-size: $size26;
|
||||
color: #333333;
|
||||
line-height: 1.5733rem /* 118/75 */;
|
||||
span{
|
||||
color: #FF0000;
|
||||
margin-right: .0267rem /* 2/75 */;
|
||||
}
|
||||
}
|
||||
.search-select-input{
|
||||
position: relative;
|
||||
|
||||
height: 100%;
|
||||
box-sizing: border-box;
|
||||
input{
|
||||
flex: 1;
|
||||
border: none;
|
||||
outline: none;
|
||||
text-align: right;
|
||||
font-size: $size26;
|
||||
color: #333333;
|
||||
// background: #F9F9F9;
|
||||
padding-right: 0.3733rem;
|
||||
// line-height: 1.5733rem /* 118/75 */;
|
||||
box-sizing: border-box;
|
||||
height: 100%;
|
||||
|
||||
|
||||
}
|
||||
input::-webkit-input-placeholder {
|
||||
font-size: $size26;
|
||||
color: #999999;
|
||||
}
|
||||
.select-box{
|
||||
position: absolute;
|
||||
right: 0;
|
||||
top: 1.8667rem /* 140/75 */;
|
||||
z-index: 5;
|
||||
width: 3.7333rem /* 280/75 */;
|
||||
// max-height: 5.0667rem /* 380/75 */;
|
||||
background: #FFFFFF;
|
||||
box-shadow: 0px 0px .2667rem /* 20/75 */ .1067rem /* 8/75 */ rgba(0,0,0,0.1);
|
||||
border-radius: .0533rem /* 4/75 */ ;
|
||||
// overflow: auto;
|
||||
.select-sroll-box{
|
||||
// position: absolute;
|
||||
// right: 0;
|
||||
// top: 1.8667rem /* 140/75 */;
|
||||
// z-index: 5;
|
||||
width: 100%;
|
||||
max-height: 5.0667rem /* 380/75 */;
|
||||
background: #FFFFFF;
|
||||
// box-shadow: 0px 0px .2667rem /* 20/75 */ .1067rem /* 8/75 */ rgba(0,0,0,0.1);
|
||||
// border-radius: .0533rem /* 4/75 */ ;
|
||||
overflow: auto;
|
||||
}
|
||||
.select-li{
|
||||
height: 1.0133rem /* 76/75 */;
|
||||
background: #fff;
|
||||
|
||||
border-radius: .0533rem /* 4/75 */ .0533rem /* 4/75 */ 0px 0px;
|
||||
font-size: $size26;
|
||||
font-family: Source Han Sans CN, Source Han Sans CN;
|
||||
font-weight: 400;
|
||||
color: #999999;
|
||||
|
||||
line-height: 1.0133rem /* 76/75 */;
|
||||
text-align: center;
|
||||
}
|
||||
.select-active{
|
||||
color: #30BF78;
|
||||
background: #F3FEFB;
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
b{
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
// top: -100%;
|
||||
// width: .2rem /* 15/75 */;
|
||||
// height: 20px;
|
||||
// background: red;
|
||||
// display: block;
|
||||
width: 0;
|
||||
height: 0;
|
||||
border: .16rem /* 12/75 */ solid transparent;
|
||||
border-bottom: .16rem /* 12/75 */ solid #fff;
|
||||
transform: translateY(-100%) translateX(-50%);
|
||||
// margin-top: -.6667rem /* 50/75 */;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
.absolute-img{
|
||||
position: absolute;
|
||||
top: .5333rem /* 40/75 */;
|
||||
right: .4rem /* 30/75 */;
|
||||
width: 4.5067rem /* 338/75 */;
|
||||
height: 3.7867rem /* 284/75 */;
|
||||
}
|
||||
}
|
||||
.tips{
|
||||
line-height: .4533rem /* 34/75 */;
|
||||
font-size: .2933rem /* 22/75 */;
|
||||
font-family: Source Han Sans CN, Source Han Sans CN;
|
||||
font-weight: 400;
|
||||
color: #999999;
|
||||
padding: .2133rem /* 16/75 */ 0 .4267rem /* 32/75 */ .8rem /* 60/75 */;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
.visitor-content{
|
||||
width: 9.2rem /* 690/75 */;
|
||||
// height: 4.32rem /* 324/75 */;
|
||||
background: #FFFFFF;
|
||||
border-radius: .2667rem /* 20/75 */;
|
||||
margin: 0 auto 0;
|
||||
|
||||
h3{
|
||||
padding: .5067rem /* 38/75 */ .3467rem /* 26/75 */ 0 .4533rem /* 34/75 */;
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
color: #222222;
|
||||
font-size: $size30;
|
||||
|
||||
img{
|
||||
width: .5867rem /* 44/75 */;
|
||||
height: .5333rem /* 40/75 */;
|
||||
margin-right: .16rem /* 12/75 */;
|
||||
}
|
||||
span{
|
||||
span{
|
||||
font-size: .32rem /* 24/75 */;
|
||||
color: #666;
|
||||
}
|
||||
}
|
||||
}
|
||||
.visitor-content-form{
|
||||
width: 100%;
|
||||
padding: 0 .3467rem /* 26/75 */ .16rem /* 12/75 */ .4533rem /* 34/75 */;
|
||||
box-sizing: border-box;
|
||||
|
||||
.upload-box{
|
||||
width: 100%;
|
||||
height: 1.9733rem /* 148/75 */;
|
||||
// padding: 0 .6933rem /* 52/75 */ 0 0;
|
||||
padding-right: .3733rem /* 28/75 */;
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
color: #333333;
|
||||
font-size: $size26;
|
||||
label{
|
||||
line-height: 1.9733rem /* 148/75 */;
|
||||
span{
|
||||
color: #FF0000;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
.upload-button{
|
||||
position: relative;
|
||||
width: 1.3333rem /* 100/75 */;
|
||||
height: 1.3333rem /* 100/75 */;
|
||||
background: #FFFFFF;
|
||||
border-radius: .1333rem /* 10/75 */;
|
||||
border: .0267rem /* 2/75 */ dashed #D9D9D9;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
// overflow: hidden;
|
||||
input{
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
width: 1.3333rem /* 100/75 */;
|
||||
height: 1.3333rem /* 100/75 */;
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
.face-img{
|
||||
position: relative;
|
||||
width: 1.3333rem /* 100/75 */;
|
||||
height: 1.3333rem /* 100/75 */;
|
||||
background: #FFFFFF;
|
||||
border-radius: .1333rem /* 10/75 */;
|
||||
img{
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border-radius: .1333rem /* 10/75 */;
|
||||
|
||||
}
|
||||
input{
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
width: 1.3333rem /* 100/75 */;
|
||||
height: 1.3333rem /* 100/75 */;
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.disclaimer-box{
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
input{
|
||||
margin-right: .1333rem /* 10/75 */;
|
||||
}
|
||||
span{
|
||||
color: #30BF78;
|
||||
}
|
||||
}
|
||||
.tel-tips{
|
||||
line-height: .4533rem /* 34/75 */;
|
||||
font-size: .2933rem /* 22/75 */;
|
||||
font-family: Source Han Sans CN, Source Han Sans CN;
|
||||
font-weight: 400;
|
||||
color: #999999;
|
||||
padding: 0 0 .4267rem /* 32/75 */ .8rem /* 60/75 */;
|
||||
box-sizing: border-box;
|
||||
margin-top: -.24rem /* 18/75 */;
|
||||
span{
|
||||
color: #409eff;
|
||||
}
|
||||
}
|
||||
.submit-button{
|
||||
display: block;
|
||||
width: 6.72rem /* 504/75 */;
|
||||
height: 1.12rem /* 84/75 */;
|
||||
background: #D9D9D9;
|
||||
border-radius: 1.3333rem /* 100/75 */ ;
|
||||
opacity: 1;
|
||||
font-size: $size30;
|
||||
font-family: Source Han Sans CN, Source Han Sans CN;
|
||||
font-weight: 500;
|
||||
color: #222222;
|
||||
border: none;
|
||||
outline: none;
|
||||
margin: 1.0133rem /* 76/75 */ auto 0;
|
||||
}
|
||||
.active-button{
|
||||
background-color: #30BF78;
|
||||
color: #fff;
|
||||
}
|
||||
}
|
||||
.disclaimer-model-fixed{
|
||||
position: fixed;
|
||||
left: 0;
|
||||
top: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: #fff;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
padding: .4rem /* 30/75 */;
|
||||
box-sizing: border-box;
|
||||
h3{
|
||||
font-size: .4267rem /* 32/75 */;
|
||||
line-height: .8rem /* 60/75 */;
|
||||
text-align: center;
|
||||
}
|
||||
.disclaimer-model{
|
||||
flex: 1;
|
||||
line-height: .5333rem /* 40/75 */;
|
||||
text-align: justify;
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
||||
@@ -0,0 +1,720 @@
|
||||
<template>
|
||||
<div v-if="true" class='box'>
|
||||
<div class="apply-box">
|
||||
<img class="text" src="../assets/zhinengfangke.png" alt="">
|
||||
<p>来访提前约 拜访开门无需按铃</p>
|
||||
<div class="apply-content">
|
||||
<h3>
|
||||
<img src="../assets/icon-shenfenzheng.png" alt="">
|
||||
<span>拜访信息<span>(我找谁)</span></span>
|
||||
</h3>
|
||||
<div class="apply-content-form">
|
||||
<!-- <Selectli label="被拜访对象" v-model="form.visitingTel" :columns="visitDict" :isMust="true" :isline="true" name="name" nameId="userId"/> -->
|
||||
<!-- <div class="search-select-box">
|
||||
<label class="label"><span>* </span>被拜访人</label>
|
||||
<div class="search-select-input">
|
||||
<input @click.stop="onClickVisitor" @input="onInputVisior" :value="visitorName" type="text" placeholder="可填写选择">
|
||||
<div v-if="isSelect && visitDict.length" class="select-box">
|
||||
<b></b>
|
||||
<div class="select-sroll-box">
|
||||
<div @click.self="onClickSelect(item)" v-for="item in visitDict" :class="item.userId == form.visitingTel ? 'select-active' : ''" class="select-li" :key="item.userId">{{ item.name }}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="isSelect && !visitDict.length" class="select-box">
|
||||
<b></b>
|
||||
<div class="select-li" >查无此人</div>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
</div> -->
|
||||
|
||||
<Inputli v-if="telName" v-model="telName" @input="onInputName" label="被访人" :isMust="true" :isline="true" isMustPosition="left"/>
|
||||
<Inputli v-else v-model="form.visitingTel" @blur="onBlurTel" @input="onInputTel" label="被访人电话" :isMust="true" :isline="true" isMustPosition="left"/>
|
||||
<Selectdate v-model="form.hours" label="来访时间" :isMust="true" :isline="false" :minDate="minDate"/>
|
||||
</div>
|
||||
</div>
|
||||
<img class="absolute-img" src="../assets/woyaoyuyue.png" alt="">
|
||||
</div>
|
||||
<p class="tips">
|
||||
说明:拜访时间前后一小时都可刷脸通过门禁
|
||||
</p>
|
||||
<div class="visitor-content">
|
||||
<h3>
|
||||
<img src="../assets/icon-shenfenzheng.png" alt="">
|
||||
<span>访客信息<span>(我是谁)</span></span>
|
||||
</h3>
|
||||
<div class="visitor-content-form">
|
||||
<Inputli v-model="form.name" label="访客姓名" :isMust="true" :isline="true" isMustPosition="left"/>
|
||||
<Inputli v-model="form.phone" label="联系方式" :isMust="true" :isline="true" isMustPosition="left"/>
|
||||
<Inputli v-model="form.visitingNum" label="随行人数" :isMust="true" :isline="true" isMustPosition="left"/>
|
||||
<Inputli v-model="form.reason" label="来访事由" :isMust="true" :isline="true" isMustPosition="left"/>
|
||||
<div class="upload-box">
|
||||
<label for=""><span>* </span>人脸照片</label>
|
||||
<div v-if="!form.img" class="upload-button">
|
||||
<img @click="onClickUpload" src="../assets/xiangji.png" alt="">
|
||||
<input v-if="isDisabled" @change="onChangeFile" type="file" accept="image/*">
|
||||
</div>
|
||||
<div v-else class="face-img">
|
||||
<img :src="form.img" alt="">
|
||||
<input v-if="true" @change="onChangeFile" type="file" accept="image/*">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<p class="tips">
|
||||
说明:人脸照片用于通过门禁系统,请上传正脸无遮挡照片
|
||||
</p>
|
||||
<p class="tel-tips">
|
||||
如果您在使用中遇到问题请联系:<span @click="onClickCall">400040-1573</span>
|
||||
</p>
|
||||
|
||||
<!-- <div class="disclaimer-box">
|
||||
<input type="checkbox">
|
||||
<p>勾选表示同意《<span>用户协议</span>》</p>
|
||||
</div> -->
|
||||
<button @click="onClcikSubmit" class="submit-button " :class="isSubmit ? 'active-button' : ''">提交</button>
|
||||
<Successmodel v-if="isSuccess" @click="onClickAffirm" />
|
||||
<div v-if="false" class="disclaimer-model-fixed">
|
||||
<h3>用户协议</h3>
|
||||
<div class="disclaimer-model">
|
||||
阿哈撒发哈师范哈撒发哈很舒服哈哈
|
||||
阿哈撒发哈师范哈撒发哈很舒服哈哈
|
||||
阿哈撒发哈师范哈撒发哈很舒服哈哈
|
||||
阿哈撒发哈师范哈撒发哈很舒服哈哈
|
||||
阿哈撒发哈师范哈撒发哈很舒服哈哈
|
||||
阿哈撒发哈师范哈撒发哈很舒服哈哈
|
||||
阿哈撒发哈师范哈撒发哈很舒服哈哈
|
||||
阿哈撒发哈师范哈撒发哈很舒服哈哈
|
||||
阿哈撒发哈师范哈撒发哈很舒服哈哈
|
||||
阿哈撒发哈师范哈撒发哈很舒服哈哈
|
||||
阿哈撒发哈师范哈撒发哈很舒服哈哈
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { reactive, ref, watch } from 'vue'
|
||||
import { useRouter, useRoute } from 'vue-router'
|
||||
import { useStore } from 'vuex'
|
||||
import { Toast, ImagePreview , Uploader, Dialog } from 'vant';
|
||||
import { rulesForm, resetForm, rulesPhone, rulesFormFBoolean, formatDate } from '@/com/index'
|
||||
import Inputli from '@/components/input-li.vue'
|
||||
import Selectli from '@/components/select-li.vue'
|
||||
import Selectdate from '@/components/select-li-date.vue'
|
||||
import Successmodel from '../components/success.vue'
|
||||
|
||||
import { postApply, getVisitor, getUserNameByTel } from '@/api/user.js'
|
||||
import { uploadApi } from '@/api/upload'
|
||||
/* @data */
|
||||
const router = useRouter()
|
||||
const route = useRoute()
|
||||
|
||||
const store = useStore()
|
||||
const phoneReg = /(^1\d{10}$)|(^[0-9]\d{7}$)/;
|
||||
let form = reactive({
|
||||
name: "",
|
||||
phone: "",
|
||||
hours: "",
|
||||
reason: "",
|
||||
img: "",
|
||||
visitingTel: "",
|
||||
visitingNum: '',
|
||||
})
|
||||
const isSubmit = ref(false)
|
||||
const visitDict = ref([]) // 被访客数据
|
||||
const visitAllDict = ref([]) // 被访客数据
|
||||
const isDisabled = ref(false) // 是否能提交
|
||||
const isSuccess = ref(false) // 是否提交成功
|
||||
const isSelect = ref( false) // 是否显示下拉选择
|
||||
const visitorName = ref( '') // 是否显示下拉选择的名字
|
||||
const telName = ref( '') // 电话查询姓名
|
||||
|
||||
|
||||
/* watch */
|
||||
watch(() => form, (v1, v2) => {
|
||||
isSubmit.value = rulesFormFBoolean(v2)
|
||||
if(v2.name && v2.phone){
|
||||
if(!phoneReg.test(v2.phone)){
|
||||
isDisabled.value = false
|
||||
}else{
|
||||
isDisabled.value = true
|
||||
}
|
||||
}else{
|
||||
isDisabled.value = false
|
||||
}
|
||||
|
||||
},{ deep: true }
|
||||
) // 深度监听 ) // 监听单个
|
||||
/* @method */
|
||||
const onInputTel = (e) =>{
|
||||
}
|
||||
const onInputName = (e) =>{
|
||||
form.visitingTel = ''
|
||||
telName.value = ''
|
||||
}
|
||||
|
||||
const onBlurTel = (phone) =>{
|
||||
console.log(phone)
|
||||
if(rulesPhone(phone)){
|
||||
getUserNameByTel(phone).then(res =>{
|
||||
console.log(res)
|
||||
if(res.data){
|
||||
telName.value = res.data
|
||||
}
|
||||
}).catch(err =>{
|
||||
console.log(err)
|
||||
Dialog.alert({
|
||||
message: err.msg,
|
||||
}).then(() => {
|
||||
// on close
|
||||
});
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
// const onBlurVisitor = () =>{
|
||||
// isSelect.value = false
|
||||
// let item = visitAllDict.value.find(item =>{ return item.userId == form.visitingTel })
|
||||
// if(item){
|
||||
// visitorName.value = item.name
|
||||
// visitDict.value = visitAllDict.value
|
||||
// }else{
|
||||
// visitorName.value = '' // 是否显示下拉选择的名字
|
||||
// visitDict.value = visitAllDict.value
|
||||
|
||||
// }
|
||||
// }
|
||||
// 输入框
|
||||
// const onInputVisior = (e) =>{
|
||||
// visitorName.value = e.target.value
|
||||
// let arr = []
|
||||
// visitAllDict.value.map( item =>{
|
||||
// if(item.name.search(e.target.value) != -1){
|
||||
// arr.push(item)
|
||||
// }
|
||||
// })
|
||||
// visitDict.value = [ ...arr ]
|
||||
// }
|
||||
// 点击选择了拜访对象
|
||||
// const onClickSelect = (item) =>{
|
||||
// form.visitingTel = item.userId
|
||||
// visitorName.value = item.name
|
||||
// isSelect.value = false
|
||||
|
||||
// }
|
||||
// const onClickVisitor = () =>{
|
||||
// isSelect.value = true
|
||||
// }
|
||||
// 点击确认模态框
|
||||
const onClickAffirm = () =>{
|
||||
router.go(-1)
|
||||
}
|
||||
const onClickUpload = () =>{
|
||||
if(isDisabled.value){
|
||||
|
||||
}else{
|
||||
Toast.fail('请填写访客姓名和正确的联系方式!')
|
||||
}
|
||||
}
|
||||
const onClcikSubmit = () =>{
|
||||
if(isSubmit.value){
|
||||
if(rulesPhone(form.phone) && rulesPhone(form.visitingTel)){
|
||||
Toast.loading({ duration: 0, forbidClick: true, message: '提交中', });
|
||||
postApply(form).then(res =>{
|
||||
Toast.clear();
|
||||
isSuccess.value = true
|
||||
})
|
||||
}
|
||||
|
||||
}else{
|
||||
Toast.fail('请先填写完整信息后提交!')
|
||||
}
|
||||
|
||||
}
|
||||
// 上传照片
|
||||
const onChangeFile = (e) =>{
|
||||
console.log(e.target.files[0].size)
|
||||
if(e.target.files[0]){
|
||||
newcompressImg(e.target.files[0], 0.5).then(res =>{
|
||||
let formData = new FormData()
|
||||
// formData.append('file', e.target.files[0])
|
||||
formData.append('file', res.file)
|
||||
formData.append('userId', form.phone)
|
||||
formData.append('name', form.name)
|
||||
Toast.loading({ duration: 0, forbidClick: true, message: '上传中', });
|
||||
uploadApi(formData).then(res =>{
|
||||
Toast.success(res.msg);
|
||||
form.img = res.data
|
||||
})
|
||||
}).catch(err =>{
|
||||
Toast.fail('图片上传失败,请重新上传')
|
||||
})
|
||||
}
|
||||
}
|
||||
const onClickCall = () =>{
|
||||
window.location.href = 'tel:400-040-1573'
|
||||
}
|
||||
const newcompressImg = (file, quality) =>{
|
||||
var qualitys = 0.52
|
||||
if (parseInt((file.size / 1024).toFixed(2)) < 1024) {
|
||||
qualitys = 0.85
|
||||
}
|
||||
if (5 * 1024 < parseInt((file.size / 1024).toFixed(2))) {
|
||||
qualitys = 0.92
|
||||
}
|
||||
if (quality) {
|
||||
qualitys = quality
|
||||
}
|
||||
if (file[0]) {
|
||||
return Promise.all(Array.from(file).map(e => this.compressImg(e,
|
||||
qualitys))) // 如果是 file 数组返回 Promise 数组
|
||||
} else {
|
||||
return new Promise((resolve) => {
|
||||
if ((file.size / 1024).toFixed(2) < 300) {
|
||||
resolve({
|
||||
file: file
|
||||
})
|
||||
} else {
|
||||
const reader = new FileReader() // 创建 FileReader
|
||||
reader.onload = ({
|
||||
target: {
|
||||
result: src
|
||||
}
|
||||
}) => {
|
||||
const image = new Image() // 创建 img 元素
|
||||
image.onload = async() => {
|
||||
const canvas = document.createElement('canvas') // 创建 canvas 元素
|
||||
const context = canvas.getContext('2d')
|
||||
var targetWidth = image.width
|
||||
var targetHeight = image.height
|
||||
var originWidth = image.width
|
||||
var originHeight = image.height
|
||||
if (1 * 1024 <= parseInt((file.size / 1024).toFixed(2)) && parseInt((file.size / 1024).toFixed(2)) <= 10 * 1024) {
|
||||
var maxWidth = 1600
|
||||
var maxHeight = 1600
|
||||
targetWidth = originWidth
|
||||
targetHeight = originHeight
|
||||
// 图片尺寸超过的限制
|
||||
if (originWidth > maxWidth || originHeight > maxHeight) {
|
||||
if (originWidth / originHeight > maxWidth / maxHeight) {
|
||||
// 更宽,按照宽度限定尺寸
|
||||
targetWidth = maxWidth
|
||||
targetHeight = Math.round(maxWidth * (originHeight / originWidth))
|
||||
} else {
|
||||
targetHeight = maxHeight
|
||||
targetWidth = Math.round(maxHeight * (originWidth / originHeight))
|
||||
}
|
||||
}
|
||||
}
|
||||
if (10 * 1024 <= parseInt((file.size / 1024).toFixed(2)) && parseInt((file.size / 1024).toFixed(2)) <= 20 * 1024) {
|
||||
maxWidth = 1400
|
||||
maxHeight = 1400
|
||||
targetWidth = originWidth
|
||||
targetHeight = originHeight
|
||||
// 图片尺寸超过的限制
|
||||
if (originWidth > maxWidth || originHeight > maxHeight) {
|
||||
if (originWidth / originHeight > maxWidth / maxHeight) {
|
||||
// 更宽,按照宽度限定尺寸
|
||||
targetWidth = maxWidth
|
||||
targetHeight = Math.round(maxWidth * (originHeight / originWidth))
|
||||
} else {
|
||||
targetHeight = maxHeight
|
||||
targetWidth = Math.round(maxHeight * (originWidth / originHeight))
|
||||
}
|
||||
}
|
||||
}
|
||||
canvas.width = targetWidth
|
||||
canvas.height = targetHeight
|
||||
context.clearRect(0, 0, targetWidth, targetHeight)
|
||||
context.drawImage(image, 0, 0, targetWidth, targetHeight) // 绘制 canvas
|
||||
const canvasURL = canvas.toDataURL('image/jpeg', qualitys)
|
||||
const buffer = atob(canvasURL.split(',')[1])
|
||||
let length = buffer.length
|
||||
const bufferArray = new Uint8Array(new ArrayBuffer(length))
|
||||
while (length--) {
|
||||
bufferArray[length] = buffer.charCodeAt(length)
|
||||
}
|
||||
const miniFile = new File([bufferArray], file.name, {
|
||||
type: 'image/jpeg'
|
||||
})
|
||||
resolve({
|
||||
file: miniFile,
|
||||
origin: file,
|
||||
beforeSrc: src,
|
||||
afterSrc: canvasURL,
|
||||
beforeKB: Number((file.size / 1024).toFixed(2)),
|
||||
afterKB: Number((miniFile.size / 1024).toFixed(2))
|
||||
})
|
||||
}
|
||||
image.src = src
|
||||
}
|
||||
reader.readAsDataURL(file)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* @setup */
|
||||
const minDate = ref( formatDate(new Date()))
|
||||
console.log(route.query.tel)
|
||||
if(route.query.tel){
|
||||
form.visitingTel = route.query.tel
|
||||
onBlurTel(route.query.tel)
|
||||
}
|
||||
getVisitor().then( res=>{
|
||||
visitDict.value = res.data
|
||||
visitAllDict.value = res.data
|
||||
})
|
||||
|
||||
</script>
|
||||
|
||||
<style lang='scss' scoped>
|
||||
.box{
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: #F5F5F5;
|
||||
padding: 0 0 1.08rem /* 81/75 */;
|
||||
box-sizing: border-box;
|
||||
overflow: auto;
|
||||
.apply-box{
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 8.0267rem /* 602/75 */;
|
||||
background: url('../assets/yuyuebeijing.png') left top/ 100% 100% no-repeat;
|
||||
padding: 1.04rem /* 78/75 */ 0 0;
|
||||
box-sizing: border-box;
|
||||
.text{
|
||||
width: 3.5467rem /* 266/75 */;
|
||||
height: 1.1467rem /* 86/75 */;
|
||||
margin-left: .6133rem /* 46/75 */;
|
||||
}
|
||||
p{
|
||||
line-height: .48rem /* 36/75 */;
|
||||
font-size: $sm-size;
|
||||
font-family: Source Han Sans CN, Source Han Sans CN;
|
||||
font-weight: 400;
|
||||
color: #999999;
|
||||
padding: .1067rem /* 8/75 */ 0 0 .7467rem /* 56/75 */;
|
||||
}
|
||||
.apply-content{
|
||||
width: 9.2rem /* 690/75 */;
|
||||
height: 4.32rem /* 324/75 */;
|
||||
background: #FFFFFF;
|
||||
border-radius: .2667rem /* 20/75 */;
|
||||
margin: 1.0133rem /* 76/75 */ auto 0;
|
||||
|
||||
h3{
|
||||
padding: .5067rem /* 38/75 */ .3467rem /* 26/75 */ 0 .4533rem /* 34/75 */;
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
color: #222222;
|
||||
font-size: $size30;
|
||||
|
||||
img{
|
||||
width: .5867rem /* 44/75 */;
|
||||
height: .5333rem /* 40/75 */;
|
||||
margin-right: .16rem /* 12/75 */;
|
||||
}
|
||||
span{
|
||||
span{
|
||||
font-size: .32rem /* 24/75 */;
|
||||
color: #666;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
.apply-content-form{
|
||||
width: 100%;
|
||||
padding: 0 .3467rem /* 26/75 */ 0 .4533rem /* 34/75 */;
|
||||
box-sizing: border-box;
|
||||
.search-select-box{
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 1.5733rem /* 118/75 */;
|
||||
// background: #F9F9F9;
|
||||
// border-radius: .2667rem /* 20/75 */;
|
||||
padding: 0 .0267rem /* 2/75 */ 0;
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
// margin-bottom: .2667rem /* 20/75 */;
|
||||
border-bottom: 0.0267rem dashed #D9D9D9;
|
||||
.label{
|
||||
flex: 1;
|
||||
font-size: $size26;
|
||||
color: #333333;
|
||||
line-height: 1.5733rem /* 118/75 */;
|
||||
span{
|
||||
color: #FF0000;
|
||||
margin-right: .0267rem /* 2/75 */;
|
||||
}
|
||||
}
|
||||
.search-select-input{
|
||||
position: relative;
|
||||
|
||||
height: 100%;
|
||||
box-sizing: border-box;
|
||||
input{
|
||||
flex: 1;
|
||||
border: none;
|
||||
outline: none;
|
||||
text-align: right;
|
||||
font-size: $size26;
|
||||
color: #333333;
|
||||
// background: #F9F9F9;
|
||||
padding-right: 0.3733rem;
|
||||
// line-height: 1.5733rem /* 118/75 */;
|
||||
box-sizing: border-box;
|
||||
height: 100%;
|
||||
|
||||
|
||||
}
|
||||
input::-webkit-input-placeholder {
|
||||
font-size: $size26;
|
||||
color: #999999;
|
||||
}
|
||||
.select-box{
|
||||
position: absolute;
|
||||
right: 0;
|
||||
top: 1.8667rem /* 140/75 */;
|
||||
z-index: 5;
|
||||
width: 3.7333rem /* 280/75 */;
|
||||
// max-height: 5.0667rem /* 380/75 */;
|
||||
background: #FFFFFF;
|
||||
box-shadow: 0px 0px .2667rem /* 20/75 */ .1067rem /* 8/75 */ rgba(0,0,0,0.1);
|
||||
border-radius: .0533rem /* 4/75 */ ;
|
||||
// overflow: auto;
|
||||
.select-sroll-box{
|
||||
// position: absolute;
|
||||
// right: 0;
|
||||
// top: 1.8667rem /* 140/75 */;
|
||||
// z-index: 5;
|
||||
width: 100%;
|
||||
max-height: 5.0667rem /* 380/75 */;
|
||||
background: #FFFFFF;
|
||||
// box-shadow: 0px 0px .2667rem /* 20/75 */ .1067rem /* 8/75 */ rgba(0,0,0,0.1);
|
||||
// border-radius: .0533rem /* 4/75 */ ;
|
||||
overflow: auto;
|
||||
}
|
||||
.select-li{
|
||||
height: 1.0133rem /* 76/75 */;
|
||||
background: #fff;
|
||||
|
||||
border-radius: .0533rem /* 4/75 */ .0533rem /* 4/75 */ 0px 0px;
|
||||
font-size: $size26;
|
||||
font-family: Source Han Sans CN, Source Han Sans CN;
|
||||
font-weight: 400;
|
||||
color: #999999;
|
||||
|
||||
line-height: 1.0133rem /* 76/75 */;
|
||||
text-align: center;
|
||||
}
|
||||
.select-active{
|
||||
color: #30BF78;
|
||||
background: #F3FEFB;
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
b{
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
// top: -100%;
|
||||
// width: .2rem /* 15/75 */;
|
||||
// height: 20px;
|
||||
// background: red;
|
||||
// display: block;
|
||||
width: 0;
|
||||
height: 0;
|
||||
border: .16rem /* 12/75 */ solid transparent;
|
||||
border-bottom: .16rem /* 12/75 */ solid #fff;
|
||||
transform: translateY(-100%) translateX(-50%);
|
||||
// margin-top: -.6667rem /* 50/75 */;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
.absolute-img{
|
||||
position: absolute;
|
||||
top: .5333rem /* 40/75 */;
|
||||
right: .4rem /* 30/75 */;
|
||||
width: 4.5067rem /* 338/75 */;
|
||||
height: 3.7867rem /* 284/75 */;
|
||||
}
|
||||
}
|
||||
.tips{
|
||||
line-height: .4533rem /* 34/75 */;
|
||||
font-size: .2933rem /* 22/75 */;
|
||||
font-family: Source Han Sans CN, Source Han Sans CN;
|
||||
font-weight: 400;
|
||||
color: #999999;
|
||||
padding: .2133rem /* 16/75 */ 0 .4267rem /* 32/75 */ .8rem /* 60/75 */;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
.visitor-content{
|
||||
width: 9.2rem /* 690/75 */;
|
||||
// height: 4.32rem /* 324/75 */;
|
||||
background: #FFFFFF;
|
||||
border-radius: .2667rem /* 20/75 */;
|
||||
margin: 0 auto 0;
|
||||
|
||||
h3{
|
||||
padding: .5067rem /* 38/75 */ .3467rem /* 26/75 */ 0 .4533rem /* 34/75 */;
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
color: #222222;
|
||||
font-size: $size30;
|
||||
|
||||
img{
|
||||
width: .5867rem /* 44/75 */;
|
||||
height: .5333rem /* 40/75 */;
|
||||
margin-right: .16rem /* 12/75 */;
|
||||
}
|
||||
span{
|
||||
span{
|
||||
font-size: .32rem /* 24/75 */;
|
||||
color: #666;
|
||||
}
|
||||
}
|
||||
}
|
||||
.visitor-content-form{
|
||||
width: 100%;
|
||||
padding: 0 .3467rem /* 26/75 */ .16rem /* 12/75 */ .4533rem /* 34/75 */;
|
||||
box-sizing: border-box;
|
||||
|
||||
.upload-box{
|
||||
width: 100%;
|
||||
height: 1.9733rem /* 148/75 */;
|
||||
// padding: 0 .6933rem /* 52/75 */ 0 0;
|
||||
padding-right: .3733rem /* 28/75 */;
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
color: #333333;
|
||||
font-size: $size26;
|
||||
label{
|
||||
line-height: 1.9733rem /* 148/75 */;
|
||||
span{
|
||||
color: #FF0000;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
.upload-button{
|
||||
position: relative;
|
||||
width: 1.3333rem /* 100/75 */;
|
||||
height: 1.3333rem /* 100/75 */;
|
||||
background: #FFFFFF;
|
||||
border-radius: .1333rem /* 10/75 */;
|
||||
border: .0267rem /* 2/75 */ dashed #D9D9D9;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
// overflow: hidden;
|
||||
input{
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
width: 1.3333rem /* 100/75 */;
|
||||
height: 1.3333rem /* 100/75 */;
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
.face-img{
|
||||
position: relative;
|
||||
width: 1.3333rem /* 100/75 */;
|
||||
height: 1.3333rem /* 100/75 */;
|
||||
background: #FFFFFF;
|
||||
border-radius: .1333rem /* 10/75 */;
|
||||
img{
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border-radius: .1333rem /* 10/75 */;
|
||||
|
||||
}
|
||||
input{
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
width: 1.3333rem /* 100/75 */;
|
||||
height: 1.3333rem /* 100/75 */;
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.disclaimer-box{
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
input{
|
||||
margin-right: .1333rem /* 10/75 */;
|
||||
}
|
||||
span{
|
||||
color: #30BF78;
|
||||
}
|
||||
}
|
||||
.tel-tips{
|
||||
line-height: .4533rem /* 34/75 */;
|
||||
font-size: .2933rem /* 22/75 */;
|
||||
font-family: Source Han Sans CN, Source Han Sans CN;
|
||||
font-weight: 400;
|
||||
color: #999999;
|
||||
padding: 0 0 .4267rem /* 32/75 */ .8rem /* 60/75 */;
|
||||
box-sizing: border-box;
|
||||
margin-top: -.24rem /* 18/75 */;
|
||||
span{
|
||||
color: #409eff;
|
||||
}
|
||||
}
|
||||
.submit-button{
|
||||
display: block;
|
||||
width: 6.72rem /* 504/75 */;
|
||||
height: 1.12rem /* 84/75 */;
|
||||
background: #D9D9D9;
|
||||
border-radius: 1.3333rem /* 100/75 */ ;
|
||||
opacity: 1;
|
||||
font-size: $size30;
|
||||
font-family: Source Han Sans CN, Source Han Sans CN;
|
||||
font-weight: 500;
|
||||
color: #222222;
|
||||
border: none;
|
||||
outline: none;
|
||||
margin: 1.0133rem /* 76/75 */ auto 0;
|
||||
}
|
||||
.active-button{
|
||||
background-color: #30BF78;
|
||||
color: #fff;
|
||||
}
|
||||
}
|
||||
.disclaimer-model-fixed{
|
||||
position: fixed;
|
||||
left: 0;
|
||||
top: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: #fff;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
padding: .4rem /* 30/75 */;
|
||||
box-sizing: border-box;
|
||||
h3{
|
||||
font-size: .4267rem /* 32/75 */;
|
||||
line-height: .8rem /* 60/75 */;
|
||||
text-align: center;
|
||||
}
|
||||
.disclaimer-model{
|
||||
flex: 1;
|
||||
line-height: .5333rem /* 40/75 */;
|
||||
text-align: justify;
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
||||
@@ -0,0 +1,721 @@
|
||||
<template>
|
||||
<div v-if="true" class='box'>
|
||||
<div class="apply-box">
|
||||
<img class="text" src="../assets/zhinengfangke.png" alt="">
|
||||
<p>来访提前约 拜访开门无需按铃</p>
|
||||
<div class="apply-content">
|
||||
<h3>
|
||||
<img src="../assets/icon-shenfenzheng.png" alt="">
|
||||
<span>拜访信息<span>(我找谁)</span></span>
|
||||
</h3>
|
||||
<div class="apply-content-form">
|
||||
<!-- <Selectli label="被拜访对象" v-model="form.visitingTel" :columns="visitDict" :isMust="true" :isline="true" name="name" nameId="userId"/> -->
|
||||
<!-- <div class="search-select-box">
|
||||
<label class="label"><span>* </span>被拜访人</label>
|
||||
<div class="search-select-input">
|
||||
<input @click.stop="onClickVisitor" @input="onInputVisior" :value="visitorName" type="text" placeholder="可填写选择">
|
||||
<div v-if="isSelect && visitDict.length" class="select-box">
|
||||
<b></b>
|
||||
<div class="select-sroll-box">
|
||||
<div @click.self="onClickSelect(item)" v-for="item in visitDict" :class="item.userId == form.visitingTel ? 'select-active' : ''" class="select-li" :key="item.userId">{{ item.name }}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="isSelect && !visitDict.length" class="select-box">
|
||||
<b></b>
|
||||
<div class="select-li" >查无此人</div>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
</div> -->
|
||||
|
||||
<Inputli v-if="telName" v-model="telName" @input="onInputName" label="被访人" :isMust="true" :isline="true" isMustPosition="left"/>
|
||||
<Inputli v-else v-model="form.visitingTel" @blur="onBlurTel" @input="onInputTel" label="被访人电话" :isMust="true" :isline="true" isMustPosition="left"/>
|
||||
<Selectdate v-model="form.hours" label="来访时间" :isMust="true" :isline="false" :minDate="minDate"/>
|
||||
</div>
|
||||
</div>
|
||||
<img class="absolute-img" src="../assets/woyaoyuyue.png" alt="">
|
||||
</div>
|
||||
<p class="tips">
|
||||
说明:拜访时间前后一小时都可刷脸通过门禁
|
||||
</p>
|
||||
<div class="visitor-content">
|
||||
<h3>
|
||||
<img src="../assets/icon-shenfenzheng.png" alt="">
|
||||
<span>访客信息<span>(我是谁)</span></span>
|
||||
</h3>
|
||||
<div class="visitor-content-form">
|
||||
<Inputli v-model="form.name" label="访客姓名" :isMust="true" :isline="true" isMustPosition="left"/>
|
||||
<Inputli v-model="form.phone" label="联系方式" :isMust="true" :isline="true" isMustPosition="left"/>
|
||||
<Inputli v-model="form.visitingNum" label="随行人数" :isMust="true" :isline="true" isMustPosition="left"/>
|
||||
<Inputli v-model="form.reason" label="来访事由" :isMust="true" :isline="true" isMustPosition="left"/>
|
||||
<div class="upload-box">
|
||||
<label for=""><span>* </span>人脸照片</label>
|
||||
<div v-if="!form.img" class="upload-button">
|
||||
<img @click="onClickUpload" src="../assets/xiangji.png" alt="">
|
||||
<input v-if="isDisabled" @change="onChangeFile" type="file" accept="image/*">
|
||||
</div>
|
||||
<div v-else class="face-img">
|
||||
<img :src="form.img" alt="">
|
||||
<input v-if="true" @change="onChangeFile" type="file" accept="image/*">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<p class="tips">
|
||||
说明:人脸照片用于通过门禁系统,请上传正脸无遮挡照片
|
||||
</p>
|
||||
<p class="tel-tips">
|
||||
如果您在使用中遇到问题请联系:<span @click="onClickCall">400040-1573</span>
|
||||
</p>
|
||||
|
||||
<!-- <div class="disclaimer-box">
|
||||
<input type="checkbox">
|
||||
<p>勾选表示同意《<span>用户协议</span>》</p>
|
||||
</div> -->
|
||||
<button @click="onClcikSubmit" class="submit-button " :class="isSubmit ? 'active-button' : ''">提交</button>
|
||||
<Successmodel v-if="isSuccess" @click="onClickAffirm" />
|
||||
<div v-if="false" class="disclaimer-model-fixed">
|
||||
<h3>用户协议</h3>
|
||||
<div class="disclaimer-model">
|
||||
阿哈撒发哈师范哈撒发哈很舒服哈哈
|
||||
阿哈撒发哈师范哈撒发哈很舒服哈哈
|
||||
阿哈撒发哈师范哈撒发哈很舒服哈哈
|
||||
阿哈撒发哈师范哈撒发哈很舒服哈哈
|
||||
阿哈撒发哈师范哈撒发哈很舒服哈哈
|
||||
阿哈撒发哈师范哈撒发哈很舒服哈哈
|
||||
阿哈撒发哈师范哈撒发哈很舒服哈哈
|
||||
阿哈撒发哈师范哈撒发哈很舒服哈哈
|
||||
阿哈撒发哈师范哈撒发哈很舒服哈哈
|
||||
阿哈撒发哈师范哈撒发哈很舒服哈哈
|
||||
阿哈撒发哈师范哈撒发哈很舒服哈哈
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { reactive, ref, watch } from 'vue'
|
||||
import { useRouter, useRoute } from 'vue-router'
|
||||
import { useStore } from 'vuex'
|
||||
import { Toast, ImagePreview , Uploader, Dialog } from 'vant';
|
||||
import { rulesForm, resetForm, rulesPhone, rulesFormFBoolean, formatDate } from '@/com/index'
|
||||
import Inputli from '@/components/input-li.vue'
|
||||
import Selectli from '@/components/select-li.vue'
|
||||
import Selectdate from '@/components/select-li-date.vue'
|
||||
import Successmodel from '../components/success.vue'
|
||||
|
||||
import { postApply, getVisitor, getUserNameByTel } from '@/api/user.js'
|
||||
import { uploadApi } from '@/api/upload'
|
||||
/* @data */
|
||||
const router = useRouter()
|
||||
const route = useRoute()
|
||||
|
||||
const store = useStore()
|
||||
const phoneReg = /(^1\d{10}$)|(^[0-9]\d{7}$)/;
|
||||
let form = reactive({
|
||||
name: "",
|
||||
phone: "",
|
||||
hours: "",
|
||||
reason: "",
|
||||
img: "",
|
||||
visitingTel: "",
|
||||
visitingNum: '',
|
||||
})
|
||||
const isSubmit = ref(false)
|
||||
const visitDict = ref([]) // 被访客数据
|
||||
const visitAllDict = ref([]) // 被访客数据
|
||||
const isDisabled = ref(false) // 是否能提交
|
||||
const isSuccess = ref(false) // 是否提交成功
|
||||
const isSelect = ref( false) // 是否显示下拉选择
|
||||
const visitorName = ref( '') // 是否显示下拉选择的名字
|
||||
const telName = ref( '') // 电话查询姓名
|
||||
|
||||
|
||||
/* watch */
|
||||
watch(() => form, (v1, v2) => {
|
||||
isSubmit.value = rulesFormFBoolean(v2)
|
||||
if(v2.name && v2.phone){
|
||||
if(!phoneReg.test(v2.phone)){
|
||||
isDisabled.value = false
|
||||
}else{
|
||||
isDisabled.value = true
|
||||
}
|
||||
}else{
|
||||
isDisabled.value = false
|
||||
}
|
||||
|
||||
},{ deep: true }
|
||||
) // 深度监听 ) // 监听单个
|
||||
/* @method */
|
||||
const onInputTel = (e) =>{
|
||||
}
|
||||
const onInputName = (e) =>{
|
||||
form.visitingTel = ''
|
||||
telName.value = ''
|
||||
}
|
||||
|
||||
const onBlurTel = (phone) =>{
|
||||
console.log(phone)
|
||||
if(rulesPhone(phone)){
|
||||
getUserNameByTel(phone).then(res =>{
|
||||
console.log(res)
|
||||
if(res.data){
|
||||
telName.value = res.data
|
||||
}
|
||||
}).catch(err =>{
|
||||
Toast.clear();
|
||||
console.log(err)
|
||||
Dialog.alert({
|
||||
message: err.msg,
|
||||
}).then(() => {
|
||||
// on close
|
||||
});
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
// const onBlurVisitor = () =>{
|
||||
// isSelect.value = false
|
||||
// let item = visitAllDict.value.find(item =>{ return item.userId == form.visitingTel })
|
||||
// if(item){
|
||||
// visitorName.value = item.name
|
||||
// visitDict.value = visitAllDict.value
|
||||
// }else{
|
||||
// visitorName.value = '' // 是否显示下拉选择的名字
|
||||
// visitDict.value = visitAllDict.value
|
||||
|
||||
// }
|
||||
// }
|
||||
// 输入框
|
||||
// const onInputVisior = (e) =>{
|
||||
// visitorName.value = e.target.value
|
||||
// let arr = []
|
||||
// visitAllDict.value.map( item =>{
|
||||
// if(item.name.search(e.target.value) != -1){
|
||||
// arr.push(item)
|
||||
// }
|
||||
// })
|
||||
// visitDict.value = [ ...arr ]
|
||||
// }
|
||||
// 点击选择了拜访对象
|
||||
// const onClickSelect = (item) =>{
|
||||
// form.visitingTel = item.userId
|
||||
// visitorName.value = item.name
|
||||
// isSelect.value = false
|
||||
|
||||
// }
|
||||
// const onClickVisitor = () =>{
|
||||
// isSelect.value = true
|
||||
// }
|
||||
// 点击确认模态框
|
||||
const onClickAffirm = () =>{
|
||||
router.go(-1)
|
||||
}
|
||||
const onClickUpload = () =>{
|
||||
if(isDisabled.value){
|
||||
|
||||
}else{
|
||||
Toast.fail('请填写访客姓名和正确的联系方式!')
|
||||
}
|
||||
}
|
||||
const onClcikSubmit = () =>{
|
||||
if(isSubmit.value){
|
||||
if(rulesPhone(form.phone) && rulesPhone(form.visitingTel)){
|
||||
Toast.loading({ duration: 0, forbidClick: true, message: '提交中', });
|
||||
postApply(form).then(res =>{
|
||||
Toast.clear();
|
||||
isSuccess.value = true
|
||||
})
|
||||
}
|
||||
|
||||
}else{
|
||||
Toast.fail('请先填写完整信息后提交!')
|
||||
}
|
||||
|
||||
}
|
||||
// 上传照片
|
||||
const onChangeFile = (e) =>{
|
||||
console.log(e.target.files[0].size)
|
||||
if(e.target.files[0]){
|
||||
newcompressImg(e.target.files[0], 0.5).then(res =>{
|
||||
let formData = new FormData()
|
||||
// formData.append('file', e.target.files[0])
|
||||
formData.append('file', res.file)
|
||||
formData.append('userId', form.phone)
|
||||
formData.append('name', form.name)
|
||||
Toast.loading({ duration: 0, forbidClick: true, message: '上传中', });
|
||||
uploadApi(formData).then(res =>{
|
||||
Toast.success(res.msg);
|
||||
form.img = res.data
|
||||
})
|
||||
}).catch(err =>{
|
||||
Toast.fail('图片上传失败,请重新上传')
|
||||
})
|
||||
}
|
||||
}
|
||||
const onClickCall = () =>{
|
||||
window.location.href = 'tel:400-040-1573'
|
||||
}
|
||||
const newcompressImg = (file, quality) =>{
|
||||
var qualitys = 0.52
|
||||
if (parseInt((file.size / 1024).toFixed(2)) < 1024) {
|
||||
qualitys = 0.85
|
||||
}
|
||||
if (5 * 1024 < parseInt((file.size / 1024).toFixed(2))) {
|
||||
qualitys = 0.92
|
||||
}
|
||||
if (quality) {
|
||||
qualitys = quality
|
||||
}
|
||||
if (file[0]) {
|
||||
return Promise.all(Array.from(file).map(e => this.compressImg(e,
|
||||
qualitys))) // 如果是 file 数组返回 Promise 数组
|
||||
} else {
|
||||
return new Promise((resolve) => {
|
||||
if ((file.size / 1024).toFixed(2) < 300) {
|
||||
resolve({
|
||||
file: file
|
||||
})
|
||||
} else {
|
||||
const reader = new FileReader() // 创建 FileReader
|
||||
reader.onload = ({
|
||||
target: {
|
||||
result: src
|
||||
}
|
||||
}) => {
|
||||
const image = new Image() // 创建 img 元素
|
||||
image.onload = async() => {
|
||||
const canvas = document.createElement('canvas') // 创建 canvas 元素
|
||||
const context = canvas.getContext('2d')
|
||||
var targetWidth = image.width
|
||||
var targetHeight = image.height
|
||||
var originWidth = image.width
|
||||
var originHeight = image.height
|
||||
if (1 * 1024 <= parseInt((file.size / 1024).toFixed(2)) && parseInt((file.size / 1024).toFixed(2)) <= 10 * 1024) {
|
||||
var maxWidth = 1600
|
||||
var maxHeight = 1600
|
||||
targetWidth = originWidth
|
||||
targetHeight = originHeight
|
||||
// 图片尺寸超过的限制
|
||||
if (originWidth > maxWidth || originHeight > maxHeight) {
|
||||
if (originWidth / originHeight > maxWidth / maxHeight) {
|
||||
// 更宽,按照宽度限定尺寸
|
||||
targetWidth = maxWidth
|
||||
targetHeight = Math.round(maxWidth * (originHeight / originWidth))
|
||||
} else {
|
||||
targetHeight = maxHeight
|
||||
targetWidth = Math.round(maxHeight * (originWidth / originHeight))
|
||||
}
|
||||
}
|
||||
}
|
||||
if (10 * 1024 <= parseInt((file.size / 1024).toFixed(2)) && parseInt((file.size / 1024).toFixed(2)) <= 20 * 1024) {
|
||||
maxWidth = 1400
|
||||
maxHeight = 1400
|
||||
targetWidth = originWidth
|
||||
targetHeight = originHeight
|
||||
// 图片尺寸超过的限制
|
||||
if (originWidth > maxWidth || originHeight > maxHeight) {
|
||||
if (originWidth / originHeight > maxWidth / maxHeight) {
|
||||
// 更宽,按照宽度限定尺寸
|
||||
targetWidth = maxWidth
|
||||
targetHeight = Math.round(maxWidth * (originHeight / originWidth))
|
||||
} else {
|
||||
targetHeight = maxHeight
|
||||
targetWidth = Math.round(maxHeight * (originWidth / originHeight))
|
||||
}
|
||||
}
|
||||
}
|
||||
canvas.width = targetWidth
|
||||
canvas.height = targetHeight
|
||||
context.clearRect(0, 0, targetWidth, targetHeight)
|
||||
context.drawImage(image, 0, 0, targetWidth, targetHeight) // 绘制 canvas
|
||||
const canvasURL = canvas.toDataURL('image/jpeg', qualitys)
|
||||
const buffer = atob(canvasURL.split(',')[1])
|
||||
let length = buffer.length
|
||||
const bufferArray = new Uint8Array(new ArrayBuffer(length))
|
||||
while (length--) {
|
||||
bufferArray[length] = buffer.charCodeAt(length)
|
||||
}
|
||||
const miniFile = new File([bufferArray], file.name, {
|
||||
type: 'image/jpeg'
|
||||
})
|
||||
resolve({
|
||||
file: miniFile,
|
||||
origin: file,
|
||||
beforeSrc: src,
|
||||
afterSrc: canvasURL,
|
||||
beforeKB: Number((file.size / 1024).toFixed(2)),
|
||||
afterKB: Number((miniFile.size / 1024).toFixed(2))
|
||||
})
|
||||
}
|
||||
image.src = src
|
||||
}
|
||||
reader.readAsDataURL(file)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* @setup */
|
||||
const minDate = ref( formatDate(new Date()))
|
||||
console.log(route.query.tel)
|
||||
if(route.query.tel){
|
||||
form.visitingTel = route.query.tel
|
||||
onBlurTel(route.query.tel)
|
||||
}
|
||||
getVisitor().then( res=>{
|
||||
visitDict.value = res.data
|
||||
visitAllDict.value = res.data
|
||||
})
|
||||
|
||||
</script>
|
||||
|
||||
<style lang='scss' scoped>
|
||||
.box{
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: #F5F5F5;
|
||||
padding: 0 0 1.08rem /* 81/75 */;
|
||||
box-sizing: border-box;
|
||||
overflow: auto;
|
||||
.apply-box{
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 8.0267rem /* 602/75 */;
|
||||
background: url('../assets/yuyuebeijing.png') left top/ 100% 100% no-repeat;
|
||||
padding: 1.04rem /* 78/75 */ 0 0;
|
||||
box-sizing: border-box;
|
||||
.text{
|
||||
width: 3.5467rem /* 266/75 */;
|
||||
height: 1.1467rem /* 86/75 */;
|
||||
margin-left: .6133rem /* 46/75 */;
|
||||
}
|
||||
p{
|
||||
line-height: .48rem /* 36/75 */;
|
||||
font-size: $sm-size;
|
||||
font-family: Source Han Sans CN, Source Han Sans CN;
|
||||
font-weight: 400;
|
||||
color: #999999;
|
||||
padding: .1067rem /* 8/75 */ 0 0 .7467rem /* 56/75 */;
|
||||
}
|
||||
.apply-content{
|
||||
width: 9.2rem /* 690/75 */;
|
||||
height: 4.32rem /* 324/75 */;
|
||||
background: #FFFFFF;
|
||||
border-radius: .2667rem /* 20/75 */;
|
||||
margin: 1.0133rem /* 76/75 */ auto 0;
|
||||
|
||||
h3{
|
||||
padding: .5067rem /* 38/75 */ .3467rem /* 26/75 */ 0 .4533rem /* 34/75 */;
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
color: #222222;
|
||||
font-size: $size30;
|
||||
|
||||
img{
|
||||
width: .5867rem /* 44/75 */;
|
||||
height: .5333rem /* 40/75 */;
|
||||
margin-right: .16rem /* 12/75 */;
|
||||
}
|
||||
span{
|
||||
span{
|
||||
font-size: .32rem /* 24/75 */;
|
||||
color: #666;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
.apply-content-form{
|
||||
width: 100%;
|
||||
padding: 0 .3467rem /* 26/75 */ 0 .4533rem /* 34/75 */;
|
||||
box-sizing: border-box;
|
||||
.search-select-box{
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 1.5733rem /* 118/75 */;
|
||||
// background: #F9F9F9;
|
||||
// border-radius: .2667rem /* 20/75 */;
|
||||
padding: 0 .0267rem /* 2/75 */ 0;
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
// margin-bottom: .2667rem /* 20/75 */;
|
||||
border-bottom: 0.0267rem dashed #D9D9D9;
|
||||
.label{
|
||||
flex: 1;
|
||||
font-size: $size26;
|
||||
color: #333333;
|
||||
line-height: 1.5733rem /* 118/75 */;
|
||||
span{
|
||||
color: #FF0000;
|
||||
margin-right: .0267rem /* 2/75 */;
|
||||
}
|
||||
}
|
||||
.search-select-input{
|
||||
position: relative;
|
||||
|
||||
height: 100%;
|
||||
box-sizing: border-box;
|
||||
input{
|
||||
flex: 1;
|
||||
border: none;
|
||||
outline: none;
|
||||
text-align: right;
|
||||
font-size: $size26;
|
||||
color: #333333;
|
||||
// background: #F9F9F9;
|
||||
padding-right: 0.3733rem;
|
||||
// line-height: 1.5733rem /* 118/75 */;
|
||||
box-sizing: border-box;
|
||||
height: 100%;
|
||||
|
||||
|
||||
}
|
||||
input::-webkit-input-placeholder {
|
||||
font-size: $size26;
|
||||
color: #999999;
|
||||
}
|
||||
.select-box{
|
||||
position: absolute;
|
||||
right: 0;
|
||||
top: 1.8667rem /* 140/75 */;
|
||||
z-index: 5;
|
||||
width: 3.7333rem /* 280/75 */;
|
||||
// max-height: 5.0667rem /* 380/75 */;
|
||||
background: #FFFFFF;
|
||||
box-shadow: 0px 0px .2667rem /* 20/75 */ .1067rem /* 8/75 */ rgba(0,0,0,0.1);
|
||||
border-radius: .0533rem /* 4/75 */ ;
|
||||
// overflow: auto;
|
||||
.select-sroll-box{
|
||||
// position: absolute;
|
||||
// right: 0;
|
||||
// top: 1.8667rem /* 140/75 */;
|
||||
// z-index: 5;
|
||||
width: 100%;
|
||||
max-height: 5.0667rem /* 380/75 */;
|
||||
background: #FFFFFF;
|
||||
// box-shadow: 0px 0px .2667rem /* 20/75 */ .1067rem /* 8/75 */ rgba(0,0,0,0.1);
|
||||
// border-radius: .0533rem /* 4/75 */ ;
|
||||
overflow: auto;
|
||||
}
|
||||
.select-li{
|
||||
height: 1.0133rem /* 76/75 */;
|
||||
background: #fff;
|
||||
|
||||
border-radius: .0533rem /* 4/75 */ .0533rem /* 4/75 */ 0px 0px;
|
||||
font-size: $size26;
|
||||
font-family: Source Han Sans CN, Source Han Sans CN;
|
||||
font-weight: 400;
|
||||
color: #999999;
|
||||
|
||||
line-height: 1.0133rem /* 76/75 */;
|
||||
text-align: center;
|
||||
}
|
||||
.select-active{
|
||||
color: #30BF78;
|
||||
background: #F3FEFB;
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
b{
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
// top: -100%;
|
||||
// width: .2rem /* 15/75 */;
|
||||
// height: 20px;
|
||||
// background: red;
|
||||
// display: block;
|
||||
width: 0;
|
||||
height: 0;
|
||||
border: .16rem /* 12/75 */ solid transparent;
|
||||
border-bottom: .16rem /* 12/75 */ solid #fff;
|
||||
transform: translateY(-100%) translateX(-50%);
|
||||
// margin-top: -.6667rem /* 50/75 */;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
.absolute-img{
|
||||
position: absolute;
|
||||
top: .5333rem /* 40/75 */;
|
||||
right: .4rem /* 30/75 */;
|
||||
width: 4.5067rem /* 338/75 */;
|
||||
height: 3.7867rem /* 284/75 */;
|
||||
}
|
||||
}
|
||||
.tips{
|
||||
line-height: .4533rem /* 34/75 */;
|
||||
font-size: .2933rem /* 22/75 */;
|
||||
font-family: Source Han Sans CN, Source Han Sans CN;
|
||||
font-weight: 400;
|
||||
color: #999999;
|
||||
padding: .2133rem /* 16/75 */ 0 .4267rem /* 32/75 */ .8rem /* 60/75 */;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
.visitor-content{
|
||||
width: 9.2rem /* 690/75 */;
|
||||
// height: 4.32rem /* 324/75 */;
|
||||
background: #FFFFFF;
|
||||
border-radius: .2667rem /* 20/75 */;
|
||||
margin: 0 auto 0;
|
||||
|
||||
h3{
|
||||
padding: .5067rem /* 38/75 */ .3467rem /* 26/75 */ 0 .4533rem /* 34/75 */;
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
color: #222222;
|
||||
font-size: $size30;
|
||||
|
||||
img{
|
||||
width: .5867rem /* 44/75 */;
|
||||
height: .5333rem /* 40/75 */;
|
||||
margin-right: .16rem /* 12/75 */;
|
||||
}
|
||||
span{
|
||||
span{
|
||||
font-size: .32rem /* 24/75 */;
|
||||
color: #666;
|
||||
}
|
||||
}
|
||||
}
|
||||
.visitor-content-form{
|
||||
width: 100%;
|
||||
padding: 0 .3467rem /* 26/75 */ .16rem /* 12/75 */ .4533rem /* 34/75 */;
|
||||
box-sizing: border-box;
|
||||
|
||||
.upload-box{
|
||||
width: 100%;
|
||||
height: 1.9733rem /* 148/75 */;
|
||||
// padding: 0 .6933rem /* 52/75 */ 0 0;
|
||||
padding-right: .3733rem /* 28/75 */;
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
color: #333333;
|
||||
font-size: $size26;
|
||||
label{
|
||||
line-height: 1.9733rem /* 148/75 */;
|
||||
span{
|
||||
color: #FF0000;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
.upload-button{
|
||||
position: relative;
|
||||
width: 1.3333rem /* 100/75 */;
|
||||
height: 1.3333rem /* 100/75 */;
|
||||
background: #FFFFFF;
|
||||
border-radius: .1333rem /* 10/75 */;
|
||||
border: .0267rem /* 2/75 */ dashed #D9D9D9;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
// overflow: hidden;
|
||||
input{
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
width: 1.3333rem /* 100/75 */;
|
||||
height: 1.3333rem /* 100/75 */;
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
.face-img{
|
||||
position: relative;
|
||||
width: 1.3333rem /* 100/75 */;
|
||||
height: 1.3333rem /* 100/75 */;
|
||||
background: #FFFFFF;
|
||||
border-radius: .1333rem /* 10/75 */;
|
||||
img{
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border-radius: .1333rem /* 10/75 */;
|
||||
|
||||
}
|
||||
input{
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
width: 1.3333rem /* 100/75 */;
|
||||
height: 1.3333rem /* 100/75 */;
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.disclaimer-box{
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
input{
|
||||
margin-right: .1333rem /* 10/75 */;
|
||||
}
|
||||
span{
|
||||
color: #30BF78;
|
||||
}
|
||||
}
|
||||
.tel-tips{
|
||||
line-height: .4533rem /* 34/75 */;
|
||||
font-size: .2933rem /* 22/75 */;
|
||||
font-family: Source Han Sans CN, Source Han Sans CN;
|
||||
font-weight: 400;
|
||||
color: #999999;
|
||||
padding: 0 0 .4267rem /* 32/75 */ .8rem /* 60/75 */;
|
||||
box-sizing: border-box;
|
||||
margin-top: -.24rem /* 18/75 */;
|
||||
span{
|
||||
color: #409eff;
|
||||
}
|
||||
}
|
||||
.submit-button{
|
||||
display: block;
|
||||
width: 6.72rem /* 504/75 */;
|
||||
height: 1.12rem /* 84/75 */;
|
||||
background: #D9D9D9;
|
||||
border-radius: 1.3333rem /* 100/75 */ ;
|
||||
opacity: 1;
|
||||
font-size: $size30;
|
||||
font-family: Source Han Sans CN, Source Han Sans CN;
|
||||
font-weight: 500;
|
||||
color: #222222;
|
||||
border: none;
|
||||
outline: none;
|
||||
margin: 1.0133rem /* 76/75 */ auto 0;
|
||||
}
|
||||
.active-button{
|
||||
background-color: #30BF78;
|
||||
color: #fff;
|
||||
}
|
||||
}
|
||||
.disclaimer-model-fixed{
|
||||
position: fixed;
|
||||
left: 0;
|
||||
top: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: #fff;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
padding: .4rem /* 30/75 */;
|
||||
box-sizing: border-box;
|
||||
h3{
|
||||
font-size: .4267rem /* 32/75 */;
|
||||
line-height: .8rem /* 60/75 */;
|
||||
text-align: center;
|
||||
}
|
||||
.disclaimer-model{
|
||||
flex: 1;
|
||||
line-height: .5333rem /* 40/75 */;
|
||||
text-align: justify;
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
||||
@@ -0,0 +1,124 @@
|
||||
<template>
|
||||
<div class='box'>
|
||||
<div class="content">
|
||||
<img class="icon-h1" src="../assets/yuyuejilu.png" alt="">
|
||||
<div class="title">请输入预约时填写的手机号</div>
|
||||
<p>手机号用于查询所提交的预约记录</p>
|
||||
<input @input="onInputPhone" v-model="phone" placeholder="输入手机号" :maxlength="11" />
|
||||
<button @click="onClickQuery" :class=" phone.length >= 11 ? 'active-button' : '' " class="query-button">查询</button>
|
||||
<!-- <p v-for="item in 90">54444444444444</p> -->
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref } from 'vue'
|
||||
import { useRouter } from 'vue-router'
|
||||
import { useStore } from 'vuex'
|
||||
import { rulesForm, resetForm, rulesPhone } from '@/com/index'
|
||||
import { postApply, getVisitor, getByPhone } from '@/api/user.js'
|
||||
import { Toast, ImagePreview } from 'vant';
|
||||
|
||||
/* @data */
|
||||
const router = useRouter()
|
||||
const store = useStore()
|
||||
let phone = ref('')
|
||||
|
||||
/* @setup */
|
||||
const getStorage = localStorage.getItem('iphone')
|
||||
if(getStorage){
|
||||
phone.value = getStorage
|
||||
}
|
||||
/* @method */
|
||||
const onInputPhone = (e) =>{
|
||||
// console.log(e.target.value.length)
|
||||
}
|
||||
const onClickQuery = () =>{
|
||||
if(phone.value.length >= 11){
|
||||
if( rulesPhone(phone.value)){
|
||||
console.log('可以提交')
|
||||
localStorage.setItem('iphone', phone.value)
|
||||
let obj = { phone: phone.value }
|
||||
Toast.loading({ duration: 0, forbidClick: true, message: '查询中', });
|
||||
getByPhone(obj).then(res =>{
|
||||
console.log(res)
|
||||
Toast.clear()
|
||||
router.replace('/applyRecord/'+phone.value)
|
||||
}).catch(err =>{
|
||||
console.log(err)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang='scss' scoped>
|
||||
.box{
|
||||
// position: relative;
|
||||
// display: flex;
|
||||
// flex-direction: column;
|
||||
overflow: auto;
|
||||
align-items: center;
|
||||
padding: 2rem /* 150/75 */ 0 0;
|
||||
box-sizing: border-box;
|
||||
|
||||
|
||||
.icon-h1{
|
||||
width: 5.3333rem /* 400/75 */;
|
||||
height: 4rem /* 300/75 */;
|
||||
margin: 0 auto;
|
||||
}
|
||||
.title{
|
||||
line-height: .72rem /* 54/75 */;
|
||||
font-size: .48rem /* 36/75 */;
|
||||
font-family: Source Han Sans CN, Source Han Sans CN;
|
||||
font-weight: 400;
|
||||
color: #222222;
|
||||
margin: .4533rem /* 34/75 */ auto .16rem /* 12/75 */;
|
||||
// margin: 0 auto;
|
||||
text-align: center;
|
||||
}
|
||||
p{
|
||||
line-height: .48rem /* 36/75 */;
|
||||
font-size: $sm-size;
|
||||
font-family: Source Han Sans CN, Source Han Sans CN;
|
||||
font-weight: 400;
|
||||
color: #999999;
|
||||
text-align: center;
|
||||
|
||||
}
|
||||
input{
|
||||
display: block;
|
||||
width: 6.72rem /* 504/75 */;
|
||||
height: 1.12rem /* 84/75 */;
|
||||
background: #F5F5F5;
|
||||
border-radius: 1.3333rem /* 100/75 */;
|
||||
margin: .9067rem /* 68/75 */ auto 0;
|
||||
font-size: $md-size;
|
||||
border: none;
|
||||
outline: none;
|
||||
padding: 0 .56rem /* 42/75 */;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
input::-webkit-input-placeholder{
|
||||
color: #999999;
|
||||
}
|
||||
.query-button{
|
||||
display: block;
|
||||
width: 6.72rem /* 504/75 */;
|
||||
height: 1.12rem /* 84/75 */;
|
||||
background: #D9D9D9;
|
||||
border-radius: 1.3333rem /* 100/75 */ ;
|
||||
color: #222222;
|
||||
border: none;
|
||||
font-size: $size30;
|
||||
margin: .64rem /* 48/75 */ auto 0;
|
||||
}
|
||||
.active-button{
|
||||
background-color: #30BF78;
|
||||
color: #fff;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,196 @@
|
||||
<template>
|
||||
<div class='box' @scroll="onScroll">
|
||||
<div v-for="item in recordArr" class="apply-list" :key="item.id">
|
||||
<h3 class="h3">
|
||||
<span>提交时间:{{ item.createTime }}</span>
|
||||
<!-- refuse拒绝 pass通过 状态 -->
|
||||
<div class="status" :class="stateEnum[item.status].className">{{ stateEnum[item.status].statusName }}</div>
|
||||
</h3>
|
||||
<div class="apply-content">
|
||||
<div class="user-info">
|
||||
<img src="../assets/lanseyuanquan.png" alt="">
|
||||
<span>拜访人:{{ item.name }}</span>
|
||||
</div>
|
||||
<div class="user-info">
|
||||
<img src="../assets/huangseyuanquan.png" alt="">
|
||||
<span>拜访时间:{{ item.hours }}</span>
|
||||
</div>
|
||||
<p>
|
||||
{{ item.status == 2 && item.remark ? item.remark : stateEnum[item.status].statusText }}
|
||||
<span class="triangle"></span>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, reactive } from 'vue'
|
||||
import { useRouter, useRoute } from 'vue-router'
|
||||
import { useStore } from 'vuex'
|
||||
import { rulesForm, resetForm, rulesPhone } from '@/com/index'
|
||||
import { postApply, getVisitor, getByPhone } from '@/api/user.js'
|
||||
import { Toast, ImagePreview } from 'vant';
|
||||
/* @data */
|
||||
const router = useRouter()
|
||||
const route = useRoute()
|
||||
const store = useStore()
|
||||
// console.log(route.params.iphone)
|
||||
const query = reactive({
|
||||
// phone: route.params.iphone,
|
||||
current: 1,
|
||||
size: 10
|
||||
})
|
||||
const total = ref()
|
||||
const recordArr = ref([])
|
||||
const stateEnum = store.state.stateEnum
|
||||
|
||||
/* @setup */
|
||||
console.log(localStorage.getItem('userToken'))
|
||||
let windowHeight = document.documentElement.clientHeight || document.body.clientHeight;
|
||||
console.log(windowHeight)
|
||||
getByPhone(query).then(res =>{
|
||||
// console.log(res)
|
||||
recordArr.value = res.data
|
||||
total.value = res.total
|
||||
// alert(windowHeight)
|
||||
|
||||
}).catch(err =>{
|
||||
console.log(err)
|
||||
})
|
||||
/* @method */
|
||||
let old = 0
|
||||
const onScroll = (e) =>{
|
||||
if(e.target.scrollTop > old){ // 说明是下拉
|
||||
if(e.target.scrollHeight <= windowHeight + Math.ceil(e.target.scrollTop) ){ // 说明到底了
|
||||
console.log('到底了')
|
||||
if(recordArr.value.length < total.value ){
|
||||
query.current++
|
||||
getList()
|
||||
}else{
|
||||
Toast.success('数据已全部加载完成!');
|
||||
|
||||
}
|
||||
}
|
||||
}else{ // 说明是上拉
|
||||
|
||||
}
|
||||
old = e.target.scrollTop
|
||||
|
||||
// setTimeout(()=>{
|
||||
// alert(e.target.scrollHeight - e.target.scrollTop)
|
||||
|
||||
// },2000)
|
||||
}
|
||||
const getList = () =>{
|
||||
Toast.loading({ duration: 0, forbidClick: true, message: '加载中', });
|
||||
getByPhone(query).then(res =>{
|
||||
// console.log(res)
|
||||
recordArr.value = [ ...recordArr.value , ...res.data]
|
||||
total.value = res.total
|
||||
Toast.clear();
|
||||
|
||||
}).catch(err =>{
|
||||
query.current--
|
||||
console.log(err)
|
||||
})
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang='scss' scoped>
|
||||
.box{
|
||||
width: 100%;
|
||||
height: 100vh;
|
||||
overflow: auto;
|
||||
background: #EDEDED;
|
||||
padding: .4rem /* 30/75 */;
|
||||
box-sizing: border-box;
|
||||
.apply-list{
|
||||
width: 100%;
|
||||
// height: 5.0667rem /* 380/75 */;
|
||||
background: #FFFFFF;
|
||||
border-radius: .2667rem /* 20/75 */;
|
||||
padding: 0 .4rem /* 30/75 */ .5867rem /* 44/75 */;
|
||||
box-sizing: border-box;
|
||||
margin-bottom: .4rem /* 30/75 */;
|
||||
|
||||
|
||||
.h3{
|
||||
width: 100%;
|
||||
height: 1.2267rem /* 92/75 */;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
border-bottom: .0267rem /* 2/75 */ dashed #D9D9D9;
|
||||
padding: 0 .1067rem /* 8/75 */;
|
||||
box-sizing: border-box;
|
||||
span{
|
||||
font-size: $sm-size;
|
||||
font-family: Source Han Sans CN, Source Han Sans CN;
|
||||
font-weight: 400;
|
||||
color: #999999;
|
||||
}
|
||||
.status{
|
||||
font-size: $size26;
|
||||
font-family: Source Han Sans CN, Source Han Sans CN;
|
||||
font-weight: 500;
|
||||
color: #448CF7;
|
||||
}
|
||||
.pass{
|
||||
color: #18C297;
|
||||
}
|
||||
.refuse{
|
||||
color: #FF6643;
|
||||
}
|
||||
}
|
||||
.apply-content{
|
||||
width: 100%;
|
||||
padding: .5067rem /* 38/75 */ 0 0;
|
||||
.user-info{
|
||||
padding: 0 .24rem /* 18/75 */;
|
||||
box-sizing: border-box;
|
||||
font-size: $md-size;
|
||||
font-family: Source Han Sans CN, Source Han Sans CN;
|
||||
font-weight: 400;
|
||||
color: #000000;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
height: .56rem /* 42/75 */;
|
||||
margin-bottom: .2133rem /* 16/75 */;
|
||||
img{
|
||||
width: .2667rem /* 20/75 */;
|
||||
height: .2667rem /* 20/75 */;
|
||||
margin-right: .2133rem /* 16/75 */;
|
||||
}
|
||||
}
|
||||
p{
|
||||
position: relative;
|
||||
width: 8.2133rem /* 616/75 */;
|
||||
padding: .2133rem /* 16/75 */ .4533rem /* 34/75 */;
|
||||
box-sizing: border-box;
|
||||
line-height: .48rem /* 36/75 */;
|
||||
// height: .9067rem /* 68/75 */;
|
||||
background: #EAEEF6;
|
||||
// background: #fff;
|
||||
border-radius: .1333rem /* 10/75 */;
|
||||
font-size: $sm-size;
|
||||
font-family: Source Han Sans CN, Source Han Sans CN;
|
||||
font-weight: 400;
|
||||
color: #5F6583;
|
||||
margin-top: .5067rem /* 38/75 */;
|
||||
.triangle{
|
||||
position: absolute;
|
||||
top: -.08rem /* 6/75 */;
|
||||
left: .5333rem /* 40/75 */;
|
||||
width: .2rem /* 15/75 */;
|
||||
height: .2rem /* 15/75 */;
|
||||
transform: rotateZ(-45deg);
|
||||
background: #EAEEF6;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,786 @@
|
||||
<template>
|
||||
<div v-if="true" class='box'>
|
||||
<div class="apply-box">
|
||||
<img class="text" src="../assets/zhinengfangke.png" alt="">
|
||||
<p>来访提前约 拜访开门无需按铃</p>
|
||||
<img class="absolute-img" src="../assets/woyaoyuyue.png" alt="">
|
||||
|
||||
<div class="apply-content">
|
||||
<h3>
|
||||
<img src="../assets/icon-shenfenzheng.png" alt="">
|
||||
<span>拜访信息<span>(我找谁)</span></span>
|
||||
</h3>
|
||||
<div class="apply-content-form">
|
||||
<Inputli v-model="form.name" label="访客姓名" :isMust="true" :isline="true" isMustPosition="left"/>
|
||||
<Inputli v-model="form.phone" label="联系方式" :isMust="true" :isline="true" isMustPosition="left"/>
|
||||
<Inputli v-model="form.visitingNum" label="随行人数" :isMust="true" :isline="true" isMustPosition="left"/>
|
||||
<Inputli v-model="form.reason" label="来访事由" :isMust="true" :isline="true" isMustPosition="left"/>
|
||||
<div class="upload-box">
|
||||
<label for=""><span>* </span>人脸照片</label>
|
||||
<div v-if="!form.img" class="upload-button">
|
||||
<img @click="onClickUpload" src="../assets/xiangji.png" alt="">
|
||||
<input v-if="isDisabled" @change="onChangeFile" type="file" accept="image/*">
|
||||
</div>
|
||||
<div v-else class="face-img">
|
||||
<img :src="form.img" alt="">
|
||||
<input v-if="true" @change="onChangeFile" type="file" accept="image/*">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<p class="tips">
|
||||
说明:人脸照片用于通过门禁系统,请上传正脸无遮挡照片
|
||||
</p>
|
||||
<p class="tel-tips">
|
||||
如果您在使用中遇到问题请联系:<span @click="onClickCall">400040-1573</span>
|
||||
</p>
|
||||
<div class="visitor-content">
|
||||
<h3>
|
||||
<img src="../assets/icon-shenfenzheng.png" alt="">
|
||||
<span>访客信息<span>(我是谁)</span></span>
|
||||
</h3>
|
||||
<div class="visitor-content-form">
|
||||
<Inputli v-if="telName" v-model="telName" @input="onInputName" label="被访人" :isMust="true" :isline="true" isMustPosition="left"/>
|
||||
<Inputli v-else v-model="form.visitingTel" @blur="onBlurTel" @input="onInputTel" label="被访人电话" :isMust="true" :isline="true" isMustPosition="left"/>
|
||||
<Selectdate v-model="form.hours" label="来访时间" :isMust="true" :isline="false" :minDate="minDate"/>
|
||||
</div>
|
||||
</div>
|
||||
<p class="tips" style="margin-top: .2rem /* 15/75 */">
|
||||
说明:拜访时间前后一小时都可刷脸通过门禁
|
||||
</p>
|
||||
|
||||
<!-- <p class="tips">
|
||||
说明:拜访时间前后一小时都可刷脸通过门禁
|
||||
</p>
|
||||
<div v-if="false" class="visitor-content">
|
||||
<h3>
|
||||
<img src="../assets/icon-shenfenzheng.png" alt="">
|
||||
<span>访客信息<span>(我是谁)</span></span>
|
||||
</h3>
|
||||
<div class="visitor-content-form">
|
||||
<Inputli v-if="telName" v-model="telName" @input="onInputName" label="被访人" :isMust="true" :isline="true" isMustPosition="left"/>
|
||||
<Inputli v-else v-model="form.visitingTel" @blur="onBlurTel" @input="onInputTel" label="被访人电话" :isMust="true" :isline="true" isMustPosition="left"/>
|
||||
<Selectdate v-model="form.hours" label="来访时间" :isMust="true" :isline="false" :minDate="minDate"/>
|
||||
</div>
|
||||
</div>
|
||||
<p class="tips">
|
||||
说明:人脸照片用于通过门禁系统,请上传正脸无遮挡照片
|
||||
</p>
|
||||
<p class="tel-tips">
|
||||
如果您在使用中遇到问题请联系:<span @click="onClickCall">400040-1573</span>
|
||||
</p> -->
|
||||
|
||||
<!-- <div class="disclaimer-box">
|
||||
<input type="checkbox">
|
||||
<p>勾选表示同意《<span>用户协议</span>》</p>
|
||||
</div> -->
|
||||
<button @click="onClcikSubmit" class="submit-button " :class="isSubmit ? 'active-button' : ''">提交</button>
|
||||
<Successmodel v-if="isSuccess" @click="onClickAffirm" />
|
||||
<div v-if="false" class="disclaimer-model-fixed">
|
||||
<h3>用户协议</h3>
|
||||
<div class="disclaimer-model">
|
||||
阿哈撒发哈师范哈撒发哈很舒服哈哈
|
||||
阿哈撒发哈师范哈撒发哈很舒服哈哈
|
||||
阿哈撒发哈师范哈撒发哈很舒服哈哈
|
||||
阿哈撒发哈师范哈撒发哈很舒服哈哈
|
||||
阿哈撒发哈师范哈撒发哈很舒服哈哈
|
||||
阿哈撒发哈师范哈撒发哈很舒服哈哈
|
||||
阿哈撒发哈师范哈撒发哈很舒服哈哈
|
||||
阿哈撒发哈师范哈撒发哈很舒服哈哈
|
||||
阿哈撒发哈师范哈撒发哈很舒服哈哈
|
||||
阿哈撒发哈师范哈撒发哈很舒服哈哈
|
||||
阿哈撒发哈师范哈撒发哈很舒服哈哈
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { reactive, ref, watch } from 'vue'
|
||||
import { useRouter, useRoute } from 'vue-router'
|
||||
import { useStore } from 'vuex'
|
||||
import { Toast, ImagePreview , Uploader, Dialog } from 'vant';
|
||||
import { rulesForm, resetForm, rulesPhone, rulesFormFBoolean, formatDate } from '@/com/index'
|
||||
import Inputli from '@/components/input-li.vue'
|
||||
import Selectli from '@/components/select-li.vue'
|
||||
import Selectdate from '@/components/select-li-date.vue'
|
||||
import Successmodel from '../components/success.vue'
|
||||
|
||||
import { postApply, getVisitor, getUserNameByTel } from '@/api/user.js'
|
||||
import { uploadApi } from '@/api/upload'
|
||||
/* @data */
|
||||
const router = useRouter()
|
||||
const route = useRoute()
|
||||
|
||||
const store = useStore()
|
||||
const phoneReg = /(^1\d{10}$)|(^[0-9]\d{7}$)/;
|
||||
let form = reactive({
|
||||
name: "",
|
||||
phone: "",
|
||||
hours: "",
|
||||
reason: "",
|
||||
img: "",
|
||||
visitingTel: "",
|
||||
visitingNum: '',
|
||||
})
|
||||
const isSubmit = ref(false)
|
||||
const visitDict = ref([]) // 被访客数据
|
||||
const visitAllDict = ref([]) // 被访客数据
|
||||
const isDisabled = ref(false) // 是否能提交
|
||||
const isSuccess = ref(false) // 是否提交成功
|
||||
const isSelect = ref( false) // 是否显示下拉选择
|
||||
const visitorName = ref( '') // 是否显示下拉选择的名字
|
||||
const telName = ref( '') // 电话查询姓名
|
||||
|
||||
|
||||
/* watch */
|
||||
watch(() => form, (v1, v2) => {
|
||||
isSubmit.value = rulesFormFBoolean(v2)
|
||||
if(v2.name && v2.phone){
|
||||
if(!phoneReg.test(v2.phone)){
|
||||
isDisabled.value = false
|
||||
}else{
|
||||
isDisabled.value = true
|
||||
}
|
||||
}else{
|
||||
isDisabled.value = false
|
||||
}
|
||||
|
||||
},{ deep: true }
|
||||
) // 深度监听 ) // 监听单个
|
||||
/* @method */
|
||||
const onInputTel = (e) =>{
|
||||
}
|
||||
const onInputName = (e) =>{
|
||||
form.visitingTel = ''
|
||||
telName.value = ''
|
||||
}
|
||||
|
||||
const onBlurTel = (phone) =>{
|
||||
console.log(phone)
|
||||
if(rulesPhone(phone)){
|
||||
getUserNameByTel(phone).then(res =>{
|
||||
console.log(res)
|
||||
if(res.data){
|
||||
telName.value = res.data
|
||||
}
|
||||
}).catch(err =>{
|
||||
console.log(err)
|
||||
Dialog.alert({
|
||||
message: err.msg,
|
||||
}).then(() => {
|
||||
// on close
|
||||
});
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
// const onBlurVisitor = () =>{
|
||||
// isSelect.value = false
|
||||
// let item = visitAllDict.value.find(item =>{ return item.userId == form.visitingTel })
|
||||
// if(item){
|
||||
// visitorName.value = item.name
|
||||
// visitDict.value = visitAllDict.value
|
||||
// }else{
|
||||
// visitorName.value = '' // 是否显示下拉选择的名字
|
||||
// visitDict.value = visitAllDict.value
|
||||
|
||||
// }
|
||||
// }
|
||||
// 输入框
|
||||
// const onInputVisior = (e) =>{
|
||||
// visitorName.value = e.target.value
|
||||
// let arr = []
|
||||
// visitAllDict.value.map( item =>{
|
||||
// if(item.name.search(e.target.value) != -1){
|
||||
// arr.push(item)
|
||||
// }
|
||||
// })
|
||||
// visitDict.value = [ ...arr ]
|
||||
// }
|
||||
// 点击选择了拜访对象
|
||||
// const onClickSelect = (item) =>{
|
||||
// form.visitingTel = item.userId
|
||||
// visitorName.value = item.name
|
||||
// isSelect.value = false
|
||||
|
||||
// }
|
||||
// const onClickVisitor = () =>{
|
||||
// isSelect.value = true
|
||||
// }
|
||||
// 点击确认模态框
|
||||
const onClickAffirm = () =>{
|
||||
router.go(-1)
|
||||
}
|
||||
const onClickUpload = () =>{
|
||||
if(isDisabled.value){
|
||||
|
||||
}else{
|
||||
Toast.fail('请填写访客姓名和正确的联系方式!')
|
||||
}
|
||||
}
|
||||
const onClcikSubmit = () =>{
|
||||
if(isSubmit.value){
|
||||
if(rulesPhone(form.phone) && rulesPhone(form.visitingTel)){
|
||||
Toast.loading({ duration: 0, forbidClick: true, message: '提交中', });
|
||||
postApply(form).then(res =>{
|
||||
Toast.clear();
|
||||
isSuccess.value = true
|
||||
})
|
||||
}
|
||||
|
||||
}else{
|
||||
Toast.fail('请先填写完整信息后提交!')
|
||||
}
|
||||
|
||||
}
|
||||
// 上传照片
|
||||
const onChangeFile = (e) =>{
|
||||
console.log(e.target.files[0].size)
|
||||
if(e.target.files[0]){
|
||||
newcompressImg(e.target.files[0], 0.5).then(res =>{
|
||||
let formData = new FormData()
|
||||
// formData.append('file', e.target.files[0])
|
||||
formData.append('file', res.file)
|
||||
formData.append('userId', form.phone)
|
||||
formData.append('name', form.name)
|
||||
Toast.loading({ duration: 0, forbidClick: true, message: '上传中', });
|
||||
uploadApi(formData).then(res =>{
|
||||
Toast.success(res.msg);
|
||||
form.img = res.data
|
||||
})
|
||||
}).catch(err =>{
|
||||
Toast.fail('图片上传失败,请重新上传')
|
||||
})
|
||||
}
|
||||
}
|
||||
const onClickCall = () =>{
|
||||
window.location.href = 'tel:400-040-1573'
|
||||
}
|
||||
const newcompressImg = (file, quality) =>{
|
||||
var qualitys = 0.52
|
||||
if (parseInt((file.size / 1024).toFixed(2)) < 1024) {
|
||||
qualitys = 0.85
|
||||
}
|
||||
if (5 * 1024 < parseInt((file.size / 1024).toFixed(2))) {
|
||||
qualitys = 0.92
|
||||
}
|
||||
if (quality) {
|
||||
qualitys = quality
|
||||
}
|
||||
if (file[0]) {
|
||||
return Promise.all(Array.from(file).map(e => this.compressImg(e,
|
||||
qualitys))) // 如果是 file 数组返回 Promise 数组
|
||||
} else {
|
||||
return new Promise((resolve) => {
|
||||
if ((file.size / 1024).toFixed(2) < 300) {
|
||||
resolve({
|
||||
file: file
|
||||
})
|
||||
} else {
|
||||
const reader = new FileReader() // 创建 FileReader
|
||||
reader.onload = ({
|
||||
target: {
|
||||
result: src
|
||||
}
|
||||
}) => {
|
||||
const image = new Image() // 创建 img 元素
|
||||
image.onload = async() => {
|
||||
const canvas = document.createElement('canvas') // 创建 canvas 元素
|
||||
const context = canvas.getContext('2d')
|
||||
var targetWidth = image.width
|
||||
var targetHeight = image.height
|
||||
var originWidth = image.width
|
||||
var originHeight = image.height
|
||||
if (1 * 1024 <= parseInt((file.size / 1024).toFixed(2)) && parseInt((file.size / 1024).toFixed(2)) <= 10 * 1024) {
|
||||
var maxWidth = 1600
|
||||
var maxHeight = 1600
|
||||
targetWidth = originWidth
|
||||
targetHeight = originHeight
|
||||
// 图片尺寸超过的限制
|
||||
if (originWidth > maxWidth || originHeight > maxHeight) {
|
||||
if (originWidth / originHeight > maxWidth / maxHeight) {
|
||||
// 更宽,按照宽度限定尺寸
|
||||
targetWidth = maxWidth
|
||||
targetHeight = Math.round(maxWidth * (originHeight / originWidth))
|
||||
} else {
|
||||
targetHeight = maxHeight
|
||||
targetWidth = Math.round(maxHeight * (originWidth / originHeight))
|
||||
}
|
||||
}
|
||||
}
|
||||
if (10 * 1024 <= parseInt((file.size / 1024).toFixed(2)) && parseInt((file.size / 1024).toFixed(2)) <= 20 * 1024) {
|
||||
maxWidth = 1400
|
||||
maxHeight = 1400
|
||||
targetWidth = originWidth
|
||||
targetHeight = originHeight
|
||||
// 图片尺寸超过的限制
|
||||
if (originWidth > maxWidth || originHeight > maxHeight) {
|
||||
if (originWidth / originHeight > maxWidth / maxHeight) {
|
||||
// 更宽,按照宽度限定尺寸
|
||||
targetWidth = maxWidth
|
||||
targetHeight = Math.round(maxWidth * (originHeight / originWidth))
|
||||
} else {
|
||||
targetHeight = maxHeight
|
||||
targetWidth = Math.round(maxHeight * (originWidth / originHeight))
|
||||
}
|
||||
}
|
||||
}
|
||||
canvas.width = targetWidth
|
||||
canvas.height = targetHeight
|
||||
context.clearRect(0, 0, targetWidth, targetHeight)
|
||||
context.drawImage(image, 0, 0, targetWidth, targetHeight) // 绘制 canvas
|
||||
const canvasURL = canvas.toDataURL('image/jpeg', qualitys)
|
||||
const buffer = atob(canvasURL.split(',')[1])
|
||||
let length = buffer.length
|
||||
const bufferArray = new Uint8Array(new ArrayBuffer(length))
|
||||
while (length--) {
|
||||
bufferArray[length] = buffer.charCodeAt(length)
|
||||
}
|
||||
const miniFile = new File([bufferArray], file.name, {
|
||||
type: 'image/jpeg'
|
||||
})
|
||||
resolve({
|
||||
file: miniFile,
|
||||
origin: file,
|
||||
beforeSrc: src,
|
||||
afterSrc: canvasURL,
|
||||
beforeKB: Number((file.size / 1024).toFixed(2)),
|
||||
afterKB: Number((miniFile.size / 1024).toFixed(2))
|
||||
})
|
||||
}
|
||||
image.src = src
|
||||
}
|
||||
reader.readAsDataURL(file)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* @setup */
|
||||
const minDate = ref( formatDate(new Date()))
|
||||
console.log(route.query.tel)
|
||||
if(route.query.tel){
|
||||
form.visitingTel = route.query.tel
|
||||
onBlurTel(route.query.tel)
|
||||
}
|
||||
getVisitor().then( res=>{
|
||||
visitDict.value = res.data
|
||||
visitAllDict.value = res.data
|
||||
})
|
||||
|
||||
</script>
|
||||
|
||||
<style lang='scss' scoped>
|
||||
.box{
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: #F5F5F5;
|
||||
padding: 0 0 1.08rem /* 81/75 */;
|
||||
box-sizing: border-box;
|
||||
overflow: auto;
|
||||
.apply-box{
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 8.0267rem /* 602/75 */;
|
||||
background: url('../assets/yuyuebeijing.png') left top/ 100% 100% no-repeat;
|
||||
padding: 1.04rem /* 78/75 */ 0 0;
|
||||
box-sizing: border-box;
|
||||
.text{
|
||||
width: 3.5467rem /* 266/75 */;
|
||||
height: 1.1467rem /* 86/75 */;
|
||||
margin-left: .6133rem /* 46/75 */;
|
||||
}
|
||||
p{
|
||||
line-height: .48rem /* 36/75 */;
|
||||
font-size: $sm-size;
|
||||
font-family: Source Han Sans CN, Source Han Sans CN;
|
||||
font-weight: 400;
|
||||
color: #999999;
|
||||
padding: .1067rem /* 8/75 */ 0 0 .7467rem /* 56/75 */;
|
||||
}
|
||||
.apply-content{
|
||||
width: 9.2rem /* 690/75 */;
|
||||
// height: 4.32rem /* 324/75 */;
|
||||
background: #FFFFFF;
|
||||
border-radius: .2667rem /* 20/75 */;
|
||||
margin: 1.0133rem /* 76/75 */ auto 0;
|
||||
|
||||
h3{
|
||||
padding: .5067rem /* 38/75 */ .3467rem /* 26/75 */ 0 .4533rem /* 34/75 */;
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
color: #222222;
|
||||
font-size: $size30;
|
||||
|
||||
img{
|
||||
width: .5867rem /* 44/75 */;
|
||||
height: .5333rem /* 40/75 */;
|
||||
margin-right: .16rem /* 12/75 */;
|
||||
}
|
||||
span{
|
||||
span{
|
||||
font-size: .32rem /* 24/75 */;
|
||||
color: #666;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
.apply-content-form{
|
||||
width: 100%;
|
||||
padding: 0 .3467rem /* 26/75 */ 0 .4533rem /* 34/75 */;
|
||||
box-sizing: border-box;
|
||||
.search-select-box{
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 1.5733rem /* 118/75 */;
|
||||
// background: #F9F9F9;
|
||||
// border-radius: .2667rem /* 20/75 */;
|
||||
padding: 0 .0267rem /* 2/75 */ 0;
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
// margin-bottom: .2667rem /* 20/75 */;
|
||||
border-bottom: 0.0267rem dashed #D9D9D9;
|
||||
.label{
|
||||
flex: 1;
|
||||
font-size: $size26;
|
||||
color: #333333;
|
||||
line-height: 1.5733rem /* 118/75 */;
|
||||
span{
|
||||
color: #FF0000;
|
||||
margin-right: .0267rem /* 2/75 */;
|
||||
}
|
||||
}
|
||||
.search-select-input{
|
||||
position: relative;
|
||||
|
||||
height: 100%;
|
||||
box-sizing: border-box;
|
||||
input{
|
||||
flex: 1;
|
||||
border: none;
|
||||
outline: none;
|
||||
text-align: right;
|
||||
font-size: $size26;
|
||||
color: #333333;
|
||||
// background: #F9F9F9;
|
||||
padding-right: 0.3733rem;
|
||||
// line-height: 1.5733rem /* 118/75 */;
|
||||
box-sizing: border-box;
|
||||
height: 100%;
|
||||
|
||||
|
||||
}
|
||||
input::-webkit-input-placeholder {
|
||||
font-size: $size26;
|
||||
color: #999999;
|
||||
}
|
||||
.select-box{
|
||||
position: absolute;
|
||||
right: 0;
|
||||
top: 1.8667rem /* 140/75 */;
|
||||
z-index: 5;
|
||||
width: 3.7333rem /* 280/75 */;
|
||||
// max-height: 5.0667rem /* 380/75 */;
|
||||
background: #FFFFFF;
|
||||
box-shadow: 0px 0px .2667rem /* 20/75 */ .1067rem /* 8/75 */ rgba(0,0,0,0.1);
|
||||
border-radius: .0533rem /* 4/75 */ ;
|
||||
// overflow: auto;
|
||||
.select-sroll-box{
|
||||
// position: absolute;
|
||||
// right: 0;
|
||||
// top: 1.8667rem /* 140/75 */;
|
||||
// z-index: 5;
|
||||
width: 100%;
|
||||
max-height: 5.0667rem /* 380/75 */;
|
||||
background: #FFFFFF;
|
||||
// box-shadow: 0px 0px .2667rem /* 20/75 */ .1067rem /* 8/75 */ rgba(0,0,0,0.1);
|
||||
// border-radius: .0533rem /* 4/75 */ ;
|
||||
overflow: auto;
|
||||
}
|
||||
.select-li{
|
||||
height: 1.0133rem /* 76/75 */;
|
||||
background: #fff;
|
||||
|
||||
border-radius: .0533rem /* 4/75 */ .0533rem /* 4/75 */ 0px 0px;
|
||||
font-size: $size26;
|
||||
font-family: Source Han Sans CN, Source Han Sans CN;
|
||||
font-weight: 400;
|
||||
color: #999999;
|
||||
|
||||
line-height: 1.0133rem /* 76/75 */;
|
||||
text-align: center;
|
||||
}
|
||||
.select-active{
|
||||
color: #30BF78;
|
||||
background: #F3FEFB;
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
b{
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
// top: -100%;
|
||||
// width: .2rem /* 15/75 */;
|
||||
// height: 20px;
|
||||
// background: red;
|
||||
// display: block;
|
||||
width: 0;
|
||||
height: 0;
|
||||
border: .16rem /* 12/75 */ solid transparent;
|
||||
border-bottom: .16rem /* 12/75 */ solid #fff;
|
||||
transform: translateY(-100%) translateX(-50%);
|
||||
// margin-top: -.6667rem /* 50/75 */;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
.upload-box{
|
||||
width: 100%;
|
||||
height: 1.9733rem /* 148/75 */;
|
||||
// padding: 0 .6933rem /* 52/75 */ 0 0;
|
||||
padding-right: .3733rem /* 28/75 */;
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
color: #333333;
|
||||
font-size: $size26;
|
||||
label{
|
||||
line-height: 1.9733rem /* 148/75 */;
|
||||
span{
|
||||
color: #FF0000;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
.upload-button{
|
||||
position: relative;
|
||||
width: 1.3333rem /* 100/75 */;
|
||||
height: 1.3333rem /* 100/75 */;
|
||||
background: #FFFFFF;
|
||||
border-radius: .1333rem /* 10/75 */;
|
||||
border: .0267rem /* 2/75 */ dashed #D9D9D9;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
// overflow: hidden;
|
||||
input{
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
width: 1.3333rem /* 100/75 */;
|
||||
height: 1.3333rem /* 100/75 */;
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
.face-img{
|
||||
position: relative;
|
||||
width: 1.3333rem /* 100/75 */;
|
||||
height: 1.3333rem /* 100/75 */;
|
||||
background: #FFFFFF;
|
||||
border-radius: .1333rem /* 10/75 */;
|
||||
img{
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border-radius: .1333rem /* 10/75 */;
|
||||
|
||||
}
|
||||
input{
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
width: 1.3333rem /* 100/75 */;
|
||||
height: 1.3333rem /* 100/75 */;
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.absolute-img{
|
||||
position: absolute;
|
||||
top: .5333rem /* 40/75 */;
|
||||
right: .4rem /* 30/75 */;
|
||||
width: 4.5067rem /* 338/75 */;
|
||||
height: 3.7867rem /* 284/75 */;
|
||||
}
|
||||
}
|
||||
.tips{
|
||||
line-height: .4533rem /* 34/75 */;
|
||||
font-size: .2933rem /* 22/75 */;
|
||||
font-family: Source Han Sans CN, Source Han Sans CN;
|
||||
font-weight: 400;
|
||||
color: #999999;
|
||||
padding: .2133rem /* 16/75 */ 0 .4267rem /* 32/75 */ .8rem /* 60/75 */;
|
||||
box-sizing: border-box;
|
||||
margin-top: 5.3333rem /* 400/75 */;
|
||||
}
|
||||
.visitor-content{
|
||||
width: 9.2rem /* 690/75 */;
|
||||
// height: 4.32rem /* 324/75 */;
|
||||
background: #FFFFFF;
|
||||
border-radius: .2667rem /* 20/75 */;
|
||||
margin: 0 auto 0;
|
||||
// margin-top: 5.3333rem /* 400/75 */;
|
||||
|
||||
h3{
|
||||
padding: .5067rem /* 38/75 */ .3467rem /* 26/75 */ 0 .4533rem /* 34/75 */;
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
color: #222222;
|
||||
font-size: $size30;
|
||||
|
||||
img{
|
||||
width: .5867rem /* 44/75 */;
|
||||
height: .5333rem /* 40/75 */;
|
||||
margin-right: .16rem /* 12/75 */;
|
||||
}
|
||||
span{
|
||||
span{
|
||||
font-size: .32rem /* 24/75 */;
|
||||
color: #666;
|
||||
}
|
||||
}
|
||||
}
|
||||
.visitor-content-form{
|
||||
width: 100%;
|
||||
padding: 0 .3467rem /* 26/75 */ .16rem /* 12/75 */ .4533rem /* 34/75 */;
|
||||
box-sizing: border-box;
|
||||
|
||||
.upload-box{
|
||||
width: 100%;
|
||||
height: 1.9733rem /* 148/75 */;
|
||||
// padding: 0 .6933rem /* 52/75 */ 0 0;
|
||||
padding-right: .3733rem /* 28/75 */;
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
color: #333333;
|
||||
font-size: $size26;
|
||||
label{
|
||||
line-height: 1.9733rem /* 148/75 */;
|
||||
span{
|
||||
color: #FF0000;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
.upload-button{
|
||||
position: relative;
|
||||
width: 1.3333rem /* 100/75 */;
|
||||
height: 1.3333rem /* 100/75 */;
|
||||
background: #FFFFFF;
|
||||
border-radius: .1333rem /* 10/75 */;
|
||||
border: .0267rem /* 2/75 */ dashed #D9D9D9;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
// overflow: hidden;
|
||||
input{
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
width: 1.3333rem /* 100/75 */;
|
||||
height: 1.3333rem /* 100/75 */;
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
.face-img{
|
||||
position: relative;
|
||||
width: 1.3333rem /* 100/75 */;
|
||||
height: 1.3333rem /* 100/75 */;
|
||||
background: #FFFFFF;
|
||||
border-radius: .1333rem /* 10/75 */;
|
||||
img{
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border-radius: .1333rem /* 10/75 */;
|
||||
|
||||
}
|
||||
input{
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
width: 1.3333rem /* 100/75 */;
|
||||
height: 1.3333rem /* 100/75 */;
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.disclaimer-box{
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
input{
|
||||
margin-right: .1333rem /* 10/75 */;
|
||||
}
|
||||
span{
|
||||
color: #30BF78;
|
||||
}
|
||||
}
|
||||
.tel-tips{
|
||||
line-height: .4533rem /* 34/75 */;
|
||||
font-size: .2933rem /* 22/75 */;
|
||||
font-family: Source Han Sans CN, Source Han Sans CN;
|
||||
font-weight: 400;
|
||||
color: #999999;
|
||||
padding: 0 0 .4267rem /* 32/75 */ .8rem /* 60/75 */;
|
||||
box-sizing: border-box;
|
||||
margin-top: -.24rem /* 18/75 */;
|
||||
span{
|
||||
color: #409eff;
|
||||
}
|
||||
}
|
||||
.submit-button{
|
||||
display: block;
|
||||
width: 6.72rem /* 504/75 */;
|
||||
height: 1.12rem /* 84/75 */;
|
||||
background: #D9D9D9;
|
||||
border-radius: 1.3333rem /* 100/75 */ ;
|
||||
opacity: 1;
|
||||
font-size: $size30;
|
||||
font-family: Source Han Sans CN, Source Han Sans CN;
|
||||
font-weight: 500;
|
||||
color: #222222;
|
||||
border: none;
|
||||
outline: none;
|
||||
margin: 1.0133rem /* 76/75 */ auto 0;
|
||||
}
|
||||
.active-button{
|
||||
background-color: #30BF78;
|
||||
color: #fff;
|
||||
}
|
||||
}
|
||||
.disclaimer-model-fixed{
|
||||
position: fixed;
|
||||
left: 0;
|
||||
top: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: #fff;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
padding: .4rem /* 30/75 */;
|
||||
box-sizing: border-box;
|
||||
h3{
|
||||
font-size: .4267rem /* 32/75 */;
|
||||
line-height: .8rem /* 60/75 */;
|
||||
text-align: center;
|
||||
}
|
||||
.disclaimer-model{
|
||||
flex: 1;
|
||||
line-height: .5333rem /* 40/75 */;
|
||||
text-align: justify;
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
||||
@@ -0,0 +1,404 @@
|
||||
<template>
|
||||
<div class="box">
|
||||
<header>
|
||||
<h2>门禁人脸信息</h2>
|
||||
<h3> <img src="../assets/img/dunpai.png" alt=""> 公司门禁系统人脸上传和查看 </h3>
|
||||
<div class="entering-box">
|
||||
<img src="../assets/img/shenfenzheng.png" alt="">
|
||||
<div class="entering-center">
|
||||
<p>特殊人员录入</p>
|
||||
<p>暂未进入公司钉钉组织人员</p>
|
||||
</div>
|
||||
<button @click="onClickGoSpecialCrowd" class="entering-button">录入</button>
|
||||
</div>
|
||||
</header>
|
||||
<div class="content">
|
||||
<h2>通讯录</h2>
|
||||
<div class="content-box" >
|
||||
<div class="nav">
|
||||
<div @click="onClickDept(item.deptId)" v-for="item in deptArr" class="li" :class="item.deptId == deptId ? 'active' : ''" :style=" item.name.length >= 6 ? 'padding-right: 0.28rem;' : '' " :key="item.userId">
|
||||
{{ item.name }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="user-content">
|
||||
<div class="user-scroll">
|
||||
<div v-for="item in userArr" class="user-list">
|
||||
<div @click="onClickPreviewImg(item.img)" class="img-box">
|
||||
<img v-if="item.img" :src="item.img" alt="">
|
||||
</div>
|
||||
<div class="name">{{ item.name }}</div>
|
||||
<div @click="onClcikUser(item)" v-if="item.img" class="button">查看</div>
|
||||
<div @click="onClcikUser(item)" v-else class="button active-button">上传</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<Facemodel @change="onChangeFile" @cancel="isFace = false; form.face =''" @save="onClciksave" v-if="isFace" :faceImg="form.face" />
|
||||
|
||||
</template>
|
||||
<script setup>
|
||||
import { rulesPhone, compareTime, timeDiff,formatDate } from '../com/index.js'
|
||||
// import { getShop, getKind } from '../api/user.js'
|
||||
import { reactive, ref } from 'vue'
|
||||
import { Toast, ImagePreview, Skeleton } from 'vant';
|
||||
import dd from 'dingtalk-jsapi'
|
||||
import { getToken, getDept, getUserListByDept, putUserId } from '@/api/doorAdmin.js'
|
||||
import Facemodel from '@/components/face-model.vue'
|
||||
import { uploadApi } from '@/api/upload'
|
||||
import { useRouter } from 'vue-router';
|
||||
|
||||
|
||||
const router = useRouter()
|
||||
const deptArr = ref([]) // 部门数据
|
||||
const userArr = ref([]) // 用户
|
||||
const deptId = ref('') // 选中的部门Id
|
||||
const isFace = ref(false)
|
||||
const form = reactive({ //
|
||||
face: '',
|
||||
userId: '',
|
||||
name: ''
|
||||
})
|
||||
const token = ref('')
|
||||
const isLoading = ref(false)
|
||||
localStorage.setItem('redirect', '/home')
|
||||
token.value = localStorage.getItem('token')
|
||||
|
||||
// setTimeout( ()=>{
|
||||
// form.face = 'https://img0.baidu.com/it/u=3229206321,1418550973&fm=253&fmt=auto&app=138&f=JPEG?w=800&h=500'
|
||||
// }, 2000)
|
||||
|
||||
// method
|
||||
// 点击预栏图片
|
||||
const onClickPreviewImg = (img) =>{
|
||||
dd.previewImage({
|
||||
urls: [img
|
||||
],
|
||||
current: 1,
|
||||
success: () => {},
|
||||
fail: () => {},
|
||||
complete: () => {},
|
||||
});
|
||||
}
|
||||
// 点击切换部门
|
||||
const onClickDept = (Id) =>{
|
||||
if(deptId.value != Id){
|
||||
deptId.value = Id
|
||||
userList()
|
||||
}
|
||||
}
|
||||
// 点击上传了文件
|
||||
const onChangeFile = (file) =>{
|
||||
console.log(file)
|
||||
if(file){
|
||||
let reader = new FileReader()
|
||||
reader.readAsDataURL(file) // 转base64
|
||||
reader.onload = () =>{ // 简化代码 - 转换完成
|
||||
form.face = reader.result
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
// 点击保存
|
||||
const onClciksave = (file) =>{
|
||||
if(form.face && file){
|
||||
let formData = new FormData()
|
||||
formData.append('file', file)
|
||||
formData.append('userId', form.userId)
|
||||
formData.append('name', form.name)
|
||||
Toast.loading({ duration: 0, forbidClick: true, message: '上传中', });
|
||||
uploadApi(formData).then(res =>{
|
||||
form.face = res.data
|
||||
let obj = { userId: form.userId, img: form.face }
|
||||
putUserId(obj).then(response =>{
|
||||
userList()
|
||||
isFace.value = false
|
||||
Toast.success(response.msg);
|
||||
})
|
||||
})
|
||||
}else if(form.face && !file ){ // 说明之前有数据现在没传
|
||||
isFace.value = false
|
||||
}else if(!form.face && !file){
|
||||
Toast.fail('请先上传照片!');
|
||||
}
|
||||
// if(file){ // 文件是否上传了
|
||||
// let formData = new FormData()
|
||||
// formData.append('face', file)
|
||||
// formData.append('userId', form.userId)
|
||||
// formData.append('name', form.name)
|
||||
// Toast.loading({ duration: 0, forbidClick: true, message: '保存中', });
|
||||
// uploadApi(formData).then(res =>{
|
||||
// Toast.success(res.msg);
|
||||
// form.img = res.data
|
||||
|
||||
// })
|
||||
// }else{
|
||||
// Toast.fail('请先上传照片!');
|
||||
// }
|
||||
|
||||
}
|
||||
// 点击用户上传照片或查看
|
||||
const onClcikUser = (item) =>{
|
||||
console.log(item)
|
||||
isFace.value = true
|
||||
form.face = item.img
|
||||
form.userId = item.userId
|
||||
form.name = item.name
|
||||
}
|
||||
const login = () =>{
|
||||
Toast.loading({ duration: 0, forbidClick: true, message: '登录中', });
|
||||
dd.getAuthCode({
|
||||
corpId: 'ding03f8e88dde9b426835c2f4657eb6378f',
|
||||
success: (res) => {
|
||||
const { code } = res;
|
||||
localStorage.removeItem('token');
|
||||
localStorage.removeItem('user');
|
||||
getToken(code).then(data =>{
|
||||
localStorage.setItem('user', data.data)
|
||||
localStorage.setItem('token', data.data.authorization)
|
||||
Toast.clear()
|
||||
Toast.success('登录成功')
|
||||
deptList()
|
||||
})
|
||||
}
|
||||
});
|
||||
}
|
||||
// 获取部门用户
|
||||
const userList = () =>{
|
||||
isLoading.value = false
|
||||
getUserListByDept(deptId.value).then(res =>{
|
||||
isLoading.value = true
|
||||
userArr.value = res.data
|
||||
|
||||
})
|
||||
}
|
||||
// 获取部门列表
|
||||
const deptList = () =>{
|
||||
getDept().then(res =>{
|
||||
deptArr.value = res.data
|
||||
deptId.value = res.data[0].deptId
|
||||
userList()
|
||||
})
|
||||
}
|
||||
// 跳转特殊人员
|
||||
const onClickGoSpecialCrowd = () =>{
|
||||
router.push('/specialCrowd')
|
||||
}
|
||||
|
||||
|
||||
if(token.value){
|
||||
// localStorage.setItem('token', 123)
|
||||
deptList()
|
||||
}else{
|
||||
login()
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.box{
|
||||
display: flex;
|
||||
flex-direction:column ;
|
||||
header{
|
||||
width: 100%;
|
||||
height: 5.8933rem /* 442/75 */;
|
||||
background: url('../assets/img/shouyebeijing.png') left top/100% 100% no-repeat;
|
||||
h2{
|
||||
line-height: 1.12rem /* 84/75 */;
|
||||
font-size: .7467rem /* 56/75 */;
|
||||
font-family: Source Han Sans CN, Source Han Sans CN;
|
||||
font-weight: 500;
|
||||
color: #FFFFFF;
|
||||
padding: .8533rem /* 64/75 */ 0 0 .64rem /* 48/75 */;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
h3{
|
||||
display: flex;
|
||||
padding: .32rem /* 24/75 */ 0 0 .7467rem /* 56/75 */;
|
||||
box-sizing: border-box;
|
||||
line-height: .5333rem /* 40/75 */;
|
||||
font-size: $sm-size;
|
||||
font-family: Source Han Sans CN, Source Han Sans CN;
|
||||
font-weight: 400;
|
||||
color: #FFFFFF;
|
||||
img{
|
||||
width: .5333rem /* 40/75 */;
|
||||
height: .5333rem /* 40/75 */;
|
||||
margin-right: .1067rem /* 8/75 */;
|
||||
|
||||
}
|
||||
}
|
||||
.entering-box{
|
||||
width: 8rem /* 600/75 */;
|
||||
height: 1.6rem /* 120/75 */;
|
||||
margin: .6667rem /* 50/75 */ auto 0;
|
||||
background: #202F44;
|
||||
border-radius: .5333rem /* 40/75 */ .5333rem /* 40/75 */ 0px 0px;
|
||||
padding: 0 .4rem /* 30/75 */ .8rem /* 60/75 */ .4533rem /* 34/75 */;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
img{
|
||||
width: .6133rem /* 46/75 */;
|
||||
height: .48rem /* 36/75 */;
|
||||
margin-right: .2933rem /* 22/75 */;
|
||||
}
|
||||
.entering-center{
|
||||
flex: 1;
|
||||
font-size: $md-size;
|
||||
font-family: Source Han Sans CN, Source Han Sans CN;
|
||||
font-weight: 500;
|
||||
color: #FFFFFF;
|
||||
p:nth-child(1){
|
||||
line-height: .56rem /* 42/75 */;
|
||||
padding: .2933rem /* 22/75 */ 0 0;
|
||||
}
|
||||
p:nth-child(2){
|
||||
line-height: .4533rem /* 34/75 */;
|
||||
font-size: $sm-size;
|
||||
font-weight: 400;
|
||||
color: #B6B7B8;
|
||||
}
|
||||
}
|
||||
.entering-button{
|
||||
width: 1.4667rem /* 110/75 */;
|
||||
height: .6933rem /* 52/75 */;
|
||||
background: #F6C976;
|
||||
border-radius: .5333rem /* 40/75 */;
|
||||
outline: none;
|
||||
font-size: $size26;
|
||||
font-family: Source Han Sans CN, Source Han Sans CN;
|
||||
font-weight: 500;
|
||||
color: #202F44;
|
||||
border: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
.content{
|
||||
width: 100%;
|
||||
background: #FFFFFF;
|
||||
border-radius: .5333rem /* 40/75 */ .5333rem /* 40/75 */ 0px 0px;
|
||||
margin-top: -20px;
|
||||
overflow: auto;
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column ;
|
||||
h2{
|
||||
padding: .4267rem /* 32/75 */ .48rem /* 36/75 */;
|
||||
box-sizing: border-box;
|
||||
line-height: .8rem /* 60/75 */;
|
||||
font-size: .5333rem /* 40/75 */;
|
||||
font-family: Source Han Sans CN, Source Han Sans CN;
|
||||
font-weight: 500;
|
||||
color: #222222;
|
||||
}
|
||||
.content-box{
|
||||
overflow: auto;
|
||||
display: flex;
|
||||
flex: 1;
|
||||
.nav{
|
||||
width: 3.6533rem /* 274/75 */;
|
||||
height: 100%;
|
||||
// width: 360px;
|
||||
padding: 0 0 0 .4rem /* 30/75 */;
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
align-content: flex-start;
|
||||
// flex-direction: column;
|
||||
flex-wrap: wrap;
|
||||
|
||||
border-right: .0267rem /* 2/75 */ dashed #D9D9D9;
|
||||
|
||||
.li{
|
||||
display:block;
|
||||
|
||||
box-sizing: border-box;
|
||||
height: .9067rem /* 68/75 */;
|
||||
line-height: .9067rem /* 68/75 */;
|
||||
border-radius: 0px .8rem /* 60/75 */ .8rem /* 60/75 */ 0px ;
|
||||
padding: 0 .48rem /* 36/75 */ 0 .24rem /* 18/75 */;
|
||||
|
||||
box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
font-size: $md-size;
|
||||
font-family: Source Han Sans CN, Source Han Sans CN;
|
||||
font-weight: 400;
|
||||
color: #5F6583;
|
||||
margin-bottom: .28rem /* 21/75 */;
|
||||
}
|
||||
.active{
|
||||
color: #FFFFFF;
|
||||
background: #448CF7;
|
||||
|
||||
}
|
||||
}
|
||||
.user-content{
|
||||
flex: 1;
|
||||
height: 100%;
|
||||
overflow: auto;
|
||||
|
||||
.user-scroll{
|
||||
width: 100%;
|
||||
// height: 100%;
|
||||
}
|
||||
|
||||
.user-list{
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 0 .4rem /* 30/75 */;
|
||||
box-sizing: border-box;
|
||||
margin-bottom: .5333rem /* 40/75 */;
|
||||
.img-box{
|
||||
width: .9867rem /* 74/75 */;
|
||||
height: .9867rem /* 74/75 */;
|
||||
border-radius:.1333rem /* 10/75 */;
|
||||
|
||||
background: #D9D9D9;
|
||||
img{
|
||||
display: block;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border-radius:.1333rem /* 10/75 */;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.name{
|
||||
padding: 0 0 0 .2933rem /* 22/75 */;
|
||||
box-sizing: border-box;
|
||||
flex: 1;
|
||||
line-height: .9867rem /* 74/75 */;
|
||||
font-size: $size30;
|
||||
font-family: Source Han Sans CN, Source Han Sans CN;
|
||||
font-weight: 400;
|
||||
color: #4B4C4E;
|
||||
}
|
||||
.button{
|
||||
width: 1.2267rem /* 92/75 */;
|
||||
height: .6667rem /* 50/75 */;
|
||||
background: #EDEDED;
|
||||
border-radius:.1333rem /* 10/75 */;
|
||||
border: none;
|
||||
outline: none;
|
||||
font-size: $sm-size;
|
||||
font-family: Source Han Sans CN, Source Han Sans CN;
|
||||
font-weight: 400;
|
||||
color: #999999;
|
||||
box-sizing: border-box;
|
||||
text-align: center;
|
||||
line-height: .6667rem /* 50/75 */;
|
||||
}
|
||||
.active-button{
|
||||
background: #EBFCF4;
|
||||
border: .0267rem /* 2/75 */ solid #30BF78;
|
||||
color: #30BF78;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,14 @@
|
||||
<template>
|
||||
<div>
|
||||
登录
|
||||
<button @click="onClcikGo">注册</button>
|
||||
</div>
|
||||
</template>
|
||||
<script setup>
|
||||
import { useRouter } from 'vue-router';
|
||||
const router = useRouter()
|
||||
console.log(router)
|
||||
const onClcikGo = () =>{
|
||||
router.push('/register')
|
||||
}
|
||||
</script>
|
||||
@@ -0,0 +1,5 @@
|
||||
<template>
|
||||
<div>
|
||||
注册
|
||||
</div>
|
||||
</template>
|
||||
@@ -0,0 +1,370 @@
|
||||
<template>
|
||||
<div class='box'>
|
||||
<header @click="onClickAdd">
|
||||
<img src="../assets/img/baiseshenfenzheng.png" alt="">
|
||||
<span>新增特殊人员</span>
|
||||
</header>
|
||||
<h2>
|
||||
<div class="title">已录入人员 <img class="subscript" src="../assets/img/xiabiao.png" alt=""></div>
|
||||
<div class="tips">注:人员信息删除后不可在刷脸通过门禁</div>
|
||||
</h2>
|
||||
<div class="content">
|
||||
<div class="search-box">
|
||||
<input type="text" placeholder="输入员工姓名进行搜索">
|
||||
<img src="../assets/img/sousuo.png" alt="">
|
||||
</div>
|
||||
<div v-if="specialArr.length" class="scroll-content">
|
||||
<div v-for="item in specialArr" class="user-list" :key="item.id">
|
||||
<div class="img-box">
|
||||
<img @click="onClickPreviewImg(item.img)" v-if="item.img" :src="item.img" alt="">
|
||||
</div>
|
||||
<div class="name">
|
||||
<span>{{ item.name }}</span>
|
||||
<p>联系方式:{{ item.tel }}</p>
|
||||
</div>
|
||||
<div @click="onClickLook(item)" class="button">查看</div>
|
||||
<div @click="onClickDelete(item)" class="remove-button">删除</div>
|
||||
</div>
|
||||
</div>
|
||||
<div v-else class="scroll-content">
|
||||
<div class="no-have">
|
||||
暂无特殊人员
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<Addmodel @cancel="isAddmodel = false" @save="onClciksave" v-if="isAddmodel" />
|
||||
<Removemodel @delete="onClickDeleteAffirm" @cancel="isRemovemodel = false" v-if="isRemovemodel" />
|
||||
<Facemodel @save="onClickSaveFace" @change="onChangeFace" @cancel="isFacemodel = false" v-if="isFacemodel" :faceImg="updateFaceImg" />
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, reactive } from 'vue'
|
||||
import { useRouter } from 'vue-router'
|
||||
import { useStore } from 'vuex'
|
||||
import { rulesForm, resetForm, rulesPhone } from '@/com/index'
|
||||
import Addmodel from '@/components/add-model.vue'
|
||||
import Removemodel from '@/components/remove-model.vue'
|
||||
import Facemodel from '@/components/face-model.vue'
|
||||
import dd from 'dingtalk-jsapi'
|
||||
import { getToken, getDept, getUserListByDept, putUserId, getSpecial, putSpecial, postSpecial, putSpecialFace } from '@/api/doorAdmin.js'
|
||||
import { uploadApi } from '@/api/upload'
|
||||
import { Toast } from 'vant'
|
||||
|
||||
|
||||
/* @data */
|
||||
const router = useRouter()
|
||||
const store = useStore()
|
||||
const isAddmodel = ref(false) // 新增特殊人员模态框
|
||||
const isRemovemodel = ref(false) // 删除特殊人员模态框
|
||||
const isFacemodel = ref(false) // 人脸模态框
|
||||
const specialArr = ref([]) // 特殊人员数据
|
||||
const update = ref() // 特殊人员修改数据
|
||||
|
||||
const deleteId = ref('') // 需要删除的id
|
||||
const updateFaceImg = ref() // 修改人脸照片base64或之前的数据
|
||||
const query = reactive({
|
||||
current: -1,
|
||||
size: 10,
|
||||
})
|
||||
/* @setup */
|
||||
|
||||
/* @method */
|
||||
// 点击预栏图片
|
||||
const onClickPreviewImg = (img) =>{
|
||||
dd.previewImage({
|
||||
urls: [img
|
||||
],
|
||||
current: 1,
|
||||
success: () => {},
|
||||
fail: () => {},
|
||||
complete: () => {},
|
||||
});
|
||||
}
|
||||
const onChangeFace = (file) =>{
|
||||
if(file){
|
||||
let reader = new FileReader()
|
||||
reader.readAsDataURL(file) // 转base64
|
||||
reader.onload = () =>{ // 简化代码 - 转换完成
|
||||
updateFaceImg.value = reader.result
|
||||
}
|
||||
}
|
||||
}
|
||||
// 点击确认保存修改图片
|
||||
const onClickSaveFace = (file) =>{
|
||||
console.log(update.value)
|
||||
if(file){
|
||||
let formData = new FormData()
|
||||
formData.append('file', file)
|
||||
formData.append('userId', update.value.tel)
|
||||
formData.append('name', update.value.name)
|
||||
Toast.loading({ duration: 0, forbidClick: true, message: '上传中', });
|
||||
uploadApi(formData).then(res =>{
|
||||
// form.face = res.data
|
||||
let obj = { id: update.value.id, img: res.data }
|
||||
putSpecialFace(obj).then(response =>{
|
||||
specialList()
|
||||
isFacemodel.value = false
|
||||
Toast.success(response.msg);
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
// 点击查看按钮
|
||||
const onClickLook = (item) =>{
|
||||
update.value = item
|
||||
isFacemodel.value = true
|
||||
updateFaceImg.value = item.img
|
||||
console.log(item)
|
||||
}
|
||||
// 点击新增特殊人员按钮
|
||||
const onClickAdd = () =>{
|
||||
isAddmodel.value = true
|
||||
}
|
||||
// 确认删除
|
||||
const onClickDeleteAffirm = () =>{
|
||||
console.log(deleteId.value)
|
||||
putSpecial(deleteId.value).then(res =>{
|
||||
Toast.success(res.msg)
|
||||
isRemovemodel.value = false
|
||||
specialList()
|
||||
})
|
||||
}
|
||||
// 点击删除
|
||||
const onClickDelete = (item) =>{
|
||||
console.log(item)
|
||||
deleteId.value = item.id
|
||||
isRemovemodel.value = true
|
||||
}
|
||||
// 点击保存
|
||||
const onClciksave = (specialForm) =>{
|
||||
console.log(specialForm)
|
||||
if( !specialForm.face ){
|
||||
Toast.fail('请上传人脸照片!')
|
||||
}else if( !specialForm.userId ){
|
||||
Toast.fail('请输入人员联系方式!')
|
||||
}else if( !specialForm.name){
|
||||
Toast.fail('请输入人员姓名!')
|
||||
}else {
|
||||
if(rulesPhone(specialForm.userId)){
|
||||
let formData = new FormData()
|
||||
formData.append('file', specialForm.face)
|
||||
formData.append('userId', specialForm.userId)
|
||||
formData.append('name', specialForm.name)
|
||||
Toast.loading({ duration: 0, forbidClick: true, message: '保存中', });
|
||||
uploadApi(formData).then(res =>{
|
||||
let obj = { tel: specialForm.userId, img: res.data, name: specialForm.name }
|
||||
postSpecial(obj).then(response =>{
|
||||
specialList()
|
||||
isAddmodel.value = false
|
||||
Toast.success(response.msg);
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
// 特殊人员列表
|
||||
const specialList = () =>{
|
||||
getSpecial(query).then(res =>{
|
||||
specialArr.value = res.data
|
||||
})
|
||||
}
|
||||
|
||||
/* @setup */
|
||||
specialList()
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
<style lang='scss' scoped>
|
||||
.box{
|
||||
padding: .6667rem /* 50/75 */ .4rem /* 30/75 */ .4rem /* 30/75 */;
|
||||
box-sizing: border-box;
|
||||
background: #F4F6F7;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
header{
|
||||
width: 8.4267rem /* 632/75 */;
|
||||
height: 1.6rem /* 120/75 */;
|
||||
background: linear-gradient(108deg, #7CB5FF 0%, #448CF7 84%);
|
||||
box-shadow: 0px .1067rem /* 8/75 */ .2667rem /* 20/75 */ 0px #C2DBFF;
|
||||
border-radius: 1.3333rem /* 100/75 */;
|
||||
display: flex;
|
||||
// justify-content: center;
|
||||
align-items: center;
|
||||
padding: 0 0 0 2.4533rem /* 184/75 */;
|
||||
box-sizing: border-box;
|
||||
margin: 0 auto;
|
||||
img{
|
||||
width: .72rem /* 54/75 */;
|
||||
height: .6933rem /* 52/75 */;
|
||||
margin-right: .2133rem /* 16/75 */;
|
||||
}
|
||||
span{
|
||||
font-size: $lg-size;
|
||||
font-family: Source Han Sans CN, Source Han Sans CN;
|
||||
font-weight: 500;
|
||||
color: #FFFFFF;
|
||||
line-height: 1.6rem /* 120/75 */;
|
||||
|
||||
}
|
||||
}
|
||||
h2{
|
||||
margin-top: .64rem /* 48/75 */;
|
||||
height: 1.2533rem /* 94/75 */;
|
||||
display: flex;
|
||||
.title{
|
||||
position: relative;
|
||||
width: 3.0933rem /* 232/75 */;
|
||||
line-height: 1.2533rem /* 94/75 */;
|
||||
font-size: $lg-size;
|
||||
font-family: Source Han Sans CN, Source Han Sans CN;
|
||||
font-weight: 500;
|
||||
color: #222222;
|
||||
background: url('../assets/img/tixing.png') left top/100% 100% no-repeat;
|
||||
border-radius: .2667rem /* 20/75 */ .2667rem /* 20/75 */ 0 0 ;
|
||||
text-align: center;
|
||||
.subscript{
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
bottom: 0;
|
||||
transform: translateX(-50%) translateY(50%);
|
||||
width: .6133rem /* 46/75 */;
|
||||
height: .2667rem /* 20/75 */;
|
||||
}
|
||||
}
|
||||
|
||||
.tips{
|
||||
font-size: $sm-size;
|
||||
font-family: Source Han Sans CN, Source Han Sans CN;
|
||||
font-weight: 400;
|
||||
color: #999999;
|
||||
margin-left: .5333rem /* 40/75 */;
|
||||
line-height: 1.2533rem /* 94/75 */;
|
||||
|
||||
}
|
||||
}
|
||||
.content{
|
||||
flex: 1;
|
||||
overflow: auto;
|
||||
background-color: #FFFFFF;
|
||||
border-radius:0 .2667rem /* 20/75 */ .2667rem /* 20/75 */ .2667rem /* 20/75 */;
|
||||
padding:.5867rem /* 44/75 */ .3733rem /* 28/75 */;
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
.search-box{
|
||||
width: 100%;
|
||||
height: .9333rem /* 70/75 */;
|
||||
background: #EEEFF3;
|
||||
border-radius: .1333rem /* 10/75 */;
|
||||
padding: 0 .4533rem /* 34/75 */ 0 .3467rem /* 26/75 */ ;
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: .6667rem /* 50/75 */;
|
||||
input{
|
||||
flex: 1;
|
||||
background: #EEEFF3;
|
||||
padding: 0 .6667rem /* 50/75 */ 0 0;
|
||||
box-sizing: border-box;
|
||||
line-height: .9333rem /* 70/75 */;
|
||||
outline: none;
|
||||
border: none;
|
||||
font-size: $sm-size;
|
||||
}
|
||||
input::-webkit-input-placeholder{
|
||||
color: #CCCCCC;
|
||||
font-size: $sm-size;
|
||||
}
|
||||
img{
|
||||
width: .48rem /* 36/75 */;
|
||||
height: .48rem /* 36/75 */;
|
||||
}
|
||||
}
|
||||
.scroll-content{
|
||||
flex: 1;
|
||||
overflow: auto;
|
||||
.user-list{
|
||||
display: flex;
|
||||
align-items: center;
|
||||
// padding: 0 .4rem /* 30/75 */;
|
||||
box-sizing: border-box;
|
||||
margin-bottom: .5333rem /* 40/75 */;
|
||||
.img-box{
|
||||
width: .9867rem /* 74/75 */;
|
||||
height: .9867rem /* 74/75 */;
|
||||
border-radius:.1333rem /* 10/75 */;
|
||||
|
||||
background: #D9D9D9;
|
||||
img{
|
||||
display: block;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border-radius:.1333rem /* 10/75 */;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.name{
|
||||
padding: 0 0 0 .2933rem /* 22/75 */;
|
||||
box-sizing: border-box;
|
||||
flex: 1;
|
||||
// line-height: .9867rem /* 74/75 */;
|
||||
font-size: $size30;
|
||||
font-family: Source Han Sans CN, Source Han Sans CN;
|
||||
font-weight: 400;
|
||||
color: #4B4C4E;
|
||||
span{
|
||||
line-height: .6133rem /* 46/75 */;
|
||||
color: #4B4C4E;
|
||||
}
|
||||
p{
|
||||
font-size: $sm-size;
|
||||
line-height: .4533rem /* 34/75 */;
|
||||
color: #B6B7B8;
|
||||
|
||||
}
|
||||
}
|
||||
.button{
|
||||
width: 1.2267rem /* 92/75 */;
|
||||
height: .6667rem /* 50/75 */;
|
||||
background: #EDEDED;
|
||||
border-radius:.1333rem /* 10/75 */;
|
||||
border: none;
|
||||
outline: none;
|
||||
font-size: $sm-size;
|
||||
font-family: Source Han Sans CN, Source Han Sans CN;
|
||||
font-weight: 400;
|
||||
color: #999999;
|
||||
box-sizing: border-box;
|
||||
text-align: center;
|
||||
line-height: .6667rem /* 50/75 */;
|
||||
margin-right: .2133rem /* 16/75 */;
|
||||
}
|
||||
.remove-button{
|
||||
width: 1.2267rem /* 92/75 */;
|
||||
height: .6667rem /* 50/75 */;
|
||||
background: #FFE9E4;
|
||||
border-radius:.1333rem /* 10/75 */;
|
||||
border: none;
|
||||
outline: none;
|
||||
font-size: $sm-size;
|
||||
font-family: Source Han Sans CN, Source Han Sans CN;
|
||||
font-weight: 400;
|
||||
color: #FF6643;
|
||||
box-sizing: border-box;
|
||||
text-align: center;
|
||||
line-height: .6667rem /* 50/75 */;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
.scroll-content::-webkit-scrollbar {
|
||||
display: none; /* Chrome Safari */
|
||||
} // 超出部分隐藏滚动条
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,340 @@
|
||||
<template>
|
||||
<div class='box'>
|
||||
<header>
|
||||
<div class="header-top">
|
||||
<h1><img src="../assets/userhome/dingsheng.png" alt=""></h1>
|
||||
<img class="h3" src="../assets/userhome/zhiengfangke.png" alt="">
|
||||
<p>欢迎进入鼎盛无际智能访客系统</p>
|
||||
</div>
|
||||
<div class="plate-box">
|
||||
<div @click="onClickGo('/apply')" class="list">
|
||||
<h4>来访预约</h4>
|
||||
<p>登记来访</p>
|
||||
<img class="icon-arrowhead" src="../assets/userhome/youjiantou.png" alt="">
|
||||
<img class="img" src="../assets/userhome/ren.png" alt="">
|
||||
</div>
|
||||
<div @click="onClickGo('/applyRecord')" class="list">
|
||||
<h4>预约记录</h4>
|
||||
<p>记录查询</p>
|
||||
<img class="icon-arrowhead" src="../assets/userhome/youjiantou.png" alt="">
|
||||
<img class="img" src="../assets/userhome/fang.png" alt="">
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
<div class="content">
|
||||
<div class="contact-box">
|
||||
<h3><span>联系我们 </span><p><b class="square"></b></p> </h3>
|
||||
<div class="time">法定工作日 09:00-12:00 14:00-18:00</div>
|
||||
<p @click="onClickCall" class="text-list">
|
||||
<img src="../assets/userhome/dianhua.png" alt="">
|
||||
<span>服务热线:400040-1573</span>
|
||||
</p>
|
||||
<p class="text-list">
|
||||
<img src="../assets/userhome/dingwei.png" alt="">
|
||||
<span>地址:四川省泸州市高新区众创中心12楼</span>
|
||||
</p>
|
||||
</div>
|
||||
<div class="controls-box">
|
||||
<img class="icon-img" src="../assets/caozuo.png" >
|
||||
<p>操作手册</p>
|
||||
<img class="icon-right" src="../assets/youjiantou.png" alt="">
|
||||
<a href="https://www.yuque.com/zhoupangpang-m5aid/qp94nz/hhvxk757iolg8gah?singleDoc#"></a>
|
||||
</div>
|
||||
<!-- <div><button @click="onClickUpdate">修改token</button></div> -->
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref } from 'vue'
|
||||
import { useRouter } from 'vue-router'
|
||||
import { useStore } from 'vuex'
|
||||
import { rulesForm, resetForm, rulesPhone } from '@/com/index'
|
||||
import { getWeChatCode, login } from '../api/user'
|
||||
import { Toast, ImagePreview } from 'vant';
|
||||
|
||||
/* @data */
|
||||
const router = useRouter()
|
||||
const store = useStore()
|
||||
const url = 'http://visitor.scdswj.cn/?code=071ucW200YtsQR1AUj3007Tabj2ucW26&state=STATE'
|
||||
/* @setup */
|
||||
// url.split('?')[1].split('&').map(item =>{
|
||||
// if(item.split('=')[0] === 'code'){
|
||||
// // code = item.split('=')[1]
|
||||
// console.log(item.split('=')[1])
|
||||
// alert(item.split('=')[1])
|
||||
// }
|
||||
// })
|
||||
localStorage.setItem('redirect', '/userhome')
|
||||
|
||||
/* @method */
|
||||
// const onClickUpdate = () =>{
|
||||
// localStorage.setItem("userToken", 'res.data.authorization');
|
||||
// }
|
||||
const onClickGo = (url = '/userHome') =>{
|
||||
router.push(url)
|
||||
}
|
||||
const onClickCall = () =>{
|
||||
window.location.href = 'tel:400-040-1573'
|
||||
}
|
||||
const onClickMap = () =>{
|
||||
window.location.href = ''
|
||||
}
|
||||
//判断是否是微信内置的浏览器
|
||||
const isWXBrowserFun = ()=> {
|
||||
return (
|
||||
String(navigator.userAgent.toLowerCase().match(/MicroMessenger/i)) ===
|
||||
"micromessenger"
|
||||
);
|
||||
}
|
||||
//截取地址栏code
|
||||
const getUrlCode = (name) =>{
|
||||
if(window.location.href.indexOf(name) === -1) return
|
||||
let code = ''
|
||||
window.location.href.split('?')[1].split('&').map(item =>{
|
||||
if(item.split('=')[0] === name){
|
||||
code = item.split('=')[1]
|
||||
}
|
||||
})
|
||||
return code
|
||||
}
|
||||
//访问微信地址,用来获取code
|
||||
const weChatCode = () =>{
|
||||
getWeChatCode().then(res =>{
|
||||
window.location.href = res.data
|
||||
})
|
||||
}
|
||||
//把code传递给后台接口,静默登录
|
||||
const wxLogin = (code) =>{
|
||||
login(code).then((res) => {
|
||||
console.log(res)
|
||||
if (res.code===200) {
|
||||
localStorage.setItem("userToken", res.data.authorization);
|
||||
Toast.success('登录成功!')
|
||||
} else {
|
||||
Toast.fail('登录失败!')
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
const isWXBrowser = isWXBrowserFun();
|
||||
if (isWXBrowser) {
|
||||
const userToken = localStorage.getItem('userToken')
|
||||
if(!userToken){
|
||||
let code = getUrlCode("code");
|
||||
console.log(code)
|
||||
if (code) {
|
||||
wxLogin(code); //后台登录
|
||||
} else {
|
||||
weChatCode(); //微信授权
|
||||
}
|
||||
}
|
||||
}else {
|
||||
alert('请在微信中打开!')
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang='scss' scoped>
|
||||
.box{
|
||||
background-color: #F4F5F8;
|
||||
header{
|
||||
width: 100%;
|
||||
height: 6.9333rem /* 520/75 */;
|
||||
background: url('../assets/userhome/beijign.png') left top/100% 100% no-repeat;
|
||||
.header-top{
|
||||
width: 100%;
|
||||
height: 4.1867rem /* 314/75 */;
|
||||
background: url('../assets/userhome/topbeijing.png') left top/100% 100% no-repeat;
|
||||
|
||||
h1{
|
||||
padding: .7467rem /* 56/75 */ .64rem /* 48/75 */;
|
||||
box-sizing: border-box;
|
||||
img{
|
||||
width: 2.1333rem /* 160/75 */;
|
||||
height: .5867rem /* 44/75 */;
|
||||
}
|
||||
}
|
||||
.h3{
|
||||
width: 3.12rem /* 234/75 */;
|
||||
height: .7733rem /* 58/75 */;
|
||||
margin: 0 0 .2133rem /* 16/75 */ .6667rem /* 50/75 */;
|
||||
}
|
||||
p{
|
||||
line-height: .48rem /* 36/75 */;
|
||||
font-size: .32rem /* 24/75 */;
|
||||
font-family: Source Han Sans CN, Source Han Sans CN;
|
||||
font-weight: 400;
|
||||
color: #514E4B;
|
||||
padding: 0 0 0 .7467rem /* 56/75 */;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
}
|
||||
.plate-box{
|
||||
width: 100%;
|
||||
height: 3.3333rem /* 250/75 */;
|
||||
padding: 0 .4267rem /* 32/75 */;
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
.list{
|
||||
position: relative;
|
||||
flex: 1;
|
||||
height: 3.3333rem /* 250/75 */;
|
||||
background: linear-gradient(180deg, rgba(255,255,255,0) 0%, #FFFFFF 100%);
|
||||
border-radius: .2667rem /* 20/75 */;
|
||||
opacity: 1;
|
||||
border: .0267rem /* 2/75 */ solid #FFFFFF;
|
||||
h4{
|
||||
padding: .4533rem /* 34/75 */ 0 .1333rem /* 10/75 */ .5067rem /* 38/75 */;
|
||||
box-sizing: border-box;
|
||||
line-height: .6133rem /* 46/75 */;
|
||||
font-size: $size30;
|
||||
font-family: Source Han Sans CN, Source Han Sans CN;
|
||||
font-weight: 500;
|
||||
color: #222222;
|
||||
}
|
||||
p{
|
||||
line-height: .4533rem /* 34/75 */;
|
||||
font-size: .2933rem /* 22/75 */;
|
||||
font-family: Source Han Sans CN, Source Han Sans CN;
|
||||
font-weight: 400;
|
||||
color: #5F6583;
|
||||
padding: 0 0 0 .5333rem /* 40/75 */;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
.icon-arrowhead{
|
||||
width: .5333rem /* 40/75 */;
|
||||
height: .5333rem /* 40/75 */;
|
||||
margin: .7733rem /* 58/75 */ 0 0 .4533rem /* 34/75 */;
|
||||
}
|
||||
.img{
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
right: .3733rem /* 28/75 */;
|
||||
width: 1.5733rem /* 118/75 */;
|
||||
height: 1.8133rem /* 136/75 */;
|
||||
}
|
||||
}
|
||||
.list:first-child{
|
||||
margin-right: .3467rem /* 26/75 */;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
.content{
|
||||
width: 100%;
|
||||
padding: 1.12rem /* 84/75 */ .4rem /* 30/75 */ 0;
|
||||
box-sizing: border-box;
|
||||
.contact-box{
|
||||
width: 100%;
|
||||
height: 4.24rem /* 318/75 */;
|
||||
// background: linear-gradient(261deg, #FFFFFF 0%, rgba(255,255,255,0) 100%);
|
||||
background: url('../assets/userhome/ditu.png') left top/100% 100% no-repeat;
|
||||
background-color: #FFFFFF;
|
||||
border-radius: .2667rem /* 20/75 */ 1.0667rem /* 80/75 */ .2667rem /* 20/75 */ .2667rem /* 20/75 */;
|
||||
h3{
|
||||
position: relative;
|
||||
// padding: .48rem /* 36/75 */ .5333rem /* 40/75 */ .2667rem /* 20/75 */;
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
|
||||
span{
|
||||
display: block;
|
||||
padding: .48rem /* 36/75 */ 0 0 .5333rem /* 40/75 */ ;
|
||||
|
||||
line-height: .6133rem /* 46/75 */;
|
||||
font-size: $size30;
|
||||
font-family: Source Han Sans CN, Source Han Sans CN;
|
||||
font-weight: 500;
|
||||
color: #000000;
|
||||
position: relative;
|
||||
z-index: 2;
|
||||
}
|
||||
p{
|
||||
position: relative;
|
||||
flex: 1;
|
||||
.square{
|
||||
position: absolute;
|
||||
bottom: .0;
|
||||
left: 0;
|
||||
z-index: 1;
|
||||
transform: translateX(-70%) translateY(-20%);
|
||||
width: .24rem /* 18/75 */;
|
||||
height: .24rem /* 18/75 */;
|
||||
background: #30BF78;
|
||||
border-radius: 0px 0px 0px 0px;
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
.time{
|
||||
padding: .2667rem /* 20/75 */ 0 0 .5333rem /* 40/75 */;
|
||||
box-sizing: border-box;
|
||||
line-height: .4533rem /* 34/75 */;
|
||||
font-size: .2933rem /* 22/75 */;
|
||||
font-family: Source Han Sans CN, Source Han Sans CN;
|
||||
font-weight: 400;
|
||||
color: #5F6583;
|
||||
margin-bottom: .56rem /* 42/75 */;
|
||||
}
|
||||
.text-list{
|
||||
padding: 0 .64rem /* 48/75 */;
|
||||
box-sizing: border-box;
|
||||
line-height: .5333rem /* 40/75 */;
|
||||
font-size: $size26;
|
||||
font-family: Source Han Sans CN, Source Han Sans CN;
|
||||
font-weight: 500;
|
||||
color: #5F6583;
|
||||
display: flex;
|
||||
margin-bottom: .3733rem /* 28/75 */;
|
||||
|
||||
img{
|
||||
width: .5333rem /* 40/75 */;
|
||||
height: .5333rem /* 40/75 */;
|
||||
margin-right: .2133rem /* 16/75 */;
|
||||
}
|
||||
}
|
||||
}
|
||||
.controls-box{
|
||||
position: relative;
|
||||
height: 1.3333rem /* 100/75 */;
|
||||
background: rgba(255,255,255,0.8);
|
||||
border-radius:.2667rem /* 20/75 */;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 0 .24rem /* 18/75 */ 0 .4533rem /* 34/75 */;
|
||||
box-sizing: border-box;
|
||||
margin-top: .32rem /* 24/75 */ ;
|
||||
.icon-img{
|
||||
width: .8533rem /* 64/75 */;
|
||||
height: .8533rem /* 64/75 */;
|
||||
}
|
||||
p{
|
||||
flex: 1;
|
||||
font-size: $lg-size;
|
||||
font-family: Inter, Inter;
|
||||
font-weight: 500;
|
||||
color: #5F6583;
|
||||
line-height: .5067rem /* 38/75 */;
|
||||
padding: 0 0 0 .24rem /* 18/75 */;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
.icon-right{
|
||||
width: .64rem /* 48/75 */;
|
||||
height: .64rem /* 48/75 */;
|
||||
}
|
||||
a{
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
||||
@@ -0,0 +1,25 @@
|
||||
<template>
|
||||
<div class='box'>
|
||||
<Successmodel />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref } from 'vue'
|
||||
import { useRouter } from 'vue-router'
|
||||
import { useStore } from 'vuex'
|
||||
import { rulesForm } from '@/com/index'
|
||||
import Successmodel from '@/components/success.vue'
|
||||
/* @data */
|
||||
const router = useRouter()
|
||||
const store = useStore()
|
||||
|
||||
/* @setup */
|
||||
|
||||
/* @method */
|
||||
|
||||
</script>
|
||||
|
||||
<style lang='scss' scoped>
|
||||
|
||||
</style>
|
||||
@@ -0,0 +1,192 @@
|
||||
<template>
|
||||
<div class='box'>
|
||||
<header class="tabbar">
|
||||
<div @click="onClickTabbar(item)" v-for="item in stateEnum" class="tabbar-li" :key="item.status" :class="query.status == item.status ? 'active' : ''">
|
||||
{{ item.statusName }}
|
||||
<img v-if="query.status == item.status" src="../assets/maomaochong.png" alt="">
|
||||
</div>
|
||||
|
||||
</header>
|
||||
<div v-if="recordArr.length" class="content">
|
||||
<div @click="onClcikItem(item)" v-for="item in recordArr" class="wait-list" :key="item.id">
|
||||
<h5>被拜访人:{{ item.visitingName }}</h5>
|
||||
<h5>拜访时间:{{ item.hours }}</h5>
|
||||
<div class="apply-box">
|
||||
<p><span>访客姓名:</span><span>{{ item.name }}</span></p>
|
||||
<p><span>联系方式:</span><span>{{ item.phone }}</span></p>
|
||||
<p><span>随行人数:</span><span>{{ item.visitingNum }} </span></p>
|
||||
<p><span>来访事由:</span><span>{{ item.reason }}</span></p>
|
||||
</div>
|
||||
<!-- refuse 拒绝 pass 通过 状态 -->
|
||||
<div class="status" :class="stateEnum[item.status].className">{{ stateEnum[item.status].statusName }}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="isLoading && recordArr.length == 0" class="content">
|
||||
<div class="no-have">
|
||||
暂无数据
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, reactive } from 'vue'
|
||||
import { useRouter, useRoute } from 'vue-router'
|
||||
import { useStore } from 'vuex'
|
||||
import dd from 'dingtalk-jsapi'
|
||||
import { Toast, ImagePreview } from 'vant';
|
||||
|
||||
import { rulesForm, resetForm, rulesPhone } from '@/com/index'
|
||||
import { getToken, getVisitorRecord } from '@/api/admin.js'
|
||||
|
||||
/* @data */
|
||||
const router = useRouter()
|
||||
const route = useRoute()
|
||||
const store = useStore()
|
||||
const stateEnum = store.state.stateEnum
|
||||
const recordArr = ref([])
|
||||
const isLoading = ref(false)
|
||||
|
||||
const query = reactive({
|
||||
status: 0,
|
||||
size: -1,
|
||||
current: 1,
|
||||
})
|
||||
|
||||
console.log(route)
|
||||
/* @setup */
|
||||
|
||||
/* @method */
|
||||
const onClcikItem = (item) =>{
|
||||
// window.location.href = item.instanceUrl
|
||||
// window.open(item.instanceUrl, '审批详情');
|
||||
dd.openLink({
|
||||
url: item.instanceUrl,
|
||||
success: () => {},
|
||||
fail: () => {},
|
||||
complete: () => {},
|
||||
});
|
||||
}
|
||||
const onClickTabbar = (item) =>{
|
||||
if(query.status != item.status){
|
||||
query.status = item.status
|
||||
recordArr.value = []
|
||||
visitorList()
|
||||
}
|
||||
|
||||
}
|
||||
const visitorList = () =>{
|
||||
Toast.loading({ duration: 0, forbidClick: true, message: '加载中', });
|
||||
getVisitorRecord(query).then(res =>{
|
||||
isLoading.value = true
|
||||
recordArr.value = res.data
|
||||
}).catch(err =>{
|
||||
isLoading.value = true
|
||||
})
|
||||
}
|
||||
visitorList()
|
||||
|
||||
</script>
|
||||
|
||||
<style lang='scss' scoped>
|
||||
.box{
|
||||
background: #F9FBFC;;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
.tabbar{
|
||||
height: 1.8933rem /* 142/75 */;
|
||||
line-height: .6133rem /* 46/75 */;
|
||||
display: flex;
|
||||
font-size: $md-size;
|
||||
font-family: Source Han Sans CN, Source Han Sans CN;
|
||||
font-weight: 400;
|
||||
color: #999999;
|
||||
padding: .56rem /* 42/75 */ .4rem /* 30/75 */ 0;
|
||||
box-sizing: border-box;
|
||||
.tabbar-li{
|
||||
position: relative;
|
||||
flex: 1;
|
||||
text-align: center;
|
||||
img{
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
bottom: .48rem /* 36/75 */;
|
||||
width: .6133rem /* 46/75 */;
|
||||
height: .2667rem /* 20/75 */;
|
||||
}
|
||||
}
|
||||
.active{
|
||||
font-size: $size30;
|
||||
font-family: Source Han Sans CN, Source Han Sans CN;
|
||||
font-weight: 500;
|
||||
color: #222222;
|
||||
}
|
||||
}
|
||||
.content{
|
||||
width: 100%;
|
||||
flex: 1;
|
||||
padding: 0 .4rem /* 30/75 */;
|
||||
box-sizing: border-box;
|
||||
overflow: auto;
|
||||
.wait-list{
|
||||
position: relative;
|
||||
width: 100%;
|
||||
// height: 470px;
|
||||
background: #FFFFFF;
|
||||
border-radius: .2667rem /* 20/75 */;
|
||||
padding: .48rem /* 36/75 */;
|
||||
box-sizing: border-box;
|
||||
margin-bottom: .2667rem /* 20/75 */;
|
||||
h5{
|
||||
height: .6667rem /* 50/75 */;
|
||||
font-size: $md-size;
|
||||
font-family: Source Han Sans CN, Source Han Sans CN;
|
||||
font-weight: 400;
|
||||
color: #222222;
|
||||
}
|
||||
.apply-box{
|
||||
|
||||
width: 100%;
|
||||
padding: .4rem /* 30/75 */ .3733rem /* 28/75 */ .5067rem /* 38/75 */;
|
||||
box-sizing: border-box;
|
||||
border-radius: .1333rem /* 10/75 */;
|
||||
font-size: $md-size;
|
||||
font-family: Source Han Sans CN, Source Han Sans CN;
|
||||
font-weight: 400;
|
||||
color: #999999;
|
||||
line-height: .72rem /* 54/75 */;
|
||||
background: #F5F7F9;
|
||||
span:last-child{
|
||||
color: #5F6583;
|
||||
}
|
||||
}
|
||||
.status{
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
width: 1.52rem /* 114/75 */;
|
||||
height: .6667rem /* 50/75 */;
|
||||
line-height: .6667rem /* 50/75 */;
|
||||
background: #FFE9E4;
|
||||
border-radius: 0px .2667rem /* 20/75 */ 0px .1333rem /* 10/75 */;
|
||||
color: #FF6643;
|
||||
font-size: $sm-size;
|
||||
font-family: Source Han Sans CN, Source Han Sans CN;
|
||||
font-weight: 400;
|
||||
color: #FF6643;
|
||||
text-align: center;
|
||||
|
||||
}
|
||||
.refuse{
|
||||
color: #5F6583;
|
||||
background: #EAEEF6;
|
||||
}
|
||||
.pass{
|
||||
color: #30BF78;
|
||||
background: #E7F8F5;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||