首页
关于
Search
1
前端跨域的解决方案
24 阅读
2
vue3封装el-button
21 阅读
3
nodejs实现mysql的增删改查
20 阅读
4
表格内容溢出显示省略号浮空提示内容
19 阅读
5
实现数组的push、filter、map方法
18 阅读
未分类
JavaScript
登录
Search
标签搜索
JavaScript
vue
组件封装
nodejs
笔记
谷歌插件
mysql
Nginx
数组
数组方法实现
原生js
promise
async、await
靓仔
累计撰写
15
篇文章
累计收到
0
条评论
首页
栏目
未分类
JavaScript
页面
关于
搜索到
14
篇与
的结果
2025-01-03
几种不同格式的下载方法和文件类型大小的方法
通用的下载方法/** * @description 通用下载方法 * @param {Blob} blob 文件blob * @param {String} filename 文件名 */ export const download = (blob, filename) => { const link = document.createElement('a') link.href = window.URL.createObjectURL(blob) link.download = filename link.click() window.URL.revokeObjectURL(link.href) }下载文件/** * @description 下载文件 * @param {String} url 文件地址 * @param {String} filename 文件名 */ export const downloadFile = async (url, filename) => { try { const response = await fetch(url) const blob = await response.blob() download(blob, filename) } catch (error) { console.error('下载失败:', error) throw error } }下载Excel文件#需要安装XLSX插件 npm install xlsx yarn add xlsx pnpm add xlsx/** * @description 下载Excel文件 * @param {Array} data 数据数组 * @param {String} filename 文件名 * @param {Array} headers 表头 */ export const downloadExcel = (data, filename, headers) => { // 创建工作簿 const worksheet = XLSX.utils.json_to_sheet(data, { header: headers }) const workbook = XLSX.utils.book_new() XLSX.utils.book_append_sheet(workbook, worksheet, 'Sheet1') // 生成excel文件并下载 const excelBuffer = XLSX.write(workbook, { bookType: 'xlsx', type: 'array' }) const blob = new Blob([excelBuffer], { type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' }) //第一个方法 download(blob, `${filename}.xlsx`) }下载图片类型/** * @description 下载图片 * @param {String} url 图片地址 * @param {String} filename 文件名 */ export const downloadImage = async (url, filename) => { try { const response = await fetch(url) const blob = await response.blob() const ext = url.split('.').pop().split('?')[0] //调用上面第一个方法 download(blob, `${filename}.${ext}`) } catch (error) { console.error('图片下载失败:', error) throw error } }获取文件大小方法/** * @description 获取文件大小 * @param {Number} bytes 字节数 * @param {Number} decimals 小数位数 * @return {String} */ export const formatBytes = (bytes, decimals = 2) => { if (bytes === 0) return '0 Bytes' const k = 1024 const dm = decimals < 0 ? 0 : decimals const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'] const i = Math.floor(Math.log(bytes) / Math.log(k)) return `${parseFloat((bytes / Math.pow(k, i)).toFixed(dm))} ${sizes[i]}` }获取文件类型/** * @description 获取文件类型 * @param {String} filename 文件名 * @return {String} */ export const getFileType = (filename) => { const ext = filename.split('.').pop().toLowerCase() const typeMap = { // 图片 'jpg': 'image', 'jpeg': 'image', 'png': 'image', 'gif': 'image', 'webp': 'image', // 文档 'doc': 'document', 'docx': 'document', 'pdf': 'document', 'txt': 'document', // 表格 'xls': 'spreadsheet', 'xlsx': 'spreadsheet', 'csv': 'spreadsheet', // 压缩包 'zip': 'archive', 'rar': 'archive', '7z': 'archive', // 音视频 'mp3': 'audio', 'mp4': 'video', 'avi': 'video' } return typeMap[ext] || 'unknown' }
2025年01月03日
1 阅读
0 评论
0 点赞
2025-01-02
分享一个毛玻璃样式的登录页面
使用的是scss 记得安装sass 任选以下一个都可以,取决于你的包管理工具是啥# npm install sass # yarn add sass # pnpm add sasstemplate部分代码<template> <div class="login-container"> <div class="login-background"> <div class="gradient-circles"> <div class="circle circle-1"></div> <div class="circle circle-2"></div> <div class="circle circle-3"></div> </div> </div> <div class="glassmorphism-card"> <div class="login-content"> <div class="login-header"> <img src="/vite.svg" alt="Logo" class="logo" /> <h1>系统</h1> <p class="subtitle">知识的殿堂,智慧的源泉</p> </div> <login-form @login="handleLogin" /> <div class="login-footer"> <p>© {{ new Date().getFullYear() }} System. All rights reserved.</p> </div> </div> </div> </div> </template>JavaScript部分代码<script setup> import LoginForm from '../components/login/LoginForm.vue'; const handleLogin = (credentials) => { //处理逻辑 }; </script>css部分代码<style scoped lang="scss"> .login-container { height: 100vh; display: flex; align-items: center; justify-content: center; position: relative; background: linear-gradient(135deg, #1a237e 0%, #0d47a1 100%); } .login-background { position: fixed; width: 100%; height: 100%; top: 0; left: 0; } .gradient-circles { position: absolute; width: 100%; height: 100%; .circle { position: absolute; border-radius: 50%; filter: blur(60px); } .circle-1 { width: 600px; height: 600px; background: rgba(64, 158, 255, 0.3); top: -200px; right: -100px; animation: float 8s infinite; } .circle-2 { width: 450px; height: 450px; background: rgba(103, 58, 183, 0.3); bottom: -150px; left: -100px; animation: float 10s infinite; } .circle-3 { width: 300px; height: 300px; background: rgba(233, 30, 99, 0.3); top: 40%; left: 60%; animation: float 12s infinite; } } .glassmorphism-card { width: 460px; padding: 40px; background: rgba(255, 255, 255, 0.1); backdrop-filter: blur(20px); border-radius: 24px; border: 1px solid rgba(255, 255, 255, 0.2); box-shadow: 0 8px 32px rgba(0, 0, 0, 0.1); animation: slideIn 0.6s ease-out; } .login-content { .login-header { text-align: center; margin-bottom: 2rem; .logo { width: 80px; height: 80px; margin-bottom: 1rem; animation: pulse 2s infinite; } h1 { font-size: 2rem; color: #ffffff; margin: 0; font-weight: 600; text-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); } .subtitle { color: rgba(255, 255, 255, 0.8); margin-top: 0.5rem; font-size: 1rem; } } } .login-footer { text-align: center; margin-top: 2rem; color: rgba(255, 255, 255, 0.7); font-size: 0.9rem; } @keyframes float { 0%, 100% { transform: translateY(0) rotate(0deg); } 50% { transform: translateY(-20px) rotate(5deg); } } @keyframes slideIn { from { transform: translateY(20px); opacity: 0; } to { transform: translateY(0); opacity: 1; } } @keyframes pulse { 0%, 100% { transform: scale(1); } 50% { transform: scale(1.05); } } </style>loginForm组件template部分<template> <el-form ref="formRef" :model="form" :rules="rules" class="login-form" @submit.prevent="handleSubmit" > <el-form-item prop="username"> <el-input v-model="form.username" prefix-icon="User" placeholder="用户名" :class="{ 'input-focus': activeInput === 'username' }" @focus="activeInput = 'username'" @blur="activeInput = ''" /> </el-form-item> <el-form-item prop="password"> <el-input v-model="form.password" prefix-icon="Lock" type="password" placeholder="密码" :class="{ 'input-focus': activeInput === 'password' }" @focus="activeInput = 'password'" @blur="activeInput = ''" show-password /> </el-form-item> <div class="form-options"> <el-checkbox v-model="form.remember" class="remember-checkbox"> 记住我 </el-checkbox> <el-button link type="primary" class="forgot-password"> 忘记密码? </el-button> </div> <el-button type="primary" native-type="submit" class="submit-button" :loading="loading" round > 登录 </el-button> </el-form> </template>-JavaScript部分<script setup> import { ref } from 'vue'; const emit = defineEmits(['login']); const formRef = ref(); const loading = ref(false); const activeInput = ref(''); const form = ref({ username: '', password: '', remember: false }); const rules = { username: [ { required: true, message: '请输入用户名', trigger: 'blur' }, { min: 3, message: '用户名至少3个字符', trigger: 'blur' } ], password: [ { required: true, message: '请输入密码', trigger: 'blur' }, { min: 6, message: '密码至少6个字符', trigger: 'blur' } ] }; const handleSubmit = async() => { if (!formRef.value) return; try { loading.value = true; await formRef.value.validate(); emit('login', { username: form.value.username, password: form.value.password, remember: form.value.remember }); } catch (error) { console.error('表单验证失败:', error); } finally { loading.value = false; } }; </script>css部分<style scoped lang="scss"> .login-form { .el-input { --el-input-bg-color: rgba(255, 255, 255, 0.1); --el-input-border-color: rgba(255, 255, 255, 0.2); --el-input-hover-border: rgba(255, 255, 255, 0.3); --el-input-focus-border: rgba(255, 255, 255, 0.4); --el-input-text-color: #ffffff; --el-input-placeholder-color: rgba(255, 255, 255, 0.6); :deep(.el-input__wrapper) { box-shadow: none; background: rgba(255, 255, 255, 0.1); backdrop-filter: blur(5px); transition: all 0.3s ease; &:hover { background: rgba(255, 255, 255, 0.15); } &.is-focus { background: rgba(255, 255, 255, 0.2); } } :deep(.el-input__icon) { color: rgba(255, 255, 255, 0.8); } } .el-form-item { margin-bottom: 1.5rem; } } .form-options { display: flex; justify-content: space-between; align-items: center; margin-bottom: 1.5rem; .remember-checkbox { :deep(.el-checkbox__label) { color: rgba(255, 255, 255, 0.8); } :deep(.el-checkbox__input) { .el-checkbox__inner { background-color: rgba(255, 255, 255, 0.1); border-color: rgba(255, 255, 255, 0.3); } } } .forgot-password { color: rgba(255, 255, 255, 0.8); &:hover { color: #ffffff; } } } .submit-button { width: 100%; height: 44px; font-size: 1.1rem; letter-spacing: 1px; background: linear-gradient(45deg, #42a5f5, #1976d2); border: none; transition: all 0.3s ease; &:hover { transform: translateY(-2px); box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2); background: linear-gradient(45deg, #64b5f6, #1e88e5); } &:active { transform: translateY(0); } } </style>
2025年01月02日
1 阅读
0 评论
0 点赞
2024-12-26
几种常见的类型判断的工具类函数
分享几种常见的类型判断的工具类函数1、判断数据类型/** * @description 判断数据类型 * @param {Any} val 需要判断类型的数据 * @return {String} */ export const getType = (val) => { return Object.prototype.toString.call(val).slice(8, -1).toLowerCase() }2、判断是否为对象/** * @description 判断是否为对象 * @param {Any} val 需要判断的数据 * @return {Boolean} */ export const isObject = (val) => { return getType(val) === 'object' }3、判断是否为数组/** * @description 判断是否为数组 * @param {Any} val 需要判断的数据 * @return {Boolean} */ export const isArray = (val) => { return getType(val) === 'array' }4、判断是否为空/** * @description 判断是否为空 * @param {Any} val 需要判断的数据 * @return {Boolean} */ export const isEmpty = (val) => { if (isArray(val) || typeof val === 'string') { return val.length === 0 } if (val instanceof Map || val instanceof Set) { return val.size === 0 } if (isObject(val)) { return Object.keys(val).length === 0 } return false }
2024年12月26日
1 阅读
0 评论
0 点赞
2023-09-22
表格内容溢出显示省略号浮空提示内容
表格列数据组件内容显示封装<template> <el-tooltip :key="key" :disabled="tipShow" placement="top" effect="light" popper-class="popper-class" > <template #content> <span :class="newLine === 'true' && 'new-line'">{{ content }}</span> </template> <p ref="tipContent" v-resize:200="onResize" class="tips"> <slot>{{ content }}</slot> </p> </el-tooltip> </template> <script> import { computed, defineComponent, ref, onMounted } from 'vue' export default defineComponent({ name: 'tips', isComponents: true, props: { content: { type: null, required: true, default: '' }, attributes: { type: Object, default: () => {} }, newLine: { type: String, default: '' }, key: { type: null, default: Date.now() + '-' + Math.floor(Math.random() * 10000) } }, setup(props) { const tipContent = ref(null) const tipShow = ref(true) const getBoolean = () => { if ( props.content && tipContent.value && tipContent.value.scrollWidth > tipContent.value.clientWidth ) { return false } if (props.attributes && props.attributes.hasOwnProperty('disabled')) { return props.attributes.disabled } return true } onMounted(() => { tipShow.value = getBoolean() }) const onResize = () => { tipShow.value = getBoolean() } return { tipContent, tipShow, onResize } } }) </script> <style lang="scss" scoped> .tips { width: 100%; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } .line { white-space: pre; } </style> <style lang="scss"> .popper-class { max-width: 900px; } </style> <template> <el-tooltip :key="key" :disabled="tipShow" placement="top" effect="light" popper-class="popper-class" > <template #content> <span :class="newLine === 'true' && 'new-line'">{{ content }}</span> </template> <p ref="tipContent" v-resize:200="onResize" class="tips"> <slot>{{ content }}</slot> </p> </el-tooltip> </template> <script> import { computed, defineComponent, ref, onMounted } from 'vue' export default defineComponent({ name: 'tips', isComponents: true, props: { content: { type: null, required: true, default: '' }, attributes: { type: Object, default: () => {} }, newLine: { type: String, default: '' }, key: { type: null, default: Date.now() + '-' + Math.floor(Math.random() * 10000) } }, setup(props) { const tipContent = ref(null) const tipShow = ref(true) const getBoolean = () => { if ( props.content && tipContent.value && tipContent.value.scrollWidth > tipContent.value.clientWidth ) { return false } if (props.attributes && props.attributes.hasOwnProperty('disabled')) { return props.attributes.disabled } return true } onMounted(() => { tipShow.value = getBoolean() }) const onResize = () => { tipShow.value = getBoolean() } return { tipContent, tipShow, onResize } } }) </script> <style lang="scss" scoped> .tips { width: 100%; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } .line { white-space: pre; } </style> <style lang="scss"> .popper-class { max-width: 900px; } </style>
2023年09月22日
19 阅读
0 评论
0 点赞
2023-08-31
原生ajax请求和promise ajax请求实现
原生ajax实现const url = "/user/login"; let xhr = new XMLHttpRequest(); // 创建 Http 请求 xhr.open("GET", url, true); // 设置状态监听函数 xhr.onreadystatechange = function() { if (this.readyState !== 4) return; // 当请求成功时 if (this.status === 200) { handle(this.response); } else { console.error(this.statusText); } }; // 设置请求失败时的监听函数 xhr.onerror = function() { console.error(this.statusText); }; // 设置请求头信息 xhr.responseType = "json"; xhr.setRequestHeader("Accept", "application/json"); // 发送 Http 请求 xhr.send(null);promise ajax实现 1、前端可以通过getData(url).then(res=>{console.log(res即为获取到的数据)}) 2、通过 async await方式const dataJson = async()=>{ let res = await getData(url) console.log(res);//res即为后台返回的数据 }// promise 封装实现: function getData(url) { // 创建一个 promise 对象 let promise = new Promise(function(resolve, reject) { let xhr = new XMLHttpRequest(); // 新建一个 http 请求 xhr.open("GET", url, true); // 设置状态的监听函数 xhr.onreadystatechange = function() { if (this.readyState !== 4) return; // 当请求成功或失败时,改变 promise 的状态 if (this.status === 200) { resolve(this.response); } else { reject(new Error(this.statusText)); } }; // 设置错误监听函数 xhr.onerror = function() { reject(new Error(this.statusText)); }; // 设置响应的数据类型 xhr.responseType = "json"; // 设置请求头信息 xhr.setRequestHeader("Accept", "application/json"); // 发送 http 请求 xhr.send(null); }); return promise; }
2023年08月31日
15 阅读
0 评论
1 点赞
1
2
3