空痕博客 - 编程技术分享
首页
小记
php
python
uniapp
前端
其他
机器人
QQ机器人
项目
功能库
应用
其他页面
友情链接
用户留言
联系空痕
热门文章
PHP搭建QQ机器人(QQ官方)
下载文件到指定文件夹
欢迎回来 Typecho !
UTS引用原生jar包进行原生插件开发
上传文件到夸克网盘python代码
标签搜索
uniapp
PHP
python
VUE
模板
夸克网盘
html
APP
KongHen
机器人
QQ
UTS
ID3
uniapp-x
pyinstaller
redis
Echarts
邮箱
js
lyear
发布
登录
注册
空痕博客 - 编程技术分享
最新发布
2025-10-09
全新任务管理平台(流量主变现系统)开源
项目简介 项目结构 接口管理:PHP + Mysql 后台管理系统:Vue3 + ts + TDesign 任务单页:Vue3 小程序:uniapp + Vue2 变现说明 基础流程: 后台创建任务 复制任务链接 分享到社群或私域 用户打开任务页面 跳转到小程序观看广告 观看广告 下发奖励 收入说明 微信小程序官方广告收入 其他推广/广告收入 系统演示 演示站点 空痕任务管理系统 后台数据为静态演示数据,无法更改 演示图片 管理后台 控制台图片 任务单页 任务单页图片 小程序 小程序图片 安装教程 管理后台 安装依赖 npm install 构建项目 npm run build 新建站网站及数据库 推荐:PHP 8.0 推荐:Mysql 5.7 开启SSL(必须) 配置伪静态 location / { try_files $uri $uri/ /index.html; } location /api/ { if (!-e $request_filename) { rewrite ^/(.*)$ /$1.php last; } } 导入数据库 导入/后台/数据库/task_dev_xma_run.sql到Mysql数据库 修改/后台/api/config.php 管理账户密码 JWT配置(密钥、过期时间) 数据库配置 上传后台代码 上传/后台/dist目录中的全部文件到网站根目录 上传/后台/api目录到网站根目录 任务单页 安装依赖 npm install 修改/任务单页/src/App.vue中的接口信息 修改后台地址 修改视频教程地址 构建项目 npm run build 新建网站 静态网站 开启SSL(必须) 上传任务单页代码 上传/任务单页/dist目录中的全部文件到网站根目录 小程序 使用HbuildX打开小程序 在manifest.json中获取新AppID 修改/pages/user/view中的后台地址 修改/pages/user/work中的二维码 发行到微信小程序 在微信开发者工具中上传代码 登录微信小程序后台配置 配置request合法域名 https://task.dev.xma.run https://www.duitang.com 配置downloadFile合法域名 https://c-ssl.duitang.com 配置明文scheme拉起此小程序 pages/user/view;pages/user/work 代搭建/教学 请联系微信:KongHen02 项目地址 GitHub
应用
# PHP
# uniapp
# VUE
# 小程序
# 开源
KongHen02
2天前
0
36
1
2025-10-01
极简在线剪切板源码(html+php)
开发原因 要在多个设备之间复制长文本,但是设备上没有安装微信、QQ等聊天软件,所以很难复制,逐字输入太慢,且如果文本时长链接、脚本命令或代码就容易输入错误,所以需要一个在线剪切板工具。 网上搜索,没有找到想要的,就使用AI开发了一个很简单的在线剪切板。 功能列表 创建剪切板 获取剪切板 剪切板列表 生成剪切板链接 添加查看密码 删除剪切板 使用说明 直接上传到服务器即可使用 剪切板内容存储使用json文件存储 演示站点 演示站点 在线剪切板 演示截图 在线剪切板演示图片图片 代码下载 在线剪切板.zip 下载地址:https://cdn.x7x.fun/uploads/20251001/fc08409ece526fdb.zip 提取码:
PHP
# PHP
# html
# 小工具
KongHen02
10月1日
0
58
0
2025-08-31
修复RuleApp在微信环境不能设置头像问题
问题说明: 问题:RuleApp在微信内无法获取用户头像,且用户无法设置 产生原因:微信修改用户信息获取规则 修复方法: 新增微信环境设置头像按钮 <!-- #ifdef MP-WEIXIN --> <button class="cu-btn bg-gradual-blue radius" open-type="chooseAvatar" @chooseavatar="avatarUpload"></button> <!-- #endif -->修改演示图片 修改avatarUpload函数,并新增uploadAvatarToSever函数 uploadAvatarToSever(path) { const uploadTask = uni.uploadFile({ url: that.$API.upload(), filePath: path, // header: { // "Content-Type": "multipart/form-data", // }, name: 'file', formData: { 'token': token }, success: function(uploadFileRes) { setTimeout(function() { uni.hideLoading(); }, 1000); var data = JSON.parse(uploadFileRes.data); //var data = uploadFileRes.data; if (data.code == 1) { // uni.showToast({ // title: data.msg, // icon: 'none' // }) that.avatar = data.data.url; that.avatarNew = data.data.url; localStorage.removeItem('toAvatar'); that.userEdit(); //console.log(that.avatar) } else { uni.showToast({ title: "头像上传失败,请检查接口", icon: 'none' }) } }, fail: function() { setTimeout(function() { uni.hideLoading(); }, 1000); } }) }, avatarUpload(data) { var that = this; var token = ""; if (localStorage.getItem('userinfo')) { var userInfo = JSON.parse(localStorage.getItem('userinfo')); token = userInfo.token; token = userInfo.token; } // #ifdef APP-PLUS || H5 base64ToPath(data) .then(path => { that.uploadAvatarToSever(path) }) .catch(error => { console.error("失败" + error) }) // #endif // #ifdef MP-WEIXIN const path = data.detail.avatarUrl that.uploadAvatarToSever(path) // #endif },修复结果: 修复后,在微信内编辑用户信息页面会有设置头像按钮,点击按钮会调用微信官方获取头像接口,选择微信头像或者设置其他头像接口,返回用户选择的头像临时路径,使用data.detail.avatarUrl获取临时路径,调用uploadAvatarToSever函数上传到服务器。 完整代码: GitHub - RuleApp(KongHen) 原项目地址: GitHub - RuleApp(buxia97)
uniapp
# uniapp
# RuleApp
# 规则之树
# 微信小程序
# GitHub
KongHen02
8月31日
0
82
0
2025-08-22
故障风格404页面
效果演示 点击查看在线演示 图片演示图片 完整代码 <!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>系统故障 - 404</title> <style> * { margin: 0; padding: 0; box-sizing: border-box; } body { background: #0a0a0a; font-family: 'Courier New', monospace; height: 100vh; overflow: hidden; display: flex; align-items: center; justify-content: center; color: #00ff41; cursor: crosshair; } .matrix-bg { position: absolute; width: 100%; height: 100%; opacity: 0.1; background: repeating-linear-gradient( 0deg, transparent, transparent 2px, #00ff41 2px, #00ff41 4px ); animation: scan 8s linear infinite; } @keyframes scan { 0% { transform: translateY(-100%); } 100% { transform: translateY(100%); } } .container { text-align: center; position: relative; z-index: 10; } .error-code { font-size: 120px; font-weight: bold; position: relative; display: inline-block; color: #fff; letter-spacing: 10px; animation: flicker 0.5s infinite alternate; } .error-code::before, .error-code::after { content: "404"; position: absolute; top: 0; left: 0; width: 100%; height: 100%; background: transparent; overflow: hidden; } .error-code::before { left: 2px; text-shadow: -2px 0 #ff00c8; animation: glitch-1 0.3s infinite ease-in-out alternate-reverse; clip: rect(44px, 450px, 56px, 0); } .error-code::after { left: -2px; text-shadow: -2px 0 #00ffff, 2px 2px #ff00c8; animation: glitch-2 0.3s infinite ease-in-out alternate-reverse; clip: rect(44px, 450px, 56px, 0); } @keyframes glitch-1 { 0% { clip: rect(31px, 9999px, 94px, 0); } 20% { clip: rect(112px, 9999px, 76px, 0); } 40% { clip: rect(85px, 9999px, 77px, 0); } 60% { clip: rect(62px, 9999px, 34px, 0); } 80% { clip: rect(97px, 9999px, 89px, 0); } 100% { clip: rect(53px, 9999px, 47px, 0); } } @keyframes glitch-2 { 0% { clip: rect(65px, 9999px, 119px, 0); } 20% { clip: rect(52px, 9999px, 74px, 0); } 40% { clip: rect(4px, 9999px, 78px, 0); } 60% { clip: rect(100px, 9999px, 19px, 0); } 80% { clip: rect(22px, 9999px, 98px, 0); } 100% { clip: rect(89px, 9999px, 113px, 0); } } @keyframes flicker { 0%, 19%, 21%, 23%, 25%, 54%, 56%, 100% { text-shadow: 0 0 5px #00ff41, 0 0 10px #00ff41, 0 0 20px #00ff41; } 20%, 22%, 24%, 55% { text-shadow: none; } } .error-message { font-size: 18px; color: #ff0040; margin: 20px 0; animation: pulse 2s infinite; text-transform: uppercase; letter-spacing: 3px; } @keyframes pulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.3; } } .home-button { display: inline-block; padding: 15px 30px; margin-top: 30px; border: 2px solid #00ff41; background: transparent; color: #00ff41; text-decoration: none; text-transform: uppercase; letter-spacing: 2px; position: relative; overflow: hidden; transition: all 0.3s; font-family: 'Courier New', monospace; } .home-button:hover { color: #0a0a0a; box-shadow: 0 0 20px #00ff41; } .home-button::before { content: ''; position: absolute; top: 0; left: -100%; width: 100%; height: 100%; background: #00ff41; transition: left 0.3s; z-index: -1; } .home-button:hover::before { left: 0; } .noise { position: absolute; top: 0; left: 0; width: 100%; height: 100%; background: radial-gradient(circle, transparent 20%, rgba(255,255,255,0.03) 20.1%, transparent 21%), radial-gradient(circle, transparent 40%, rgba(255,255,255,0.03) 40.1%, transparent 41%); animation: noise 0.5s steps(10) infinite; pointer-events: none; } @keyframes noise { 0%, 100% { transform: translate(0); } 10% { transform: translate(-2px, -2px); } 20% { transform: translate(2px, 2px); } 30% { transform: translate(-2px, 2px); } 40% { transform: translate(2px, -2px); } 50% { transform: translate(-2px, -2px); } 60% { transform: translate(2px, 2px); } 70% { transform: translate(-2px, 2px); } 80% { transform: translate(2px, -2px); } 90% { transform: translate(-2px, -2px); } } .system-info { position: absolute; bottom: 20px; left: 20px; font-size: 12px; color: #666; font-family: monospace; animation: typewriter 3s steps(30) 1; } @keyframes typewriter { from { width: 0; } to { width: 100%; } } @media (max-width: 768px) { .error-code { font-size: 80px; } .error-message { font-size: 14px; } } </style> </head> <body> <div class="matrix-bg"></div> <div class="noise"></div> <div class="container"> <h1 class="error-code">404</h1> <p class="error-message">系统故障 - 页面失踪</p> <p style="color: #666; margin-top: 10px;">检测到异常活动,启动安全协议</p> <a href="https://www.khkj6.com" class="home-button">返回安全区</a> </div> <script> // 随机故障效果 setInterval(() => { document.body.style.filter = `hue-rotate(${Math.random() * 360}deg)`; setTimeout(() => { document.body.style.filter = 'none'; }, 100); }, 3000); // 鼠标追踪效果 document.addEventListener('mousemove', (e) => { const x = e.clientX / window.innerWidth; const y = e.clientY / window.innerHeight; const glitch = document.querySelector('.error-code'); glitch.style.transform = `translate(${x * 4}px, ${y * 4}px)`; }); </script> </body> </html>
前端
# 模板
# html
# 404
KongHen02
8月22日
0
85
0
2025-08-21
uniapp-x实现自定义tabbar
uniapp-x自带导航栏位置固定,且UI无法修改。如果需要适配自己的应用UI及色彩就需要自定义tabbar。 实现说明 将tabbar写入主页面,需要显示的页面作为组件引入。 示例样式 演示示例图片 实现方法 使用swiper实现 说明: 所有页面一次性加载 允许左右滑动 优点:允许滑动切换,用户体验升级 演示代码 <template> <!-- 页面内容区域 --> <swiper style="flex: 1;" :current="selectedIndex" @change="swiperChange"> <swiper-item item-id="index"> <IndexPage></IndexPage> </swiper-item> <swiper-item item-id="more"> <MorePage></MorePage> </swiper-item> <swiper-item item-id="user"> <UserPage></UserPage> </swiper-item> </swiper> <!-- tabber区域 --> <view class="tab-bar-container"> <view v-for="(item, index) in tabList" class="tab-bar-item" @click="switchTab(index)"> <image class="tab-bar-icon" :src="(selectedIndex === index ? item.s_icon : item.icon)"></image> <text class="tab-bar-text" :style="'color:' + (selectedIndex === index ? '#F59E0B' : '#999999') +';'">{{ item.name }}</text> </view> </view> </template> <script setup lang="uts"> // 导入页面 import IndexPage from "./tabbar/index.uvue" import MorePage from "./tabbar/more.uvue" import UserPage from "./tabbar/user.uvue" // tabbar接口类型 type TabInfo = { name : string, icon : string, s_icon : string } // 页面列表 const tabList = reactive<TabInfo[]>([ { name: "首页", icon: "/static/tabbar/home.png", s_icon: "/static/tabbar/home_selected.png" }, { name: "活动", icon: "/static/tabbar/more.png", s_icon: "/static/tabbar/more_selected.png" }, { name: "我的", icon: "/static/tabbar/user.png", s_icon: "/static/tabbar/user_selected.png" } ]) // 选中的页面 const selectedIndex = ref<number>(0) // swiper切换 const swiperChange = (e: UniSwiperChangeEvent) => { let index = e.detail.current if (selectedIndex.value === index) return selectedIndex.value = index } // 页面切换 const switchTab = (index : number) => { if (selectedIndex.value === index) return selectedIndex.value = index } </script> <style lang="scss"> .tab-bar-container { position: fixed; bottom: 60rpx; width: 80%; left: 10%; z-index: 999; display: flex; flex-direction: row; justify-content: space-around; height: 120rpx; border-radius: 60rpx; box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.1); background: rgba(255, 255, 255, 0.4); } .tab-bar-item { display: flex; flex-direction: column; align-items: center; justify-content: center; padding: 15rpx 40rpx; } .tab-bar-icon { width: 44rpx; height: 44rpx; margin-bottom: 8rpx; } .tab-bar-text { font-size: 24rpx; } </style>官方示例 说明: 单次只加载一个页面 加载成功后使用v-show控制显示/隐藏,不重复加载(官方使用CSS属性visibility控制,测试不行) 优点:分页加载,减小单次加载压力(如果页面DOM多的话) 演示代码 <template> <!-- 页面内容区域 --> <view style="flex: 1;"> <IndexPage v-if="tabList[0].init" v-show="selectedIndex==0"></IndexPage> <MorePage v-if="tabList[1].init" v-show="selectedIndex==1"></MorePage> <MorePage v-if="tabList[2].init" v-show="selectedIndex==2"></MorePage> </view> <!-- tabber区域 --> <view class="tab-bar-container"> <view v-for="(item, index) in tabList" class="tab-bar-item" @click="switchTab(index)"> <image class="tab-bar-icon" :src="(selectedIndex === index ? item.s_icon : item.icon)"></image> <text class="tab-bar-text" :style="'color:' + (selectedIndex === index ? '#F59E0B' : '#999999') +';'">{{ item.name }}</text> </view> </view> </template> <script setup lang="uts"> // 导入页面 import IndexPage from "./tabbar/index.uvue" import MorePage from "./tabbar/more.uvue" import UserPage from "./tabbar/user.uvue" // tabbar接口类型 type TabInfo = { init: boolean, name : string, icon : string, s_icon : string } // 页面列表 const tabList = reactive<TabInfo[]>([ { init: true, name: "首页", icon: "/static/tabbar/home.png", s_icon: "/static/tabbar/home_selected.png" }, { init: false, name: "更多", icon: "/static/tabbar/more.png", s_icon: "/static/tabbar/more_selected.png" }, { init: false, name: "我的", icon: "/static/tabbar/user.png", s_icon: "/static/tabbar/user_selected.png" } ]) // 选中的页面 const selectedIndex = ref<number>(0) // 页面切换 const switchTab = (index : number) => { if (selectedIndex.value === index) return if (!tabList[index].init) { tabList[index].init = true } selectedIndex.value = index } </script> <style lang="scss"> .tab-bar-container { position: fixed; bottom: 60rpx; width: 80%; left: 10%; z-index: 999; display: flex; flex-direction: row; justify-content: space-around; height: 120rpx; border-radius: 60rpx; box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.1); background: rgba(255, 255, 255, 0.4); } .tab-bar-item { display: flex; flex-direction: column; align-items: center; justify-content: center; padding: 15rpx 40rpx; } .tab-bar-icon { width: 44rpx; height: 44rpx; margin-bottom: 8rpx; } .tab-bar-text { font-size: 24rpx; } </style>其他方法 使用share-element组件实现 复制官方代码,偶先切换页面组件闪动问题。官方uniapp-xapp的demo测试正常,不知道申明原因。 使用components组件+share-element组件实现的tabbar组件实现,tabbar组件会出现与页面移入方向反向滑动的动画 share-element文档 静态资源 tabbar图标(png) 下载地址:https://www.khkj6.com/usr/uploads/2025/08/2337268233.zip 提取码:
uniapp-x
# VUE
# uniapp-x
# tabbar
# swiper
KongHen02
8月21日
0
85
1
1
2
...
5
下一页
易航博客
小柚博客
易航博客
笒鬼鬼
mp4网
易航博客
免费API
安排博客