update:更新log,引入入场加载Loading,增加文档注释

This commit is contained in:
zouzhibing 2022-09-01 16:43:46 +08:00
parent fe9a1fa88e
commit 3e5bab6097
21 changed files with 681 additions and 66 deletions

View File

@ -2,4 +2,4 @@
NODE_ENV = 'development' NODE_ENV = 'development'
# 本地环境接口地址 # 本地环境接口地址
VITE_API_URL = '/api' VUE_APP_BASE_API = '/api'

View File

@ -1,2 +1,5 @@
# 线上环境 # 线上环境
NODE_ENV = "production" NODE_ENV = "production"
# 线上环境接口地址
VUE_APP_BASE_API = '/api'

View File

@ -1,2 +1,6 @@
# 测试环境 # 测试环境
NODE_ENV = "test" NODE_ENV = "test"
# 测试环境接口地址
VUE_APP_BASE_API = '/api'

View File

@ -7,7 +7,64 @@
<title>Vite + Vue + TS</title> <title>Vite + Vue + TS</title>
</head> </head>
<body> <body>
<div id="app"></div> <div id="app">
<style>
html,
body,
#app {
width: 100%;
height: 100%;
padding: 0;
margin: 0;
}
.init-loading-wrap{
width: 100%;
height: 100%;
display: flex;
align-items: center;
justify-content: center;
}
.init-loading-inner {
width: 20px;
height: 50px;
background: #1890ff;
float: left;
margin: 0 3px;
animation: init-loading-inner linear 1s infinite;
-webkit-animation: init-loading-inner linear 1s infinite;
}
.init-loading-inner:nth-child(1){
animation-delay:0s;
}
.init-loading-inner:nth-child(2){
animation-delay:0.15s;
}
.init-loading-inner:nth-child(3){
animation-delay:0.3s;
}
.init-loading-inner:nth-child(4){
animation-delay:0.45s;
}
.init-loading-inner:nth-child(5){
animation-delay:0.6s;
}
@keyframes init-loading-inner{
0%,60%,100% {transform: scale(1);}
30% {transform: scaleY(3);}
}
@-webkit-keyframes init-loading-inner{
0%,60%,100% {transform: scale(1);}
30% {transform: scaleY(3);}
}
</style>
<div class="init-loading-wrap">
<div class="init-loading-inner"></div>
<div class="init-loading-inner"></div>
<div class="init-loading-inner"></div>
<div class="init-loading-inner"></div>
<div class="init-loading-inner"></div>
</div>
</div>
<script type="module" src="/src/main.ts"></script> <script type="module" src="/src/main.ts"></script>
</body> </body>
</html> </html>

View File

@ -19,6 +19,7 @@
"@vueuse/core": "^9.1.1", "@vueuse/core": "^9.1.1",
"@wangeditor/editor": "^5.1.14", "@wangeditor/editor": "^5.1.14",
"@wangeditor/editor-for-vue": "^5.1.12", "@wangeditor/editor-for-vue": "^5.1.12",
"axios": "^0.27.2",
"clipboard": "^2.0.10", "clipboard": "^2.0.10",
"core-js": "^3.6.5", "core-js": "^3.6.5",
"dayjs": "^1.11.4", "dayjs": "^1.11.4",

View File

@ -0,0 +1,108 @@
```
export interface AxiosRequestConfig {
// `url` 是用于请求的服务器 URL
url?: string;
// `method` 是创建请求时使用的方法
method?: Method;
// `baseURL` 将自动加在 `url` 前面,除非 `url` 是一个绝对 URL。
// 它可以通过设置一个 `baseURL` 便于为 axios 实例的方法传递相对 URL
baseURL?: string;
// `transformRequest` 允许在向服务器发送前,修改请求数据
// 只能用在 'PUT', 'POST' 和 'PATCH' 这几个请求方法
// 后面数组中的函数必须返回一个字符串,或 ArrayBuffer或 Stream
transformRequest?: AxiosTransformer | AxiosTransformer[];
// `transformResponse` 在传递给 then/catch 前,允许修改响应数据
transformResponse?: AxiosTransformer | AxiosTransformer[];
// `headers` 是即将被发送的自定义请求头
headers?: any;
// `params` 是即将与请求一起发送的 URL 参数
// 必须是一个无格式对象(plain object)或 URLSearchParams 对象
params?: any;
// `paramsSerializer` 是一个负责 `params` 序列化的函数
paramsSerializer?: (params: any) => string;
// `data` 是作为请求主体被发送的数据
// 只适用于这些请求方法 'PUT', 'POST', 和 'PATCH'
// 在没有设置 `transformRequest` 时,必须是以下类型之一:
// - string, plain object, ArrayBuffer, ArrayBufferView, URLSearchParams
// - 浏览器专属FormData, File, Blob
// - Node 专属: Stream
data?: any;
// `timeout` 指定请求超时的毫秒数(0 表示无超时时间)
// 如果请求话费了超过 `timeout` 的时间,请求将被中断
timeout?: number;
// 超时提示消息
timeoutErrorMessage?: string;
// `withCredentials` 表示跨域请求时是否需要使用凭证
withCredentials?: boolean;
// `adapter` 允许自定义处理请求,以使测试更轻松
adapter?: AxiosAdapter;
// `auth` 表示应该使用 HTTP 基础验证,并提供凭据
auth?: AxiosBasicCredentials;
// `responseType` 表示服务器响应的数据类型,可以是 'arraybuffer', 'blob', 'document', 'json', 'text', 'stream'
responseType?: ResponseType;
// `xsrfCookieName` 是用作 xsrf token 的值的cookie的名称
xsrfCookieName?: string;
// `xsrfHeaderName` 是携带 xsrf 令牌值的 http 标头的名称
xsrfHeaderName?: string;
// `onUploadProgress` 允许为上传处理进度事件
onUploadProgress?: (progressEvent: any) => void;
// `onDownloadProgress` 允许为下载处理进度事件
onDownloadProgress?: (progressEvent: any) => void;
// `maxContentLength` 定义允许的响应内容的最大尺寸
maxContentLength?: number;
// `validateStatus` 定义对于给定的HTTP 响应状态码是 resolve 或 reject promise 。
// 如果 `validateStatus` 返回 `true` (或者设置为 `null``undefined`)
// promise 将被 resolve; 否则promise 将被 rejecte
validateStatus?: ((status: number) => boolean) | null;
// 请求体最大尺寸
maxBodyLength?: number;
// `maxRedirects` 定义在 node.js 中 follow 的最大重定向数目
// 如果设置为0将不会 follow 任何重定向
maxRedirects?: number;
// `socketPath` 定义了一个在 node.js 中使用的 UNIX Socket。
// 只能指定 `socketPath``proxy`
// 如果两者都指定,则使用 `socketPath`
socketPath?: string | null;
// `httpAgent``httpsAgent` 分别在 node.js 中用于定义在执行 http 和 https 时使用的自定义代理。
httpAgent?: any;
httpsAgent?: any;
// 'proxy' 定义代理服务器的主机名称和端口
proxy?: AxiosProxyConfig | false;
// `cancelToken` 指定用于取消请求的 cancel token
cancelToken?: CancelToken;
// 将其设置为`false`它将不会解压缩您的响应而是保留原始的Content-Encoding头。
// 默认是true
decompress?: boolean;
// 控制响应数据是否转换
transitional?: TransitionalOptions
}
```

View File

@ -0,0 +1,44 @@
export const errorCodeType = function(code:string):string{
let errMessage:string = "未知错误"
switch (code) {
case 400:
errMessage = '请求失败!请您稍后重试'
break
case 401:
errMessage = '未授权,请重新登录'
break
case 403:
errMessage = '当前账号无权限访问!'
break
case 404:
errMessage = '你所访问的资源不存在!'
break
case 405:
errMessage = '请求方式错误!请您稍后重试'
break
case 408:
errMessage = '请求超时!请您稍后重试'
break
case 500:
errMessage = '服务器端出错'
break
case 501:
errMessage = '网络未实现'
break
case 502:
errMessage = '网络错误'
break
case 503:
errMessage = '服务不可用'
break
case 504:
errMessage = '网络超时'
break
case 505:
errMessage = 'http版本不支持该请求'
break
default:
errMessage = `其他连接错误 --${code}`
}
return errMessage
}

View File

@ -1 +0,0 @@

57
src/api/request.ts Normal file
View File

@ -0,0 +1,57 @@
import axios, { AxiosInstance, AxiosError, AxiosRequestConfig, AxiosResponse } from 'axios'
import { ElMessage } from "element-plus";
import {useUserStore} from "@/store/modules/user"
// 创建axios实例 进行基本参数配置
const service = axios.create({
// 默认请求地址,根据环境的不同可在.env 文件中进行修改
baseURL: import.meta.env.VUE_APP_BASE_API,
// 设置接口访问超时时间
timeout: 3000000, // request timeout
// 跨域时候允许携带凭证
withCredentials: true
})
// request interceptor 接口请求拦截
service.interceptors.request.use((config:AxiosRequestConfig)=>{
/**
* token,token进行JWT校验
* token storagevuexpinia
*/
const userStore = useUserStore();
const token: string = userStore.token;
// 自定义请求头
if(token){ config.headers['Authorization'] = token}
return config
},(error: AxiosError) => {
// 请求错误,这里可以用全局提示框进行提示
return Promise.reject(error);
})
// response interceptor 接口响应拦截
service.interceptors.response.use((response: AxiosResponse) =>{
// 直接返回res当然你也可以只返回res.data
// 系统如果有自定义code也可以在这里处理
return response
},(error: AxiosError) => {
return Promise.reject(error)
})
/**
* @description
* opt
* err
* type
* duration
*/
function showErrMessage (opt, err, type:any= 'error', duration:number = 5000){
ElMessage({
message: err.msg,
type:type,
duration: duration
})
}
export default service

9
src/api/user.ts Normal file
View File

@ -0,0 +1,9 @@
import request from './request'
export function login(data) {
return request({
url: '/vue-element-perfect/user/login',
method: 'post',
data
})
}

View File

@ -11,15 +11,14 @@ import 'virtual:svg-icons-register'
import SvgIcon from '@/components/SvgIcon/index.vue'// svg component import SvgIcon from '@/components/SvgIcon/index.vue'// svg component
// UI框架 element-plus // UI框架 element-plus
import ElementPlus from 'element-plus' import ElementPlus from 'element-plus'
import UContainerLayout from '@/components/u-container-layout/index.vue'
import 'element-plus/dist/index.css' import 'element-plus/dist/index.css'
// 引入暗黑模式 element-plus 2.2 内置暗黑模式 // 引入暗黑模式 element-plus 2.2 内置暗黑模式
import 'element-plus/theme-chalk/dark/css-vars.css' import 'element-plus/theme-chalk/dark/css-vars.css'
// 自定义暗黑模式 // 自定义暗黑模式
import "@/styles/element-dark.scss"; import "@/styles/element-dark.scss";
// 引入全局组件布局
import UContainerLayout from '@/components/u-container-layout/index.vue'
const app = createApp(App) const app = createApp(App)
app.component('svg-icon',SvgIcon) app.component('svg-icon',SvgIcon)

View File

@ -70,7 +70,6 @@ export const useTagsViewStore = defineStore({
delAllViews(){ delAllViews(){
return new Promise((resolve) => { return new Promise((resolve) => {
this.visitedViews = this.visitedViews.filter(v=>v.meta.affix) this.visitedViews = this.visitedViews.filter(v=>v.meta.affix)
console.log('===============',this.visitedViews)
this.cachedViews = this.visitedViews.filter(v=>v.meta.affix) this.cachedViews = this.visitedViews.filter(v=>v.meta.affix)
resolve([...this.visitedViews]) resolve([...this.visitedViews])
}) })

View File

@ -46,6 +46,7 @@ export const useUserStore = defineStore({
}, },
}, },
// 进行持久化存储
persist: { persist: {
// 本地存储的名称 // 本地存储的名称
key: "userState", key: "userState",

124
src/utils/Print.js Normal file
View File

@ -0,0 +1,124 @@
/* @Print.js
* DH (http://denghao.me)
* 2017-7-14
*/
(function (window, document) {
var Print = function (dom, options) {
if (!(this instanceof Print)) return new Print(dom, options);
this.options = this.extend({
noPrint: '.no-print',
onStart: function () { },
onEnd: function () { }
}, options);
if ((typeof dom) === "string") {
this.dom = document.querySelector(dom);
} else {
this.dom = dom;
}
this.init();
};
Print.prototype = {
init: function () {
var content = this.getStyle() + this.getHtml();
this.writeIframe(content);
},
extend: function (obj, obj2) {
for (var k in obj2) {
obj[k] = obj2[k];
}
return obj;
},
getStyle: function () {
var str = "",
styles = document.querySelectorAll('style,link');
for (var i = 0; i < styles.length; i++) {
str += styles[i].outerHTML;
}
str += "<style>" + (this.options.noPrint ? this.options.noPrint : '.no-print') + "{display:none;}</style>";
return str;
},
getHtml: function () {
var inputs = document.querySelectorAll('input');
var textareas = document.querySelectorAll('textarea');
var selects = document.querySelectorAll('select');
for (var k in inputs) {
if (inputs[k].type == "checkbox" || inputs[k].type == "radio") {
if (inputs[k].checked == true) {
inputs[k].setAttribute('checked', "checked")
} else {
inputs[k].removeAttribute('checked')
}
} else if (inputs[k].type == "text") {
inputs[k].setAttribute('value', inputs[k].value)
}
}
for (var k2 in textareas) {
if (textareas[k2].type == 'textarea') {
textareas[k2].innerHTML = textareas[k2].value
}
}
for (var k3 in selects) {
if (selects[k3].type == 'select-one') {
var child = selects[k3].children;
for (var i in child) {
if (child[i].tagName == 'OPTION') {
if (child[i].selected == true) {
child[i].setAttribute('selected', "selected")
} else {
child[i].removeAttribute('selected')
}
}
}
}
}
return this.dom.outerHTML;
},
writeIframe: function (content) {
var w, doc, iframe = document.createElement('iframe'),
f = document.body.appendChild(iframe);
iframe.id = "myIframe";
iframe.style = "position:absolute;width:0;height:0;top:-10px;left:-10px;";
w = f.contentWindow || f.contentDocument;
doc = f.contentDocument || f.contentWindow.document;
doc.open();
doc.write(content);
doc.close();
this.toPrint(w, function () {
document.body.removeChild(iframe)
});
},
toPrint: function (w, cb) {
var _this = this;
w.onload = function () {
try {
setTimeout(function () {
w.focus();
typeof _this.options.onStart === 'function' && _this.options.onStart();
if (!w.document.execCommand('print', false, null)) {
w.print();
}
typeof _this.options.onEnd === 'function' && _this.options.onEnd();
w.close();
cb && cb()
});
} catch (err) {
console.log('err', err);
}
}
}
};
window.Print = Print;
}(window, document));

View File

@ -1,35 +0,0 @@
export default {
imgs: [
'爱你',
'爱情',
'爱心',
'傲慢',
'白眼',
'抱拳',
'鄙视',
'闭嘴',
'便便',
'擦汗',
'菜刀',
'差劲',
'呲牙',
'大哭',
'蛋糕',
'刀',
'得意',
'凋谢',
'发呆',
'NO',
'OK',
'发抖',
'发怒',
'饭',
'飞吻',
'奋斗',
'疯了',
'尴尬',
'勾引',
'鼓掌',
'哈欠',
],
}

View File

@ -42,7 +42,7 @@
新疆: [87.9236, 43.5883], 新疆: [87.9236, 43.5883],
河南: [113.4668, 34.6234], 河南: [113.4668, 34.6234],
西藏: [116.3896, 39.91], 西藏: [91.091762, 30.037072],
浙江: [119.5313, 29.8773], 浙江: [119.5313, 29.8773],
福建: [119.4543, 25.9222], 福建: [119.4543, 25.9222],
湖南: [113.0823, 28.2568], 湖南: [113.0823, 28.2568],

124
src/views/other/Print.js Normal file
View File

@ -0,0 +1,124 @@
/* @Print.js
* DH (http://denghao.me)
* 2017-7-14
*/
(function (window, document) {
var Print = function (dom, options) {
if (!(this instanceof Print)) return new Print(dom, options);
this.options = this.extend({
noPrint: '.no-print',
onStart: function () { },
onEnd: function () { }
}, options);
if ((typeof dom) === "string") {
this.dom = document.querySelector(dom);
} else {
this.dom = dom;
}
this.init();
};
Print.prototype = {
init: function () {
var content = this.getStyle() + this.getHtml();
this.writeIframe(content);
},
extend: function (obj, obj2) {
for (var k in obj2) {
obj[k] = obj2[k];
}
return obj;
},
getStyle: function () {
var str = "",
styles = document.querySelectorAll('style,link');
for (var i = 0; i < styles.length; i++) {
str += styles[i].outerHTML;
}
str += "<style>" + (this.options.noPrint ? this.options.noPrint : '.no-print') + "{display:none;}</style>";
return str;
},
getHtml: function () {
var inputs = document.querySelectorAll('input');
var textareas = document.querySelectorAll('textarea');
var selects = document.querySelectorAll('select');
for (var k in inputs) {
if (inputs[k].type == "checkbox" || inputs[k].type == "radio") {
if (inputs[k].checked == true) {
inputs[k].setAttribute('checked', "checked")
} else {
inputs[k].removeAttribute('checked')
}
} else if (inputs[k].type == "text") {
inputs[k].setAttribute('value', inputs[k].value)
}
}
for (var k2 in textareas) {
if (textareas[k2].type == 'textarea') {
textareas[k2].innerHTML = textareas[k2].value
}
}
for (var k3 in selects) {
if (selects[k3].type == 'select-one') {
var child = selects[k3].children;
for (var i in child) {
if (child[i].tagName == 'OPTION') {
if (child[i].selected == true) {
child[i].setAttribute('selected', "selected")
} else {
child[i].removeAttribute('selected')
}
}
}
}
}
return this.dom.outerHTML;
},
writeIframe: function (content) {
var w, doc, iframe = document.createElement('iframe'),
f = document.body.appendChild(iframe);
iframe.id = "myIframe";
iframe.style = "position:absolute;width:0;height:0;top:-10px;left:-10px;";
w = f.contentWindow || f.contentDocument;
doc = f.contentDocument || f.contentWindow.document;
doc.open();
doc.write(content);
doc.close();
this.toPrint(w, function () {
document.body.removeChild(iframe)
});
},
toPrint: function (w, cb) {
var _this = this;
w.onload = function () {
try {
setTimeout(function () {
w.focus();
typeof _this.options.onStart === 'function' && _this.options.onStart();
if (!w.document.execCommand('print', false, null)) {
w.print();
}
typeof _this.options.onEnd === 'function' && _this.options.onEnd();
w.close();
cb && cb()
});
} catch (err) {
console.log('err', err);
}
}
}
};
window.Print = Print;
}(window, document));

View File

@ -23,7 +23,7 @@
</el-form> </el-form>
<el-descriptions title="配置项 " :column="1" border class="descriptions"> <el-descriptions title="配置项 " :column="1" border class="descriptions">
<el-descriptions-item label="value"> 双向绑定的 value 使用示例v-model='content' </el-descriptions-item> <el-descriptions-item label="value"> 双向绑定的 value 使用示例v-model='content' </el-descriptions-item>
<el-descriptions-item label="参考文档"> <a href="https://www.wangeditor.com/v5/for-frame.html"> https://www.wangeditor.com/v5/for-frame.html </a> </el-descriptions-item> <el-descriptions-item label="参考文档"> <a href="https://www.wangeditor.com/v5/for-frame.html" target="_blank"> https://www.wangeditor.com/v5/for-frame.html </a> </el-descriptions-item>
</el-descriptions> </el-descriptions>

View File

@ -1,25 +1,42 @@
<template> <template>
<u-container-layout> <u-container-layout>
<div> <div id="wrap" style="margin-bottom: 20px">
<el-button type="primary" @click="print(1)">打印图片</el-button> <div>
<el-button type="primary" @click="print(2)">打印表格</el-button> <el-button type="primary" @click="print(1)" >打印图片</el-button>
</div> <el-button type="primary" @click="print(2)">打印Json数据</el-button>
<div style="margin-top: 20px"> <el-button type="primary" @click="print(3)">打印HTML</el-button>
<img :src="im1" style="width: 50%" /> </div>
</div> <div style="margin-top: 20px">
<div> <img :src="printImg" style="width: 300px" />
<el-table :data="tableData" style="width: 100%"> </div>
<el-table-column prop="date" label="日期" width="180" /> <div id="tableBox">
<el-table-column prop="name" label="名字" width="180" /> <el-table :data="tableData" style="width: 100%">
<el-table-column prop="address" label="地址" /> <el-table-column prop="date" label="日期" width="180" />
</el-table> <el-table-column prop="name" label="名字" width="180" />
<el-table-column prop="address" label="地址" />
</el-table>
</div>
</div> </div>
<el-descriptions title="配置项 " :column="1" border class="descriptions">
<el-descriptions-item label="官方文档"> <a href="https://github.com/crabbly/Print.js" target="_blank">https://github.com/crabbly/Print.js</a> </el-descriptions-item>
<el-descriptions-item label="printable"> 文档来源pdf或图像的urlhtml元素的id或json数据的对象 </el-descriptions-item>
<el-descriptions-item label="type"> 可打印类型可用的打印选项包括pdfhtmlimagejson和raw-html </el-descriptions-item>
<el-descriptions-item label="documentTitle"> 打印htmlimage或json时它将显示为文档标题如果用户尝试将打印作业保存为pdf文件它也将是文档的名称 </el-descriptions-item>
<el-descriptions-item label="scanStyles">设置为false时库不会处理应用于正在打印的html的样式使用css参数时很有用 </el-descriptions-item>
<el-descriptions-item label="targetStyle"> 默认情况下在打印HTML元素时库仅处理某些样式此选项允许您传递要处理的样式数组例如['padding-top''border-bottom'] </el-descriptions-item>
<el-descriptions-item label="gridHeaderStyle"> 打印JSON数据时网格标题的可选样式 </el-descriptions-item>
<el-descriptions-item label="properties"> 在打印JSON时使用这些是对象属性名称 </el-descriptions-item>
<el-descriptions-item label="honorColor"> 要以彩色打印文本请将此属性设置为true默认情况下所有文本都将以黑色打印 </el-descriptions-item>
<el-descriptions-item label="css"> 这允许我们传递一个或多个应该应用于正在打印的html的css文件URL值可以是包含单个URL的字符串也可以是包含多个URL的数组 </el-descriptions-item>
</el-descriptions>
</u-container-layout> </u-container-layout>
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import printJS from 'print-js' import printJS from 'print-js'
import im1 from '@/assets/image/im1.jpeg' import '@/utils/Print'
import printImg from '@/assets/image/im1.jpeg'
const tableData = [ const tableData = [
{ {
@ -49,7 +66,7 @@
case 1: case 1:
printJS({ printJS({
type: 'image', type: 'image',
printable: im1, printable: [printImg],
documentTitle: '打印图片', documentTitle: '打印图片',
}) })
break break
@ -67,6 +84,24 @@
}) })
break break
case 3: case 3:
// printJS({
// type: 'wrap',
// documentTitle: '',
// printable: "tableBox",
// scanStyles:false,
// targetStyles: ['*'], //
// honorColor: true, //
// style: '@page {margin: 0 10mm};', //
// gridStyle: 'border: 1px solid lightgray;font-size: 12px;',
// })
Print('#wrap', {
onStart: function () {
console.log('onStart', new Date())
},
onEnd: function () {
console.log('onEnd', new Date())
}
})
break break
} }
} }

View File

@ -2,31 +2,66 @@
<u-container-layout> <u-container-layout>
<el-input v-model="inputData" placeholder="请输入" style="width: 400px; max-width: 100%" /> <el-input v-model="inputData" placeholder="请输入" style="width: 400px; max-width: 100%" />
<el-button type="primary" @click="handleQrcode(1)"> <el-button type="primary" @click="handleQrcode(1)">
<el-icon style="margin-right: 6px"><collection /></el-icon> <el-icon style="margin-right: 6px"><collection /></el-icon>
</el-button> </el-button>
<el-button type="primary" @click="handleQrcode(2)">生成带logo</el-button> <el-button type="primary" @click="handleQrcode(2)">生成带logo</el-button>
<el-button type="primary" @click="handleQrcode(3)">生成随机颜色二维码</el-button>
<el-button type="primary" @click="handleQrcode(4)">下载</el-button>
<div> <div>
<vue-qr :logoSrc="src" :text="inputData" :size="200"></vue-qr> <vue-qr :logoSrc="logoSrc" :text="inputData" :size="200" :callback="qrcodeCallback" :color-dark="randomColor" ></vue-qr>
</div> </div>
<el-descriptions title="配置项 " :column="1" border class="descriptions">
<el-descriptions-item label="官方文档"> <a href="https://github.com/Binaryify/vue-qr" target="_blank">https://github.com/Binaryify/vue-qr</a> </el-descriptions-item>
<el-descriptions-item label="text"> 二维码内容默认为 'https://github.com/zouzhibin/vue-admin-perfect' </el-descriptions-item>
<el-descriptions-item label="logoSrc"> 嵌入至二维码中心的 LOGO 地址 </el-descriptions-item>
<el-descriptions-item label="size"> 尺寸, 长宽一致, 包含外边距默认为 200 </el-descriptions-item>
<el-descriptions-item label="margin"> 二维码图像的外边距, 默认 20px </el-descriptions-item>
<el-descriptions-item label="logoMargin"> 标识周围的空白边框, 默认为0 </el-descriptions-item>
<el-descriptions-item label="correctLevel"> 容错级别 0-3 </el-descriptions-item>
<el-descriptions-item label="autoColor"> 若为 true, 背景图的主要颜色将作为实点的颜色, colorDark,默认 true </el-descriptions-item>
<el-descriptions-item label="colorDark"> 实点的颜色,默认颜色值 =>黑色 </el-descriptions-item>
<el-descriptions-item label="colorLight"> 空白区的颜色 </el-descriptions-item>
<el-descriptions-item label="callback"> 生成的二维码 Data URI 可以在回调中取得,第一个参数为二维码 data URL, 第二个参数为 props 传过来的 qid(因为二维码生成是异步的,所以加个 id 用于排序) </el-descriptions-item>
</el-descriptions>
</u-container-layout> </u-container-layout>
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import { ref } from 'vue' import { ref } from 'vue'
import vueQr from 'vue-qr/src/packages/vue-qr.vue' import vueQr from 'vue-qr/src/packages/vue-qr.vue'
import three from '@/assets/logo.png' import three from '@/assets/logo.png'
const src = ref(null) import { getColor } from '@/utils/index'
const src2 = ref() const logoSrc = ref(null)
import clip from '@/utils/clipboard' const qrcodeUrl = ref(null)
const randomColor = ref('black')
const inputData = ref('https://github.com/zouzhibin/vue-admin-perfect') const inputData = ref('https://github.com/zouzhibin/vue-admin-perfect')
const handleQrcode = (type) => { const handleQrcode = (type) => {
switch (type) { switch (type) {
case 1: case 1:
src.value = null randomColor.value = 'black'
logoSrc.value = null
return return
case 2: case 2:
src.value = three logoSrc.value = three
return return
case 3:
randomColor.value = getColor()
return
case 4:
let name = new Date().getTime();
let a = document.createElement("a");
a.style.display = "none";
a.download = name;
a.href = qrcodeUrl.value;
document.body.appendChild(a);
a.click();
a.remove()
return;
} }
} }
const qrcodeCallback = (url)=>{
qrcodeUrl.value = url
}
</script> </script>

View File

@ -696,11 +696,24 @@ async@^3.2.3:
resolved "https://registry.npmmirror.com/async/-/async-3.2.4.tgz#2d22e00f8cddeb5fde5dd33522b56d1cf569a81c" resolved "https://registry.npmmirror.com/async/-/async-3.2.4.tgz#2d22e00f8cddeb5fde5dd33522b56d1cf569a81c"
integrity sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ== integrity sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ==
asynckit@^0.4.0:
version "0.4.0"
resolved "https://registry.npmmirror.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79"
integrity sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==
atob@^2.1.2: atob@^2.1.2:
version "2.1.2" version "2.1.2"
resolved "https://registry.npmmirror.com/atob/-/atob-2.1.2.tgz#6d9517eb9e030d2436666651e86bd9f6f13533c9" resolved "https://registry.npmmirror.com/atob/-/atob-2.1.2.tgz#6d9517eb9e030d2436666651e86bd9f6f13533c9"
integrity sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg== integrity sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==
axios@^0.27.2:
version "0.27.2"
resolved "https://registry.npmmirror.com/axios/-/axios-0.27.2.tgz#207658cc8621606e586c85db4b41a750e756d972"
integrity sha512-t+yRIyySRTp/wua5xEr+z1q60QmLq8ABsS5O9Me1AsE5dfKqgnCFzwiCZZ/cGNd1lq4/7akDWMxdhVlucjmnOQ==
dependencies:
follow-redirects "^1.14.9"
form-data "^4.0.0"
balanced-match@^1.0.0: balanced-match@^1.0.0:
version "1.0.2" version "1.0.2"
resolved "https://registry.npmmirror.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" resolved "https://registry.npmmirror.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee"
@ -950,6 +963,13 @@ color-name@~1.1.4:
resolved "https://registry.npmmirror.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" resolved "https://registry.npmmirror.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2"
integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==
combined-stream@^1.0.8:
version "1.0.8"
resolved "https://registry.npmmirror.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f"
integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==
dependencies:
delayed-stream "~1.0.0"
commander@^2.20.3: commander@^2.20.3:
version "2.20.3" version "2.20.3"
resolved "https://registry.npmmirror.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" resolved "https://registry.npmmirror.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33"
@ -1164,6 +1184,11 @@ define-property@^2.0.2:
is-descriptor "^1.0.2" is-descriptor "^1.0.2"
isobject "^3.0.1" isobject "^3.0.1"
delayed-stream@~1.0.0:
version "1.0.0"
resolved "https://registry.npmmirror.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619"
integrity sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==
delegate@^3.1.2: delegate@^3.1.2:
version "3.2.0" version "3.2.0"
resolved "https://registry.npmmirror.com/delegate/-/delegate-3.2.0.tgz#b66b71c3158522e8ab5744f720d8ca0c2af59166" resolved "https://registry.npmmirror.com/delegate/-/delegate-3.2.0.tgz#b66b71c3158522e8ab5744f720d8ca0c2af59166"
@ -1813,11 +1838,25 @@ flatted@^3.1.0:
resolved "https://registry.npmmirror.com/flatted/-/flatted-3.2.6.tgz#022e9218c637f9f3fc9c35ab9c9193f05add60b2" resolved "https://registry.npmmirror.com/flatted/-/flatted-3.2.6.tgz#022e9218c637f9f3fc9c35ab9c9193f05add60b2"
integrity sha512-0sQoMh9s0BYsm+12Huy/rkKxVu4R1+r96YX5cG44rHV0pQ6iC3Q+mkoMFaGWObMFYQxCVT+ssG1ksneA2MI9KQ== integrity sha512-0sQoMh9s0BYsm+12Huy/rkKxVu4R1+r96YX5cG44rHV0pQ6iC3Q+mkoMFaGWObMFYQxCVT+ssG1ksneA2MI9KQ==
follow-redirects@^1.14.9:
version "1.15.1"
resolved "https://registry.npmmirror.com/follow-redirects/-/follow-redirects-1.15.1.tgz#0ca6a452306c9b276e4d3127483e29575e207ad5"
integrity sha512-yLAMQs+k0b2m7cVxpS1VKJVvoz7SS9Td1zss3XRwXj+ZDH00RJgnuLx7E44wx02kQLrdM3aOOy+FpzS7+8OizA==
for-in@^1.0.2: for-in@^1.0.2:
version "1.0.2" version "1.0.2"
resolved "https://registry.npmmirror.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80" resolved "https://registry.npmmirror.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80"
integrity sha512-7EwmXrOjyL+ChxMhmG5lnW9MPt1aIeZEwKhQzoBUdTV0N3zuwWDZYVJatDvZ2OyzPUvdIAZDsCetk3coyMfcnQ== integrity sha512-7EwmXrOjyL+ChxMhmG5lnW9MPt1aIeZEwKhQzoBUdTV0N3zuwWDZYVJatDvZ2OyzPUvdIAZDsCetk3coyMfcnQ==
form-data@^4.0.0:
version "4.0.0"
resolved "https://registry.npmmirror.com/form-data/-/form-data-4.0.0.tgz#93919daeaf361ee529584b9b31664dc12c9fa452"
integrity sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==
dependencies:
asynckit "^0.4.0"
combined-stream "^1.0.8"
mime-types "^2.1.12"
frac@~1.1.2: frac@~1.1.2:
version "1.1.2" version "1.1.2"
resolved "https://registry.npmmirror.com/frac/-/frac-1.1.2.tgz#3d74f7f6478c88a1b5020306d747dc6313c74d0b" resolved "https://registry.npmmirror.com/frac/-/frac-1.1.2.tgz#3d74f7f6478c88a1b5020306d747dc6313c74d0b"
@ -2591,6 +2630,11 @@ micromatch@^4.0.4:
braces "^3.0.2" braces "^3.0.2"
picomatch "^2.3.1" picomatch "^2.3.1"
mime-db@1.52.0:
version "1.52.0"
resolved "https://registry.npmmirror.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70"
integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==
mime-match@^1.0.2: mime-match@^1.0.2:
version "1.0.2" version "1.0.2"
resolved "https://registry.npmmirror.com/mime-match/-/mime-match-1.0.2.tgz#3f87c31e9af1a5fd485fb9db134428b23bbb7ba8" resolved "https://registry.npmmirror.com/mime-match/-/mime-match-1.0.2.tgz#3f87c31e9af1a5fd485fb9db134428b23bbb7ba8"
@ -2598,6 +2642,13 @@ mime-match@^1.0.2:
dependencies: dependencies:
wildcard "^1.1.0" wildcard "^1.1.0"
mime-types@^2.1.12:
version "2.1.35"
resolved "https://registry.npmmirror.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a"
integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==
dependencies:
mime-db "1.52.0"
mimic-response@^3.1.0: mimic-response@^3.1.0:
version "3.1.0" version "3.1.0"
resolved "https://registry.npmmirror.com/mimic-response/-/mimic-response-3.1.0.tgz#2d1d59af9c1b129815accc2c46a022a5ce1fa3c9" resolved "https://registry.npmmirror.com/mimic-response/-/mimic-response-3.1.0.tgz#2d1d59af9c1b129815accc2c46a022a5ce1fa3c9"