小程序练手

一直想写一款自己的小程序,所以趁着空闲的时间研究了一下uniapp和微信小程序的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
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
<template>
<view class="login-container">
<uni-icons type="contact-filled" size="100" color="#AFAFAF"></uni-icons>
<button type="primary" class="btn-login" @click="getUserProfile">一键登录</button>
<text class="tips-text">请登录</text>
</view>
</template>

<script>
const app = getApp();
const baseUrl = app.globalData.baseUrl;
import {
mapMutations,
mapState
} from 'vuex'

export default {
name: 'my-login',
data() {
return {

};
},
computed: {
...mapState('m_user', ['redirectInfo'])
},
methods: {
...mapMutations('m_user', ['updateUserInfo', 'updateToken', 'updateRedirectInfo']),
// 获取微信用户的基本信息
getUserProfile() {
uni.getUserProfile({
desc: '你的授权信息',
success: (res) => {
console.log(res)
// 将信息存到 vuex 中
this.updateUserInfo(res.userInfo)
this.getToken(res)
},
fail: (res) => {
return uni.$showMsg('您取消了登录授权')
}
})
},
async getToken(info) {
let self = this
// 获取 code 对应的值
const [err, res] = await uni.login().catch(err => err)
if (err || res.errMsg !== 'login:ok') return uni.$showMsg('登录失败!')
// 准备参数
const query = {
code: res.code,
encryptedData: info.encryptedData,
iv: info.iv,
rawData: info.rawData,
signature: info.signature
}
await uni.request({
method: "POST",
data: query,
url: baseUrl + "/login",
success: function(msg) {
console.log(msg)
if (msg.data.resultCode !== 2000) return uni.$showMsg('登录失败!')
self.updateToken(msg.data.data)
self.navigateBack()
}
})
},
navigateBack() {
let self = this
uni.navigateBack()
}
}
}
</script>
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
@PostMapping("/login")
public ApiResult<String> login(@RequestBody LoginBean loginBean) {
System.out.println(loginBean);
// 获取code值请求微信API或者openid
String code = loginBean.getCode();
String rawData = loginBean.getRawData();
JSON rawJson = JSONUtil.parse(rawData);
String nickName = rawJson.getByPath("nickName", String.class);
String avatarUrl = rawJson.getByPath("avatarUrl", String.class);
String response = HttpUtil.get("https://api.weixin.qq.com/sns/jscode2session?appid=" + APP_ID + "&secret=" + SECRET + "&js_code=" + code + "&grant_type=authorization_code");
JSON parse = JSONUtil.parse(response);
String openId = parse.getByPath("openid", String.class);
User user = userMapper.findByOpenId(openId);
String sign;
if (user == null) {
User u = new User();
u.setOpenId(openId);
u.setAvatarUrl(avatarUrl);
u.setNickName(nickName);
u.setTotalScore(0L);
userMapper.insert(u);
Long id = u.getId();
sign = JwtUtil.sign(id);
} else {
Long id = user.getId();
sign = JwtUtil.sign(id);
}
return ApiResult.resultWith(ResultCodeEnum.SUCCESS, sign);
}

之后所有需要用到登陆信息的页面会先验证token,确认身份后再继续执行,否则重返登陆页

获取个人信息

因为前面登陆将token已经记录,所以此时通过token查询后台即可获取登陆人的信息

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
<template>
<view class="my-userinfo-container">
<!-- 头像和昵称区域 -->
<view class="top-box">
<image :src="userinfo.avatarUrl" class="avatar"></image>
<view class="nickname">{{userinfo.nickName}}</view>
</view>

<!-- 面板区域 -->
<view class="panel-list">
<!-- 第1个面板 -->
<view class="panel">
<view class="panel-body">
<view class="panel-item">
<text>{{totalScore}}</text>
<text>我的积分</text>
</view>
<view class="panel-item">
<text>0</text>
<text>我的兑换</text>
</view>
<view class="panel-item">
<text>0</text>
<text>我的审核</text>
</view>
</view>
</view>
<!-- 第3个面板 -->
<view class="panel">
<view class="panel-list-item" @click="logout">
<text>退出登录</text>
<uni-icons type="arrowright" size="15"></uni-icons>
</view>
</view>
</view>
</view>
</template>

<script>
import {
mapState,
mapMutations
} from 'vuex'
const app = getApp();
const baseUrl = app.globalData.baseUrl;
export default {
data() {
return {
totalScore: Number
};
},
computed: {
...mapState('m_user', ['userinfo'])
},
created() {
this.getUserInfo()
},
methods: {
...mapMutations('m_user', ['updateAddress', 'updateUserInfo', 'updateToken']),
async logout() {
const [err, succ] = await uni.showModal({
title: '提示',
content: '确认退出登录吗?'
}).catch(err => err)

if (succ && succ.confirm) {
this.updateAddress({})
this.updateUserInfo({})
this.updateToken('')
}
},
getUserInfo() {
var self = this;
uni.request({
method: "POST",
url: baseUrl + "/userInfo",
header: {
"token": uni.getStorageSync('token')
},
success: function(data) {
self.totalScore = data.data.data.totalScore
}
})
}
}
}
</script>
1
2
3
4
5
6
@PostMapping("/userInfo")
public ApiResult<User> userInfo(HttpServletRequest request) {
Long userId = (Long) request.getAttribute("userId");
User user = userMapper.selectByPrimaryKey(userId);
return ApiResult.resultWith(ResultCodeEnum.SUCCESS, user);
}

资源上传

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
<template>
<view>
<van-field clearable label="标题" left-icon="font" placeholder="请输入标题内容" :value="title"
@change="title = $event.mp.detail" />
<van-field type="textarea" clearable left-icon="comment" label="描述" placeholder="请输入描述内容" :value="describe"
@change="describe = $event.mp.detail" autosize />
<van-cell title="地点" :value="address" @click="chooseAddr" />
<van-cell title="时间" :value="date" @click="onDisplay" />
<van-calendar :show="show" :min-date="minDate" @close="onClose" @confirm="onConfirm" :show-confirm="false" />
<van-divider contentPosition="center">上传资源</van-divider>
<van-uploader :file-list="previewList" accept="media" multiple="true" @after-read="previewImg" max-count="9"
@delete="deleteImg" />
<van-button type="danger" @click="submit" block round icon="good-job">上传</van-button>

</view>
</template>

<script>
const app = getApp();
const baseUrl = app.globalData.baseUrl;
export default {
data() {
return {
minDate: new Date(2022, 0, 1).getTime(),
describe: '',
title: '',
date: '',
address: '',
addressDetail: '',
fileList: [],
previewList: [],
file: null,
show: false,
typeId: Number
};
},
methods: {
onLoad(options) {
this.typeId = options.typeId
},
chooseAddr() {
this.getAuthorizeInfo();
},
// 位置授权
getAuthorizeInfo() {
const that = this;
uni.authorize({
scope: 'scope.userLocation',
success() {
// 允许授权
that.getLocationInfo();
},
fail() {
// 拒绝授权
that.openConfirm();
console.log("你拒绝了授权,无法获得周边信息")
}
})
},
// 获取地理位置
getLocationInfo() {
const that = this;
uni.getLocation({
type: 'wgs84',
success(res) {
uni.chooseLocation({
latitude: res.latitude,
longitude: res.longitude,
success: function(data) {
that.address = data.name
that.addressDetail = data.address
}
})
}
});
},
// 再次获取授权。当用户第一次拒绝后再次请求授权
openConfirm() {
uni.showModal({
title: '请求授权当前位置',
content: '需要获取您的地理位置,请确认授权',
success: (res) => {
if (res.confirm) {
uni.openSetting(); // 打开地图权限设置
} else if (res.cancel) {
uni.showToast({
title: '你拒绝了授权,无法获得周边信息',
icon: 'none',
duration: 1000
})
}
}
});
},
onDisplay() {
this.show = true
},
onClose() {
this.show = false
},
formatDate(date) {
date = new Date(date);
return `${date.getYear()+1900}/${date.getMonth() + 1}/${date.getDate()}`;
},
onConfirm(event) {
this.show = false,
console.log(event)
this.date = this.formatDate(event.detail)
},
previewImg(e) {
const {
previewFile
} = e.detail
const filrList = e.detail.file
console.log(filrList)
for (const key in filrList) {
const element = filrList[key];
this.previewList.push({
// 相当于将previewFile所有的属性都放入
...previewFile,
url: element.url
})
}
},
deleteImg(event) {
console.log(event)
const {
index,
name
} = event.detail;
this.previewList.splice(index, 1);
},
submit() {
uni.showLoading({
title: "开始上传..."
})
let self = this
let length = self.previewList.length
if (length !== 0) {
uni.request({
method: "POST",
url: baseUrl + "/saveBasicInformation",
data: {
"title": self.title,
"describe": self.describe,
"date": self.date,
"address": self.address,
"addressDetail": self.addressDetail,
"typeId": self.typeId
},
header:{
"token": uni.getStorageSync('token')
},
success: function(data) {
for (let i = 0; i < length; i++) {
uni.uploadFile({
filePath: self.previewList[i].url,
url: baseUrl + "/uploadFile",
name: "previewList",
formData: {
"previewList": self.previewList[i].url,
"mediaBaseInfoId": data.data.data
},
header: {
"content-type": "multipart/form-data",
"token": uni.getStorageSync('token')
},
success: function() {
uni.showToast({
title: '上传成功',
success: function() {
setTimeout(function () {
uni.navigateBack();
}, 1500);
}
})
},
fail: function() {
uni.showToast({
title: '上传失败'
})
}
})
}
}
})
}
}
}
}
</script>

很简单的页面地点获取使用了wx.chooseLocation()方法获取当前地理位置,其他好像也没啥可说的,该模块的功能就是记录生活,将视频或者图片配上文字描述、地理位置和时间上传到服务器,根据上传的类型获得不同的积分,积分可用于之后的兑换模块

资源展示

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
<template>
<view class="event-list">
<!-- 循环 -->
<view v-for="(item,index) in imgList" :key="index">
<view class="event-link">
<view class="event-img">
<van-grid :column-num="item.mediaUrls.length>=3?3:item.mediaUrls.length" :border="false">
<van-grid-item v-for="(itm,inm) in item.mediaUrls" :key="inm" use-slot>
<image v-show="item.mediaUrls.length<2" mode="widthFix" style="width: 100%;" :src="itm.url"
@click="imgClick(itm.url,item.mediaUrls)"></image>
<image v-show="item.mediaUrls.length>=2" mode="aspectFill"
style="width: 100%; height: 200rpx;" :src="itm.url"
@click="imgClick(itm.url,item.mediaUrls)"></image>
</van-grid-item>
</van-grid>

</view>
<view class="event-content">
<view class="event-title">
<van-icon name="fire" />{{item.title}}
</view>
<view class="event-desc">
<van-icon name="comment-circle" />{{item.describe}}
</view>
<view class="event-box">
<view class="event-address">
<van-icon name="map-marked" />{{item.address+' | '}}{{item.addressDetail}}
</view>
<view class="event-time">
<van-icon name="underway" />{{item.date}}
</view>
</view>
</view>
</view>
</view>
<!-- 循环 -->
<van-dialog id="van-dialog" />
</view>
</template>

<script>
import Dialog from '../../wxcomponents/vant/dist/dialog/dialog';
const app = getApp();
const baseUrl = app.globalData.baseUrl;
import {
mapState
} from 'vuex'

export default {
data() {
return {
imgList: [],
page:1
}
},
computed: {
...mapState('m_user', ['token'])
},
onLoad() {
if (!this.token) {
uni.showLoading({
title: '请先登陆'
});
setTimeout(function() {
uni.switchTab({
url: '/pages/my/my'
})
}, 500);
} else {
this.getImgList()
}
},
methods: {
//上拉刷新事件
onReachBottom() {
if (this.status == 'nomore') {
return
}
this.page++;
this.getImgList();
},
getImgList() {
uni.showLoading({
title: "加载中……"
});
let self = this
uni.request({
method: "GET",
url: baseUrl + "/showMedia",
data: {
"page": self.page,
"pageSize": 10,
"mediaType": 0
},
header: {
"token": uni.getStorageSync('token')
},
success: function(data) {
uni.hideLoading();
self.imgList.push(...data.data.data)
}
})
},
imgClick(currenturl, mediaUrls) {
var imgSrcList = new Array();
for (let index in mediaUrls) {
imgSrcList.push(mediaUrls[index].url)
}
uni.previewImage({
current: currenturl,
urls: imgSrcList
})
},
saveImage(url) {
Dialog.confirm({
title: 'save',
message: '是否需要保存照片到本地',
})
.then(() => {
uni.showLoading({
title: '正在保存图片...'
});
uni.getImageInfo({
src: url,
success: function(res) {
const url = res.path
uni.saveImageToPhotosAlbum({
filePath: url,
success: function() {
uni.showToast({
icon: 'none',
mask: true,
title: '文件已保存', //保存路径
duration: 3000,
})
},
fail: function() {
uni.showToast({
icon: 'none',
mask: true,
title: '文件保存失败', //保存路径
duration: 3000,
})
}
});
},
complete: function() {
uni.hideLoading();
}
})
})
.catch(() => {

});
},
}
}
</script>

资源展示模块就是根据之前的上传图片或者影像进行在线查看或者播放,通过wx.saveVideoToPhotosAlbumwx.saveImageToPhotosAlbumapi进行本地保存

吃啥玩啥

这个模块是专门为我这种有选择困难症的人群准备的,技术没啥难点,加了个有趣的功能,同一个按钮连续点击三次时会播放我录制的语音,告诉自己别再挑了就这个吧,哈哈哈哈哈哈哈

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
<template>
<view>
<view class="container">
<h1 class="general title"></h1><b id="what">{{eatwhat}}</b>
<van-button type="warning" @click="eatsubmit" round>看天命</van-button>
</view>
<van-divider dashed />
<view class="container">
<h1 class="general title"></h1><b id="what">{{playwhat}}</b>
<van-button type="warning" @click="playsubmit" round>看天命</van-button>
</view>
<van-divider dashed />
<view class="container">
<h1 class="general title"></h1><b id="what">{{gowhere}}</b>
<van-button type="warning" @click="gosubmit" round>看天命</van-button>
</view>
</view>
</template>

<script>
var audio;
export default {
data() {
return {
eatwhat: '什么',
eatTime: 0,
playwhat: '什么',
playTime: 0,
gowhere: '哪儿',
goTime: 0,
foodList: [],
playList: [],
goList: []
};
},
onLoad: function(options) {
var _this = this;
audio = uni.createInnerAudioContext();
audio.onPlay(() => {
console.info('开始播放');
});
//监听播放过程,进度处理
audio.onTimeUpdate(() => {});
//播放结束
audio.onStop(() => {
console.info('播放结束');
});
//播放暂停
audio.onPause(() => {
console.info('播放暂停');
});
audio.src = 'http://115.28.105.227:8888/wxapplets/20220729_153926.m4a';
},
methods: {
eatsubmit() {
var self = this;
self.eatTime = self.eatTime + 1
if (self.eatTime > 3) {
self.playClick()
}
var r = Math.ceil(Math.random() * self.foodList.length)
self.eatwhat = self.foodList[r - 1];
},
playsubmit() {
var self = this;
self.playTime = self.playTime + 1
if (self.playTime > 3) {
self.playClick()
}
var r = Math.ceil(Math.random() * self.playList.length)
self.playwhat = self.playList[r - 1];
},
gosubmit() {
var self = this;
self.goTime = self.goTime + 1
if (self.goTime > 3) {
self.playClick()
}
var r = Math.ceil(Math.random() * self.goList.length)
self.gowhere = self.goList[r - 1];
},
//播放操作
playClick: function() {
audio.autoplay = true;
//判断是否是播放中
if (audio.paused) {
audio.play(); //播放
} else {
audio.pause(); //暂停
}
},
//关闭
stopClick: function() {
audio.stop();
},
}
}
</script>

AI聊天

这个模块对接了chatGPT接口,进行一个智能问答

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
<template>
<view>
<scroll-view scroll-with-animation scroll-y="true" style="width: 100%;">
<!-- 用来获取消息体高度 -->
<view id="okk" scroll-with-animation>
<!-- 消息 -->
<view class="flex-column-start" v-for="(x,i) in msgList" :key="i">
<!-- 用户消息 头像可选加入-->
<view v-if="x.my" class="flex justify-end padding-right one-show align-start padding-top">
<!-- <image v-if="!x.my" class="chat-img" src="../../static/..." mode="aspectFill" ></image> -->
<view class="flex justify-end" style="width: 400rpx;">
<view class="margin-left padding-chat bg-cyan" style="border-radius: 35rpx;">
<text style="word-break: break-all;">{{x.msg}}</text>
</view>
</view>
<!-- <image class="chat-img margin-left" src="../../static/..." mode="aspectFill" ></image> -->
</view>
<!-- 机器人消息 -->
<view v-if="!x.my" class="flex-row-start margin-left margin-top one-show">
<view class="chat-img flex-row-center">
<image style="height: 75rpx;width: 75rpx;" src="../../static/images/robt.png"
mode="aspectFit"></image>
</view>
<view class="flex" style="width: 500rpx;">
<view class="margin-left padding-chat flex-column-start"
style="border-radius: 35rpx;background-color: #f9f9f9;">
<text style="word-break: break-all;">{{x.msg}}</text>
</view>
</view>
</view>
</view>
<!-- loading是显示 -->
<view v-show="msgLoad" class="flex-row-start margin-left margin-top">
<view class="chat-img flex-row-center">
<image style="height: 75rpx;width: 75rpx;" src="../../static/image/robt.png" mode="aspectFit">
</image>
</view>
<view class="flex" style="width: 500rpx;">
<view class="margin-left padding-chat flex-column-start"
style="border-radius: 35rpx;background-color: #f9f9f9;">
<view class="cuIcon-loading turn-load" style="font-size: 35rpx;color: #3e9982;">

</view>
</view>
</view>
</view>
<!-- 防止消息底部被遮 -->
<view style="height: 130rpx;">

</view>
</view>

</scroll-view>

<!-- 底部导航栏 -->
<view class="flex-column-center" style="position: fixed;bottom:0px;width: 100%;">
<view class="bottom-dh-char flex-row-around" style="font-size: 55rpx;">
<!-- vue无法使用软键盘"发送" -->
<input v-model="msg" class="dh-input" type="text" style="background-color: #f0f0f0;" @confirm="sendMsg"
confirm-type="search" placeholder-class="my-neirong-sm" placeholder="用一句简短的话描述您的问题" />
<button @click="sendMsg" :disabled="msgLoad" class="btn bg-cyan round">发送</button>
</view>
</view>
</view>
</template>

<script>
const app = getApp();
const baseUrl = app.globalData.baseUrl;
export default {
onLoad() {
this.userId = new Date().getTime()
},
data() {
return {
msgLoad: false,
anData: {},
userId: "",
animationData: {},
showTow: false,
msgList: [{
my: false,
msg: "我是小🐟,请问有什么问题可以帮助您?"
}],
msgContent: "",
msg: ""
}
},
methods: {
sendMsg() {
// 消息为空不做任何操作
if (this.msg == "") {
return 0;
}
this.msgList.push({
"msg": this.msg,
"my": true
})
this.msgContent = this.msg
this.msgLoad = true
// 清除消息
this.msg = ""
let self = this
uni.request({
method: "POST",
url: baseUrl + "/talk",
data: {
"prompt": this.msgContent
},
header:{
"content-type": "application/x-www-form-urlencoded"
},
success: function(data) {
console.log(data.data.data)
let text = data.data.data
.replaceAll("openai:", "")
.replaceAll("openai:", "")
.replaceAll("OpenAi:", "")
.replaceAll("OpenAi:", "")
.replaceAll("OpenAI:", "")
.replaceAll("OpenAI:", "")
.replaceAll(/^\n|\n$/g, "")
console.log('text:'+text)
self.msgList.push({
"msg": text,
"my": false
})
self.msgContent += ("openai:" + self.msg + "\n")
self.msgLoad = false
}
})
// });
},
hideKey() {
uni.hideKeyboard()
},
}
}
</script>
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
@PostMapping("/talk")
public ApiResult<String> talk(HttpServletRequest request,String prompt) {
Map<String, String> headers = new HashMap<>();
headers.put("Content-Type", "application/json;charset=UTF-8");
JSONObject json = new JSONObject();
//选择模型
json.set("model", "text-davinci-003");
//添加我们需要输入的内容
json.set("prompt", prompt);
json.set("temperature", 0);
json.set("max_tokens", 2048);
json.set("top_p", 1);
json.set("frequency_penalty", 0.0);
json.set("presence_penalty", 0.6);
HttpResponse response = HttpRequest.post("https://api.openai.com/v1/completions")
.headerMap(headers, false)
.bearerAuth("token")
.body(String.valueOf(json))
.timeout(5 * 60 * 1000)
.execute();
String body = response.body();
JSON parse = JSONUtil.parse(body);
String reply = parse.getByPath("choices[0].text", String.class);
System.out.println(reply);
return ApiResult.resultWith(ResultCodeEnum.SUCCESS, reply);
}

后续模块还没有想好,有想法了继续写

后续

今早重新发布了一下之前的小程序发现头像和昵称获取有问题,所以查了一下资料,如下

23年3月1日,chatGPT彻底被墙,此前接口不用VPN代理无法使用了

赏个🍗吧
0%