前端 | 前端图床搭建实践(前端).png

项目背景

前端开发过程中不可避免会用到图片、视频等多媒体物料,常见的处理方案通常会进行动静分离,将图片等资源放置在图床上,除了使用业界常用的图床资源,比如:七牛云、微博图床等,除了借助第三方图床外,我们也可以自己搭建一个图床,为团队业务开发提供更好的基础服务,提升开发体验及效率。本文旨在回顾总结下自建图床的前端部分实现方案,希望能够给有类似需求的同学一些借鉴和方案。

方案

前端部分架构选型,考虑到Vue3即将成为主版本,作为前端基建侧的应用,考虑想要使用Vue3全家桶来进行前端侧的相关实现,这里使用了vite(vue-template-ts)+vue3+vuex@next+vue-router@next的使用方案,也为vite的打包构建进行一步的技术预(cai)研(keng)。(ps:vite确实快,但是目前直接上工业环境还需要考量,还有不少坑,个人认为跨语言的前端工程化可能会是后续前端工程化的发展方向)

目录

  • src
    • assets
    • components
      • index.ts
      • Card.vue
      • Login.vue
      • Upload.vue
      • WrapperLayouts.vue
      • WrapperLogin.vue
      • WrapperUpload.vue
    • config
      • index.ts
      • menuMap.ts
      • routes.ts
    • layouts
      • index.ts
      • Aside.vue
      • Layouts.vue
      • Main.vue
      • Nav.vue
    • route
      • index.ts
    • store
      • index.ts
    • utils
      • index.ts
      • reg.ts
      • validate.ts
    • views
      • Page.vue
    • App.vue
    • index.scss
    • main.ts
    • vue-app-env.d.ts
  • index.html
  • tsconfig.json
  • vite.config.ts

实践

前端图床涉及到权限验证,对于获取图片不进行认证确认,而对于需要进行上传及删除图片操作会需要进行登录鉴权

源码

vue3中可以通过class以及template两种方案来书写,使用composition-api的方案,个人建议还是使用class-component更加舒服,也更像react的写法,这里夹杂使用了composition-api和options-api的使用,目前vue是兼容的,对于从vue2中过来的同学,可以逐步去适应composition-api的写法,然后逐步按照hooks的函数式的思路去进行前端的业务实现

vite.config.ts

vite构建相关的一些配置,可以根据项目需求进行环境配置

const path = require('path')
// vite.config.js # or vite.config.ts
console.log(path.resolve(__dirname, './src'))module.exports = {alias: {// 键必须以斜线开始和结束'/@/': path.resolve(__dirname, './src'),},/*** 在生产中服务时的基本公共路径。* @default '/'*/base: './',/*** 与“根”相关的目录,构建输出将放在其中。如果目录存在,它将在构建之前被删除。* @default 'dist'*/outDir: 'dist',port: 3000,// 是否自动在浏览器打开open: false,// 是否开启 httpshttps: false,// 服务端渲染ssr: false,// 引入第三方的配置//   optimizeDeps: {//     include: ["moment", "echarts", "axios", "mockjs"],//   },proxy: {// 如果是 /bff 打头,则访问地址如下'/bff/': {target: 'http://localhost:30096/',// 'http://10.186.2.55:8170/',  changeOrigin: true,rewrite: (path) => path.replace(/^\/bff/, ''),}},optimizeDeps: {include: ['element-plus/lib/locale/lang/zh-cn', 'axios'],},
}

Page.vue

每个子项目页面的展示,只需要一个组件,进行不同的数据渲染即可

<template><div class="page-header"><el-row><el-col :span="12"><el-page-header:content="$route.fullPath.split('/').slice(2).join(' > ')"@back="handleBack"/></el-col><el-col :span="12"><section class="header-button"><!-- <el-button class="folder-add" :icon="FolderAdd" @click="handleFolder" >新建文件夹</el-button> --><el-button class="upload" :icon="Upload" type="success" @click="handleImage">上传图片</el-button></section></el-col></el-row></div><div class="page"><el-row :gutter="10"><el-col v-for="(item, index) in cards" :xs="12" :sm="8" :md="6" :lg="4" :xl="4"><Card@next="handleRouteView(item.ext, item.name)"@delete="handleDelete":name="item.name":src="item.src":ext="item.ext":key="index"/></el-col></el-row><el-paginationlayout="sizes, prev, pager, next, total"@size-change="handleSizeChange"@current-change="handlePageChange":current-page.sync="pageNum":page-size="pageSize":total="total"></el-pagination><router-view /></div><WrapperUpload ref="wrapper-upload" :headers="computedHeaders" /><WrapperLogin ref="wrapper-login" />
</template><script lang="ts">
import {defineComponent,
} from 'vue';
import { useRoute } from 'vue-router'
import {FolderAdd,Upload
} from '@element-plus/icons-vue'import { Card, WrapperUpload, WrapperLogin } from '../components'export default defineComponent({name: 'Page',components: {Card,WrapperUpload,WrapperLogin},props: {},setup() {return {FolderAdd,Upload}},data() {return {cards: [],total: 30,pageSize: 30,pageNum: 1,bucketName: '',prefix: '',}},watch: {$route: {immediate: true,handler(val) {console.log('val', val)if (val) {this.handleCards()}}}},methods: {handleBack() {this.$router.go(-1)},handleFolder() {},handleDelete(useName) {console.log('useName', useName)const [bucketName, ...objectName] = useName.split('/');console.log('bukcetName', bucketName);console.log('objectName', objectName.join('/'));if (sessionStorage.getItem('token')) {this.$http.post("/bff/imagepic/object/removeObject", {bucketName: bucketName,objectName: objectName.join('/')}, {headers: {'Authorization': sessionStorage.getItem('token'),}}).then(res => {console.log('removeObject', res)if (res.data.success) {this.$message.success(`${objectName.pop()}图片删除成功`);setTimeout(() => {this.$router.go(0)}, 100)} else {this.$message.error(`${objectName.pop()}图片删除失败,失败原因:${res.data.data}`)}})} else {this.$refs[`wrapper-login`].handleOpen()}},handleImage() {sessionStorage.getItem('token')? this.$refs[`wrapper-upload`].handleOpen(): this.$refs[`wrapper-login`].handleOpen()},handleRouteView(ext, name) {// console.log('extsss', ext)if (ext == 'file') {console.log('$router', this.$router)console.log('$route.name', this.$route.name, this.$route.path)this.$router.addRoute(this.$route.name,{path: `:${name}`,name: name,component: () => import('./Page.vue')})console.log('$router.options.routes', this.$router.options.routes)this.$router.push({path: `/page/${this.$route.params.id}/${name}`})} else {}},handlePageChange(val) {this.pageNum = val;this.handleCards();},handleSizeChange(val) {this.pageSize = val;this.handleCards();},handleCards() {this.cards = [];let [bucketName, prefix] = this.$route.path.split('/').splice(2);this.bucketName = bucketName;this.prefix = prefix;console.log('bucketName', bucketName, prefix)this.$http.post("/bff/imagepic/object/listObjects", {bucketName: bucketName,prefix: prefix ? prefix + '/' : '',pageSize: this.pageSize,pageNum: this.pageNum}).then(res => {console.log('listObjects', res.data)if (res.data.success) {this.total = res.data.data.total;if (prefix) {this.total -= 1;return res.data.data.lists.filter(f => f.name != prefix + '/')}return res.data.data.lists}}).then(data => {console.log('data', data)data.forEach(d => {// 当前目录下if (d.name) {this.$http.post('/bff/imagepic/object/presignedGetObject', {bucketName: bucketName,objectName: d.name}).then(url => {// console.log('url', url)if (url.data.success) {const ext = url.data.data.split('?')[0];// console.log('ext', ext)let src = '', ext_type = '';switch (true) {case /\.(png|jpg|jpeg|gif|svg|webp)$/.test(ext):src = url.data.data;ext_type = 'image';break;case /\.(mp4)$/.test(ext):src = 'icon_mp4';ext_type = 'mp4';break;case /\.(xls)$/.test(ext):src = 'icon_xls';ext_type = 'xls';break;case /\.(xlsx)$/.test(ext):src = 'icon_xlsx';ext_type = 'xlsx';break;case /\.(pdf)$/.test(ext):src = 'icon_pdf';ext_type = 'pdf';break;default:src = 'icon_unknow';ext_type = 'unknown';break;}this.cards.push({name: d.name,src: src,ext: ext_type})}})} else {if (d.prefix) {const src = 'icon_file', ext_type = 'file';this.cards.push({name: d.prefix.slice(0, -1),src: src,ext: ext_type})}}})})}},computed: {computedHeaders: function () {console.log('this.$route.fullPath', this.$route.fullPath)return {'Authorization': sessionStorage.getItem('token'),'bucket': this.bucketName,'folder': this.$route.fullPath.split('/').slice(3).join('/')}}}
})
</script><style lang="scss">
@import "../index.scss";
.page-header {margin: 1rem;.header-info {display: flex;align-items: center;justify-content: space-between;}.header-button {display: flex;align-items: center;justify-content: right;.el-button.upload {background-color: $color-primary;}.el-button.upload:hover {background-color: lighten($color: $color-primary, $amount: 10%);}}
}.page {margin: 1rem;height: 90vh;.el-row {height: calc(100% - 6rem);overflow-y: scroll;}.el-pagination {margin: 1rem 0;}
}
</style>

Login.vue

进行基础的登录/注册实现,可在外侧进行弹窗及嵌入的包裹,将业务逻辑与展现形式分离

<template><div :class="loginClass"><section class="login-header"><span class="title">{{ title }}</span></section><section class="login-form"><template v-if="form == 'login'"><el-formref="login-form"label-width="70px"label-position="left":model="loginForm":rules="loginRules"><el-form-item:key="item.prop"v-for="item in loginFormItems":label="item.label":prop="item.prop"><el-inputv-model="loginForm[`${item.prop}`]":placeholder="item.placeholder":type="item.type"></el-input></el-form-item></el-form></template><template v-else-if="form == 'register'"><el-formref="register-form"label-width="100px"label-position="left":model="registerForm":rules="registerRules"><el-form-item:key="item.prop"v-for="item in registerFormItems":label="item.label":prop="item.prop"><el-inputv-model="registerForm[`${item.prop}`]":placeholder="item.placeholder":type="item.type"></el-input></el-form-item></el-form></template></section><section class="login-select"><span class="change" v-if="form == 'login'" @click="isShow = true">修改密码</span><span class="go" @click="handleGo(form)">{{ form == 'login' ? ' 去注册 >>' : ' 去登录 >>' }}</span></section><section class="login-button"><template v-if="form == 'login'"><el-button @click="handleLogin">登录</el-button></template><template v-else-if="form == 'register'"><el-button @click="handleRegister">注册</el-button></template></section></div><el-dialog v-model="isShow"><el-formref="change-form"label-width="130px"label-position="left":model="changeForm":rules="changeRules"><el-form-item:key="item.prop"v-for="item in changeFormItems":label="item.label":prop="item.prop"><el-inputv-model="changeForm[`${item.prop}`]":placeholder="item.placeholder":type="item.type"></el-input></el-form-item></el-form><div class="change-button"><el-button class="cancel" @click="isShow = false">取消</el-button><el-button class="confirm" @click="handleConfirm" type="primary">确认</el-button></div></el-dialog>
</template><script lang="ts">
import {defineComponent
} from 'vue';import { validatePwd, validateEmail, validateName, validatePhone } from '../utils/index';export default defineComponent({name: 'Login',props: {title: {type: String,default: ''},border: {type: Boolean,default: false}},data() {return {form: 'login',isShow: false,loginForm: {phone: '',upwd: ''},loginRules: {phone: [{required: true,validator: validatePhone,trigger: 'blur',}],upwd: [{validator: validatePwd,required: true,trigger: 'blur',}]},loginFormItems: [{label: "手机号",prop: "phone",placeholder: '请输入手机号'},{label: "密码",prop: "upwd",placeholder: '',type: 'password'}],registerForm: {name: '',tfs: '',email: '',phone: '',upwd: '',rpwd: ''},registerFormItems: [{label: "姓名",prop: "name",placeholder: ''},{label: "TFS账号",prop: "tfs",placeholder: ''},{label: "邮箱",prop: "email",placeholder: ''},{label: "手机号",prop: "phone",placeholder: ''},{label: "请输入密码",prop: "upwd",placeholder: '',type: 'password'},{label: "请确认密码",prop: "rpwd",placeholder: '',type: 'password'}],registerRules: {name: [{validator: validateName,trigger: 'blur',}],tfs: [{required: true,message: '请按要求输入tfs账号',trigger: 'blur',}],email: [{required: true,validator: validateEmail,trigger: 'blur',}],phone: [{required: true,validator: validatePhone,trigger: 'blur',}],upwd: [{required: true,validator: validatePwd,trigger: 'blur',}],rpwd: [{required: true,validator: validatePwd,trigger: 'blur',},{validator(rule: any, value: any, callback: any) {if (value != this.registerForm.upwd) {callback(new Error('输入的密码不同'))}},trigger: 'blur',}],},changeForm: {phone: '',opwd: '',npwd: '',rpwd: ''},changeFormItems: [{label: "手机号",prop: "phone",placeholder: '请输入手机号'},{label: "请输入原始密码",prop: "opwd",placeholder: '',type: 'password'},{label: "请输入新密码",prop: "npwd",placeholder: '',type: 'password'},{label: "请重复新密码",prop: "rpwd",placeholder: '',type: 'password'}],changeRules: {phone: [{required: true,validator: validatePhone,trigger: 'blur',}],opwd: [{required: true,validator: validatePwd,trigger: 'blur',}],npwd: [{required: true,validator: validatePwd,trigger: 'blur',}],rpwd: [{required: true,validator: validatePwd,trigger: 'blur',},{validator(rule: any, value: any, callback: any) {if (value != this.changeForm.npwd) {callback(new Error('输入的密码不同'))}},trigger: 'blur',}],}}},computed: {loginClass() {return this.border ? 'login login-unwrapper' : 'login login-wrapper'}},methods: {handleGo(form) {if (form == 'login') {this.form = 'register'} else if (form == 'register') {this.form = 'login'}},handleLogin() {this.$http.post("/bff/imagepic/auth/login", {phone: this.loginForm.phone,upwd: this.loginForm.upwd}).then(res => {if (res.data.success) {this.$message.success('登录成功');sessionStorage.setItem('token', res.data.data.token);this.$router.go(0);} else {this.$message.error(res.data.data.err);}})},handleRegister() {this.$http.post("/bff/imagepic/auth/register", {name: this.registerForm.name,tfs: this.registerForm.tfs,email: this.registerForm.email,phone: this.registerForm.phone,upwd: this.registerForm.upwd}).then(res => {if (res.data.success) {this.$message.success('注册成功');} else {this.$message.error(res.data.data.err);}})},handleConfirm() {this.$http.post("/bff/imagepic/auth/change", {phone: this.changeForm.phone,opwd: this.changeForm.opwd,npwd: this.changeForm.npwd}).then(res => {if (res.data.success) {this.$message.success('修改密码成功');} else {this.$message.error(res.data.data.err);}})}}})
</script><style lang="scss">
@import "../index.scss";
.login-wrapper {
}.login-unwrapper {border: 1px solid #ececec;border-radius: 4px;
}.login {&-header {text-align: center;.title {font-size: 1.875rem;font-size: bold;color: #333;}}&-form {margin-top: 2rem;}&-select {display: flex;justify-content: right;align-items: center;cursor: pointer;.go {color: orange;text-decoration: underline;margin-left: 0.5rem;}.go:hover {color: orangered;}.change {color: skyblue;}.change:hover {color: rgb(135, 178, 235);}}&-button {margin-top: 2rem;.el-button {width: 100%;background-color: $color-primary;color: white;}}
}.change-button {display: flex;justify-content: space-around;align-items: center;.confirm {background-color: $color-primary;}
}
</style>

routes.ts

vue-router@next中的动态路由方案略有不同,有类似rank的排名机制,具体可以参考vue-router@next的官方文档

import { WrapperLayouts } from '../components';
import menuMap from './menuMap'
// 1. 定义路由组件, 注意,这里一定要使用 文件的全名(包含文件后缀名)
const routes = [{ path: "/",component: WrapperLayouts,redirect: `/page/${Object.keys(menuMap)[0]}`,children: [{path: '/page/:id',name: 'page',component: () => import('../views/Page.vue'),children: [{path: '/page/:id(.*)*',// redirect: `/page/${Object.keys(menuMap)[0]}`,name: 'pageno',component: () => import('../views/Page.vue')}]}]},
];export default routes;
import {createRouter, createWebHashHistory} from 'vue-router';import { routes } from '../config';// Vue-router新版本中,需要使用createRouter来创建路由
export default  createRouter({// 指定路由的模式,此处使用的是hash模式history: createWebHashHistory(),routes // short for `routes: routes`
})

Aside.vue

结合路由进行左边侧边栏的路由跳转及显示

<template><div class="aside"><el-menu @select="handleSelect" :default-active="Array.isArray($route.params.id) ? $route.params.id[0] : $route.params.id"><el-menu-item v-for="(menu, index) in menuLists" :index="menu.id" ><span>{{menu.label}}</span></el-menu-item></el-menu></div>
</template><script lang="ts">
import {computed,defineComponent,getCurrentInstance,onMounted,reactive,ref,toRefs,
} from 'vue';export default defineComponent({name: 'Aside',props: {menuMap: {type: Object,default: () => {}}},components: {},methods: {handleSelect(e) {console.log('$route', this.$route.params.id)console.log('select', e)this.$router.push(`/page/${e}`)}},setup(props, context) {console.log('props', props.menuMap)//引用全局变量const { proxy } = getCurrentInstance();const menuMap = props.menuMap;let menuLists = reactive([]);//dom挂载后onMounted(() => {handleMenuLists();});function handleMenuLists() {(proxy as any).$http.get('/bff/imagepic/bucket/listBuckets').then(res => {console.log('listBuckets', res);if(res.data.success) {res.data.data.forEach(element => {menuMap[`${element.name}`] && menuLists.push({id: element.name,label: menuMap[`${element.name}`]}) })}})}return {...toRefs(menuLists),handleMenuLists,menuLists};}
})
</script><style lang="scss">
.aside {height: 100%;background-color: #fff;width: 100%;border-right: 1px solid #d7d7d7;
}
</style>

总结

前端图床作为前端基建侧的一项重要的开发工具,不仅能够为业务开发人员提供更好的开发体验,也能节省业务开发过程中造成的效率降低,从而提升开发效率,降低成本损耗。前端展示的实现有多种不同的方案,对于有着更高要求的前端图床实现也可以基于需求进行更高层次的展示与提升。

查看全文
如若内容造成侵权/违法违规/事实不符,请联系编程学习网邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!

相关文章

  1. 小程序笔记

    ‘一、跟普通开发不同点 运行环境不同&#xff1a;网页浏览器&#xff0c;小程序微信环境 API&#xff1a;运行环境不同&#xff0c;所以无法调用DOM和BOM得API&#xff0c;但是小程序可以调用微信环境API,如地理位置&#xff0c;扫码&#xff0c;支付 开发模式不同&#xff…...

    2024/5/6 12:47:29
  2. 【牛客网】KY152 最短路径问题

    这道题是求最短路径&#xff0c;由于n最大可以为1000&#xff0c;而Floyd算法的复杂度为O(n3)&#xff0c;因此会超时&#xff0c;所以只能用Dijkstra算法&#xff0c;题目要求我们不仅求出最短路径&#xff0c;还要求出最短路径下的最少花费&#xff1a; #include <iostre…...

    2024/5/6 6:26:55
  3. 单片机(ISIS 7 Professional):简易数码管显示0~999计数代码项目

    之前有一篇文章主要介绍用C语言制作一个按钮的简易0~99控制计数器&#xff0c; 单片机(ISIS 7 Professional)&#xff1a;简易数码管显示0~99计数可加减代码项目https://blog.csdn.net/MOKI36_/article/details/122811517?spm1001.2014.3001.5501这一篇文章主要介绍用C语言制…...

    2024/5/6 7:21:07
  4. Android 架构组件之 WorkManager 的使用指南及项目实践

    文章目录使用场景定义选择 WorkManager 的理由 Why?多线程任务如何选择推荐的解决方案&#xff1a;即时任务延期任务精确任务走进源码WorkerWorkRequestWorkManagerDataWorkStatusDemo 快速使用项目实践首先放一个WorkManger介绍视频&#xff1a;中文官方介绍视频&#xff08;…...

    2024/4/20 20:26:26
  5. Sentinel限流熔断应用实践

    Sentinel简介 背景分析 在我们日常生活中&#xff0c;经常会在淘宝、天猫、京东、拼多多等平台上参与商品的秒杀、抢购以及一些优惠活动&#xff0c;也会在节假日使用12306 手机APP抢火车票、高铁票&#xff0c;甚至有时候还要帮助同事、朋友为他们家小孩拉投票、刷票&#x…...

    2024/4/13 12:36:27
  6. SushiSwap的MasterChef解读--转载

    SushiSwap的MasterChef解读 biakia0610 于 2021-04-13 14:22:31 发布 412 收藏 1 分类专栏&#xff1a; 区块链 文章标签&#xff1a; 区块链 版权声明&#xff1a;本文为博主原创文章&#xff0c;遵循CC 4.0 BY-SA 版权协议&#xff0c;转载请附上原文出处链接和本声明。 本…...

    2024/4/13 12:36:32
  7. 大概是最简单的 rtmp 推流服务器搭建方法

    转载自&#xff1a;点击跳转原文 我使用的centos&#xff0c;按照下面方法一遍过 一开始想到要弄一个简单的 rtmp 服务器是为了给同学上课投射屏幕用。因为我用的是 Linux &#xff0c;没法用国产的那些课室软件给他们投放屏幕&#xff0c;于是只好出此下策了。 我使用的系统…...

    2024/4/18 10:28:29
  8. 《Linux内核设计与实现》读书笔记—进程地址空间

    地址空间 Linux操作系统采用虚拟内存技术&#xff0c;因此系统中的所有进程之间以虚拟方式共享内存。对一个进程而言&#xff0c;它可以访问整个系统的所有物理内存&#xff0c;并且它拥有的地址空间也可以远远大于系统物理内存。尽管一个进程可以寻址4GB的虚拟内存&#xff0…...

    2024/5/4 10:51:46
  9. WEB漏洞-SQL注入之Oracle,MongoDB等注入

    数据库注入流程 简要了解各数据库 Access&#xff0c;Mysql&#xff0c;mssql&#xff0c;mongoDB&#xff0c;postgresql&#xff0c;sqlite&#xff0c;oracle&#xff0c;sybase等 Access 表名​ 列名 ​ 数据 除了Access其他数据库组成结构基本都类似。 Mysql&#…...

    2024/4/14 17:00:14
  10. Mybatis-plus进阶之代码生成器

    前言 Mybatis也有对应的反向工程mybatis-generator来生成相关的Mapper接口和xml配置。Mybatis-plus的代码生成更为简单。 导入pom依赖 <dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-generator</artifactId><vers…...

    2024/4/13 12:36:22
  11. 力扣:移除元素

    力扣&#xff1a;移除元素 代码随想录解析 题目&#xff1a; 给你一个数组 nums 和一个值 val&#xff0c;你需要 原地 移除所有数值等于 val 的元素&#xff0c;并返回移除后数组的新长度。 不要使用额外的数组空间&#xff0c;你必须仅使用 O(1) 额外空间并 原地 修改输入数组…...

    2024/4/16 21:17:20
  12. Servlet学习日记4——HTTP协议特点及通信流程

    目录 一、什么是HTTP 二、HTTP协议特点 三、HTTP协议通信流程 四、请求报文和响应报文 4.1 HTTP请求报文 4.2 HTTP相应报文 五、常见状态码 一、什么是HTTP 超文本传输协议&#xff08;HTTP&#xff0c;HyperText Transfer Protocol&#xff09;是互联网上应用最为广泛…...

    2024/4/13 12:36:52
  13. 视频平台授权时EasyTool探测不到加密机,该如何解决?

    在此前的文章中&#xff0c;我们提到过EasyGBS、EasyNVR、EasyCVR、EasyDSS等视频平台的授权方式&#xff0c;有加密机、加密狗、激活码三种方式&#xff0c;其中以加密机使用的较多。 在授权过程中&#xff0c;需要使用到我们开发的EasyTool探测工具。EasyTool探测工具在探测…...

    2024/4/13 12:37:17
  14. cutelyst教程_02 _Cutelyst基础

    Tutorial_02_CutelystBasics 教程_02 _Cutelyst基础 Daniel Nicoletti edited this page on May 8, 2020 14 revisions ​Daniel Nicoletti在2020年5月8日第14次修订时编辑了本页 OVERVIEW 总览 IntroductionCutelyst BasicsMore Cutelyst BasicsBasic CRUDAuthenticatio…...

    2024/4/14 16:35:30
  15. DAY6 / CSS / 三大特性+盒子模型+PS基础

    目录 CSS的三大特性 层叠性 继承性 优先级 盒子模型 边框 border 内边距 padding 外边距 margin PS测量 CSS的三大特性 层叠性 后来居上&#xff0c;相同选择器设置相同样式时&#xff0c;一个样式会覆盖&#xff08;层叠&#xff09;另一个样式 就近原则&#xff0…...

    2024/4/13 12:37:47
  16. 火了,开源的Python抢票神器,春节返厂就看这一波了

    大家好&#xff0c;我是朝阳王嘉尔。 假期即将到来&#xff0c;抢票返厂又该提上日程了&#xff01;在Github上也有很多优秀的开发者开源了一些基于Python的抢票项目&#xff0c;比如一直很火的12306/py12306&#xff0c;目前已经累计超40k Star&#xff01; 但如果你尝试使用…...

    2024/4/7 21:52:13
  17. vue2X与vue3X的区别(未完)

    按键修饰符 官网链接 非兼容&#xff1a;不再支持使用数字 (即键码) 作为 v-on 修饰符 非兼容&#xff1a;不再支持 config.keyCodes <!-- 键码版本 --> <input v-on:keyup.13"submit" /><!-- 别名版本 --> <input v-on:keyup.enter"sub…...

    2024/5/4 5:45:18
  18. 第十二章 JavaSE专题之面向对象三大特性 -继承

    1、继承概述 继承&#xff1a;解决代码复用&#xff0c;当多个类存在相同的属性(变量)和方法时&#xff0c;可以从这些类中抽象出父类&#xff0c;在父类中定义相同的属性和方法&#xff0c;所有子类不需要重新定义这些属性和方法&#xff0c;只需要通过extends来生命继承父类…...

    2024/4/13 12:37:17
  19. 【机试题目】中科大上机题(二)

    火车票订购&#xff1a;火车经过X站&#xff0c;火车最大载客人数为m&#xff0c;有n个订票请求&#xff0c;请求订购从a站到b站的k张票&#xff0c;若能满足订购要求则输出1&#xff0c;否则输出0.第一行有两个数&#xff0c;分别是n&#xff0c;m&#xff0c;接下来有n行&…...

    2024/5/4 10:08:09
  20. springboot项目使用validation-api进行参数校验

    一、引入依赖 要使用参数校验注解&#xff0c;需要引入以下依赖&#xff0c;注意springboot2.0的web模块已经包含此依赖 <dependency><groupId>jakarta.validation</groupId><artifactId>jakarta.validation-api</artifactId></dependency&g…...

    2024/4/7 21:52:09

最新文章

  1. 职场高手的秘而不宣:与主要领导相处的四大智慧:1. 巧送关怀,2. 智避冲突,3. 坚守原则,4. 敢于表达

    在职场中&#xff0c;与主要领导的关系往往成为影响个人职业发展的重要因素。有些人凭借与领导的紧密关系&#xff0c;即使能力平平也能获得重用&#xff1b;而有些人虽然才华横溢&#xff0c;却因与领导关系不佳而错失良机。那么&#xff0c;那些在职场上如鱼得水的人&#xf…...

    2024/5/6 15:25:50
  2. 梯度消失和梯度爆炸的一些处理方法

    在这里是记录一下梯度消失或梯度爆炸的一些处理技巧。全当学习总结了如有错误还请留言&#xff0c;在此感激不尽。 权重和梯度的更新公式如下&#xff1a; w w − η ⋅ ∇ w w w - \eta \cdot \nabla w ww−η⋅∇w 个人通俗的理解梯度消失就是网络模型在反向求导的时候出…...

    2024/5/6 9:38:23
  3. vscode为什么设置不了中文?

    VSCode中文插件安装 在VSCode中设置中文的首要步骤是安装“Chinese (Simplified) Language Pack for Visual Studio Code”扩展插件。这一过程十分简单&#xff0c;只需打开VSCode&#xff0c;进入扩展市场&#xff0c;搜索“ Chinese (Simplified) Language Pack ”然后点击…...

    2024/5/5 23:26:06
  4. 数据挖掘中的PCA和KMeans:Airbnb房源案例研究

    目录 一、PCA简介 二、数据集概览 三、数据预处理步骤 四、PCA申请 五、KMeans 聚类 六、PCA成分分析 七、逆变换 八、质心分析 九、结论 十、深入探究 10.1 第 1 步&#xff1a;确定 PCA 组件的最佳数量 10.2 第 2 步&#xff1a;使用 9 个组件重做 PCA 10.3 解释 PCA 加载和特…...

    2024/5/5 8:53:00
  5. 【JavaScript】如何在npm中切换源以及使用指定源安装依赖

    忘不掉的是什么我也不知道 想不起当年模样 看也看不到 去也去不了的地方 也许那老街的腔调是属于我的忧伤 嘴角那点微笑越来越勉强 忘不掉的是什么我也不知道 放不下熟悉片段 回头望一眼 已经很多年的时间 透过手指间看着天 我又回到那老街 靠在你们身边渐行渐远 …...

    2024/5/5 8:47:29
  6. 【外汇早评】美通胀数据走低,美元调整

    原标题:【外汇早评】美通胀数据走低,美元调整昨日美国方面公布了新一期的核心PCE物价指数数据,同比增长1.6%,低于前值和预期值的1.7%,距离美联储的通胀目标2%继续走低,通胀压力较低,且此前美国一季度GDP初值中的消费部分下滑明显,因此市场对美联储后续更可能降息的政策…...

    2024/5/4 23:54:56
  7. 【原油贵金属周评】原油多头拥挤,价格调整

    原标题:【原油贵金属周评】原油多头拥挤,价格调整本周国际劳动节,我们喜迎四天假期,但是整个金融市场确实流动性充沛,大事频发,各个商品波动剧烈。美国方面,在本周四凌晨公布5月份的利率决议和新闻发布会,维持联邦基金利率在2.25%-2.50%不变,符合市场预期。同时美联储…...

    2024/5/4 23:54:56
  8. 【外汇周评】靓丽非农不及疲软通胀影响

    原标题:【外汇周评】靓丽非农不及疲软通胀影响在刚结束的周五,美国方面公布了新一期的非农就业数据,大幅好于前值和预期,新增就业重新回到20万以上。具体数据: 美国4月非农就业人口变动 26.3万人,预期 19万人,前值 19.6万人。 美国4月失业率 3.6%,预期 3.8%,前值 3…...

    2024/5/4 23:54:56
  9. 【原油贵金属早评】库存继续增加,油价收跌

    原标题:【原油贵金属早评】库存继续增加,油价收跌周三清晨公布美国当周API原油库存数据,上周原油库存增加281万桶至4.692亿桶,增幅超过预期的74.4万桶。且有消息人士称,沙特阿美据悉将于6月向亚洲炼油厂额外出售更多原油,印度炼油商预计将每日获得至多20万桶的额外原油供…...

    2024/5/6 9:21:00
  10. 【外汇早评】日本央行会议纪要不改日元强势

    原标题:【外汇早评】日本央行会议纪要不改日元强势近两日日元大幅走强与近期市场风险情绪上升,避险资金回流日元有关,也与前一段时间的美日贸易谈判给日本缓冲期,日本方面对汇率问题也避免继续贬值有关。虽然今日早间日本央行公布的利率会议纪要仍然是支持宽松政策,但这符…...

    2024/5/4 23:54:56
  11. 【原油贵金属早评】欧佩克稳定市场,填补伊朗问题的影响

    原标题:【原油贵金属早评】欧佩克稳定市场,填补伊朗问题的影响近日伊朗局势升温,导致市场担忧影响原油供给,油价试图反弹。此时OPEC表态稳定市场。据消息人士透露,沙特6月石油出口料将低于700万桶/日,沙特已经收到石油消费国提出的6月份扩大出口的“适度要求”,沙特将满…...

    2024/5/4 23:55:05
  12. 【外汇早评】美欲与伊朗重谈协议

    原标题:【外汇早评】美欲与伊朗重谈协议美国对伊朗的制裁遭到伊朗的抗议,昨日伊朗方面提出将部分退出伊核协议。而此行为又遭到欧洲方面对伊朗的谴责和警告,伊朗外长昨日回应称,欧洲国家履行它们的义务,伊核协议就能保证存续。据传闻伊朗的导弹已经对准了以色列和美国的航…...

    2024/5/4 23:54:56
  13. 【原油贵金属早评】波动率飙升,市场情绪动荡

    原标题:【原油贵金属早评】波动率飙升,市场情绪动荡因中美贸易谈判不安情绪影响,金融市场各资产品种出现明显的波动。随着美国与中方开启第十一轮谈判之际,美国按照既定计划向中国2000亿商品征收25%的关税,市场情绪有所平复,已经开始接受这一事实。虽然波动率-恐慌指数VI…...

    2024/5/4 23:55:16
  14. 【原油贵金属周评】伊朗局势升温,黄金多头跃跃欲试

    原标题:【原油贵金属周评】伊朗局势升温,黄金多头跃跃欲试美国和伊朗的局势继续升温,市场风险情绪上升,避险黄金有向上突破阻力的迹象。原油方面稍显平稳,近期美国和OPEC加大供给及市场需求回落的影响,伊朗局势并未推升油价走强。近期中美贸易谈判摩擦再度升级,美国对中…...

    2024/5/4 23:54:56
  15. 【原油贵金属早评】市场情绪继续恶化,黄金上破

    原标题:【原油贵金属早评】市场情绪继续恶化,黄金上破周初中国针对于美国加征关税的进行的反制措施引发市场情绪的大幅波动,人民币汇率出现大幅的贬值动能,金融市场受到非常明显的冲击。尤其是波动率起来之后,对于股市的表现尤其不安。隔夜美国股市出现明显的下行走势,这…...

    2024/5/6 1:40:42
  16. 【外汇早评】美伊僵持,风险情绪继续升温

    原标题:【外汇早评】美伊僵持,风险情绪继续升温昨日沙特两艘油轮再次发生爆炸事件,导致波斯湾局势进一步恶化,市场担忧美伊可能会出现摩擦生火,避险品种获得支撑,黄金和日元大幅走强。美指受中美贸易问题影响而在低位震荡。继5月12日,四艘商船在阿联酋领海附近的阿曼湾、…...

    2024/5/4 23:54:56
  17. 【原油贵金属早评】贸易冲突导致需求低迷,油价弱势

    原标题:【原油贵金属早评】贸易冲突导致需求低迷,油价弱势近日虽然伊朗局势升温,中东地区几起油船被袭击事件影响,但油价并未走高,而是出于调整结构中。由于市场预期局势失控的可能性较低,而中美贸易问题导致的全球经济衰退风险更大,需求会持续低迷,因此油价调整压力较…...

    2024/5/4 23:55:17
  18. 氧生福地 玩美北湖(上)——为时光守候两千年

    原标题:氧生福地 玩美北湖(上)——为时光守候两千年一次说走就走的旅行,只有一张高铁票的距离~ 所以,湖南郴州,我来了~ 从广州南站出发,一个半小时就到达郴州西站了。在动车上,同时改票的南风兄和我居然被分到了一个车厢,所以一路非常愉快地聊了过来。 挺好,最起…...

    2024/5/4 23:55:06
  19. 氧生福地 玩美北湖(中)——永春梯田里的美与鲜

    原标题:氧生福地 玩美北湖(中)——永春梯田里的美与鲜一觉醒来,因为大家太爱“美”照,在柳毅山庄去寻找龙女而错过了早餐时间。近十点,向导坏坏还是带着饥肠辘辘的我们去吃郴州最富有盛名的“鱼头粉”。说这是“十二分推荐”,到郴州必吃的美食之一。 哇塞!那个味美香甜…...

    2024/5/4 23:54:56
  20. 氧生福地 玩美北湖(下)——奔跑吧骚年!

    原标题:氧生福地 玩美北湖(下)——奔跑吧骚年!让我们红尘做伴 活得潇潇洒洒 策马奔腾共享人世繁华 对酒当歌唱出心中喜悦 轰轰烈烈把握青春年华 让我们红尘做伴 活得潇潇洒洒 策马奔腾共享人世繁华 对酒当歌唱出心中喜悦 轰轰烈烈把握青春年华 啊……啊……啊 两…...

    2024/5/4 23:55:06
  21. 扒开伪装医用面膜,翻六倍价格宰客,小姐姐注意了!

    原标题:扒开伪装医用面膜,翻六倍价格宰客,小姐姐注意了!扒开伪装医用面膜,翻六倍价格宰客!当行业里的某一品项火爆了,就会有很多商家蹭热度,装逼忽悠,最近火爆朋友圈的医用面膜,被沾上了污点,到底怎么回事呢? “比普通面膜安全、效果好!痘痘、痘印、敏感肌都能用…...

    2024/5/5 8:13:33
  22. 「发现」铁皮石斛仙草之神奇功效用于医用面膜

    原标题:「发现」铁皮石斛仙草之神奇功效用于医用面膜丽彦妆铁皮石斛医用面膜|石斛多糖无菌修护补水贴19大优势: 1、铁皮石斛:自唐宋以来,一直被列为皇室贡品,铁皮石斛生于海拔1600米的悬崖峭壁之上,繁殖力差,产量极低,所以古代仅供皇室、贵族享用 2、铁皮石斛自古民间…...

    2024/5/4 23:55:16
  23. 丽彦妆\医用面膜\冷敷贴轻奢医学护肤引导者

    原标题:丽彦妆\医用面膜\冷敷贴轻奢医学护肤引导者【公司简介】 广州华彬企业隶属香港华彬集团有限公司,专注美业21年,其旗下品牌: 「圣茵美」私密荷尔蒙抗衰,产后修复 「圣仪轩」私密荷尔蒙抗衰,产后修复 「花茵莳」私密荷尔蒙抗衰,产后修复 「丽彦妆」专注医学护…...

    2024/5/4 23:54:58
  24. 广州械字号面膜生产厂家OEM/ODM4项须知!

    原标题:广州械字号面膜生产厂家OEM/ODM4项须知!广州械字号面膜生产厂家OEM/ODM流程及注意事项解读: 械字号医用面膜,其实在我国并没有严格的定义,通常我们说的医美面膜指的应该是一种「医用敷料」,也就是说,医用面膜其实算作「医疗器械」的一种,又称「医用冷敷贴」。 …...

    2024/5/4 23:55:01
  25. 械字号医用眼膜缓解用眼过度到底有无作用?

    原标题:械字号医用眼膜缓解用眼过度到底有无作用?医用眼膜/械字号眼膜/医用冷敷眼贴 凝胶层为亲水高分子材料,含70%以上的水分。体表皮肤温度传导到本产品的凝胶层,热量被凝胶内水分子吸收,通过水分的蒸发带走大量的热量,可迅速地降低体表皮肤局部温度,减轻局部皮肤的灼…...

    2024/5/4 23:54:56
  26. 配置失败还原请勿关闭计算机,电脑开机屏幕上面显示,配置失败还原更改 请勿关闭计算机 开不了机 这个问题怎么办...

    解析如下&#xff1a;1、长按电脑电源键直至关机&#xff0c;然后再按一次电源健重启电脑&#xff0c;按F8健进入安全模式2、安全模式下进入Windows系统桌面后&#xff0c;按住“winR”打开运行窗口&#xff0c;输入“services.msc”打开服务设置3、在服务界面&#xff0c;选中…...

    2022/11/19 21:17:18
  27. 错误使用 reshape要执行 RESHAPE,请勿更改元素数目。

    %读入6幅图像&#xff08;每一幅图像的大小是564*564&#xff09; f1 imread(WashingtonDC_Band1_564.tif); subplot(3,2,1),imshow(f1); f2 imread(WashingtonDC_Band2_564.tif); subplot(3,2,2),imshow(f2); f3 imread(WashingtonDC_Band3_564.tif); subplot(3,2,3),imsho…...

    2022/11/19 21:17:16
  28. 配置 已完成 请勿关闭计算机,win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机...

    win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机”问题的解决方法在win7系统关机时如果有升级系统的或者其他需要会直接进入一个 等待界面&#xff0c;在等待界面中我们需要等待操作结束才能关机&#xff0c;虽然这比较麻烦&#xff0c;但是对系统进行配置和升级…...

    2022/11/19 21:17:15
  29. 台式电脑显示配置100%请勿关闭计算机,“准备配置windows 请勿关闭计算机”的解决方法...

    有不少用户在重装Win7系统或更新系统后会遇到“准备配置windows&#xff0c;请勿关闭计算机”的提示&#xff0c;要过很久才能进入系统&#xff0c;有的用户甚至几个小时也无法进入&#xff0c;下面就教大家这个问题的解决方法。第一种方法&#xff1a;我们首先在左下角的“开始…...

    2022/11/19 21:17:14
  30. win7 正在配置 请勿关闭计算机,怎么办Win7开机显示正在配置Windows Update请勿关机...

    置信有很多用户都跟小编一样遇到过这样的问题&#xff0c;电脑时发现开机屏幕显现“正在配置Windows Update&#xff0c;请勿关机”(如下图所示)&#xff0c;而且还需求等大约5分钟才干进入系统。这是怎样回事呢&#xff1f;一切都是正常操作的&#xff0c;为什么开时机呈现“正…...

    2022/11/19 21:17:13
  31. 准备配置windows 请勿关闭计算机 蓝屏,Win7开机总是出现提示“配置Windows请勿关机”...

    Win7系统开机启动时总是出现“配置Windows请勿关机”的提示&#xff0c;没过几秒后电脑自动重启&#xff0c;每次开机都这样无法进入系统&#xff0c;此时碰到这种现象的用户就可以使用以下5种方法解决问题。方法一&#xff1a;开机按下F8&#xff0c;在出现的Windows高级启动选…...

    2022/11/19 21:17:12
  32. 准备windows请勿关闭计算机要多久,windows10系统提示正在准备windows请勿关闭计算机怎么办...

    有不少windows10系统用户反映说碰到这样一个情况&#xff0c;就是电脑提示正在准备windows请勿关闭计算机&#xff0c;碰到这样的问题该怎么解决呢&#xff0c;现在小编就给大家分享一下windows10系统提示正在准备windows请勿关闭计算机的具体第一种方法&#xff1a;1、2、依次…...

    2022/11/19 21:17:11
  33. 配置 已完成 请勿关闭计算机,win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机”的解决方法...

    今天和大家分享一下win7系统重装了Win7旗舰版系统后&#xff0c;每次关机的时候桌面上都会显示一个“配置Windows Update的界面&#xff0c;提示请勿关闭计算机”&#xff0c;每次停留好几分钟才能正常关机&#xff0c;导致什么情况引起的呢&#xff1f;出现配置Windows Update…...

    2022/11/19 21:17:10
  34. 电脑桌面一直是清理请关闭计算机,windows7一直卡在清理 请勿关闭计算机-win7清理请勿关机,win7配置更新35%不动...

    只能是等着&#xff0c;别无他法。说是卡着如果你看硬盘灯应该在读写。如果从 Win 10 无法正常回滚&#xff0c;只能是考虑备份数据后重装系统了。解决来方案一&#xff1a;管理员运行cmd&#xff1a;net stop WuAuServcd %windir%ren SoftwareDistribution SDoldnet start WuA…...

    2022/11/19 21:17:09
  35. 计算机配置更新不起,电脑提示“配置Windows Update请勿关闭计算机”怎么办?

    原标题&#xff1a;电脑提示“配置Windows Update请勿关闭计算机”怎么办&#xff1f;win7系统中在开机与关闭的时候总是显示“配置windows update请勿关闭计算机”相信有不少朋友都曾遇到过一次两次还能忍但经常遇到就叫人感到心烦了遇到这种问题怎么办呢&#xff1f;一般的方…...

    2022/11/19 21:17:08
  36. 计算机正在配置无法关机,关机提示 windows7 正在配置windows 请勿关闭计算机 ,然后等了一晚上也没有关掉。现在电脑无法正常关机...

    关机提示 windows7 正在配置windows 请勿关闭计算机 &#xff0c;然后等了一晚上也没有关掉。现在电脑无法正常关机以下文字资料是由(历史新知网www.lishixinzhi.com)小编为大家搜集整理后发布的内容&#xff0c;让我们赶快一起来看一下吧&#xff01;关机提示 windows7 正在配…...

    2022/11/19 21:17:05
  37. 钉钉提示请勿通过开发者调试模式_钉钉请勿通过开发者调试模式是真的吗好不好用...

    钉钉请勿通过开发者调试模式是真的吗好不好用 更新时间:2020-04-20 22:24:19 浏览次数:729次 区域: 南阳 > 卧龙 列举网提醒您:为保障您的权益,请不要提前支付任何费用! 虚拟位置外设器!!轨迹模拟&虚拟位置外设神器 专业用于:钉钉,外勤365,红圈通,企业微信和…...

    2022/11/19 21:17:05
  38. 配置失败还原请勿关闭计算机怎么办,win7系统出现“配置windows update失败 还原更改 请勿关闭计算机”,长时间没反应,无法进入系统的解决方案...

    前几天班里有位学生电脑(windows 7系统)出问题了&#xff0c;具体表现是开机时一直停留在“配置windows update失败 还原更改 请勿关闭计算机”这个界面&#xff0c;长时间没反应&#xff0c;无法进入系统。这个问题原来帮其他同学也解决过&#xff0c;网上搜了不少资料&#x…...

    2022/11/19 21:17:04
  39. 一个电脑无法关闭计算机你应该怎么办,电脑显示“清理请勿关闭计算机”怎么办?...

    本文为你提供了3个有效解决电脑显示“清理请勿关闭计算机”问题的方法&#xff0c;并在最后教给你1种保护系统安全的好方法&#xff0c;一起来看看&#xff01;电脑出现“清理请勿关闭计算机”在Windows 7(SP1)和Windows Server 2008 R2 SP1中&#xff0c;添加了1个新功能在“磁…...

    2022/11/19 21:17:03
  40. 请勿关闭计算机还原更改要多久,电脑显示:配置windows更新失败,正在还原更改,请勿关闭计算机怎么办...

    许多用户在长期不使用电脑的时候&#xff0c;开启电脑发现电脑显示&#xff1a;配置windows更新失败&#xff0c;正在还原更改&#xff0c;请勿关闭计算机。。.这要怎么办呢&#xff1f;下面小编就带着大家一起看看吧&#xff01;如果能够正常进入系统&#xff0c;建议您暂时移…...

    2022/11/19 21:17:02
  41. 还原更改请勿关闭计算机 要多久,配置windows update失败 还原更改 请勿关闭计算机,电脑开机后一直显示以...

    配置windows update失败 还原更改 请勿关闭计算机&#xff0c;电脑开机后一直显示以以下文字资料是由(历史新知网www.lishixinzhi.com)小编为大家搜集整理后发布的内容&#xff0c;让我们赶快一起来看一下吧&#xff01;配置windows update失败 还原更改 请勿关闭计算机&#x…...

    2022/11/19 21:17:01
  42. 电脑配置中请勿关闭计算机怎么办,准备配置windows请勿关闭计算机一直显示怎么办【图解】...

    不知道大家有没有遇到过这样的一个问题&#xff0c;就是我们的win7系统在关机的时候&#xff0c;总是喜欢显示“准备配置windows&#xff0c;请勿关机”这样的一个页面&#xff0c;没有什么大碍&#xff0c;但是如果一直等着的话就要两个小时甚至更久都关不了机&#xff0c;非常…...

    2022/11/19 21:17:00
  43. 正在准备配置请勿关闭计算机,正在准备配置windows请勿关闭计算机时间长了解决教程...

    当电脑出现正在准备配置windows请勿关闭计算机时&#xff0c;一般是您正对windows进行升级&#xff0c;但是这个要是长时间没有反应&#xff0c;我们不能再傻等下去了。可能是电脑出了别的问题了&#xff0c;来看看教程的说法。正在准备配置windows请勿关闭计算机时间长了方法一…...

    2022/11/19 21:16:59
  44. 配置失败还原请勿关闭计算机,配置Windows Update失败,还原更改请勿关闭计算机...

    我们使用电脑的过程中有时会遇到这种情况&#xff0c;当我们打开电脑之后&#xff0c;发现一直停留在一个界面&#xff1a;“配置Windows Update失败&#xff0c;还原更改请勿关闭计算机”&#xff0c;等了许久还是无法进入系统。如果我们遇到此类问题应该如何解决呢&#xff0…...

    2022/11/19 21:16:58
  45. 如何在iPhone上关闭“请勿打扰”

    Apple’s “Do Not Disturb While Driving” is a potentially lifesaving iPhone feature, but it doesn’t always turn on automatically at the appropriate time. For example, you might be a passenger in a moving car, but your iPhone may think you’re the one dri…...

    2022/11/19 21:16:57