调整了录音出现的一些状态,增加了重录按钮

master
limenglian 5 years ago
parent 63993fcf27
commit 24dfa47fce

@ -0,0 +1,22 @@
//app.js
App({
onLaunch: function () {
if (!wx.cloud) {
console.error('请使用 2.2.3 或以上的基础库以使用云能力')
} else {
wx.cloud.init({
// env 参数说明:
// env 参数决定接下来小程序发起的云开发调用wx.cloud.xxx会默认请求到哪个云环境的资源
// 此处请填入环境 ID, 环境 ID 可打开云控制台查看
// 如不填则使用默认环境(第一个创建的环境)
// env: 'my-env-id',
traceUser: true,
})
}
this.globalData = {
workPath:""
}
}
})

@ -0,0 +1,49 @@
{
"pages": [
"pages/index/index",
"pages/userConsole/userConsole",
"pages/storageConsole/storageConsole",
"pages/databaseGuide/databaseGuide",
"pages/addFunction/addFunction",
"pages/deployFunctions/deployFunctions",
"pages/chooseLib/chooseLib",
"pages/openapi/openapi",
"pages/openapi/serverapi/serverapi",
"pages/openapi/callback/callback",
"pages/openapi/cloudid/cloudid",
"pages/im/im",
"pages/im/room/room",
"pages/dub/dub",
"pages/mine/mine",
"pages/Dubbing/Dubbing",
"pages/previewWork/previewWork"
],
"tabBar": {
"color": "balck",
"selectedColor": "#6595e9",
"backgroundColor": "#FFFFFF",
"borderStyle": "black",
"list": [
{
"pagePath": "pages/dub/dub",
"text": "配音",
"iconPath": "tabIcon/tab_chatBox_default.png",
"selectedIconPath": "tabIcon/tab_chatBox_default.png"
},
{
"pagePath": "pages/mine/mine",
"text": "我的配音",
"iconPath": "tabIcon/tab_chatBox_default.png",
"selectedIconPath": "tabIcon/tab_chatBox_default.png"
}
]
},
"window": {
"backgroundColor": "#F6F6F6",
"backgroundTextStyle": "light",
"navigationBarBackgroundColor": "#F6F6F6",
"navigationBarTitleText": "配音吧",
"navigationBarTextStyle": "black"
},
"sitemapLocation": "sitemap.json"
}

@ -0,0 +1,156 @@
/**app.wxss**/
.container {
display: flex;
flex-direction: column;
align-items: center;
box-sizing: border-box;
}
button {
background: initial;
}
button:focus{
outline: 0;
}
button::after{
border: none;
}
page {
background: #f6f6f6;
display: flex;
flex-direction: column;
justify-content: flex-start;
}
.userinfo, .uploader, .tunnel {
margin-top: 40rpx;
height: 140rpx;
width: 100%;
background: #fff;
border: 1px solid rgba(0, 0, 0, 0.1);
border-left: none;
border-right: none;
display: flex;
flex-direction: row;
align-items: center;
transition: all 300ms ease;
}
.userinfo-avatar {
width: 100rpx;
height: 100rpx;
margin: 20rpx;
border-radius: 50%;
background-size: cover;
background-color: white;
}
.userinfo-avatar:after {
border: none;
}
.userinfo-nickname {
font-size: 32rpx;
color: #007aff;
background-color: white;
background-size: cover;
}
.userinfo-nickname::after {
border: none;
}
.uploader, .tunnel {
height: auto;
padding: 0 0 0 40rpx;
flex-direction: column;
align-items: flex-start;
box-sizing: border-box;
}
.uploader-text, .tunnel-text {
width: 100%;
line-height: 52px;
font-size: 34rpx;
color: #007aff;
}
.uploader-container {
width: 100%;
height: 400rpx;
padding: 20rpx 20rpx 20rpx 0;
display: flex;
align-content: center;
justify-content: center;
box-sizing: border-box;
border-top: 1px solid rgba(0, 0, 0, 0.1);
}
.uploader-image {
width: 100%;
height: 360rpx;
}
.tunnel {
padding: 0 0 0 40rpx;
}
.tunnel-text {
position: relative;
color: #222;
display: flex;
flex-direction: row;
align-content: center;
justify-content: space-between;
box-sizing: border-box;
border-top: 1px solid rgba(0, 0, 0, 0.1);
}
.tunnel-text:first-child {
border-top: none;
}
.tunnel-switch {
position: absolute;
right: 20rpx;
top: -2rpx;
}
.disable {
color: #888;
}
.service {
position: fixed;
right: 40rpx;
bottom: 40rpx;
width: 140rpx;
height: 140rpx;
border-radius: 50%;
background: linear-gradient(#007aff, #0063ce);
box-shadow: 0 5px 10px rgba(0, 0, 0, 0.3);
display: flex;
align-content: center;
justify-content: center;
transition: all 300ms ease;
}
.service-button {
position: absolute;
top: 40rpx;
}
.service:active {
box-shadow: none;
}
.request-text {
padding: 20rpx 0;
font-size: 24rpx;
line-height: 36rpx;
word-break: break-all;
}

@ -0,0 +1,336 @@
const FATAL_REBUILD_TOLERANCE = 10
const SETDATA_SCROLL_TO_BOTTOM = {
scrollTop: 100000,
scrollWithAnimation: true,
}
Component({
properties: {
envId: String,
collection: String,
groupId: String,
groupName: String,
userInfo: Object,
onGetUserInfo: {
type: Function,
},
getOpenID: {
type: Function,
},
},
data: {
chats: [],
textInputValue: '',
openId: '',
scrollTop: 0,
scrollToMessage: '',
hasKeyboard: false,
},
methods: {
onGetUserInfo(e) {
this.properties.onGetUserInfo(e)
},
getOpenID() {
return this.properties.getOpenID()
},
mergeCommonCriteria(criteria) {
return {
groupId: this.data.groupId,
...criteria,
}
},
async initRoom() {
this.try(async () => {
await this.initOpenID()
const { envId, collection } = this.properties
const db = this.db = wx.cloud.database({
env: envId,
})
const _ = db.command
const { data: initList } = await db.collection(collection).where(this.mergeCommonCriteria()).orderBy('sendTimeTS', 'desc').get()
console.log('init query chats', initList)
this.setData({
chats: initList.reverse(),
scrollTop: 10000,
})
this.initWatch(initList.length ? {
sendTimeTS: _.gt(initList[initList.length - 1].sendTimeTS),
} : {})
}, '初始化失败')
},
async initOpenID() {
return this.try(async () => {
const openId = await this.getOpenID()
this.setData({
openId,
})
}, '初始化 openId 失败')
},
async initWatch(criteria) {
this.try(() => {
const { collection } = this.properties
const db = this.db
const _ = db.command
console.warn(`开始监听`, criteria)
this.messageListener = db.collection(collection).where(this.mergeCommonCriteria(criteria)).watch({
onChange: this.onRealtimeMessageSnapshot.bind(this),
onError: e => {
if (!this.inited || this.fatalRebuildCount >= FATAL_REBUILD_TOLERANCE) {
this.showError(this.inited ? '监听错误,已断开' : '初始化监听失败', e, '重连', () => {
this.initWatch(this.data.chats.length ? {
sendTimeTS: _.gt(this.data.chats[this.data.chats.length - 1].sendTimeTS),
} : {})
})
} else {
this.initWatch(this.data.chats.length ? {
sendTimeTS: _.gt(this.data.chats[this.data.chats.length - 1].sendTimeTS),
} : {})
}
},
})
}, '初始化监听失败')
},
onRealtimeMessageSnapshot(snapshot) {
console.warn(`收到消息`, snapshot)
if (snapshot.type === 'init') {
this.setData({
chats: [
...this.data.chats,
...[...snapshot.docs].sort((x, y) => x.sendTimeTS - y.sendTimeTS),
],
})
this.scrollToBottom()
this.inited = true
} else {
let hasNewMessage = false
let hasOthersMessage = false
const chats = [...this.data.chats]
for (const docChange of snapshot.docChanges) {
switch (docChange.queueType) {
case 'enqueue': {
hasOthersMessage = docChange.doc._openid !== this.data.openId
const ind = chats.findIndex(chat => chat._id === docChange.doc._id)
if (ind > -1) {
if (chats[ind].msgType === 'image' && chats[ind].tempFilePath) {
chats.splice(ind, 1, {
...docChange.doc,
tempFilePath: chats[ind].tempFilePath,
})
} else chats.splice(ind, 1, docChange.doc)
} else {
hasNewMessage = true
chats.push(docChange.doc)
}
break
}
}
}
this.setData({
chats: chats.sort((x, y) => x.sendTimeTS - y.sendTimeTS),
})
if (hasOthersMessage || hasNewMessage) {
this.scrollToBottom()
}
}
},
async onConfirmSendText(e) {
this.try(async () => {
if (!e.detail.value) {
return
}
const { collection } = this.properties
const db = this.db
const _ = db.command
const doc = {
_id: `${Math.random()}_${Date.now()}`,
groupId: this.data.groupId,
avatar: this.data.userInfo.avatarUrl,
nickName: this.data.userInfo.nickName,
msgType: 'text',
textContent: e.detail.value,
sendTime: new Date(),
sendTimeTS: Date.now(), // fallback
}
this.setData({
textInputValue: '',
chats: [
...this.data.chats,
{
...doc,
_openid: this.data.openId,
writeStatus: 'pending',
},
],
})
this.scrollToBottom(true)
await db.collection(collection).add({
data: doc,
})
this.setData({
chats: this.data.chats.map(chat => {
if (chat._id === doc._id) {
return {
...chat,
writeStatus: 'written',
}
} else return chat
}),
})
}, '发送文字失败')
},
async onChooseImage(e) {
wx.chooseImage({
count: 1,
sourceType: ['album', 'camera'],
success: async res => {
const { envId, collection } = this.properties
const doc = {
_id: `${Math.random()}_${Date.now()}`,
groupId: this.data.groupId,
avatar: this.data.userInfo.avatarUrl,
nickName: this.data.userInfo.nickName,
msgType: 'image',
sendTime: new Date(),
sendTimeTS: Date.now(), // fallback
}
this.setData({
chats: [
...this.data.chats,
{
...doc,
_openid: this.data.openId,
tempFilePath: res.tempFilePaths[0],
writeStatus: 0,
},
]
})
this.scrollToBottom(true)
const uploadTask = wx.cloud.uploadFile({
cloudPath: `${this.data.openId}/${Math.random()}_${Date.now()}.${res.tempFilePaths[0].match(/\.(\w+)$/)[1]}`,
filePath: res.tempFilePaths[0],
config: {
env: envId,
},
success: res => {
this.try(async () => {
await this.db.collection(collection).add({
data: {
...doc,
imgFileID: res.fileID,
},
})
}, '发送图片失败')
},
fail: e => {
this.showError('发送图片失败', e)
},
})
uploadTask.onProgressUpdate(({ progress }) => {
this.setData({
chats: this.data.chats.map(chat => {
if (chat._id === doc._id) {
return {
...chat,
writeStatus: progress,
}
} else return chat
})
})
})
},
})
},
onMessageImageTap(e) {
wx.previewImage({
urls: [e.target.dataset.fileid],
})
},
scrollToBottom(force) {
if (force) {
console.log('force scroll to bottom')
this.setData(SETDATA_SCROLL_TO_BOTTOM)
return
}
this.createSelectorQuery().select('.body').boundingClientRect(bodyRect => {
this.createSelectorQuery().select(`.body`).scrollOffset(scroll => {
if (scroll.scrollTop + bodyRect.height * 3 > scroll.scrollHeight) {
console.log('should scroll to bottom')
this.setData(SETDATA_SCROLL_TO_BOTTOM)
}
}).exec()
}).exec()
},
async onScrollToUpper() {
if (this.db && this.data.chats.length) {
const { collection } = this.properties
const _ = this.db.command
const { data } = await this.db.collection(collection).where(this.mergeCommonCriteria({
sendTimeTS: _.lt(this.data.chats[0].sendTimeTS),
})).orderBy('sendTimeTS', 'desc').get()
this.data.chats.unshift(...data.reverse())
this.setData({
chats: this.data.chats,
scrollToMessage: `item-${data.length}`,
scrollWithAnimation: false,
})
}
},
async try(fn, title) {
try {
await fn()
} catch (e) {
this.showError(title, e)
}
},
showError(title, content, confirmText, confirmCallback) {
console.error(title, content)
wx.showModal({
title,
content: content.toString(),
showCancel: confirmText ? true : false,
confirmText,
success: res => {
res.confirm && confirmCallback()
},
})
},
},
ready() {
global.chatroom = this
this.initRoom()
this.fatalRebuildCount = 0
},
})

@ -0,0 +1,4 @@
{
"component": true,
"usingComponents": {}
}

@ -0,0 +1,85 @@
<view class="chatroom">
<view class="header">
<!-- display number of people in the room -->
<view class="left"></view>
<!-- room name -->
<view class="middle">{{groupName}}</view>
<!-- reserved -->
<view class="right"></view>
</view>
<!-- chats -->
<scroll-view
class="body"
scroll-y
scroll-with-animation="{{scrollWithAnimation}}"
scroll-top="{{scrollTop}}"
scroll-into-view="{{scrollToMessage}}"
bindscrolltoupper="onScrollToUpper"
>
<view
wx:for="{{chats}}"
wx:key="{{item._id}}"
id="item-{{index}}"
class="message {{openId == item._openid ? 'message__self' : ''}}"
>
<image
class="avatar"
src="{{item.avatar}}"
mode="scaleToFill"
></image>
<view class="main">
<view class="nickname">{{item.nickName}}</view>
<block wx:if="{{item.msgType === 'image'}}">
<view class="image-wrapper">
<view class="loading" wx:if="{{item.writeStatus > -1}}">{{item.writeStatus}}%</view>
<image
src="{{item.tempFilePath || item.imgFileID}}"
data-fileid="{{item.tempFilePath || item.imgFileID}}"
class="image-content"
style="{{item.imgStyle}}"
mode="scallToFill"
bindtap="onMessageImageTap"></image>
</view>
</block>
<block wx:else>
<view class="text-wrapper">
<view class="loading" wx:if="{{item.writeStatus === 'pending'}}">···</view>
<view class="text-content">{{item.textContent}}</view>
</view>
</block>
</view>
</view>
</scroll-view>
<!-- message sender -->
<view class="footer">
<view class="message-sender" wx:if="{{userInfo}}">
<input
class="text-input"
type="text"
confirm-type="send"
bindconfirm="onConfirmSendText"
cursor-spacing="20"
value="{{textInputValue}}"
></input>
<image
src="./photo.png"
class="btn-send-image"
mode="scaleToFill"
bindtap="onChooseImage"
></image>
</view>
<view class="message-sender" wx:if="{{!userInfo}}">
<button
open-type="getUserInfo"
bindgetuserinfo="onGetUserInfo"
class="userinfo"
>请先登录后参与聊天</button>
</view>
</view>
</view>

@ -0,0 +1,161 @@
.chatroom {
width: 100%;
height: 100%;
display: flex;
flex-direction: column;
}
.chatroom .header {
flex-basis: fit-content;
display: flex;
flex-direction: row;
border-bottom: 1px solid #ddd;
padding: 20rpx 0 30rpx;
font-size: 30rpx;
/* background: rgb(34, 187, 47);
color: rgba(255, 255, 255, 1) */
/* font-family: 'Microsoft YaHei' */
}
.chatroom .header .left {
flex: 1;
}
.chatroom .header .middle {
flex: 2;
text-align: center;
}
.chatroom .header .right {
flex: 1;
}
.chatroom .body {
flex: 2;
display: flex;
flex-direction: column;
background: rgb(237,237,237);
padding-bottom: 16rpx;
}
.body .message {
display: flex;
flex-direction: row;
position: relative;
margin: 12rpx 0;
}
.body .message.message__self {
flex-direction: row-reverse;
}
.body .message .avatar {
position: relative;
top: 5rpx;
width: 60rpx;
height: 60rpx;
border-radius: 5rpx;
margin: 15rpx;
}
.body .message .main {
flex: 1;
display: flex;
flex-direction: column;
align-items: flex-start;
}
.body .message.message__self .main {
align-items: flex-end;
}
.body .message .nickname {
font-size: 24rpx;
color: #444;
}
.body .message .text-content {
border: 1px solid transparent;
border-radius: 3px;
background-color: #fff;
margin: 2px 0 0 0;
padding: 4px 10px;
font-size: 30rpx;
display: inline-block;
}
.body .message.message__self .text-content {
background-color: paleturquoise;
}
.body .message .text-wrapper {
display: flex;
flex-direction: row;
align-items: center;
max-width: 80%;
}
.body .message.message__self .text-wrapper .loading{
font-size: 16rpx;
margin-right: 18rpx;
}
.body .message .image-wrapper {
display: flex;
flex-direction: row;
align-items: center;
}
.body .message .image-content {
max-width: 240rpx;
max-height: 240rpx;
}
.body .message.message__self .image-wrapper .loading {
font-size: 20rpx;
margin-right: 18rpx;
}
.chatroom .footer {
flex-basis: fit-content;
display: flex;
flex-direction: row;
border-top: 1px solid #ddd;
font-size: 10rpx;
padding: 20rpx 30rpx;
background: rgb(246,246,246);
}
.chatroom .footer .message-sender {
flex: 1;
display: flex;
flex-direction: row;
}
.message-sender .text-input {
flex: 1;
font-size: 16px;
border: 1px solid transparent;
border-radius: 5px;
padding: 3px 6px;
margin: 0 10px 0 5px;
background: #fff;
}
.message-sender .btn-send-image {
width: 50rpx;
height: 50rpx;
align-self: center;
}
button {
font-size: 30rpx;
}
button.userinfo {
background: darkturquoise;
color: aliceblue;
padding: 0 100rpx;
border: 1px solid #ddd;
border-radius: 20px;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 244 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 206 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 108 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 143 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 139 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

@ -0,0 +1,140 @@
// miniprogram/pages/Dubbing/Dubbing.js
Page({
/**
* 页面的初始数据
*/
data: {
isSpeaking: false,//是否正在说话
voices: [],//音频数组:
muted:false
},
/**
* 生命周期函数--监听页面加载
*/
onLoad: function (options) {
// this.videoContext = wx.createVideoContext('myVideo');
},
/**
* 生命周期函数--监听页面初次渲染完成
*/
onReady: function () {
this.videoContext = wx.createVideoContext('myVideo');
},
/**
* 生命周期函数--监听页面显示
*/
onShow: function () {
},
/**
* 生命周期函数--监听页面隐藏
*/
onHide: function () {
},
/**
* 生命周期函数--监听页面卸载
*/
onUnload: function () {
},
/**
* 页面相关事件处理函数--监听用户下拉动作
*/
onPullDownRefresh: function () {
},
/**
* 页面上拉触底事件的处理函数
*/
onReachBottom: function () {
},
/**
* 用户点击右上角分享
*/
onShareAppMessage: function () {
},
//预览素材
playingFodder:function(){
this.setData({
muted:false
})
this.videoContext.play();
},
// 开始录音,
startDub: function () {
this.videoContext.seek(0);
this.videoContext.play();
//speaking.call(this);
this.setData({
isSpeaking:true,
muted: true,
})
wx.startRecord({
success:function(res){
var tempFilepath=res.tempFilePath;
wx.saveFile({
tempFilePath: tempFilepath,
success:function(res){
var savedFilepath=res.savedFilePath;
getApp().globalData.workPath = savedFilepath;
// this.setData({
// wfilePath: savedFilePath
// });
console.log(getApp().globalData.workPath);
},
}),
wx.showToast({
title: '录音成功',
icon:'success',
duration:200
})
},
fail:function(res){
wx.showModal({
title: '提示',
content: '录音出错'
})
},
});
},
funended: function () {
console.log('录音结束');
wx.stopRecord();// 结束录音
wx.navigateTo({//视频播放完成自动跳转到预览页面
url: '../previewWork/previewWork',
})
},
//重新录音
reDub:function(){
this.startDub();
},
//结束录音
endDub:function() {
console.log('录音结束');
this.videoContext.stop();
wx.stopRecord();
wx.navigateTo({
url: '../previewWork/previewWork',
})
},
})

@ -0,0 +1,3 @@
{
"usingComponents": {}
}

@ -0,0 +1,12 @@
<!--miniprogram/pages/Dubbing/Dubbing.wxml-->
<view>
<video id="myVideo" src="cloud://dunning-bar-enr-3e46z.6475-dunning-bar-enr-3e46z-1300499016/video/video_1.mp4"
muted ="{{muted}}" bindended="funended" controls ="{{false}}" show-play-btn ="{{false}}"show-fullscreen-btn = "{{false}}" show-center-play-btn="{{false}}" style="width: 300px; height: 200px;"></video>
</view>
<view>
<button bindtap="playingFodder">预览素材</button>
<button bindtap="startDub">开始录音</button>
<button bindtap="reDub">重新录制</button>
<button bindtap="endDub">完成录音</button>
</view>

@ -0,0 +1 @@
/* miniprogram/pages/Dubbing/Dubbing.wxss */

@ -0,0 +1,60 @@
// pages/addFunction/addFunction.js
const code = `// 云函数入口函数
exports.main = (event, context) => {
console.log(event)
console.log(context)
return {
sum: event.a + event.b
}
}`
Page({
data: {
result: '',
canIUseClipboard: wx.canIUse('setClipboardData'),
},
onLoad: function (options) {
},
copyCode: function() {
wx.setClipboardData({
data: code,
success: function () {
wx.showToast({
title: '复制成功',
})
}
})
},
testFunction() {
wx.cloud.callFunction({
name: 'sum',
data: {
a: 1,
b: 2
},
success: res => {
wx.showToast({
title: '调用成功',
})
this.setData({
result: JSON.stringify(res.result)
})
},
fail: err => {
wx.showToast({
icon: 'none',
title: '调用失败',
})
console.error('[云函数] [sum] 调用失败:', err)
}
})
},
})

@ -0,0 +1,4 @@
{
"navigationBarTitleText": "云函数指引",
"usingComponents": {}
}

@ -0,0 +1,29 @@
<!--pages/addFunction/addFunction.wxml-->
<view class="container">
<view class="list">
<view class="list-item" bindtap="testFunction">
<text>测试云函数</text>
</view>
<view class="list-item">
<text class="request-text">期望输出:{"sum":3}</text>
</view>
<view class="list-item" wx:if="{{result}}">
<text class="request-text">调用结果:{{result}}</text>
</view>
</view>
<view class="guide">
<text class="headline">新增云函数</text>
<text class="p">1. 在云函数根目录 cloudfunctions 上右键选择新建云函数,命名为 sum</text>
<text class="p">2. 在创建的 cloudfunctions/sum/index.js 文件中添加如下代码</text>
<image class="image1" src="../../images/code-func-sum.png" mode="aspectFit"></image>
<button class="copyBtn" wx:if="{{canIUseClipboard}}" bindtap="copyCode">复制代码</button>
<text class="p">3. 在 cloudfunctions/sum 目录上右键上传并部署</text>
<text class="p">4. 点击测试云函数测试</text>
<text class="p">5. 打开云开发云函数管理页,选择 sum 云函数</text>
<text class="p">6. 查看 sum 的调用日志</text>
<text class="p">进阶:可在云函数中使用 wx-server-sdk 操作数据库,文件存储和调用其他云函数,详见文档</text>
</view>
</view>

@ -0,0 +1,3 @@
/* pages/addFunction/addFunction.wxss */
@import "../../style/guide.wxss";

@ -0,0 +1,66 @@
// pages/chooseLib/chooseLib.js
Page({
/**
* 页面的初始数据
*/
data: {
},
/**
* 生命周期函数--监听页面加载
*/
onLoad: function (options) {
},
/**
* 生命周期函数--监听页面初次渲染完成
*/
onReady: function () {
},
/**
* 生命周期函数--监听页面显示
*/
onShow: function () {
},
/**
* 生命周期函数--监听页面隐藏
*/
onHide: function () {
},
/**
* 生命周期函数--监听页面卸载
*/
onUnload: function () {
},
/**
* 页面相关事件处理函数--监听用户下拉动作
*/
onPullDownRefresh: function () {
},
/**
* 页面上拉触底事件的处理函数
*/
onReachBottom: function () {
},
/**
* 用户点击右上角分享
*/
onShareAppMessage: function () {
}
})

@ -0,0 +1,4 @@
{
"navigationBarTitleText": "选择基础库",
"usingComponents": {}
}

@ -0,0 +1,14 @@
<!--pages/chooseLib/chooseLib.wxml-->
<view class="container">
<view class="list">
<view class="list-item">
<text class="black">初始化失败</text>
</view>
<view class="list-item">
<text class="request-text">请使用 2.2.3 或以上的基础库以使用云能力</text>
</view>
</view>
</view>

@ -0,0 +1,7 @@
/* pages/chooseLib/chooseLib.wxss */
@import "../../style/guide.wxss";
.black {
color: black;
}

@ -0,0 +1,193 @@
// pages/databaseGuide/databaseGuide.js
const app = getApp()
Page({
data: {
step: 1,
counterId: '',
openid: '',
count: null,
queryResult: '',
},
onLoad: function (options) {
if (app.globalData.openid) {
this.setData({
openid: app.globalData.openid
})
}
},
onAdd: function () {
// const db = wx.cloud.database()
// db.collection('counters').add({
// data: {
// count: 1
// },
// success: res => {
// // 在返回结果中会包含新创建的记录的 _id
// this.setData({
// counterId: res._id,
// count: 1
// })
// wx.showToast({
// title: '新增记录成功',
// })
// console.log('[数据库] [新增记录] 成功,记录 _id: ', res._id)
// },
// fail: err => {
// wx.showToast({
// icon: 'none',
// title: '新增记录失败'
// })
// console.error('[数据库] [新增记录] 失败:', err)
// }
// })
},
onQuery: function() {
// const db = wx.cloud.database()
// // 查询当前用户所有的 counters
// db.collection('counters').where({
// _openid: this.data.openid
// }).get({
// success: res => {
// this.setData({
// queryResult: JSON.stringify(res.data, null, 2)
// })
// console.log('[数据库] [查询记录] 成功: ', res)
// },
// fail: err => {
// wx.showToast({
// icon: 'none',
// title: '查询记录失败'
// })
// console.error('[数据库] [查询记录] 失败:', err)
// }
// })
},
onCounterInc: function() {
// const db = wx.cloud.database()
// const newCount = this.data.count + 1
// db.collection('counters').doc(this.data.counterId).update({
// data: {
// count: newCount
// },
// success: res => {
// this.setData({
// count: newCount
// })
// },
// fail: err => {
// icon: 'none',
// console.error('[数据库] [更新记录] 失败:', err)
// }
// })
},
onCounterDec: function() {
// const db = wx.cloud.database()
// const newCount = this.data.count - 1
// db.collection('counters').doc(this.data.counterId).update({
// data: {
// count: newCount
// },
// success: res => {
// this.setData({
// count: newCount
// })
// },
// fail: err => {
// icon: 'none',
// console.error('[数据库] [更新记录] 失败:', err)
// }
// })
},
onRemove: function() {
// if (this.data.counterId) {
// const db = wx.cloud.database()
// db.collection('counters').doc(this.data.counterId).remove({
// success: res => {
// wx.showToast({
// title: '删除成功',
// })
// this.setData({
// counterId: '',
// count: null,
// })
// },
// fail: err => {
// wx.showToast({
// icon: 'none',
// title: '删除失败',
// })
// console.error('[数据库] [删除记录] 失败:', err)
// }
// })
// } else {
// wx.showToast({
// title: '无记录可删,请见创建一个记录',
// })
// }
},
nextStep: function () {
// 在第一步,需检查是否有 openid如无需获取
if (this.data.step === 1 && !this.data.openid) {
wx.cloud.callFunction({
name: 'login',
data: {},
success: res => {
app.globalData.openid = res.result.openid
this.setData({
step: 2,
openid: res.result.openid
})
},
fail: err => {
wx.showToast({
icon: 'none',
title: '获取 openid 失败,请检查是否有部署 login 云函数',
})
console.log('[云函数] [login] 获取 openid 失败,请检查是否有部署云函数,错误信息:', err)
}
})
} else {
const callback = this.data.step !== 6 ? function() {} : function() {
console.group('数据库文档')
console.log('https://developers.weixin.qq.com/miniprogram/dev/wxcloud/guide/database.html')
console.groupEnd()
}
this.setData({
step: this.data.step + 1
}, callback)
}
},
prevStep: function () {
this.setData({
step: this.data.step - 1
})
},
goHome: function() {
const pages = getCurrentPages()
if (pages.length === 2) {
wx.navigateBack()
} else if (pages.length === 1) {
wx.redirectTo({
url: '../index/index',
})
} else {
wx.reLaunch({
url: '../index/index',
})
}
}
})

@ -0,0 +1,4 @@
{
"navigationBarTitleText": "数据库指引",
"usingComponents": {}
}

@ -0,0 +1,134 @@
<!--pages/databaseGuide/databaseGuide.wxml-->
<view class="container">
<!-- 导航 -->
<view class="list">
<view class="list-item">
<text class="request-text">数据库指引</text>
</view>
<view class="list-item">
<text class="request-text" wx:for="{{7}}" style="color: {{step === index + 1 ? 'red': 'black'}}">{{index + 1}}</text>
</view>
<view class="list-item" wx:if="{{openid}}">
<text class="request-text">openid{{openid}}</text>
</view>
<view class="list-item" wx:if="{{counterId}}">
<text class="request-text">当前记录 ID{{counterId}}</text>
</view>
</view>
<!-- 快速操作数据库指引 -->
<!-- 简介 -->
<view class="guide" wx:if="{{step === 1}}">
<text class="headline">示例介绍</text>
<text class="p">1. 以计数器为例,在此演示如何操作数据库</text>
<text class="p">2. 数据库操作大多需要用户 openid需先配置好 login 云函数,如已配置好,点击下一步,获取用户 openid 并开始我们的指引</text>
<div class="nav">
<button class="next" size="mini" type="default" bindtap="nextStep">下一步</button>
</div>
</view>
<!-- 新建集合 -->
<view class="guide" wx:if="{{step === 2}}">
<text class="headline">新建集合</text>
<text class="p">1. 打开云开发控制台,进入到数据库管理页</text>
<image class="image1" src="../../images/console-entrance.png" mode="aspectFit"></image>
<text class="p">2. 选择添加集合,集合名为 counters</text>
<image class="flat-image" src="../../images/create-collection.png" mode="aspectFit"></image>
<text class="p">3. 可以看到 counters 集合出现在左侧集合列表中</text>
<text class="p">注:集合必须在云开发控制台中创建</text>
<div class="nav">
<button class="prev" size="mini" type="default" bindtap="prevStep">上一步</button>
<button class="next" size="mini" type="default" bindtap="nextStep">下一步</button>
</div>
</view>
<!-- 新增记录 -->
<view class="guide" wx:if="{{step === 3}}">
<text class="headline">新增记录</text>
<text class="p">1. 打开 pages/databaseGuide/databaseGuide.js 文件,定位到 onAdd 方法</text>
<text class="p">2. 把注释掉的代码解除注释</text>
<image class="code-image" src="../../images/code-db-onAdd.png" mode="aspectFit"></image>
<text class="p">3. onAdd 方法会往 counters 集合新增一个记录,新增如下格式的一个 JSON 记录</text>
<text class="code">
{
"_id": "数据库自动生成记录 ID 字段",
"_openid": "数据库自动插入记录创建者的 openid",
"count": 1
}
</text>
<text class="p">4. 点击按钮</text>
<button size="mini" type="default" bindtap="onAdd">新增记录</button>
<text class="p" wx:if="{{counterId}}">新增的记录 _id 为:{{counterId}}</text>
<text class="p">5. 在云开发 -> 数据库 -> counters 集合中可以看到新增的记录</text>
<div class="nav">
<button class="prev" size="mini" type="default" bindtap="prevStep">上一步</button>
<button class="next" size="mini" type="default" bindtap="nextStep" wx:if="{{counterId}}">下一步</button>
</div>
</view>
<!-- 查询记录 -->
<view class="guide" wx:if="{{step === 4}}">
<text class="headline">查询记录</text>
<text class="p">1. 打开 pages/databaseGuide/databaseGuide.js 文件,定位到 onQuery 方法</text>
<text class="p">2. 把注释掉的代码解除注释onQuery 方法会在下方按钮被点击时触发</text>
<image class="code-image" src="../../images/code-db-onQuery.png" mode="aspectFit"></image>
<text class="p">3. 点击按钮</text>
<button size="mini" type="default" bindtap="onQuery">查询记录</button>
<text class="code" wx:if="{{queryResult}}">{{queryResult}}</text>
<div class="nav">
<button class="prev" size="mini" type="default" bindtap="prevStep">上一步</button>
<button class="next" size="mini" type="default" bindtap="nextStep">下一步</button>
</div>
</view>
<!-- 更新记录 -->
<view class="guide" wx:if="{{step === 5}}">
<text class="headline">更新记录</text>
<text class="p">1. 打开 pages/databaseGuide/databaseGuide.js 文件,定位到 onCounterInc 和 onCounterDec 方法</text>
<text class="p">2. 把注释掉的代码解除注释</text>
<image class="code-image" src="../../images/code-db-inc-dec.png" mode="aspectFit"></image>
<text class="p">3. 点击下方按钮更新计数器</text>
<div class="counter">
<button class="minus" size="mini" type="default" bindtap="onCounterDec">-</button>
<text class="p">{{count}}</text>
<button class="plus" size="mini" type="default" bindtap="onCounterInc">+</button>
</div>
<div class="nav">
<button class="prev" size="mini" type="default" bindtap="prevStep">上一步</button>
<button class="next" size="mini" type="default" bindtap="nextStep">下一步</button>
</div>
</view>
<!-- 删除记录 -->
<view class="guide" wx:if="{{step === 6}}">
<text class="headline">删除记录</text>
<text class="p">1. 打开 pages/databaseGuide/databaseGuide.js 文件,定位到 onRemove 方法</text>
<text class="p">2. 把注释掉的代码解除注释</text>
<image class="code-image" src="../../images/code-db-onRemove.png" mode="aspectFit"></image>
<text class="p">3. 点击下方按钮删除计数器</text>
<button size="mini" type="default" bindtap="onRemove">删除记录</button>
<div class="nav">
<button class="prev" size="mini" type="default" bindtap="prevStep" wx:if="{{counterId}}">上一步</button>
<button class="next" size="mini" type="default" bindtap="nextStep">下一步</button>
</div>
</view>
<!-- 结语 -->
<view class="guide" wx:if="{{step === 7}}">
<text class="headline">完成指引 !</text>
<text class="p">恭喜你,至此已完成数据库操作入门基础,可以点击调试器中的链接,查看详尽的数据库文档</text>
<div class="nav">
<button class="prev" size="mini" type="default" bindtap="prevStep">上一步</button>
<button class="next" size="mini" type="default" bindtap="goHome">回到首页</button>
</div>
</view>
</view>

@ -0,0 +1,10 @@
/* pages/databaseGuide/databaseGuide.wxss */
@import "../../style/guide.wxss";
.guide .counter {
margin-top: 50rpx;
display: flex;
flex-direction: row;
align-content: space-between;
}

@ -0,0 +1,66 @@
// pages/deployFunctions/deployFunctions.js
Page({
/**
* 页面的初始数据
*/
data: {
},
/**
* 生命周期函数--监听页面加载
*/
onLoad: function (options) {
},
/**
* 生命周期函数--监听页面初次渲染完成
*/
onReady: function () {
},
/**
* 生命周期函数--监听页面显示
*/
onShow: function () {
},
/**
* 生命周期函数--监听页面隐藏
*/
onHide: function () {
},
/**
* 生命周期函数--监听页面卸载
*/
onUnload: function () {
},
/**
* 页面相关事件处理函数--监听用户下拉动作
*/
onPullDownRefresh: function () {
},
/**
* 页面上拉触底事件的处理函数
*/
onReachBottom: function () {
},
/**
* 用户点击右上角分享
*/
onShareAppMessage: function () {
}
})

@ -0,0 +1,4 @@
{
"navigationBarTitleText": "部署云函数",
"usingComponents": {}
}

@ -0,0 +1,21 @@
<!--pages/deployFunctions/deployFunctions.wxml-->
<view class="container">
<view class="list">
<view class="list-item">
<text class="black">调用失败</text>
</view>
<view class="list-item">
<text class="request-text">请检查 login 云函数是否已部署</text>
</view>
</view>
<view class="guide">
<text class="headline">部署 login 云函数</text>
<text class="p">1. 确保已通过工具栏云开发入口开通云开发</text>
<text class="p">2. 在 cloudfunctions/login 目录上右键上传并部署</text>
<text class="p">3. 回到首页,重新点击获取 openid</text>
</view>
</view>

@ -0,0 +1,7 @@
/* pages/deployFunctions/deployFunctions.wxss */
@import "../../style/guide.wxss";
.black {
color: black;
}

@ -0,0 +1,70 @@
// miniprogram/pages/dub/dub.js
Page({
/**
* 页面的初始数据
*/
data: {
},
/**
* 生命周期函数--监听页面加载
*/
onLoad: function (options) {
},
bindViewDub(){
wx.navigateTo({
url:'../Dubbing/Dubbing'
})
},
/**
* 生命周期函数--监听页面初次渲染完成
*/
onReady: function () {
},
/**
* 生命周期函数--监听页面显示
*/
onShow: function () {
},
/**
* 生命周期函数--监听页面隐藏
*/
onHide: function () {
},
/**
* 生命周期函数--监听页面卸载
*/
onUnload: function () {
},
/**
* 页面相关事件处理函数--监听用户下拉动作
*/
onPullDownRefresh: function () {
},
/**
* 页面上拉触底事件的处理函数
*/
onReachBottom: function () {
},
/**
* 用户点击右上角分享
*/
onShareAppMessage: function () {
}
})

@ -0,0 +1,3 @@
{
"usingComponents": {}
}

@ -0,0 +1,11 @@
<!--miniprogram/pages/dub/dub.wxml-->
<view>
<text style="font-weight:bold;font-size:20px;padding-left:10px">配音素材栏</text>
</view>
<view class="container">
<view class="divLine"></view>
</view>
<view bindtap="bindViewDub">
<image src="./workPic.png" style="width: 150px; height: 100px;"></image>
</view>
<view style="flex-wrapwrap;font-style:italic;padding-left:40px">我不叫喂!</view>

@ -0,0 +1,6 @@
/* miniprogram/pages/dub/dub.wxss */
.divLine{
background: #E0E3DA;
width: 100%;
height: 5rpx;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 277 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

@ -0,0 +1,18 @@
const app = getApp()
Page({
data: {
},
onLoad: function (options) {
if (app.globalData.openid) {
this.setData({
openid: app.globalData.openid
})
}
console.group('数据库"实时数据推送"文档')
console.log('https://developers.weixin.qq.com/miniprogram/dev/wxcloud/guide/database/realtime.html')
console.groupEnd()
},
})

@ -0,0 +1,4 @@
{
"navigationBarTitleText": "数据库指引",
"usingComponents": {}
}

@ -0,0 +1,21 @@
<view class="container">
<!-- 简介 -->
<view class="guide">
<text class="headline">即时通信 demo 介绍</text>
<text class="p">本 demo 以《聊天室》为例,在此演示如何使用数据库《实时数据推送》能力</text>
<text class="p">1. 确保正在使用基础库 2.8.1</text>
<text class="p">2. 打开云开发控制台,进入到数据库管理页</text>
<text class="p">3. 选择添加集合,集合名设置为 chatroom</text>
<text class="p">4. 将集合设置为所有人可读</text>
<text class="p">5. 确保IDE增强编译已开启如无到工具详情页中开启</text>
<text class="p">6. 点击下方按钮进入聊天室!</text>
<text class="p">注1可使用菜单栏-工具)多账号调试的功能在工具中模拟多账号登录调试</text>
<text class="p">注2实时数据推送的文档链接已在调试器中打印可打开查看</text>
</view>
<view class="uploader">
<navigator url="./room/room" open-type="navigate" class="uploader-text">
<text>进入聊天室</text>
</navigator>
</view>
</view>

@ -0,0 +1,10 @@
/* pages/databaseGuide/databaseGuide.wxss */
@import "../../style/guide.wxss";
.guide .counter {
margin-top: 50rpx;
display: flex;
flex-direction: row;
align-content: space-between;
}

@ -0,0 +1,88 @@
//index.js
const app = getApp()
Page({
data: {
avatarUrl: './user-unlogin.png',
userInfo: null,
logged: false,
takeSession: false,
requestResult: '',
chatRoomEnvId: 'release-f8415a',
chatRoomCollection: 'kecun',
chatRoomGroupId: 'tit-bricker',
chatRoomGroupName: '深夜话题',
// functions for used in chatroom components
onGetUserInfo: null,
getOpenID: null,
},
onLoad: function() {
// 获取用户信息
wx.getSetting({
success: res => {
if (res.authSetting['scope.userInfo']) {
// 已经授权,可以直接调用 getUserInfo 获取头像昵称,不会弹框
wx.getUserInfo({
success: res => {
this.setData({
avatarUrl: res.userInfo.avatarUrl,
userInfo: res.userInfo
})
}
})
}
}
})
this.setData({
onGetUserInfo: this.onGetUserInfo,
getOpenID: this.getOpenID,
})
wx.getSystemInfo({
success: res => {
console.log('system info', res)
if (res.safeArea) {
const { top, bottom } = res.safeArea
this.setData({
containerStyle: `padding-top: ${(/ios/i.test(res.system) ? 10 : 20) + top}px; padding-bottom: ${20 + res.windowHeight - bottom}px`,
})
}
},
})
},
getOpenID: async function() {
if (this.openid) {
return this.openid
}
const { result } = await wx.cloud.callFunction({
name: 'login',
config: {
env: 'release-f8415a',
},
})
return result.openid
},
onGetUserInfo: function(e) {
if (!this.logged && e.detail.userInfo) {
this.setData({
logged: true,
avatarUrl: e.detail.userInfo.avatarUrl,
userInfo: e.detail.userInfo
})
}
},
onShareAppMessage() {
return {
title: '深夜话题',
path: '/pages/index/index',
}
},
})

@ -0,0 +1,84 @@
const app = getApp()
Page({
data: {
avatarUrl: './user-unlogin.png',
userInfo: null,
logged: false,
takeSession: false,
requestResult: '',
// chatRoomEnvId: 'release-f8415a',
chatRoomCollection: 'chatroom',
chatRoomGroupId: 'demo',
chatRoomGroupName: '聊天室',
// functions for used in chatroom components
onGetUserInfo: null,
getOpenID: null,
},
onLoad: function() {
// 获取用户信息
wx.getSetting({
success: res => {
if (res.authSetting['scope.userInfo']) {
// 已经授权,可以直接调用 getUserInfo 获取头像昵称,不会弹框
wx.getUserInfo({
success: res => {
this.setData({
avatarUrl: res.userInfo.avatarUrl,
userInfo: res.userInfo
})
}
})
}
}
})
this.setData({
onGetUserInfo: this.onGetUserInfo,
getOpenID: this.getOpenID,
})
wx.getSystemInfo({
success: res => {
console.log('system info', res)
if (res.safeArea) {
const { top, bottom } = res.safeArea
this.setData({
containerStyle: `padding-top: ${(/ios/i.test(res.system) ? 10 : 20) + top}px; padding-bottom: ${20 + res.windowHeight - bottom}px`,
})
}
},
})
},
getOpenID: async function() {
if (this.openid) {
return this.openid
}
const { result } = await wx.cloud.callFunction({
name: 'login',
})
return result.openid
},
onGetUserInfo: function(e) {
if (!this.logged && e.detail.userInfo) {
this.setData({
logged: true,
avatarUrl: e.detail.userInfo.avatarUrl,
userInfo: e.detail.userInfo
})
}
},
onShareAppMessage() {
return {
title: '即时通信 Demo',
path: '/pages/im/room/room',
}
},
})

@ -0,0 +1,5 @@
{
"usingComponents": {
"chatroom": "/components/chatroom/chatroom"
}
}

@ -0,0 +1,12 @@
<view class="container" style="{{containerStyle}}">
<chatroom
style="width: 100%; height: 100%"
envId="{{chatRoomEnvId}}"
collection="{{chatRoomCollection}}"
groupId="{{chatRoomGroupId}}"
groupName="{{chatRoomGroupName}}"
userInfo="{{userInfo}}"
onGetUserInfo="{{onGetUserInfo}}"
getOpenID="{{getOpenID}}"
></chatroom>
</view>

@ -0,0 +1,10 @@
.container {
height: 100%;
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
padding-top: 80rpx;
padding-bottom: 30rpx;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 137 KiB

@ -0,0 +1,14 @@
//index.js
var app = getApp()
Page({
data: {
},
onLoad: function () {
},
bindViewTap(){
wx.switchTab({
url:'../dub/dub'
})
},
})

@ -0,0 +1,3 @@
{
"usingComponents": {}
}

@ -0,0 +1,4 @@
<view bindtap="bindViewTap">
<image src="./enter-backgroud.png" style="width: 400px; height: 750px;"></image>
</view>

@ -0,0 +1,199 @@
/**index.wxss**/
page {
background: #f6f6f6;
display: flex;
flex-direction: column;
justify-content: flex-start;
}
.userinfo, .uploader, .tunnel {
margin-top: 40rpx;
height: 140rpx;
width: 100%;
background: #fff;
border: 1px solid rgba(0, 0, 0, 0.1);
border-left: none;
border-right: none;
display: flex;
flex-direction: row;
align-items: center;
transition: all 300ms ease;
}
.userinfo-avatar {
width: 100rpx;
height: 100rpx;
margin: 20rpx;
border-radius: 50%;
background-size: cover;
background-color: white;
}
.userinfo-avatar:after {
border: none;
}
.userinfo-nickname {
font-size: 32rpx;
color: #007aff;
background-color: white;
background-size: cover;
}
.userinfo-nickname::after {
border: none;
}
.uploader, .tunnel {
height: auto;
padding: 0 0 0 40rpx;
flex-direction: column;
align-items: flex-start;
box-sizing: border-box;
}
.uploader-text, .tunnel-text {
width: 100%;
line-height: 52px;
font-size: 34rpx;
color: #007aff;
}
.uploader-container {
width: 100%;
height: 400rpx;
padding: 20rpx 20rpx 20rpx 0;
display: flex;
align-content: center;
justify-content: center;
box-sizing: border-box;
border-top: 1px solid rgba(0, 0, 0, 0.1);
}
.uploader-image {
width: 100%;
height: 360rpx;
}
.tunnel {
padding: 0 0 0 40rpx;
}
.tunnel-text {
position: relative;
color: #222;
display: flex;
flex-direction: row;
align-content: center;
justify-content: space-between;
box-sizing: border-box;
border-top: 1px solid rgba(0, 0, 0, 0.1);
}
.tunnel-text:first-child {
border-top: none;
}
.tunnel-switch {
position: absolute;
right: 20rpx;
top: -2rpx;
}
.disable {
color: #888;
}
.service {
position: fixed;
right: 40rpx;
bottom: 40rpx;
width: 140rpx;
height: 140rpx;
border-radius: 50%;
background: linear-gradient(#007aff, #0063ce);
box-shadow: 0 5px 10px rgba(0, 0, 0, 0.3);
display: flex;
align-content: center;
justify-content: center;
transition: all 300ms ease;
}
.service-button {
position: absolute;
top: 40rpx;
}
.service:active {
box-shadow: none;
}
.request-text {
padding: 20rpx 0;
font-size: 24rpx;
line-height: 36rpx;
word-break: break-all;
}
.speak-style{
position: relative;
height: 240rpx;
width: 240rpx;
border-radius: 20rpx;
margin: 50% auto;
background: #26A5FF;
}
.item-style{
margin-top: 30rpx;
margin-bottom: 30rpx;
}
.text-style{
text-align: center;
}
.record-style{
position: fixed;
bottom: 0;
left: 0;
height: 120rpx;
width: 100%;
}
.btn-style{
margin-left: 30rpx;
margin-right: 30rpx;
}
.sound-style{
position: absolute;
width: 74rpx;
height:150rpx;
margin-top: 45rpx;
margin-left: 83rpx;
}
.board {
overflow: hidden;
border-bottom: 2rpx solid #26A5FF;
}
/*列布局*/
.cell{
display: flex;
margin: 20rpx;
}
.cell-hd{
margin-left: 10rpx;
color: #885A38;
}
.cell .cell-bd{
flex:1;
position: relative;
}
/**只显示一行*/
.date{
font-size: 30rpx;
text-overflow: ellipsis;
white-space:nowrap;
overflow:hidden;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 58 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.5 KiB

@ -0,0 +1,66 @@
// miniprogram/pages/mine/mine.js
Page({
/**
* 页面的初始数据
*/
data: {
},
/**
* 生命周期函数--监听页面加载
*/
onLoad: function (options) {
},
/**
* 生命周期函数--监听页面初次渲染完成
*/
onReady: function () {
},
/**
* 生命周期函数--监听页面显示
*/
onShow: function () {
},
/**
* 生命周期函数--监听页面隐藏
*/
onHide: function () {
},
/**
* 生命周期函数--监听页面卸载
*/
onUnload: function () {
},
/**
* 页面相关事件处理函数--监听用户下拉动作
*/
onPullDownRefresh: function () {
},
/**
* 页面上拉触底事件的处理函数
*/
onReachBottom: function () {
},
/**
* 用户点击右上角分享
*/
onShareAppMessage: function () {
}
})

@ -0,0 +1,3 @@
{
"usingComponents": {}
}

@ -0,0 +1,2 @@
<!--miniprogram/pages/mine/mine.wxml-->
<text>我的配音作品:</text>

@ -0,0 +1 @@
/* miniprogram/pages/mine/mine.wxss */

@ -0,0 +1,15 @@
// miniprogram/pages/openapi/callback/callback.js
Page({
data: {
},
onLoad: function (options) {
},
onCustomerServiceButtonClick(e) {
console.log(e)
},
})

@ -0,0 +1,21 @@
<view class="container">
<view class="list">
<button open-type="contact" bindcontact="onCustomerServiceButtonClick">
进入客服消息
</button>
</view>
<view class="guide">
<text class="headline">测试须知</text>
<text class="p">1. 需在项目根目录创建消息推送配置文件 temp-cloud-callback-config.json</text>
<text class="p">2. 填写消息推送配置</text>
<text class="p">3. 右键配置文件选择上传配置</text>
<text class="p">4. 确认接收消息的云函数已上传</text>
<text class="p">5. 在手机上测试</text>
</view>
<view class="guide">
<text class="headline">示例客服消息配置</text>
<image class="code-image" src="../../../images/code-cloud-callback-config.png" mode="aspectFit"></image>
</view>
</view>

@ -0,0 +1,3 @@
/* miniprogram/pages/openapi/callback/callback.wxss */
@import "../../../style/guide.wxss";

@ -0,0 +1,60 @@
// miniprogram/pages/openapi/cloudid/cloudid.js
Page({
data: {
weRunResult: '',
userInfoResult: '',
},
onGetWeRunData() {
wx.getWeRunData({
success: res => {
wx.cloud.callFunction({
name: 'echo',
data: {
// info 字段在云函数 event 对象中会被自动替换为相应的敏感数据
info: wx.cloud.CloudID(res.cloudID),
},
}).then(res => {
console.log('[onGetWeRunData] 收到 echo 回包:', res)
this.setData({
weRunResult: JSON.stringify(res.result),
})
wx.showToast({
title: '敏感数据获取成功',
})
}).catch(err => {
console.log('[onGetWeRunData] 失败:', err)
})
}
})
},
onGetUserInfo(e) {
console.log(e)
wx.cloud.callFunction({
name: 'openapi',
data: {
action: 'getOpenData',
openData: {
list: [
e.detail.cloudID,
]
}
}
}).then(res => {
console.log('[onGetUserInfo] 调用成功:', res)
this.setData({
userInfoResult: JSON.stringify(res.result),
})
wx.showToast({
title: '敏感数据获取成功',
})
})
}
})

@ -0,0 +1,3 @@
{
"usingComponents": {}
}

@ -0,0 +1,41 @@
<!--index.wxml-->
<view class="container">
<view class="guide">
<text class="headline">开放数据调用</text>
<text class="p">通过 cloudID 获取敏感开放数据有以下两种方式</text>
<text class="p">1. 小程序端 callFunction 自动获取</text>
<text class="p">2. 通过 wx-server-sdk 获取</text>
<text class="p">以下分别先后展示这两种获取方式</text>
</view>
<view class="uploader">
<button class="uploader-text" bindtap="onGetWeRunData">getWeRunData 敏感数据获取</button>
</view>
<view class="guide">
<text class="headline">测试须知</text>
<text class="p">1. 公共库版本需大于 2.7.0</text>
<text class="p">2. 请确保 echo 函数已上传</text>
</view>
<view class="guide" style="word-break: break-all">
{{weRunResult}}
</view>
<view class="uploader">
<button class="uploader-text" open-type="getUserInfo" bindgetuserinfo="onGetUserInfo">getUserInfo 敏感数据获取</button>
</view>
<view class="guide">
<text class="headline">测试须知</text>
<text class="p">1. 公共库版本需大于 2.7.0</text>
<text class="p">2. 请确保 openapi 函数已上传</text>
</view>
<view class="guide" style="word-break: break-all">
{{userInfoResult}}
</view>
</view>

@ -0,0 +1 @@
@import "../../../style/guide.wxss";

@ -0,0 +1,109 @@
Page({
data: {
templateMessageResult: '',
wxacodeSrc: '',
wxacodeResult: '',
showClearWXACodeCache: false,
},
submitTemplateMessageForm(e) {
this.setData({
templateMessageResult: '',
})
wx.cloud.callFunction({
name: 'openapi',
data: {
action: 'sendTemplateMessage',
formId: e.detail.formId,
},
success: res => {
console.warn('[云函数] [openapi] templateMessage.send 调用成功:', res)
wx.showModal({
title: '发送成功',
content: '请返回微信主界面查看',
showCancel: false,
})
wx.showToast({
title: '发送成功,请返回微信主界面查看',
})
this.setData({
templateMessageResult: JSON.stringify(res.result)
})
},
fail: err => {
wx.showToast({
icon: 'none',
title: '调用失败',
})
console.error('[云函数] [openapi] templateMessage.send 调用失败:', err)
}
})
},
onGetWXACode() {
this.setData({
wxacodeSrc: '',
wxacodeResult: '',
showClearWXACodeCache: false,
})
// 此处为演示,将使用 localStorage 缓存,正常开发中文件 ID 应存在数据库中
const fileID = wx.getStorageSync('wxacodeCloudID')
if (fileID) {
// 有云文件 ID 缓存,直接使用该 ID
// 如需清除缓存,选择菜单栏中的 “工具 -> 清除缓存 -> 清除数据缓存”,或在 Storage 面板中删掉相应的 key
this.setData({
wxacodeSrc: fileID,
wxacodeResult: `从本地缓存中取得了小程序码的云文件 ID`,
showClearWXACodeCache: true,
})
console.log(`从本地缓存中取得了小程序码的云文件 ID${fileID}`)
} else {
wx.cloud.callFunction({
name: 'openapi',
data: {
action: 'getWXACode',
},
success: res => {
console.warn('[云函数] [openapi] wxacode.get 调用成功:', res)
wx.showToast({
title: '调用成功',
})
this.setData({
wxacodeSrc: res.result,
wxacodeResult: `云函数获取二维码成功`,
showClearWXACodeCache: true,
})
wx.setStorageSync('wxacodeCloudID', res.result)
},
fail: err => {
wx.showToast({
icon: 'none',
title: '调用失败',
})
console.error('[云函数] [openapi] wxacode.get 调用失败:', err)
}
})
}
},
clearWXACodeCache() {
wx.removeStorageSync('wxacodeCloudID')
this.setData({
wxacodeSrc: '',
wxacodeResult: '',
showClearWXACodeCache: false,
})
wx.showToast({
title: '清除成功',
})
},
})

@ -0,0 +1,3 @@
{
"usingComponents": {}
}

@ -0,0 +1,22 @@
<!--index.wxml-->
<view class="container">
<view class="uploader">
<navigator url="./serverapi/serverapi" open-type="navigate" class="uploader-text">
<text>服务端调用</text>
</navigator>
</view>
<view class="uploader">
<navigator url="./cloudid/cloudid" open-type="navigate" class="uploader-text">
<text>开放数据调用</text>
</navigator>
</view>
<view class="uploader">
<navigator url="./callback/callback" open-type="navigate" class="uploader-text">
<text>消息推送</text>
</navigator>
</view>
</view>

@ -0,0 +1,7 @@
/* miniprogram/pages/openapi/openapi.wxss */
@import "../../style/guide.wxss";
.black {
color: black;
}

@ -0,0 +1,109 @@
Page({
data: {
templateMessageResult: '',
wxacodeSrc: '',
wxacodeResult: '',
showClearWXACodeCache: false,
},
submitTemplateMessageForm(e) {
this.setData({
templateMessageResult: '',
})
wx.cloud.callFunction({
name: 'openapi',
data: {
action: 'sendTemplateMessage',
formId: e.detail.formId,
},
success: res => {
console.warn('[云函数] [openapi] templateMessage.send 调用成功:', res)
wx.showModal({
title: '发送成功',
content: '请返回微信主界面查看',
showCancel: false,
})
wx.showToast({
title: '发送成功,请返回微信主界面查看',
})
this.setData({
templateMessageResult: JSON.stringify(res.result)
})
},
fail: err => {
wx.showToast({
icon: 'none',
title: '调用失败',
})
console.error('[云函数] [openapi] templateMessage.send 调用失败:', err)
}
})
},
onGetWXACode() {
this.setData({
wxacodeSrc: '',
wxacodeResult: '',
showClearWXACodeCache: false,
})
// 此处为演示,将使用 localStorage 缓存,正常开发中文件 ID 应存在数据库中
const fileID = wx.getStorageSync('wxacodeCloudID')
if (fileID) {
// 有云文件 ID 缓存,直接使用该 ID
// 如需清除缓存,选择菜单栏中的 “工具 -> 清除缓存 -> 清除数据缓存”,或在 Storage 面板中删掉相应的 key
this.setData({
wxacodeSrc: fileID,
wxacodeResult: `从本地缓存中取得了小程序码的云文件 ID`,
showClearWXACodeCache: true,
})
console.log(`从本地缓存中取得了小程序码的云文件 ID${fileID}`)
} else {
wx.cloud.callFunction({
name: 'openapi',
data: {
action: 'getWXACode',
},
success: res => {
console.warn('[云函数] [openapi] wxacode.get 调用成功:', res)
wx.showToast({
title: '调用成功',
})
this.setData({
wxacodeSrc: res.result,
wxacodeResult: `云函数获取二维码成功`,
showClearWXACodeCache: true,
})
wx.setStorageSync('wxacodeCloudID', res.result)
},
fail: err => {
wx.showToast({
icon: 'none',
title: '调用失败',
})
console.error('[云函数] [openapi] wxacode.get 调用失败:', err)
}
})
}
},
clearWXACodeCache() {
wx.removeStorageSync('wxacodeCloudID')
this.setData({
wxacodeSrc: '',
wxacodeResult: '',
showClearWXACodeCache: false,
})
wx.showToast({
title: '清除成功',
})
},
})

@ -0,0 +1,41 @@
<view class="container">
<form class="list" bindsubmit="submitTemplateMessageForm" report-submit>
<button class="list-item" form-type="submit">
<text>发送模板消息</text>
</button>
<view class="list-item" wx:if="{{templateMessageResult}}">
<text class="request-text">调用结果:{{templateMessageResult}}</text>
</view>
</form>
<view class="guide">
<text class="headline">测试须知</text>
<text class="p">1. 需在手机上预览测试,工具中无效</text>
<text class="p">2. 需上传 cloudfunctions 目录下的 openapi 云函数</text>
<text class="p">3. 调用成功后返回到微信主界面查看收到的模板消息</text>
</view>
<view class="list">
<view class="list-item" bindtap="onGetWXACode">
<text>获取小程序码</text>
</view>
<view class="list-item" wx:if="{{wxacodeResult}}">
<text class="request-text">{{wxacodeResult}}</text>
<text class="request-text" wx:if="{{showClearWXACodeCache}}" bindtap="clearWXACodeCache">清除缓存</text>
</view>
</view>
<view class="guide">
<text class="headline">测试须知</text>
<text class="p">1. 需上传 cloudfunctions 目录下的 openapi 云函数</text>
<text class="p">2. 云函数中获取图片后会上传至存储空间并返回至小程序使用和缓存</text>
<text class="p">3. 云存储需设置为公有读</text>
</view>
<view class="guide">
<image src="{{wxacodeSrc}}" mode="aspectFit"></image>
</view>
</view>

@ -0,0 +1,7 @@
/* miniprogram/pages/openapi/openapi.wxss */
@import "../../../style/guide.wxss";
.black {
color: black;
}

@ -0,0 +1,136 @@
// miniprogram/pages/previewWork/previewWork.js
Page({
/**
* 页面的初始数据
*/
data: {
muted: 'false',
step: 1,
counterId: '',
openid: '',
count: null,
queryResult: '',
},
/**
* 生命周期函数--监听页面加载
*/
onLoad: function (options) {
},
/**
* 生命周期函数--监听页面初次渲染完成
*/
onReady: function () {
this.videoContext = wx.createVideoContext('myVideo');
},
/**
* 生命周期函数--监听页面显示
*/
onShow: function () {
},
/**
* 生命周期函数--监听页面隐藏
*/
onHide: function () {
},
/**
* 生命周期函数--监听页面卸载
*/
onUnload: function () {
},
/**
* 页面相关事件处理函数--监听用户下拉动作
*/
onPullDownRefresh: function () {
},
/**
* 页面上拉触底事件的处理函数
*/
onReachBottom: function () {
},
/**
* 用户点击右上角分享
*/
startPreview() {
this.videoContext.play();
wx.showToast({
title: '开始播放',
});
console.log("作品路径为" + getApp().globalData.workPath);
wx.playVoice({
filePath: getApp().globalData.workPath,
success: function () {
wx.showToast({
title: '播放结束',
})
},
})
},
stopPreview() {
this.videoContext.stop();
},
onAdd() {
const db = wx.cloud.database()
db.collection('user-video').add({
data: {
//count: 1,
videoID: '',
fileID: '',
cloudPath: '',
},
success: res => {
// 在返回结果中会包含新创建的记录的 _id
this.setData({
counterId: res._id,
count: 1,
fileID: '',
cloudPath:''
})
wx.showToast({
title: '新增记录成功',
})
console.log('[数据库] [新增记录] 成功,记录 _id: ', res._id)
},
fail: err => {
wx.showToast({
icon: 'none',
title: '新增记录失败'
})
console.error('[数据库] [新增记录] 失败:', err)
}
})
},
saveWork() {
wx.cloud.uploadFile({
cloudPath: 'work-1',
filePath: getApp().globalData.workPath,
success: res => {
// get resource ID
console.log(res.fileID)
},
fail: err => {
// handle error
}
})
this.onAdd();
},
onShareAppMessage: function () {
}
})

@ -0,0 +1,3 @@
{
"usingComponents": {}
}

@ -0,0 +1,4 @@
<!--miniprogram/pages/previewWork/previewWork.wxml-->
<video id="myVideo" src="cloud://dunning-bar-enr-3e46z.6475-dunning-bar-enr-3e46z-1300499016/video/video_1.mp4" muted ="{{muted}}"controls ="{{false}}" show-play-btn ="{{false}}"show-fullscreen-btn = "{{false}}" show-center-play-btn="{{false}}" style="width: 400px; height: 200px;"></video>
<button bindtap="startPreview">开始预览</button>
<button bindtap="saveWork">保存作品</button>

@ -0,0 +1 @@
/* miniprogram/pages/previewWork/previewWork.wxss */

@ -0,0 +1,32 @@
// pages/storageConsole/storageConsole.js
const app = getApp()
Page({
data: {
fileID: '',
cloudPath: '',
imagePath: '',
},
onLoad: function (options) {
const {
fileID,
cloudPath,
imagePath,
} = app.globalData
this.setData({
fileID,
cloudPath,
imagePath,
})
console.group('文件存储文档')
console.log('https://developers.weixin.qq.com/miniprogram/dev/wxcloud/guide/storage.html')
console.groupEnd()
},
})

@ -0,0 +1,4 @@
{
"navigationBarTitleText": "文件存储指引",
"usingComponents": {}
}

@ -0,0 +1,29 @@
<!--pages/storageConsole/storageConsole.wxml-->
<view class="container">
<view class="list">
<view class="list-item" bindtap="testCgi">
<text class="black">上传成功</text>
</view>
<view class="list-item">
<text class="request-text">文件 ID{{fileID}}</text>
</view>
<view class="list-item">
<text class="request-text">云文件路径:{{cloudPath}}</text>
</view>
<view class="list-item">
<image class="image1" src="{{imagePath}}" mode="aspectFit"></image>
</view>
</view>
<view class="guide">
<!-- <image class="image1" src="{{imagePath}}" mode="aspectFit"></image> -->
<text class="headline">云开发控制台中管理文件</text>
<text class="p">1. 打开云开发控制台</text>
<image class="image1" src="../../images/console-entrance.png" mode="aspectFit"></image>
<text class="p">2. 切换到文件管理标签页</text>
<text class="p">3. 可查看文件列表、管理权限</text>
<text class="p">4. 详细的教程和 API 文件,可点击调试器中打印的链接查看</text>
</view>
</view>

@ -0,0 +1,7 @@
/* pages/storageConsole/storageConsole.wxss */
@import "../../style/guide.wxss";
.black {
color: black;
}

@ -0,0 +1,13 @@
// pages/userConsole/userConsole.js
Page({
data: {
openid: ''
},
onLoad: function (options) {
this.setData({
openid: getApp().globalData.openid
})
}
})

@ -0,0 +1,4 @@
{
"navigationBarTitleText": "用户管理指引",
"usingComponents": {}
}

@ -0,0 +1,22 @@
<!--pages/userConsole/userConsole.wxml-->
<view class="container">
<view class="list">
<view class="list-item" bindtap="testCgi">
<text class="request-text">用户 openid 获取成功</text>
</view>
<view class="list-item" bindtap="testCgi">
<text class="request-text">{{openid}}</text>
</view>
</view>
<!-- 云开发用户管理指引 -->
<view class="guide">
<text class="headline">云开发管理用户</text>
<text class="p">1. 打开云开发控制台</text>
<image class="image1" src="../../images/console-entrance.png" mode="aspectFit"></image>
<text class="p">2. 切换到 "用户管理" 标签页</text>
<text class="p">3. 查看访问小程序的用户列表</text>
</view>
</view>

@ -0,0 +1,3 @@
/* pages/userConsole/userConsole.wxss */
@import "../../style/guide.wxss";

@ -0,0 +1,7 @@
{
"desc": "关于本文件的更多信息,请参考文档 https://developers.weixin.qq.com/miniprogram/dev/framework/sitemap.html",
"rules": [{
"action": "allow",
"page": "*"
}]
}

@ -0,0 +1,144 @@
page {
background: #f6f6f6;
display: flex;
flex-direction: column;
justify-content: flex-start;
}
.list {
margin-top: 40rpx;
height: auto;
width: 100%;
background: #fff;
padding: 0 40rpx;
border: 1px solid rgba(0, 0, 0, 0.1);
border-left: none;
border-right: none;
transition: all 300ms ease;
display: flex;
flex-direction: column;
align-items: stretch;
box-sizing: border-box;
}
.list-item {
width: 100%;
padding: 0;
line-height: 104rpx;
font-size: 34rpx;
color: #007aff;
border-top: 1px solid rgba(0, 0, 0, 0.1);
display: flex;
flex-direction: row;
align-content: center;
justify-content: space-between;
box-sizing: border-box;
}
.list-item:first-child {
border-top: none;
}
.list-item image {
max-width: 100%;
max-height: 20vh;
margin: 20rpx 0;
}
.request-text {
color: #222;
padding: 20rpx 0;
font-size: 24rpx;
line-height: 36rpx;
word-break: break-all;
}
.guide {
width: 100%;
padding: 40rpx;
box-sizing: border-box;
display: flex;
flex-direction: column;
}
.guide .headline {
font-size: 34rpx;
font-weight: bold;
color: #555;
line-height: 40rpx;
}
.guide .p {
margin-top: 20rpx;
font-size: 28rpx;
line-height: 36rpx;
color: #666;
}
.guide .code {
margin-top: 20rpx;
font-size: 28rpx;
line-height: 36rpx;
color: #666;
background: white;
white-space: pre;
}
.guide .code-dark {
margin-top: 20rpx;
background: rgba(0, 0, 0, 0.8);
padding: 20rpx;
font-size: 28rpx;
line-height: 36rpx;
border-radius: 6rpx;
color: #fff;
white-space: pre
}
.guide image {
max-width: 100%;
}
.guide .image1 {
margin-top: 20rpx;
max-width: 100%;
width: 356px;
height: 47px;
}
.guide .image2 {
margin-top: 20rpx;
width: 264px;
height: 100px;
}
.guide .flat-image {
height: 100px;
}
.guide .code-image {
max-width: 100%;
}
.guide .copyBtn {
width: 180rpx;
font-size: 20rpx;
margin-top: 16rpx;
margin-left: 0;
}
.guide .nav {
margin-top: 50rpx;
display: flex;
flex-direction: row;
align-content: space-between;
}
.guide .nav .prev {
margin-left: unset;
}
.guide .nav .next {
margin-right: unset;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.6 KiB

Loading…
Cancel
Save