Men的博客

欢迎光临!

0%

https://github.com/Yidadaa/ChatGPT-Next-Web
https://github.com/Chanzhaoyu/chatgpt-web
https://github.com/transitive-bullshit/chatgpt-api
https://talkie.prejade.com/#/pages/chat/index?sessionId=session_gmGMMDBl
https://github.com/maioria/chatgpt-talkieai
https://github.com/shican1234/chatgpt-admin-ui

接口生成器
目前可以支持
Vue
swagger + aiox

apiPost + aiox

Flutter

Family并不是一个Provider,而是一个Provider生成器
有时候需要批量的Providers,比如在处理网络请求的时候,可能会遇到下面这种情况,Provider中的url除了一些参数不一样

https://blog.csdn.net/qq_16368383/article/details/132301937

Vue核心原理

JS里面一些技术
回调函数
柯里化
深拷贝
new
数据原型
call
commonJs
map
reduce

我们项目中经常会用到订单的场景,订单往往是一个列表,列表总是有一些方便我们快速点击的按钮
比如说待支付的订单,会有立即支付的按钮
但是同样的订单详情一定会有相同的按钮,相同的功能。
但是我们不能将业务逻辑在列表实现一遍后再去详情去实现一遍吧?
这样不光是浪费代码,还浪费时间。
一个功能如果需要修改的话,也需要去两个地方去修改。
那有什么办法能让这个功能在一个地方实现呢?
因为我是做移动端开发的,这个场景立即让我想到了controller,控制器,业务逻辑应该在控制器去实现
但是,我应该怎么去绑定这些事件呢?
我想到最简单的办法是我写一个方法,把this指针传递过去,
列表传列表的this,详情传详情的this,这样我就可以在controller里面去调用这个方法了
但是,这样会让this很麻烦,也很不优雅,而且还是要实现方法才能调用,
怎么样能不在列表和详情实现方法,而是抽离在controller里面呢?
这时候我就想到了JavaScript的call方法,call方法可以改变this的指向,
问题又来了,我们怎么绑定呢?
这里我们根据数据来实现的,列表和详情的数据对象基本一致。
我们在列表和详情对象上都使用call方法绑定上按钮和事件
那么不论是列表还是详情都可以用call去执行方法了

定义call函数,生成buttons和事件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
// 0: "待付款",
// 1: "待发货",
// 2: "待收货",
// 3: "已完成",
// 4: "已取消",
// 5: "商家取消",
// 6: "退款中",
// 7: "退款成功",
// listHide : 订单列表隐藏按钮
// orderUserType :1: 买家 2: 卖家 3: 中间商
export function callOrderButtons(userInfo) {
// 1: 买家 2: 卖家 3: 中间商
var orderUserType = 0;
if (this.isCross == 1) {
// 串货订单
if (this.crossSaleUserId == userInfo.id) {
orderUserType = 2;
} else if (this.saleUserId == userInfo.id) {
orderUserType = 3;
} else {
// 买家
orderUserType = 1;
}
} else {
// 非串货订单
if (this.saleUserId == userInfo.id) {
//卖家
orderUserType = 2;
} else {
// 买家
orderUserType = 1;
}
}
var buttons = [];
if (this.status == 0) {
// 卖家可以取消订单、订单改价
// 买家可以取消订单和付款
if (orderUserType == 2) {
buttons.push({
name: "取消订单",
method: methods.handler_b_cancel,
class: "cancel-btn",
listHide: true,
});
buttons.push({
name: "订单改价",
method: methods.handler_b_modify,
class: "cancel-btn",
listHide: true,
});
} else if (orderUserType == 1) {
buttons.push({
name: "取消订单",
method: methods.handler_c_cancel,
class: "cancel-btn",
});
buttons.push({
name: "立即付款",
method: methods.handler_c_pay,
class: "pay-btn",
});
}
} else if (this.status == 1) {
// 卖家可以发货、拒绝订单
// 买家可以申请退款
if (orderUserType == 2) {
buttons.push({
name: "拒绝订单",
method: methods.handler_b_reject,
class: "cancel-btn",
listHide: true,
});
buttons.push({
name: "立即发货",
method: methods.handler_b_delivery,
class: "pay-btn",
});
} else if (orderUserType == 1) {
buttons.push({
name: "申请退款",
method: methods.handler_c_refund,
class: "cancel-btn",
listHide: true,
});
}
} else if (this.status == 2) {
//
// 卖家可以查看物流 、同意拒绝延期
// 买家可以查看物流和确认收货和申请退款 、申请延期
if (orderUserType == 3) {
buttons.push({
name: "查看物流",
method: methods.handler_logistics,
class: "pay-btn",
listHide: true,
});
}else if (orderUserType == 2) {
buttons.push({
name: "查看物流",
method: methods.handler_logistics,
class: "pay-btn",
listHide: true,
});
const isSale =
!this.isCross ||
(this.isCross == 1 && this.crossSaleUserId == userInfo.id);
if (
this.delayedReceiveApply &&
this.delayedReceiveApply.applyStatus == 0 &&
isSale
) {
buttons.push({
name: "拒绝延期",
method: methods.handler_deferred_delivery_reject,
class: "cancel-btn",
});
buttons.push({
name: "同意延期",
method: methods.handler_deferred_delivery_done,
class: "pay-btn",
});
}
} else if (orderUserType == 1) {
buttons.push({
name: "申请退款",
method: methods.handler_c_refund,
class: "cancel-btn",
listHide: true,
});
if (
!this.delayedReceiveApply ||
this.delayedReceiveApply.applyStatus != 0
) {
buttons.push({
name: "申请延期",
method: methods.handler_deferred_delivery_apply,
class: "cancel-btn",
listHide: true,
});
}
buttons.push({
name: "查看物流",
method: methods.handler_logistics,
class: "pay-btn",
listHide: true,
});
buttons.push({
name: "确认收货",
method: methods.handler_c_done,
class: "pay-btn",
});
}
} else if (this.status == 3) {
// 卖家无操作
// 买家可以申请退款
const latestRefundTime = new Date(this.latestRefundTime).getTime();
const now = new Date().getTime();
const timeEnable = now < latestRefundTime;
const refundDays = this.refundDays;
if (orderUserType == 1 && timeEnable && refundDays > 0) {
buttons.push({
name: "申请退款",
method: methods.handler_c_refund,
class: "cancel-btn",
listHide: true,
});
}
} else if (this.status == 6) {
// 非退货列表中的退货数据
if (orderUserType == 2) {
buttons.push({
name: "售后详情",
method: methods.handler_b_after_sale,
class: "pay-btn",
});
} else if (orderUserType == 1) {
buttons.push({
name: "售后详情",
method: methods.handler_c_after_sale,
class: "pay-btn",
});
}
} else if (this.status == 7) {
// 退货列表中退货数据
if (orderUserType == 2) {
if (this.refundApply) {
if (this.refundApply.refundStatus == 0) {
buttons.push({
name:
this.refundApply.refundType == 1 ? "拒绝退货" : "拒绝退货退款",
method: methods.handler_b_refund_reject,
class: "cancel-btn",
});
buttons.push({
name:
this.refundApply.refundType == 1 ? "同意退货" : "同意退货退款",
method: methods.handler_b_refund_agree,
class: "pay-btn",
});
} else if (this.refundApply.refundStatus == 1) {
if (this.refundApply.deliveryStatus == 1) {
buttons.push({
name: "确认收货",
method: methods.handler_b_refund_done,
class: "pay-btn",
});
}
}
}
} else if (orderUserType == 1) {
if (this.refundApply) {
if (this.refundApply.refundStatus == 0) {
buttons.push({
name: "撤销申请",
method: methods.handler_c_refund_cancel,
class: "pay-btn",
});
}else if (
this.refundApply.refundStatus == 1 &&
this.refundApply.deliveryStatus == 0
) {
buttons.push({
name: "退货给商家",
method: methods.handler_c_refund_to_b,
class: "pay-btn",
});
}
}
}
}
this.buttons = buttons;
this.orderUserType = orderUserType;
// orderName
if (
this.isCross == 1 &&
this.crossStoreId != userInfo.openStoreId &&
orderUserType != 1
) {
this.orderName = "串货订单";
} else {
this.orderName = this.storeVo ? this.storeVo.storeName : "-";
}
}

controller按钮点击事件

export const methods = {
// B端取消
async handler_b_cancel(order) {

},
// B端订单改价
handler_b_modify(order) {

},
// C端取消
async handler_c_cancel(order) {

},
handler_c_pay(order) {

},
handler_pay(order) {

},
handler_b_reject(order) {

},
handler_b_delivery(order) {

},
handler_c_refund(order) {

},
handler_logistics(order) {

},
async handler_deferred_delivery_done(order) {

},
async handler_deferred_delivery_reject(order) {

},
async handler_deferred_delivery_apply(order) {

},
async handler_c_done(order) {

},
handler_b_refund_reject(order) {

},
async handler_b_refund_agree(order) {

},
async handler_b_refund_done(order) {

},
handler_c_after_sale(order) {

},
async handler_c_refund_cancel(order) {

},
handler_b_after_sale(order) {

},
handler_c_refund_to_b(order) {

},
};

数据列表item绑定callOrderButtons

1
callOrderButtons.call(item, this.userMixin);

渲染buttons

1
2
<view v-for="(btn, btnIndex) in order.buttons" v-if="btn.listHide != true" :key="btnIndex" 
:class="btn.class" @click="btnClick(btn, order)"> {{ btn.name }}</view>

按钮点击事件

1
2
3
btnClick(btn, order) {
btn.method.call(this, order);
},

没有例外,我写年终总结应该有很多年了。
不知不觉,一年又过去了,今年算是最难的一年
今年没有赚到一点钱,且还多花掉了10多万,昨天算了一下算是真的非常伤感
不知道明年怎么样,现在行情非常的差,我也不知道要怎么准备了
面试我现在都懒得准备了,我看人家说的很对,你5年以上的开发了,除非是在行业有比较深的认识
在某写方面有比较深刻的见解,不然大家都一样
就像我吧,基本上主流的语言都已经非常的熟悉了
我可以用OC、Swift、Dart、JavaScript、Java,写项目
主流的框架也非常的熟悉,比如 React、Flutter、Vue、Spring
对主流的UI框架也非常的了解 Element UI、Uniapp等等
所以说这些东西对于我来讲都是可以能够快速上手的
会想我这一年,公司干了8个项目
包括了Flutter、React、Vue、Uniapp今年说实话也是我突飞猛进的一年
我之前的公司,我一直都是在默默的做自己手上的工作,很少去了解别人的东西
但是今年真的不一样,我现在是真的不惧怕任何项目了
但是,你所你很厉害吗?我倒是不觉得,我现在的想法就是如何去做好项目
如何能够让项目能够有一个非常好的开发体验
我们总是在想项目如何开发的快,总是想复制粘贴,然后快速让项目起来
但是现在我有点觉得不应该这么搞了,项目还是要有自己的节奏,要写还是要写的好一点。
我写东西比较随意,总是想到哪里就写到哪里。

上一章讲到啦语音系统一些设计代码,这一章重点讲一下语音房间系统的设计细节。

礼物设计

礼物购买了非常多的gift礼物特效,我们考虑到用户在刷礼物时同时会接收到非常多的礼物,那么我们如何解决礼物特效播放的问题呢
首先

  1. 数据缓存
    我们接收到礼物特效消息后,解析数据,如果数据没有缓存,将礼物特效缓存到本地
  2. 特效队列
    我们将缓存好的礼物特效放入礼物特效集合中,然后将集合中的礼物特效依次播放,如果集合中没有特效,则等待下一条礼物特效消息
  3. 礼物特效播放队列
    我们构造了礼物特效集合,这里我们监听礼物集合当集合有数据时,我们就从集合队列中拿出一个
    因为礼物特效都是有播放时间的,所以播放完,要再从队列里面拿出一个进行播放。
    当所有特效都播放完后,停止播放

声音播放控制

这里设计的播放声音有很多

  1. 通话语音
  2. 背景音乐
  3. 礼物特效音乐

也要考虑到

  1. 听筒
  2. 播放器
  3. 麦克风音乐的控制

这考虑的东西非常的多,就不细细讲啦

麦位控制

1.上麦
2.下买
3.开卖
4.关麦
还有其它管理员操作的

模块划分

顶部菜单
热门用户
麦位列表

最近开发一个仓库的流程系统,对于仓库一些流程也有一些认识:
仓库的一些常用流程包括:
入库
出库
移库
坏库
盘库
借库
库存的核心是库存量,我们能够在数据流转过程中实时监听库存变化
对于库存的统计,能够合理统计库存数据

语音平台最近一直在开发一个语音系统,整个项目设计其实是参考的来来语音
具有的功能也非常的复杂,主要的功能当然是聊天系统了。
这里就重点讲述一下聊天系统的开发实现步骤吧
首先,系统是基于腾讯云的IM语音开放的SDK开发的
用到的插件:
rtc_room_engine: 腾讯语音房间

因为腾讯方面SDK都是使用的provider,我这边也直接使用的provider进行的设计
首先是创建一个房间的管理对象room_provider

涉及数据

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
class RoomProvider with ChangeNotifier{
/// 是否是房主
bool get owner => _roomInfo?.ownerId == SpUtil.getUserId();

/// 是否是管理员
bool _admin = false;
bool get admin => _admin;

// 关闭声音
bool _closeMicrophone = false;
bool get closeMicrophone => _closeMicrophone;

/// 房间信息
TUIRoomInfo? _roomInfo;
TUIRoomInfo? get roomInfo => _roomInfo;

/// 房间信息
RoomEntity? _roomData;
RoomEntity? get roomData => _roomData;

/// 当前用户信息
TUIUserInfo? _userInfo;
TUIUserInfo? get userInfo => _userInfo;

/// 房主信息
TUIUserInfo? _roomOwner;
TUIUserInfo? get roomOwner => _roomOwner;

/// 座位信息
List<TUISeatInfo> _seatList = [];
List<TUISeatInfo> get seatList => _seatList;

/// 当前用户的座位信息
RoomSeatGiftEntity? _userSeat;
RoomSeatGiftEntity? get userSeat => _userSeat;

/// 座位用户信息
List<RoomSeatGiftEntity?> _seatUserList = [];
List<RoomSeatGiftEntity?> get seatUserList => _seatUserList;

/// 所有用户信息
List<UserEntity> _userList = [];
List<UserEntity> get userList => _userList;

num _usersTotal = 0;
num get usersTotal => _usersTotal;

/// 消息
List<MessageInfo> _messageList = [];
List<MessageInfo> get messageList => _messageList;

/// 是否被禁言
bool _isMessageDisable = false;
bool get isMessageDisable => _isMessageDisable;

/// 滚动试图
late AutoScrollController autoController = AutoScrollController(
viewportBoundaryGetter: () =>
Rect.fromLTRB(0, 0, 0, MediaQuery.of(Get.context!).padding.bottom),
axis: Axis.vertical,
);

/// 礼物特效队列
List<Map> _giftSvgaList = [];
List<Map> get giftSvgaList => _giftSvgaList;
Map? _giftSvga = null;
Map? get giftSvga => _giftSvga;


}

涉及的API

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
/// 主持人创建房间
Future<bool> createRoom(String name, int roomTypeId)

// 销毁房间接口,销毁房间必须由房间所有者发起,销毁房间之后房间不可进入。
Future<TUIActionCallback> destroyRoom()

/// 进入房间接口。
Future<bool> enterRoom(String roomId, bool ifowner, {bool? offRoute})

/// WebSocket事件
void _onWebSocketMessageReceive(WebSocketMessageInfo messageInfo)

/// 离开房间接口,用户在执行 enterRoom 之后可通过 exitRoom 离开房间。
Future<bool> exitRoom() async

/// 上麦
Future<String?> takeSeat(index) async

/// 打开本地麦克风。
Future<bool> openVoice() async

/// 获取房间信息
Future<RoomEntity?> getRoomData()

/// 发送文本消息。
Future<TUIActionCallback> sendTextMessage(MessageInfo info)

消息

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
enum MessageType {
/// 进入房间
enter(0),

/// 公告
announcement(1),

/// 礼物
gift(2),

/// 用户发的消息
user(3),

/// 声明
statement(4),

/// @TA
ta(5);

const MessageType(this.type);

final int type;

int getType() {
return type;
}
}

WebSocket消息类型

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
enum WebSocketMessageType {
/// 热度变化
hot(0),

/// 座位变化
seat(1),

/// 人数变化
people(2),

/// 清屏
clean(3),

/// 房间信息修改
updateRoom(4),

/// 管理员修改
admin(5),

/// 礼物
gift(6),

/// 上麦
takeSeat(10),

/// 下麦
leaveSeat(11),

/// 禁麦
microphone(12),

/// 踢出
out(13),

/// 禁言用户
disableMessage(14),

/// 心跳事件
beat(15);

const WebSocketMessageType(this.type);
final int type;

static WebSocketMessageType initByInt(int number) =>
WebSocketMessageType.values
.firstWhere((activity) => activity.type == number);

int getInt() => type;
}

1、grep -r 搜索内容 *
作用:在一堆文件里,哪个文件包含了你的搜索内容,并展示了搜索内容前后的文字内容
eg:在log文件夹下,有01.log, 02.log, 03.log
执行

1
grep -r 20231314 *

2、l * 关键字 *
作用:在文件列表中筛选出包含关键字的文件

1
l *6*

3、tail -f 文件名
作用:实时显示文件的最后几行
eg:

1
tail -f MyLog.log

4、tail -n X 文件名
作用:显示指定文件最后X行的内容
eg:

1
tail -n 500 MyLog.log

5、cat 文件名 | grep “关键字” -C X
作用:在指定文件中搜索关键字内容,并展示关键字上下各X行的内容
eg:

1
cat MyLog.log | grep "20231314" -C 100


1
2
3
4
5
6
7
8
9
10
{
"applinks": {
"apps": [],
"details": [{
"appID": "8XP3RU5YNZ.com.keshi.audio",
"paths": ["*","/app/*" ]
}
]
}
}

Vue3 中的响应式实现原理

在 Vue 3 中,响应式实现的原理主要依赖于 Proxy 对象和 Reflect API。Vue 3 中的响应式系统被称为 “Reactivity”。

下面是 Vue 3 响应式实现的简要步骤:

  1. 创建一个 reactive 函数,它接收一个普通对象作为参数,并返回一个响应式代理对象。
  2. reactive 函数内部,使用 Proxy 对象来创建一个代理,拦截对象的读取、写入和删除操作。
  3. 在代理的拦截器函数中,通过 Reflect API 来实际执行对原始对象的操作,并触发依赖更新。
  4. 在代理的拦截器函数中,收集依赖关系,以便在数据变化时能够通知相关的响应式依赖更新。
  5. 创建一个 effect 函数,它接收一个副作用函数作为参数,并在副作用函数执行过程中收集依赖。
  6. 在副作用函数中访问响应式对象的属性,触发依赖收集。
  7. 当响应式对象的属性发生变化时,触发之前收集的依赖更新函数。

这种基于 Proxy 的响应式实现相比 Vue 2.x 的基于 Object.defineProperty 的实现具有更好的性能和更强大的功能。它能够跟踪嵌套属性的变化,并且可以对数组进行响应式处理。

以下是一个简单的示例,演示了如何在 Vue 3 中使用响应式实现:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import { reactive, effect } from 'vue';

// 创建一个普通对象
const state = reactive({
count: 0,
});

// 创建一个副作用函数
const logCount = () => {
console.log(`Count: ${state.count}`);
};

// 在副作用函数中访问响应式对象的属性
effect(logCount); // 输出 "Count: 0"

// 修改响应式对象的属性
state.count = 1; // 输出 "Count: 1"

在上面的示例中,我们首先使用 reactive 函数创建了一个响应式代理对象 state,其中包含一个属性 count。然后,我们创建了一个副作用函数 logCount,它在执行过程中访问了 state.count 属性。最后,我们使用 effect 函数将副作用函数包裹起来,以便在 state.count 属性发生变化时触发副作用函数。

需要注意的是,以上示例是一个简化的演示,实际的 Vue 3 响应式系统还包含更多功能和细节,例如计算属性、侦听器等。但基本的响应式实现原理就是通过 Proxy 对象和 Reflect API 来实现对对象的代理和拦截,以实现依赖追踪和更新通知的机制。

Quick Fix Editor action command:
Mac: ⌘+. or Cmd+.

目前来讲,针对json,制作一款代码生成器,能够一键生成小程序项目,
想法是以json作为模版进行数据生成,解析json数据,生成代码。

数据格式
tabbar

正则匹配
. 任意字符
^ 开头
$ 结尾
[abc] 其中任意字符
[a-z] 范围内任意字符
a|b a或者b