5、6、7月份副业共收入近15000块呢,这个数字我很满意,其中主要包括3个活:
-
- 帮助朋友亲戚 做24小时自助洗车软件(用户端小程序 + 商家端小程序 + PC后台管理系统),报价7000 块,到今日已经做完全部功能,也改完了几轮bugfix。首付款拿到70% (4900块),预计本月底结清。难度:高
-
- 在一个群里面看到有老板发布说参加AI大赛,主要是使用AI做一些应用,收集好的AI应用想法,符合要求一个作品(要求没那么高,可以是demo 小单页面)给200 块。 跟老板商量一个作品预付款50块 , 我总共投稿了38 个应用(哈哈哈我老肝了,平均每天搞6个作品,预付款就能拿到300 块),整体预付款拿到近2000 块钱。历时2个月 左右,本以为尾款没希望了。 没想到在7月4日早上正在地铁上班途中收到了老板的尾款转账5260 块。38个作品符合要求 的有37个,因为投稿要手机号,让老板找人待投了17个(一个扣15块),其他的自己找家里面人手机号弄的。 难度:低
-
- 6月30日收到掘金4月份金石计划的赏金201.62 块。难度:中。
24小时自助洗车软件7000块
我在之前文章 中也更新过,之前领导同事找我做私活,兼职每个月给1万,我没干(就TM懒 )介绍给了同事18000 全职的事情(听他说总共做了4-5个月)。相比这那个兼职这个洗车软件活的性价比很低

做这个的洗车软件,付出的精力真挺多的,基本每天晚上下班后都要写功能 到很晚,以及周六、周天 都在写功能,一坐就是一天。历时2个多月,5月7日正式开始,到今日偶尔还在改bug

除了一些写代码逻辑相关,晚上还有好多时间要在开会:
-
- 开会对需求
-
- 开会对实现方案
-
- 开会UI评审
-
- 自测改bug
这里提一下如果后端 的水品不行, 或者因为是私活写的代码逻辑不那么完善,联调起来真的很慢,有的时候一坐一下午还不能联联完一个模块,一调一个报错,真TM心累。
下面说一下我们的洗车应用总共有以下几个模块
PC端
-
- 登录模块 (若依)
-
- 用户角色模块、字典、部门(若依)
-
- 订单管理
- 3.1 订单列表
- 3.2 美团核销
- 3.3 抖音核销
-
- 会员管理
- 4.1 会员列表
-
- 营销管理
- 5.1 充值规则
-
- 门店管理
- 6.1 门店列表
- 6.2 股东提现记录
- 6.3 门店未消费余额
-
- 分润管理
- 7.1 分润配置
- 7.2 分润记录
- 7.3 银行卡信息
-
- 设备管理 (门店的洗车24小时设备)
说一下我们使用的若依 应用,本身刚看到这个后台管理样式的时候我还看不上,说样式好难看。可能是好几年前使用的element UI
,并且也没有对其优化,看起来就像个老系统。但是用起来还真不错,它的代码不说写的有多好,但是该有的功能都有了。比如字典、用户中心、角色菜单鉴权、登录等等都可以不用再次开发,也节省了很多时间。
再本次使用若依中,我总共封装了4个小业务组件:
car-date-time-range
: 时间带快捷选择范围选择器(今日、昨日、本月、上月),客户要求所有的时间控件都要有快捷选择。car-search
: 配置式的列表查询组件, 支持查询、重置
js
export const SEARCH_OPTIONS = [
{
label: "网点名称",
prop: "name",
component: CarSelect,
placeholder: "请输入网点名称",
componentOptions: {
placeholder: "请选择网点名称",
options: [
{
value: "选项1",
label: "黄金糕",
},
{
value: "选项2",
label: "双皮奶",
},
{
value: "选项3",
label: "蚵仔煎",
},
{
value: "选项4",
},
],
},
},
{
label: "手机号",
prop: "name",
component: "el-input",
},
{
label: "注册时间",
prop: "name",
component: "el-input",
},
{
label: "渠道",
prop: "name",
component: CarSelect,
componentOptions: {
options: [],
},
},
];
/**
* 使用方式
* <CarSearch
:searchConfig="SEARCH_OPTIONS"
:searchParams="searchParams"
v-show="searchParams.visible"
@search="onSearch"
/>
*/
car-select
: Elemnet Select 组件不支持配置式,简单封装了一下,为了给CarSearch
配置使用car-module
: 类似于Element Card 组件,每个模块都套了一层展现:标题、内容、操作。
总结:
若依
真的挺好用的,什么请求封装等都有了,基础功能都不用你再次开发了。下次有私活了,还要用它哈哈。
用户端小程序
用户端小程序功能说明如下:
-
首页
- 总金额(展示)
- 扫码启动应用(功能)
- 优惠券对换框 (入口跳转)
- 附近网点(入口跳转)
- 充值购卡(入口跳转)
- 联系客服 (弹窗)
- 启动页面(弹窗)
- 余额不足提示(弹窗)
-
附件网点
- 门店列表展示(支持排序:最近、空位,支持城市查询)
- 门店详情展示
-
我的
-
充值金额(展示)
-
赠送金额(展示)
-
优惠券数量(展示)
-
积分(展示)
-
我的订单(模块)
- 订单列表展示(消费、充值)
-
优惠券
- 优惠券列表展示(未消费、已消费、已过期TAB切换)
-
我要充值
- 充值规则列表展示(点击充值)
- 充值成功页面(就是个倒计时要不要洗车、以及充值信息展示)
-
团购核销
- 美团、抖音券核销
- 兑换成功页面(就是个倒计时要不要洗车、以及兑换成功信息展示)
-
收费标准
- 一个表格展示洗车收费计价规则
-
积分商城
- 里面就提示还在建设中
-
合作加盟
-
里面是手机号 + 微信二维码
-
微信支付
我们支付对接的是易宝支付 ,有相关需求的可以去找他们客服人员支持,由后端调用他们的API,返回的是直接调用wx.requestPayment
api的参数,就可以直接进行微信支付了。 钱会在第二天12点前打到商家账户中,才可以提现。
扫码洗车
我们的PC端在新增设备的时候会生成一个小程序二维码,用户扫码之后就可以进行余额、优惠券启动设备了。
微信小程序二维码再生成的时候会让填写打开的Path
路径,比如/pages/index/index?deviceId=12222222
,那么用户使用微信扫码 之后就会打开这个小程序进入这个页面。可以通过page的onLoad
方法获取到deviceId
参数。
javascript
Page({
/**
* 生命周期函数--监听页面加载
*/
async onLoad(options) {
await this.getUserInfo()
// options.deviceId 获取扫码的设备ID
if(this.data.isLogin && options.deviceId) { // 已登陆 + 有设备ID 出现启动设备弹窗
setDeviceId(options.deviceId)
this.setData({
deviceId: options.deviceId,
isShowStart: true,
})
}
if(!this.data.isLogin && options.deviceId) { // 未登录 + 有设备ID 去登录
await isToLogin(options.deviceId)
}
if(this.data.branchePhone && !options.deviceId && this.data.isLogin) { // (已登陆 + 绑定过网点 + 没有设备ID参数时) 校验最低钱 提示充值弹窗
this.getMinMoney()
}
},
})
我们小程序里面还有个扫一扫,可以让用户在进入小程序内直接操作,直接调用wx.scanCode
的APi:
js
// 定义一个工具函数,用于解析 URL 参数
export function getQueryData(url) {
const query = {};
const parts = url.split('?');
if (parts.length === 2) {
const queryPart = parts[1];
const params = queryPart.split('&');
for (let i = 0; i < params.length; i++) {
const param = params[i].split('=');
const key = decodeURIComponent(param[0]);
const value = decodeURIComponent(param[1]);
query[key] = value;
}
}
return query;
}
page({
onScan() {
const vm = this
wx.scanCode({
onlyFromCamera: false,
async success(event: any) {
//path: "/pages/index/index?deviceId=111111111111"
if(event.path) {
const queryData = getQueryData(event.path) as any
if(queryData.deviceId) {
await isToLogin(queryData.deviceId)
vm.readyStart(queryData.deviceId as any)
setDeviceId(queryData.deviceId)
}
}
},
fail(error) {
console.log(error,'微信扫码错误')
}
})
},
})
手机号一键登录
这个是微信的button组件,直接定义类型就会弹出需要用户手机号登录的授权了。这个组件免费额度有1000次,后续就要充值续费才能使用了。因为我们登录页面有用户协议以及隐私政策,我写了个普通按钮以及手机号组件按钮切换,来实现提示勾选功能。
TIPS: 我们按钮原本叫《微信一键登录》,后续在小程序提交审核中,被拒绝了。说:你好,你的小程序登录页面或弹窗(调用手机号快速验证组件的前置页面),存在混淆腾讯官方的元素,包括但不限于"微信"字样、微信官方logo等,请去除相关元素,如:将手机号授权登录提示修改为"手机号快捷登录"
html
<button class="login-button" wx:if="{{!isCheck}}" bind:tap="onLogin">手机号快捷登录</button>
<button class="login-button" wx:else open-type="getPhoneNumber" bindgetphonenumber="onLogin">手机号快捷登录</button>
原本我们的小程序 ,需要用户手机号登录后,才可以使用,但是在审核中一直被卡。说明如下:
你好,小程序一进入(首页]页面未浏览体验功能服务,即要求授权手机号码、头像、呢称进行授权登录请在用户体验浏览功能服务后,再自行选择授权登录。请整改后再提交审核。
后面我们申诉:说我们的洗车工具是强服务类型的,我们的用户大多来自于线下门店扫码使用。然后又被驳回了,让我们在首页增加特殊说明:
你好,小程序一进入页面即要求授权手机号码登录,属于特定服务人群使用,请在首页页面补充说明账号仅限特定人群登录并进行登录账号鉴权。请整改后再提交审核。
添加说明如下:
html
<view>- 尊敬的客户,欢迎使用XXXX自助洗车小程序!</view>
<view>- 使用前请先登录,以便记录您的洗车订单和优惠权益。</view>
<view>- 未登录用户无法启动设备,请谅解。</view>
<view>- 登录后,您可享受充值金额赠送等专属服务。</view>
这么操作下来,通过是能通过了,但是由于每次的审核人员都不一样,有的时候就是在审核说明中提说我们已经按照之前的审核增加强服务工具类的特殊说明,但是还会被卡审核。
我们为此还开了个会议,因为本身是客户的需求是登录后才能使用,1、为了我们最小成本不用做改动。2、满足客户的需求。我们项目经理还编辑了一段文本(不愧是领导,做的总结就是有水平,我要是审核人员看到后可能都给通过了):
pre
审核小哥哥/小姐姐您辛苦了,在提交版本前跟您提前反馈一个易打回问题,这个问题已经整改过了,开头的话在单独做一下背景说明。
关于首页就是登陆页的场景说明
我们是做自助洗车的,小程序是强工具类型,我们的用户都来自于线下的门店扫码,需要登录才后才能洗车。之前的审核同学已告知需要在首页添加说明即可通过,所以小程序对此问题已经做过处理啦。辛苦您再次审核了。
本次小程序上线的内容主要是xxxx
感谢您抽出宝贵的时间审核,感谢感谢!
但是但是通过率还是不高 ,最后跟客户 协商更改下逻辑,让先浏览网点内容,在选择要不要进行登录。在每个需要登录访问的入口增加公共的判断如下(利用promise reject
阻止后续代码执行):
javascript
export const isToLogin = (deviceId) => {
return new Promise((reslove, reject) => {
const isLogin = getIsLogin()
if(isLogin) {
reslove('已登陆!!!,程序继续执行!')
}else {
const pages = getCurrentPages();
const currentPage = pages[pages.length - 1];
const currentRoute = currentPage.route;
const currentOptions = currentPage.options;
wx.navigateTo({
url: `/pages/login/login?redirectUrl=${currentRoute}&deviceId=${currentOptions?.deviceId || deviceId || ''}`,
})
reject('未登录,不可继续执行程序,跳转登录中')
}
})
}
小程序更新页面缓存
统计信息我们放在一个userinfo
接口中,使用wx.setStorageSync
存储本地,在各个page
中获取使用。
金额、消费券 等统计信息都会在用户洗车消费完成、以及充值、兑换优惠券完成后需要刷新值。而且大家也都知道自助洗车是在洗车完成后才结算账单,那么我们就需要一个实时获取账单状态的定时任务 ,并且如果用户在页面停留(首页)在完成后更新页面上的值。
但是小程序没有一个Vuex
或者Redux
,那么更新界面的值就是个问题了。我们的统计信息在【首页、我的】有展示,我可以在首页Page、以及用户Page中我可以在有订单在洗车中,生命周期中Show启动定时任务、hide中关闭定时任务。
js
// order-status.js
import apiService from '../api/index'
import { reloadUserInfo } from './user-info'
const ORDER_ACCOUNT_UUID_KEY = 'ORDER_ACCOUNT_UUID_KEY'
export const setOrderAccountUUID = (data) => {
wx.setStorageSync(ORDER_ACCOUNT_UUID_KEY, data)
}
export const getOrderAccountUUID = () => {
return wx.getStorageSync(ORDER_ACCOUNT_UUID_KEY)
}
export const removeOrderAccountUUID = () => {
wx.removeStorageSync(ORDER_ACCOUNT_UUID_KEY)
}
const paddingUpdateRegister = [] // { key: 'index', callback() {}}
export const registerUpdataCallback = (data) => {
removeUpdataCallback(data.key)
paddingUpdateRegister.push(data)
}
export const removeUpdataCallback = (key) =>{
const findIndex = paddingUpdateRegister.find((item) => item.key === key);
if(findIndex !== -1) {
paddingUpdateRegister.splice(findIndex, 1)
}
}
// 订单状态 1:已付款 3:已结算
let timer = null
export const startGetOrderResultTask = async () => {
if(timer) {
clearTimeout(timer)
}
const orderUUID = getOrderAccountUUID()
if(orderUUID) { // 有订单id 刷新状态
const response = await apiService.getOrderStatusApi({
uuid: orderUUID,
unShowLoading: true
})
if(response?.data?.orderStatus === '3') {
removeOrderAccountUUID()
// 订单结算完成,更新userinfo 接口中的金额相关字段
await reloadUserInfo()
// 更新界面展示的值
paddingUpdateRegister.forEach((item) => {
item?.callback()
})
}else {
timer = setTimeout(() => {
startGetOrderResultTask()
}, 10000)
}
}
}
我会在启动设备完成后调用setOrderAccountUUID
存储一个订单ID
,然后分别在首页、我的页面注册回调函数、以及启动定时任务检测(洗车中,其实可以在小程序端继续使用的)。
使用如下:
js
const UPDATE_KEY = 'index' // 首页模块
Page({
/**
* 生命周期函数--监听页面显示
*/
onShow() {
const vm = this;
registerUpdataCallback({
key: UPDATE_KEY,
callback() {
const storgeUserInfo = getUserInfo();
vm.setData({
totalAmount: storgeUserInfo?.totalAmount || 0,
})
}
})
},
/**
* 生命周期函数--监听页面隐藏
*/
onHide() {
removeUpdataCallback(UPDATE_KEY)
},
})
小程序端API代理
我之前跟别的同学协作开发过小程序,但是我是中途加入开发的,并没太在意API代理的问题,我查了好多文档,里面都没有提到代理的方案。问Gpt
,他告诉我的是网络代理,直接给我的小程序开发者工具打不开了。
我还给我们的服务的同学说,微信小程序没办法代理,你们需要把API都改成GET
请求,要POST
的话就需要把CROS
允许我跨域。
最后最后才知道微信小程序运行在微信客户端内,不基于浏览器引擎,因此不受传统浏览器同源策略(协议/域名/端口完全一致)的约束 .
使用第三方npm插件构建
我是想在小程序中使用vant
相关组件,但是再首次构建后(下载依赖后,点击开发者工具-> 构建NPM)再页面引入发生错误,原因是根目录中的project.config.json
配置错误,可是我使用的是官方 TS + LESS
模版额,还需要配置:
json
{
"packNpmManually": true,
"packNpmRelationList": [
{
"packageJsonPath": "./package.json",
"miniprogramNpmDistDir": "./miniprogram/"
}
],
}
默认给我编译到根目录了,正常需要再/miniprogram/
下面,然后删除构建的miniprogram_npm
,重新构建NPM就行了。
Vant Picker组件样式更改
我们附近网点有个城市筛选,展示的是省市区筛选,那默认白色的肯定不能再,我们整体红色的小程序中使用了,然后我就更改了下他的样式如下:
css
.van-picker {
background: #681414 !important;
}
.van-picker-column__item--selected {
color: #F7E2D8 !important;
}
.van-picker-column, .van-picker__cancel,.van-picker__title, .van-picker__confirm {
color: #F7E2D8 !important;
}
/* 主要是这里 hsla 就是你的北京主题色0.9 到 0.4 hsla(0,68%,24%,.9) -> hsla(0,68%,24%,.4)) */
.van-picker__mask {
background-image: linear-gradient(180deg,hsla(0,68%,24%,.9),hsla(0,68%,24%,.4)),linear-gradient(0deg,hsla(0,68%,24%,.9),hsla(0,68%,24%,.4)) !important;
}
.van-hairline--bottom:after, .van-hairline--left:after, .van-hairline--right:after, .van-hairline--surround:after, .van-hairline--top-bottom:after, .van-hairline--top:after, .van-hairline:after {
border-color: rgba(247,226,216,.2) !important;
}
绑定对象数据偶尔获取不到
在微信小程序中我们循环列表,然后这个列表有事件需要获取item
数据,你使用data-item="{{item}}"
后,再事件中使用 bind:tap="onItemClick"
绑定事件
js
Page({
onItemClick(event) {
const {item = {}} = event.target.dataset; // 获取数据
// 以上这种方式再获取绑定对象数据时会纯在,获取不到数据
// 需要变更为:
const {item = {}} = event.currentTarget.dataset
}
})
总结绑定数据时,字符串、数字等简单类型可以使用
event.target.dataset
,绑定数组、对象等就需要使用event.currentTarget.dataset
长按扫描图片二维码
再image上增加show-menu-by-longpress="{{true}}
html
<image src="{{imgUrl}}" mode="" show-menu-by-longpress="{{true}}"/>
<view>长按识别微信</view>
小程序阻止事件冒泡
以为阻止事件冒泡也是使用点击事件上的e.stopPropagation(); // 阻止事件继续向上冒泡
,是的Kimi
也是这么告诉我的,让我尝试了好大一会,最后是更改绑定事件实现的catch:tap
:
html
<view bind:tap="onParentClick">
父元素
<view catch:tap="onChildClick">子元素</view>
</view>
小程序打开地图APP功能
使用微信内置地图查看位置
js
wx.openLocation({
atitude: item.latitude, // 目标地点纬度
longitude: item.longitude, // 目标地点经度
scale: 15,
name: item.branchName, // 地点名称
address: `${item.province || ''}${item.city || ''}${item.district || ''}` // 地点详细地址
});
这么就能打开手机APP导航了,地图展示如下:
小程序中唤起拨打电话功能
js
Page({
onCall() {
const item = this.data.item;
wx.makePhoneCall({
phoneNumber: `${item.contactPhone}`, // 要拨打的电话号码
success: function() {
console.log("拨打电话成功!");
},
fail: function(error) {
console.log(error,'error111')
console.log("拨打电话失败!");
}
});
},
})
列表下拉刷新、滚动加载组件
我记得我在大约6年前,为了使用下拉刷新、滚动加载功能还引入了一个组件才能使用。那个时候不知道有没有scroll-view
这个官方组件,也有可能之前就有,是我没仔细查看文档。
html
<view class="content" style="height: calc(100% - 90rpx);">
<scroll-view
class="scrollarea"
scroll-y="{{scrollY}}"
type="list"
style="height: 100%;"
refresher-enabled
refresher-background="#681414"
bindrefresherrefresh="onPullDownRefresh"
refresher-triggered="{{isRefreshing}}"
bindscrolltolower="onReachBottom"
>
<view class="shop-list" wx:if="{{list.length}}">
<shop-item
wx:for="{{list}}"
wx:key="index"
class="shop-item"
item="{{item}}"
data-item="{{item}}"
bind:click="onItemClick"
/>
</view>
<!-- 空数据组件,允许下拉刷新 -->
<car-empty wx:else/>
<!-- 列表加载完成后展示 -->
<car-list-complate wx:if="{{isLoadAll}}"/>
</scroll-view>
</view>
js
Page({
/**
* 页面相关事件处理函数--监听用户下拉动作
*/
async onPullDownRefresh() {
this.setData({ isRefreshing: true,pageNum: 1, isLoadAll: false }); // 开始刷新
await this.getData(true)
// 停止下拉刷新
this.setData({ isRefreshing: false }); // 开始刷新
},
/**
* 页面上拉触底事件的处理函数
*/
onReachBottom() {
if(this.data.total > this.data.list.length) {
this.getData()
}else {
this.setData({
isLoadAll: true
})
}
},
async getData(reload = false) {
const params = {}
const response = await apiService.getOrderListApi(params)
this.setData({
total: response.total || 0,
list: (reload ? []: this.data.list).concat(response?.rows || []), // reload 标识是重新加载还是 滚动加载拼接
pageNum: this.data.pageNum + 1,
})
},
})
小程序发布体验版本上线审核流程
-
- 点击开发者工具的【上传】按钮,然后填写对应的版本号,以及版本描述。
-
- 登录小程序管理后台,点击版本管理,然后把开发版本中的可以置为【体验版本】,可以下载体验版本二维码给开发者、运营者等查看。
-
- 把本次开发版本提交审核,如果你使用某些获取用户权限的API,需要填写具体用途。
-
- 审核通过后,需要在审核版本中点击上线,才是正式上线。
-
- 上线后,未提交备案的小程序,在微信搜索功能查不到小程序。只能通过分享打开小程序。
可信域名配置
上传完代码,访问体验版本以及上线需要访问API地址必须是域名,并且需要在微信后台管理中配置可信域名才能访问。本地开发是IP地址也都无所谓。
总结: 之前虽然也搞过微信小程序,但是并没有这么完整,本次也算是积累不少小程序开发的经验
小程序商家端
商家端小程序功能说明如下:
-
登录 账号密码登录
-
首页
-
下拉切换网点(以下功能是都跟网点挂钩的, 网点相当于门店)
-
当日洗车、收益、消费、会员统计概览 (展示、切换网点更新数据)
-
收益管理(菜单跳转)
-
当日收益、当月收益、累计收益统计概览
- 【支持】跳转查看详情,月、年支持切换查看详情(表格展示)
-
当日消费、当月消费、累计消费统计概览
- 【支持】跳转查看详情,月、年支持切换查看详情(表格展示)
-
当日会员、当月会员、累计会员统计概览
- 【支持】跳转查看详情,月、年支持切换查看详情(表格展示)
-
当日洗车、当月洗车、累计洗车概览
-
跨店支出、跨店消费、综合收入概览
-
平均洗车单价、平均洗车时长、平均洗车频次统计概览
-
-
提现管理(菜单跳转)
-
提现管理概览统计(保证金、已提现、可提现、待提现)
-
提现记录(表格展示提现时间、手续费、提现时间)
-
提现功能(弹窗)
-
数据金额提现(提现成功刷新提现记录)
-
分润记录(菜单跳转)
-
展示分润总额
-
展示分润记录表格,下拉刷新,滚动加载(分润金额、分润比例、分润时间)
-
支出切换时间范围筛选
-
续费管理 (菜单跳转)
-
门店续费记录(列表:短信续费记录 + 主板设备续费)下拉刷新、滚动加载
-
门店已有设备列表展示
-
短信续费,选择A、B、C、D不同条数方案充值续费
-
主板设备续费,选择设备列表进行续费
-
我的订单 (菜单跳转)
-
列表展示我的订单,支持时间范围查询、支持订单类型查询、支持跨店消费类型查询、支持手机号查询。下拉刷新、滚动加载
-
设备状态(菜单跳转)
-
折叠面板展示网点下面的各个设备状态,空闲、洗车中、停用
-
退出登录
-
商家端好像没有什么总结的,都是一些统计类的,主题色跟用户端一样,就还原设计就行。
洗车软件总结
我只能说如果我不换工作,不是待遇下降了30% ,7000块就是帮朋友 做3个应用 ,我应该不会接。有孩子,有房贷,老婆不上班,我换工作后降薪。
性价比应该算是相当低了,我之前文档中还说接私活你就按照你的正常日薪 * 工时 评就行。
现在的我很感谢朋友来找我做这个私活,利用业余时间,可以有个不错的外快,累是累了点。但是买手机真香啊,618刚给老婆买了个苹果16 8 + 256 5200. 她老说苹果12内存不够用了,天天在清理内存
之前我一直做TOB的业务,很少做小程序,之前也写过感觉比较简单,看看文档就行帮朋友写过几个小模块,这次也算完整做了2个微信小程序,积累的不少开发经验。
并且听朋友的意思还有二期功能 ,好像要做会员功能,不知道再能挣多少。
AI大赛投稿
这个活动其实我本身也是质疑活动的真实性 ,而且给老板说了好久他才答应给我预付款50 ,我也告诉我朋友让他搞,他也就搞了2个。他说太费劲了,最后钱还不一定能拿到。
我本来计划搞50 个呢,谁知道搞到38 个时候老板告诉我名额满了,后悔礼拜六礼拜天没有多搞点(其实我也没想着能拿到尾款,就想着每天搞5~6个,一天300块也挺不错)
后面也跟老板多聊了下,让他以后有私活了优先找我。
掘金金石计划
我在4月份利用空闲时间学习了下qiankun
微应用源码,总结更新了几篇系列文章:
-
《2025 乾坤(qiankun)和 Vue3 最佳实践(提供模版)》这篇有幸超过10个点赞以及收藏好像进入一个什么档次多分了点钱
以及俩个组件源码的经验总结分享:
总结
以上就是我在5、6、7月份利用业余时间来挣到的一些钱,希望能多多来单子,有老板资源多的,可以拉我一把。活好、责任心强