文生图项目总结

文生图

image.png

功能点

  • 页面进来获取背景图url和图片宽高(根据比例和手机屏幕处理过的宽高)
  • 渲染图片(背景图最后生成图片模糊,换成img展示解决)
  • 添加多个文字,编辑文字内容,拖拽改变文字位置,删除文字
  • 编辑文字内容,颜色,字体,大小
  • 生成图片预览
  • 转发图片给好友、保存

bug点

  • 使用背景图最后生成图片模糊,换成img展示解决
  • 图片必须转成base64格式,最后才能保存,否则不显示(例如二维码和背景图)

拖拽插件

多个文字框时,点击改变isActive控制编辑状态框的显示隐藏

  • 只保留一个clicked 事件
  • 在外层添加时间.stop 重置数组激活状态为false

整个页面分为上中下三部分,中间可滚动

  • 整体100vh ,采用纵向flex布局
  • 上下区域高度不固定,下面样式设置直接写,不采用弹窗形式
  • 中间区域 overflow-y: auto;高度超出会自动有滚动条
  • 中间图片竖图顶部会遮挡,不能使用center布局即可

解决不同图片尺寸都要居中显示,切最后生成图片又得是图片区域

  • 采用父盒子 flex:center,内层盒子居中显示:横图可以,超高竖图顶部会有遮挡;所以判断竖图就定义宽90%,高度auto
  • 根据图片比例动态计算宽高,动态设置内层盒子的宽高;盒子里放图片和文字
  • 假如是9:16 的图片,固定一个高度,计算固定宽度;其他比例宽度为手机屏幕宽度,高度计算

删除其中一个位置会跑到上个位置

  • 拖拽left、top赋值,删除加个show变量false隐藏,不直接删除这一项

添加文字后,第一次点击聚焦拖拽框,文字会移动到左上角的位置

  • 添加文字,给了一个默认left、top值让文字显示在中间
  • 但是拖拽组件没有设置初始偏移量 x、y
  • 保持初始偏移量和添加文字默认位置一致即可解决

vcolorpicker颜色选取插件

切换字体字体包

  • vue获取文件夹下所有字体包 生成数组:字体包的名字和下拉选择名字保持一致
  • 类名定义为font-索引值
  • 这样下拉选中得到索引,动态绑定类名即可切换字体

vue瀑布流插件vue-masonry

第二版小程序

  • 第一版公众号无法实现转发图片给好友,只能分享公众号;所以修改为小程序
  • 小程序没有找到拖拽插件,所以打算用uniapp生成小程序
  • 结果uniapp也没有拖拽插件,最终使用uniapp 嵌入H5页面(编辑贺卡页面)
  • uniapp打包小程序弊端:使用uview插件占内存较大很快就超了2M
  • 于是采用分包,主包只放tabbar页面,分包可以有多个,但是总限制8M,每个包限制2M
  • 分包可以键自己的图片文件夹和插件
  • 上线要在编辑器上点击发行,才会运行在生产环境
let url = ''
let url1 = ''
let url2 = ''
if (process.env.NODE_ENV === 'development') {console.log('开发环境')url = 'http://192.168.0.19:9888'url1 = 'http://192.168.2.89:8080'url2 = 'http://192.168.0.19:9888'
} else {console.log('生产环境')url = 'https://wst.maitewang.com/stage-api'url1 = 'https://wst.maitewang.com'url2 = 'https://wst.maitewang.com/stage-api'
}export const baseUrl = url;
export const h5Url = url1;
export const imgUrl = url2;
  • 小程序发布之后,H5会有缓存,大概5个小时左右会更新;小程序24小时会基本更新所有用户

uniapp 打包小程序并嵌入H5注意事项

小程序里边嵌入H5 使用 web-view

  • 上线需要配置业务域名,即H5访问地址
  • 域名必须使用https;域名不能带端口号;需要下载文件放服务器上
  • web-view会缓存,修改H5之后,线上不会变; 在过一段时间(时间不定,一天或者几小时,无明显规律)是可以进行缓存刷新的:有需要的解决
  • 可以ngix配置不缓存html文件,即可解决;还有静态资源的缓存比较麻烦
  • 将微信从后台退出再打开并重新进入小程序;

uniapp可以直接调取微信小程序转发图片api

  • 转发有发送朋友和保存相册功能
  • 发送朋友的图片下面可以带小程序的连接,但是对小程序类别有要求,不是所有的都可以
  • 如果类别不符合不能配置转发带链接,否则转发功能也会调不起来
  • 上传、下载功能需要配置上传下载接口域名

小程序和H5互相跳转并传参

  • 小程序跳转H5直接在链接之后?拼接参数
    -<web-view class="menu" v-if="query" :src="h5Url+'/#/detail?query='+ query"></web-view>
  • 跳转参数加密 encodeURIComponent(JSON.stringify(query))
  • H5在mounted接收参数并解密JSON.parse(decodeURIComponent(this.$route.query.query))
  • H5跳转小程序
 let path = `/page_subject/detail/share?imgURL=${path1}&width=${this.width}&height=${this.height}&id=${this.id}`wx.miniProgram.navigateTo({url: path,success() {Toast.clear();},fail() {Toast('跳转失败');}, //小程序地址});

小程序右上角三个点的分享小程序默认分享好友和朋友圈都是灰色的

  • 需要写代码开启
  • 如果每个页面都需要分享,写一个公共的js文件,采用MiXin 混入的方式

新建公共share.js文件

export default {data() {return {share: {title: '快来一起制作新年贺卡吧~',// bug:require本地图片分包之后图片就显示不出来了// 不设置图片,默认展示页面 // imageUrl: 'https://ossweb-img.qq.com/images/lol/web201310/skin/big10001.jpg',path: '/pages/home/index'}}},onLoad: function() {wx.showShareMenu({withShareTicket: true,menus: ["shareAppMessage", "shareTimeline"]})},onShareAppMessage(res) { //发送给朋友return {title: this.share.title,imageUrl: this.share.imageUrl,path: this.share.path}},onShareTimeline(res) { //分享到朋友圈return {title: this.share.title,imageUrl: this.share.imageUrl,path: this.share.path}},
}

main.js文件混入

import share from './common/share.js'
Vue.mixin(share)

页面内想单独覆盖分享的文字和图片,可在页面内重写data

data() {return {share: {title: '快来一起制作新年贺卡吧~',// bug:require本地图片分包之后图片就显示不出来了// 不设置图片,默认展示页面 // imageUrl: 'https://ossweb-img.qq.com/images/lol/web201310/skin/big10001.jpg',path: '/pages/home/index'}}},

H5禁止默认的长按转发事件

  • 给图片设置 img{ pointer-events:none; }
  • 如果图片有点击事件,点击事件不会触发,可以将点击事件加载img的外层盒子上

开启微信小程序图片默认长按事件

  • 小程序<image>默认没有长按识别事件
  • 在图片标签上添加属性 show-menu-by-longpress

图片列表使用骨架屏

1707040601850.png

  • 图片加载过程会出现没有高度,所以效果不是很好
  • 监听图片加载@load,加载之前显示灰色骨架屏,加载成功显示图片
  • bug:在下拉刷新,重新调取接口后@load不执行
  • 解决:下拉刷新,先清空数组,在重新调取接口
<view v-show="!item.isLoading"></view>
<image v-show="item.isLoading" :src="baseUrl + item.img" @load="imgLoad(index)"></image>
// load回调证明图片加载完成
imgLoad(index) {this.imgList[index].isLoading = true;
},

首页关注我们页面内任意拖动

image.png

  • movable-area 可以放在最外层
  • movable-view是movable-area的直接子元素
  • movable-area必须设置宽高,子元素只会在这个区域内移动
  • movable-area设置宽高会占位置,可以position: absolute就会不占位置
  • movable-view会随着页面向上滚动而上去,使用position: fixed即可不动
<!-- 可拖拽关注 -->
<movable-area :style="{ width:`${screenWidth - 52}px`, height: `${screenHeight - 50}px`}" class="focusBox"><movable-view :x="screenWidth - 52" :y="screenHeight / 2" direction="all" @click="isFocus = true" class="focus"><image src="../../static/icon/focus.png" alt="" class="focusImg"></image></movable-view>
</movable-area>.focusBox {position: absolute;.focus {position: fixed;z-index: 999;.focusImg {width: 112rpx;height: 108rpx;}}

小程序编辑页面

http://192.168.2.89:8080/#/detail?query=%7B%22url%22%3A%22%2Fprofile%2Fupload%2F2024%2F01%2F25%2F123_20240125204643A031.jpg%22,%22id%22%3A22%7D

<template><view><web-view class="menu" v-if="query" :src="h5Url+'/#/detail?query='+ query"></web-view></view>
</template><script>import {h5Url,} from '../../common/http.js'export default {data() {return {query: '',h5Url: '',}},onLoad(options) {console.log('query', JSON.parse(decodeURIComponent(options.query)))this.query = options.querythis.h5Url = h5Urlconsole.log(1111, this.h5Url + '/#/detail?query=' + this.query)// this.getWidth(url).finally(() => {// 	this.query = encodeURIComponent(JSON.stringify({// 		url: url,// 		width: this.width,// 		height: this.height// 	}))// 	console.log(55555, {// 			url: url,// 			width: this.width,// 			height: this.height// 		},// 		this.query, h5Url + '/#/detail?query=' + this.query)// })},methods: {// 获取图片宽高getWidth(url1) {let _this = thisreturn new Promise((resolve, reject) => {let screenWidth = wx.getSystemInfoSync().windowWidth; // 获取当前窗口的宽度uni.getImageInfo({src: url,success(image) {console.log(222222, image.width, image.height);let imgRate = image.width / image.height;console.log(33333, Number((screenWidth / imgRate).toFixed()));if (imgRate <= 0.5625) {_this.width = 315;_this.height = 560;} else {_this.width = screenWidth;_this.height = Number((screenWidth / imgRate).toFixed());}resolve()},fail(err) {console.log(44444, err)_this.width = 310;_this.height = 551;reject()}});})},}}
</script><style scoped lang="scss"></style>

H5编辑页面

<template><div class="w100 vh100 flex flex-column bg-black"><div class="flex_r white bg-black w100 pd-30"><img src="../assets/img/share.png" alt="" style="width: 18px;margin-right: 6px;"><div @click="preview">转发</div></div><div @click.stop="onDeactivated" style="width: 100%; overflow-y: auto;" class="bg-black flex-1"><!-- :style="{ width: `${width}px`, height: `${height}px` }" --><div style="width: 85%;" class="imgBox relative" :class="height > 550 ? 'top' : 'middle'"><img :src="url" alt="" class="w100 h100" style="display: block;pointer-events:none"><div v-for="(item, i) in arr" :key="i"><!-- clicked - 单击组件时activated - 单击组件时调用,以显示句柄deactivated - 用户单击组件外部的任何位置时调用,以便将其停用resizing - 组件调整大小时resizestop - 组件停止调整大小时dragging - 拖动组件时dragstop - 组件停止拖动时调用@deactivated="onDeactivated":parentLimitation="true" --><VueDragResize v-if="item.show" :sticks="['mr', 'br', 'bm', 'bl',]" :isActive="item.isEdit" :w="190" :h="80":x="70" :y="200" :z="999" @resizing="resize" @dragging="resize" @clicked="onActivated(i)" contentClass="box":style="{ 'left': item.left + 'px', 'top': item.top + 'px', }"><p class="absolute gushi":style="{ 'color': item.color, 'font-size': item.size + 'px', 'opacity': item.opacity / 100, 'font-family': item.family, 'font-weight': item.bold, }">{{ item.text }}</p></VueDragResize></div><!-- 二维码 --><img :src="code" alt="" class="absolute code" :class="width < height ? 'center' : 'right'"></div></div><div class="w100 bg-white"><div class="flex bg pd-30 plr-60" :class="isIos ? 'pb-50' : ''" v-show="!index"><div @click="add" class="flex_l"><img src="../assets/img/add.png" alt="" style="width: 16px;height: 16px;"><div class="ml-6">藏头诗</div></div><div @click="add1" class="flex_l"><img src="../assets/img/add1.png" alt="" style="width: 22px;height: 22px;"><div class="ml-6">添加祝福语</div></div><div @click="changeImg" class="flex_l"><img src="../assets/img/add2.png" alt="" style="width: 22px;height: 22px;"><div class="ml-6">更换背景</div></div></div><div class="flex bg pd-30" v-show="index"><div @click="del" class="mr-20 flex_l"><img src="../assets/img/del.png" alt="" style="width: 18px;height: 18px;"><div class="ml-6">删除</div></div><div @click="action = 2" :class="action == 2 ? 'red' : ''" class="mr-20 flex_l"><img v-if="action == 2" src="../assets/img/edit-1.png" alt="" style="width: 18px;height: 18px;"><img v-else src="../assets/img/edit.png" alt="" style="width: 18px;height: 18px;"><div class="ml-6">编辑</div></div><div @click="action = 3" :class="action == 3 ? 'red' : ''" class="mr-20 flex_l"><img v-if="action == 3" src="../assets/img/color-1.png" alt="" style="width: 18px;height: 18px;"><img v-else src="../assets/img/color.png" alt="" style="width: 18px;height: 18px;"><div class="ml-6">颜色</div></div><div @click="action = 4" :class="action == 4 ? 'red' : ''" class="mr-20 flex_l"><img v-if="action == 4" src="../assets/img/size-1.png" alt="" style="width: 18px;height: 18px;"><img v-else src="../assets/img/size.png" alt="" style="width: 18px;height: 18px;"><div class="ml-6">样式</div></div><div v-if="action" @click="finish" class="flex_l"><img src="../assets/img/finish.png" alt="" style="width: 18px;height: 18px;"><div class="ml-6">完成</div></div></div><div class="pd-30 pb-40" v-if="action == 1"><!-- show-word-limit --><van-field v-model.trim="message" placeholder="输入藏头词:例如新年快乐(10字以内)" clearable type="textarea" autosize rows="1"maxlength="10"><template #button><van-button size="small" type="info" class="solo" @click="getPoetry">生成</van-button></template></van-field></div><div class="pd-30 pb-40" v-if="action == 2 || action == 5"><van-field v-model="arr[index].text" placeholder="" clearable type="textarea" autosize rows="1" /></div><div class="pd-30 pb-40" v-if="action == 3"><div class="flex mr-30 mb-30"><div>透明度</div><van-slider v-model="arr[index].opacity" :min="0" :max="100" style="width: 80%;" active-color="#E94467" /></div><div class="flex flex-wrap"><div class="mlr-12 mt-4"><colorPicker v-model="arr[index].color" /></div><div v-for="(  color, indexs  ) in   colors  " :key="indexs" class="color-option":style="{ backgroundColor: color, border: '1px solid #fff5f6' }" @click="selectColor(color)":class="{ active: color === arr[index].color, }"></div></div></div><div class="pd-30 pb-40" v-if="action == 4"><div class="flex mb-30"><div>字体大小</div><van-slider v-model="arr[index].size" :min="10" :max="80" class="flex-1 mlr-30" active-color="#E94467" /><div @click="changeBold(arr[index].bold)" :class="{ 'bold': arr[index].bold == 700 }" class="red">加粗</div></div><div class="flex_l flex-top"><div class="mr-20">选择字体</div><div style="max-height: 100px;overflow-y: auto;" class="flex-1"><div v-for="(item, i ) in fonts" :key="i" :style="{ 'font-family': 'font-' + (i + 1) }" @click="selectFont(i)":class="{ 'size-42 red': 'font-' + (i + 1) === arr[index].family }" class="mb-10">{{item }}</div></div></div></div><div class="plr-30  pb-40" v-if="action == 5"><div class="flex_l flex-top"><div style="max-height: 100px;overflow-y: auto;" class="flex-1"><div v-for="(  item, i  ) in   texts  " :key="i" @click="selectText(item)":class="{ 'size-36 red': item === arr[index].text }" class="mb-16">{{item }}</div></div></div></div></div><!-- 更换背景图组件 --><changeImg ref="changeImgRef" @getImg="getImg"></changeImg></div>
</template><script>
import { Toast, Dialog } from 'vant';
import wx from 'weixin-js-sdk';
import VueDragResize from 'vue-drag-resize';
import html2canvas from "html2canvas";
import changeImg from '../components/changeImg.vue';
export default {name: 'app',components: {VueDragResize,changeImg,},data() {return {id: '', //图片idurl: '', // 背景图width: 315,height: 560,message: "", //藏头诗提示语arr: [], // 文字index: '', // 当前编辑的文字索引action: null, // 1 藏头诗  2 编辑文字  3 颜色  4 样式  5 添加祝福语//  ['#fff', '#000000', '#F9E0C6', '#F4C68C', '#F08400', '#F08080', '#FFA07A', '#F44336', '#E91E63', '#F012BE', '#9C27B0', '#673AB7', '#7B68EE', '#3F51B5', '#2196F3',//   '#03A9F4', '#00BCD4', '#009688', '#2ECC40', '#4CAF50', '#8BC34A', '#FFEB3B',//   '#FFFF00', '#FFDC00', '#FFC107', '#FF851B','#FF5722', '#795548', '#9E9E9E', '#607D8B'],colors:['#000000', '#FFFFFF', '#F9E0C6', '#FDF6C0', '#F4C68C', '#FFA07A', '#F08080', '#F08400', '#E85500', '#FEC140', '#E6FF00', '#879D13', '#37A75D', '#2ECC40', '#149125','#009688', '#29C2BA', '#298CFE', '#3F51B5', '#7B68EE', '#9C27B0', '#E91E63','#FC0015', '#C00503', '#8A1F01', '#940304',],fonts: [],texts: ['新年快乐', '新春到了,愿你快乐,幸福平安!', '祝你新年快乐,喜事连连!', '恭祝万事顺,幸福不止步', '春节到来之际,送上我最真挚的祝福:新年快乐!','新的一年,祝你永怀善意,清澈明朗,无忧无虑,平安顺遂,吉祥圆满。','新年新气象,祝福财气旺,祝君事业有成,合家欢乐,步步高升!','岁杪春临,辞旧迎新,专此恭祝:吾师尊长,兄姊好友,新岁维祺,万事胜意。','新的一年,愿你永怀善意,清澈明朗,无忧无虑,平安顺遂,吉祥如意。','岁末将至,敬颂冬绥 。平安喜乐,万事胜意。岁岁常欢愉,年年皆胜意。','日迈月征,朝暮轮转,愿新年胜旧年,欢愉且胜意,万事尽可期。','大财,小财,意外财,财源滚滚;亲情,友情,爱情,情情如意官运;福运,财运,桃花运,运运亨通。','新的一年,愿你将遇之人皆为挚友,愿你去往之地皆为热土。天高地阔,万事胜意。人海沧沧,顺遂无忧。','祝你在新的一年里 无疾病侵扰,无岁月白头,无枯木羁绊。四时春秋平安度过,万千山水得以一游。','新年到,放鞭炮:一响鸿运照;二响忧愁抛;三响烦恼消;四响财运到;五响收入高;六响身体好;七响心情妙;八响平安罩;九响幸福绕;十响事业节节高!','祈家事平和,花朝月夕多胜意。愿人间芳华,岁岁年年长安康。乐亲朋,岁无忧,新春快乐。','裁雪为画,揉风作诗。愿岁月温柔,点点滴滴成全人间悲喜;愿你毕生欢愉,朝朝暮暮造就星河奔腾。'],imgURL: '',w: 0,h: 0,code: '', // 二维码isIos: false,}},mounted() {console.log(this.appSource())this.isIos = Boolean(this.appSource() == 'ios')console.log(JSON.parse(decodeURIComponent(this.$route.query.query)))let query = JSON.parse(decodeURIComponent(this.$route.query.query))this.url = '/stage-api' + query.urlthis.id = query.idthis.getBase64(this.url)let code = require('../assets/img/code.png')this.getBase64Code(code)// 字体//参数:1.路径;2.是否遍历子目录;3.正则表达式const files = require.context("../assets/fonts", true).keys();this.fonts = files.map(item => item.split('-')[1].split('.')[0])console.log(files.map(item => item.split('-')[1].split('.')[0]));// ['思源黑体', '包图小白体', '峰广明锐体', '豆豆字体', '站酷庆科黄油体', '锐字真言体', '卓健橄榄简体', '演示悠然小楷', '优设标题黑', '沐瑶随心手写体', '青柳隶书', '演示佛系体', '优设好身体', '优设鲨鱼菲特健康体', '阿朱泡泡体', '阿里巴巴普惠体', '庞门正道标题体', '传奇特战体', '思源宋体', '清松手写体', '龚帆免费体', '851力量体', '赤薔薇灰姑娘', '可愛少女体', '胖胖猪肉体', '千图小兔体']},methods: {//判断安卓和iosappSource() {const u = navigator.userAgent;const isiOS = !!u.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/);if (isiOS) {return "ios";} else {return "android";}},getBase64(src) {var image = new Image();image.crossOrigin = '*'; // 支持跨域图片image.src = src + '?v=' + Math.random(); // 处理缓存image.onload = () => {var base64 = this.getBase64Image(image);this.url = base64}},getBase64Image(img) {var canvas = document.createElement("canvas");canvas.width = img.width;canvas.height = img.height;var ctx = canvas.getContext("2d");ctx.drawImage(img, 0, 0, img.width, img.height);var dataURL = canvas.toDataURL("image/png"); // 可选其他值 image/jpegreturn dataURL;},//  本地二维码转base64getBase64Code(imgUrl) {window.URL = window.URL || window.webkitURL;const xhr = new XMLHttpRequest();xhr.open("get", imgUrl, true);xhr.responseType = "blob";xhr.onload = () => {if (xhr.status == 200) {//得到一个blob对象const blob = xhr.response;const oFileReader = new FileReader();oFileReader.readAsDataURL(blob);oFileReader.onloadend = e => {this.code = e.target.result;//base64编码 };}};xhr.send();},add() {this.action = 1},getPoetry() {if (!this.message) {this.$toast({message: '请输入藏头词'})} else {Toast.loading({message: '生成中...',forbidClick: true,});this.$axios.get('/stage-api/system/management/getMessages?messages=' + this.message).then(res => {console.log(res.msg)if (!res.msg) {Toast.clear();Dialog.alert({title: '温馨提示',message: '未获取到相关藏头,请更换提示语重新生成',}).then(() => {// on close});} else {this.message = ''this.arr.push({text: res.msg,color: '#FFFFFF',size: 24,opacity: 100,family: 'font-3',bold: 400,isEdit: false,show: true,top: 200,left: 70,})this.index = (this.arr.length - 1) + ''this.action = 2Toast.clear();}})}},add1() {this.arr.push({text: '新年快乐',color: '#FFFFFF',size: 28,opacity: 100,family: 'font-12',bold: 400,isEdit: false,show: true,top: 200,left: 70,})this.index = (this.arr.length - 1) + ''this.action = 5},changeImg() {this.$refs.changeImgRef.init()},getImg(query) {this.url = '/stage-api' + query.urlthis.id = query.idthis.getBase64(this.url)},finish() {this.onDeactivated()},del() {this.$set(this.arr[this.index], 'show', false)this.onDeactivated()},selectColor(color) {this.$set(this.arr[this.index], 'color', color)},selectFont(i) {this.$set(this.arr[this.index], 'family', 'font-' + (i + 1))},selectText(item) {this.$set(this.arr[this.index], 'text', item)},changeBold(flag) {this.$set(this.arr[this.index], 'bold', flag == 700 ? 400 : 700)},// 拖拽时可以确定元素位置resize(newRect) {this.w = newRect.width;this.h = newRect.height;this.$set(this.arr[this.index], 'top', newRect.top)this.$set(this.arr[this.index], 'left', newRect.left)},onActivated(i) {console.log('点击了' + i,)this.arr.forEach((el, index) => {if (index == i) {this.index = i + ''this.$set(this.arr[index], 'isEdit', true)this.action = 2} else {this.$set(this.arr[index], 'isEdit', false)}});},onDeactivated() {this.index = nullthis.action = nullthis.arr.forEach((el, index) => {this.$set(this.arr[index], 'isEdit', false)});},preview() {this.onDeactivated()Toast.loading({message: '生成中...',forbidClick: true,loadingType: 'spinner',});setTimeout(() => {html2canvas(document.querySelector('.imgBox'), {backgroudColor: null,scale: 3, // 1125}).then(canvas => {let imgUrl = canvas.toDataURL('image/png');// console.log(imgUrl);this.imgURL = imgUrl;   //base64格式// 构建FormData对象,通过该对象存储要上传的文件const formData = new FormData();// 遍历当前临时文件List,将上传文件添加到FormData对象中formData.append('baseName', this.imgURL);this.$axios.post('/stage-api/system/management/upload', formData).then(res => {console.log(88877, res.fileName)let path1 = res.fileNamelet path = `/page_subject/detail/share?imgURL=${path1}&width=${this.width}&height=${this.height}&id=${this.id}`wx.miniProgram.navigateTo({url: path,success() {Toast.clear();},fail() {Toast('跳转失败');}, //小程序地址});}).catch(err => {console.log(999, err)})})}, 100);},}
}
</script>
<style scoped lang="scss">
.imgBox {// margin-left: 30px;background: #000 url('') no-repeat center center;background-size: 100% 100%;&.top {left: 50%;top: 0%;transform: translateX(-50%);}&.middle {left: 50%;top: 50%;transform: translate(-50%, -50%);}
}.color-option {width: 60px;height: 60px;margin: 8px;border-radius: 50%;
}.color-option.active {border: 2px solid #FFFFFF;
}::v-deep .m-colorPicker .colorBtn {width: 50px;height: 50px;
}::v-deep .box .vdr-stick {width: 35px !important;height: 35px !important;// background: #E94467;border: 1px solid #fff;border-radius: 50%;background: linear-gradient(221.12deg, #FB3568 0%, #FF8B6B 100%);&.vdr-stick-br {bottom: -16px !important;right: -15px !important;}&.vdr-stick-mr {right: -15px !important;}&.vdr-stick-bm {bottom: -16px !important;}&.vdr-stick-bl {bottom: -16px !important;}
}img.code {width: 100px;height: 100px;bottom: 20px;&.right {width: 100px;height: 100px;right: 20px;}&.center {left: 50%;transform: translateX(-50%);}
}.van-cell {border: 1px solid #ccc;
}::v-deep.m-colorPicker {border: 1px solid #ccc;
}.gushi {animation: test 2s;left: 0;top: 0;
}@keyframes test {0% {left: 0px;top: 1000px;}50% {transform: scale(1.5);left: 0px;bottom: 300px;}// 100% {//   left: 0;//   top: 0;// }
}::v-deep .solo.van-button--info {color: #fff;background-color: #E94467;border: 1px solid #E94467;
}
</style>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/712084.shtml

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

相关文章

上云还是下云,最大挑战是什么?| 对话章文嵩、毕玄、王小瑞

近半年来&#xff0c;公有云领域频频发生阿里云、滴滴等平台崩溃事件&#xff0c;与此同时&#xff0c;马斯克的“X 下云省钱”言论引起了广泛关注&#xff0c;一时间&#xff0c;“上云”和“下云”成为热议话题。在最近举办的 AutoMQ 云原生创新论坛上&#xff0c;AutoMQ 联合…

大数据可视化python01

import pandas as pd import matplotlib.pyplot as plt# 设置中文改写字体 plt.rcParams[font.sans-serif] [SimHei]# 读取数据 data pd.read_csv(C:/Users/wzf/Desktop/读取数据进行数据可视化练习/实训作业练习/瓜果类单位面积产量.csv ,encoding utf-8)#输出 print(data)…

springcloud alibaba组件简介

一、Nacos 服务注册中心/统一配置中心 1、介绍 Nacos是一个配置中心&#xff0c;也是一个服务注册与发现中心。 1.1、配置中心的好处&#xff1a; &#xff08;1&#xff09;配置数据脱敏 &#xff08;2&#xff09;防止出错&#xff0c;方便管理 &#xff08;3&#xff…

AI大预言模型——ChatGPT在地学、GIS、气象、农业、生态、环境等应用

原文链接&#xff1a;AI大预言模型——ChatGPT在地学、GIS、气象、农业、生态、环境等应用 一开启大模型 1 开启大模型 1)大模型的发展历程与最新功能 2)大模型的强大功能与应用场景 3)国内外经典大模型&#xff08;ChatGPT、LLaMA、Gemini、DALLE、Midjourney、Stable Di…

ConcurrentHashMap的演进:从Java 8之前到Java 17的实现原理深度剖析

目录 一、引言二、Java 8之前的ConcurrentHashMap1、内部结构与初始化2、Segment类3、并发控制4、扩容与重哈希5、总结 三、Java 8中的ConcurrentHashMap1、数据结构2、并发控制2.1. CAS操作2.2. synchronized同步块 3、哈希计算与定位4、扩容与重哈希5、总结 四、Java 17中的C…

广汽埃安工厂:蔚来汽车的造车工厂有哪些?

具体来说&#xff0c;理想汽车目前在常州仅有一家汽车制造工厂。 一期项目于2017年12月竣工&#xff0c;2019年12月投产&#xff0c;年产能10万辆/年。 同时&#xff0c;正在规划二期工程。 产能将增至20万辆/年。 此外&#xff0c;理想还计划接管现代汽车在北京顺义的第一家工…

工业现场网络性能评估方案

最近要去一个工厂排查网络和电脑卡顿的问题,为此&#xff0c;我准备了以下的方案&#xff0c;在现场以抓包和网络监控的方式来排查。 1.评估流程 为了评估Linux系统的网络负荷&#xff0c;并使用tcpdump来捕获数据包进行分析&#xff0c;您需要遵循以下几个步骤&#xff1a; …

数据仓库与数据挖掘概述

目录 一、数据仓库概述 &#xff08;一&#xff09;从传统数据库到数据仓库 &#xff08;二&#xff09;数据仓库的4个特征 &#xff08;三&#xff09;数据仓库系统 &#xff08;四&#xff09;数据仓库系统体系结构 &#xff08;五&#xff09;数据仓库数据的粒度与组织…

论文阅读_代码生成模型_CodeGeeX

英文名称: CodeGeeX: A Pre-Trained Model for Code Generation with Multilingual Evaluations on HumanEval-X 中文名称: CodeGeeX&#xff1a;一种用于代码生成的预训练模型&#xff0c;并在HumanEval-X上进行多语言评估 链接: https://arxiv.org/abs/2303.17568 代码: http…

训练1 : 老头

以前用blender做的特效 总结 头发很费时间, 需要参考和练习眼窝周边结构还有些待准确把握从光与影中揣摩轮廓形状 从少量面掌握大体, 从多数面雕刻细节

terminal下环境不统一导致的程序报错(powersell改cmd)

1.报错现象 在terminal下利用命令行执行代码显示运行环境缺包&#xff1a; 但将命令中的参数写入参数文件&#xff0c;运行train.py时&#xff0c;程序可以正常运行&#xff1a; 直接运行train.py:程序可用&#xff1a; 2.原因分析 参考文章 控制台环境和项目环境不一致问…

【Mysql】InnoDB 中 B+ 树索引的注意事项

一、根页面万年不动 在之前的文章里&#xff0c;为了方便理解&#xff0c;都是先画存储用户记录的叶子节点&#xff0c;然后再画出存储目录项记录的内节点。 但实际上 B 树的行成过程是这样的&#xff1a; 每当为某个表创建一个 B 树索引&#xff0c;都会为这个索引创建一个根…

循环队列的实现

文章目录 循环队列的概念循环队列的实现循环队列的判空和判满链表or数组 循环队列的概念 设计你的循环队列实现。 循环队列是一种线性数据结构&#xff0c;其操作表现基于 FIFO&#xff08;先进先出&#xff09;原则并且队尾被连接在队首之后以形成一个循环。它也被称为“环形缓…

快速下载Huggingface的大语言模型

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、Huggingface是什么&#xff1f;二、基于官方huggingface-cli下载&#xff08;基础&#xff0c;断线风险&#xff09;1.安装hf下载环境2.配置环境变量3.注册…

CSAPP-信息的表示和处理

文章目录 概念扫盲思想理解经典好图安全事件 概念扫盲 1.大端高位在前&#xff0c;小端低位在前 2.逻辑运算符&#xff08;&& 、||、&#xff01;&#xff09;与位级运算&#xff08;&、|、~&#xff09;的差异 3.宏可以保证无论代码如何编译&#xff0c;都能生成…

flutterandroidx支持,【工作经验分享】

基于Linux的pc启动过程 我们都知道&#xff0c;所有的程序软件包括操作系统都是运行在内存中的&#xff0c;然而我们的操作系统一般是存放在硬盘上的&#xff0c;当我们按下开机键的时候&#xff0c;此时内存中什么程序也没有&#xff0c;因此需要借助某种方式&#xff0c;将操…

百度SEO工具,自动更新网站的工具

在网站SEO的过程中&#xff0c;不断更新网站内容是提升排名和吸引流量的关键之一。而对于大多数网站管理员来说&#xff0c;频繁手动更新文章并进行SEO优化可能会是一项繁琐且耗时的任务。针对这一问题&#xff0c;百度自动更新文章SEO工具应运而生&#xff0c;它能够帮助网站管…

chartjs 饼状图

之前要把canvas先清除掉&#xff0c;不然刷新数据&#xff0c;还会有前面的图表 function clearCanvas(){$(#donutChart).remove();$(#chartdiv).append(<canvas id"donutChart" style"min-height: 500px; height: 500px; max-height: 500px; max-width: 70%…

浅谈mysql mvcc

目录 前言 mvcc 是如何工作的&#xff1f; 数据的更新 前言 mvcc 与一个事物的隔离级别有关&#xff0c;未提交读永远读的是当前值&#xff0c;串行化是通过加锁实现&#xff0c;这两种隔离级别都与mvcc 没有任何关系。只要一提到mvcc应该想到的是读提交以及可重复读&#…

vue+element ui上传图片到七牛云服务器

本来打算做一个全部都是前端完成的资源上传到七牛云的demo&#xff0c;但是需要获取token&#xff0c;经历了九九八十一难&#xff0c;最终还是选择放弃&#xff0c;token从后端获取&#xff08;springboot&#xff09;。如果你们有前端直接能解决的麻烦记得私我哦&#xff01;…