...
@@ -14,6 +14,10 @@
|
|||||||
{
|
{
|
||||||
"launchtype" : "local"
|
"launchtype" : "local"
|
||||||
},
|
},
|
||||||
|
"mp-weixin" :
|
||||||
|
{
|
||||||
|
"launchtype" : "local"
|
||||||
|
},
|
||||||
"type" : "uniCloud"
|
"type" : "uniCloud"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -11,6 +11,13 @@ import {
|
|||||||
|
|
||||||
// 获取好友列表
|
// 获取好友列表
|
||||||
const getFriends = () => {
|
const getFriends = () => {
|
||||||
|
return request({
|
||||||
|
url: 'im/friends',
|
||||||
|
}, true)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取好友列表
|
||||||
|
const getFriendsLetter = () => {
|
||||||
return request({
|
return request({
|
||||||
url: 'im/friends/letter',
|
url: 'im/friends/letter',
|
||||||
}, true)
|
}, true)
|
||||||
@@ -85,62 +92,98 @@ const pedingFriend = (recipient) => {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
// 以下是群组相关业务的接口
|
||||||
* 好友申请数量
|
const getMyGroups = () => {
|
||||||
*/
|
|
||||||
const getPendingCount = () => {
|
|
||||||
return request({
|
return request({
|
||||||
url: 'im/friends/pending/count'
|
url: 'im/groups'
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 上传聊天附件
|
* 获取群信息,包含基础信息和 14 个用户
|
||||||
* 图片
|
|
||||||
* 语音
|
|
||||||
* 视频
|
|
||||||
*/
|
*/
|
||||||
// 基础配置
|
const getGroupInfo = (groupId) => {
|
||||||
const config = {
|
return request({
|
||||||
apiUrl: 'http://api.zh.shangkelian.cn/api/', // 正式环境
|
url: 'im/groups/' + groupId
|
||||||
timeout: 60000
|
|
||||||
}
|
|
||||||
|
|
||||||
const uploadMessageFile = (file, type) => {
|
|
||||||
config.header = {
|
|
||||||
'Accept': 'application/json',
|
|
||||||
'Authorization': store.getters.getToken || ''
|
|
||||||
}
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
uni.uploadFile({
|
|
||||||
url: config.apiUrl + 'im/upload',
|
|
||||||
filePath: file,
|
|
||||||
name: 'upload',
|
|
||||||
formData: {
|
|
||||||
type
|
|
||||||
},
|
|
||||||
header: config.header || {},
|
|
||||||
success: (res) => {
|
|
||||||
if (res.statusCode === 200) {
|
|
||||||
let updData = JSON.parse(res.data)
|
|
||||||
if (updData.status_code === 200) {
|
|
||||||
resolve(updData.data)
|
|
||||||
} else {
|
|
||||||
reject(updData)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
fail: (err) => {
|
|
||||||
console.log('ERR', err);
|
|
||||||
}
|
|
||||||
})
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const getGroupUsers = (groupId) => {
|
||||||
|
return request({
|
||||||
|
url: 'im/groups/' + groupId + '/users'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const getGroupAnnouncements = (groupId) => {
|
||||||
|
return request({
|
||||||
|
url: 'im/groups/' + groupId + '/announcements'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const createGroupAnnouncement = (groupId, content) => {
|
||||||
|
return request({
|
||||||
|
method: 'POST',
|
||||||
|
url: 'im/groups/' + groupId + '/announcements',
|
||||||
|
data: {
|
||||||
|
content: content
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const deleteGroupAnnouncement = (groupId, announcementId) => {
|
||||||
|
return request({
|
||||||
|
method: 'DELETE',
|
||||||
|
url: 'im/groups/' + groupId + '/announcements/' + announcementId
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建群聊
|
||||||
|
*/
|
||||||
|
const createGroup = (data) => {
|
||||||
|
return request({
|
||||||
|
method: 'POST',
|
||||||
|
url: 'im/groups',
|
||||||
|
data: data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const updateGroup = (groupId, data) => {
|
||||||
|
return request({
|
||||||
|
method: 'PUT',
|
||||||
|
url: 'im/groups/' + groupId,
|
||||||
|
data: data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 搜索群聊
|
||||||
|
*/
|
||||||
|
const searchGroup = (name) => {
|
||||||
|
return request({
|
||||||
|
url: 'im/groups/search?name=' + name
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const joinGroup = (groupId) => {
|
||||||
|
return request({
|
||||||
|
method: 'POST',
|
||||||
|
url: 'im/groups/' + groupId + '/join'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const quitGroup = (groupId) => {
|
||||||
|
return request({
|
||||||
|
method: 'POST',
|
||||||
|
url: 'im/groups/' + groupId + '/quit'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
export {
|
export {
|
||||||
getImToken,
|
getImToken,
|
||||||
deleteFriend,
|
deleteFriend,
|
||||||
getFriends,
|
getFriends,
|
||||||
|
getFriendsLetter,
|
||||||
getUserInfo,
|
getUserInfo,
|
||||||
getFriendInfo,
|
getFriendInfo,
|
||||||
getPedings,
|
getPedings,
|
||||||
@@ -148,6 +191,15 @@ export {
|
|||||||
rejectFriend,
|
rejectFriend,
|
||||||
searchFriend,
|
searchFriend,
|
||||||
pedingFriend,
|
pedingFriend,
|
||||||
getPendingCount,
|
getMyGroups,
|
||||||
uploadMessageFile
|
createGroup,
|
||||||
|
updateGroup,
|
||||||
|
getGroupInfo,
|
||||||
|
getGroupUsers,
|
||||||
|
getGroupAnnouncements,
|
||||||
|
createGroupAnnouncement,
|
||||||
|
deleteGroupAnnouncement,
|
||||||
|
searchGroup,
|
||||||
|
joinGroup,
|
||||||
|
quitGroup
|
||||||
}
|
}
|
||||||
|
|||||||
33
lib/emoji.js
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
export default [
|
||||||
|
"😀", "😁", "😃", "😄", "😅", "😆", "😉", "😊", "😋", "😎", "😍",
|
||||||
|
"😘", "😗", "😙", "😚", "☺", "😇", "😐", "😑", "😶", "😏", "😣", "😥", "😮", "😯", "😪",
|
||||||
|
"😫", "😴", "😌", "😛", "😜", "😝", "😒", "😓", "😔", "😕", "😲", "😷", "😖", "😞", "😟",
|
||||||
|
"😤", "😢", "😭", "😦", "😧", "😨", "😬", "😰", "😱", "😳", "😵", "😡", "😠",
|
||||||
|
"👦", "👧", "👨", "👩", "👴", "👵", "👶", "👱", "👮", "👲", "👳", "👷", "👸", "💂", "🎅", "👰", "👼",
|
||||||
|
"💆", "💇", "🙍", "🙎", "🙅", "🙆", "💁", "🙋", "🙇", "🙌", "🙏", "👤", "👥", "🚶", "🏃", "👯",
|
||||||
|
"💃", "👫", "👬", "👭", "💏", "💑", "👪", "💪", "👈", "👉", "☝", "👆", "👇", "✌", "✋", "👌",
|
||||||
|
"👍", "👎", "✊", "👊", "👋", "👏", "👐", "✍", "👣", "👀", "👂", "👃", "👅", "👄", "💋", "👓",
|
||||||
|
"👔", "👙", "👛", "👜", "👝", "🎒", "💼", "👞", "👟", "👠", "👡", "👢", "👑",
|
||||||
|
"👒", "🎩", "🎓", "💄", "💅", "💍", "🌂", "📶", "📳", "📴", "♻", "🏧","🚮", "🚰", "♿", "🚹", "🚺",
|
||||||
|
"🚻", "🚼", "🚾", "⚠", "🚸", "⛔", "🚫", "🚳", "🚭", "🚯", "🚱", "🚷", "🔞", "💈",
|
||||||
|
"🙈", "🐒", "🐶", "🐕", "🐩", "🐺", "🐱","🐈", "🐯", "🐅", "🐆", "🐴", "🐎", "🐮", "🐂",
|
||||||
|
"🐃","🐄","🐷","🐖","🐗","🐽","🐏","🐑","🐐","🐪","🐫","🐘","🐭",
|
||||||
|
"🐁","🐀","🐹","🐰","🐇","🐻","🐨","🐼","🐾","🐔","🐓","🐣","🐤","🐥",
|
||||||
|
"🐦", "🐧", "🐸", "🐊","🐢", "🐍", "🐲", "🐉", "🐳", "🐋", "🐬", "🐟", "🐠", "🐡",
|
||||||
|
"🐙", "🐚", "🐌", "🐛", "🐜", "🐝", "🐞", "🦋", "💐", "🌸", "💮", "🌹", "🌺",
|
||||||
|
"🌻", "🌼", "🌷", "🌱", "🌲", "🌳", "🌴", "🌵", "🌾", "🌿", "🍀", "🍁", "🍂", "🍃",
|
||||||
|
"🌍","🌎","🌏","🌐","🌑","🌒","🌓","🌔","🌕","🌖","🌗","🌘","🌙","🌚",
|
||||||
|
"🌛","🌜","☀","🌝","🌞","⭐","🌟","🌠","☁","⛅","☔","⚡","❄","🔥","💧","🌊",
|
||||||
|
"🏀", "🏈", "🏉", "🎾", "🎱", "🎳", "⛳", "🎣", "🎽", "🎿",
|
||||||
|
"😈", "👿", "👹", "👺", "💀", "☠", "👻", "👽", "👾", "💣",
|
||||||
|
"🌋", "🗻", "🏠", "🏡", "🏢", "🏣", "🏤", "🏥", "🏦", "🏨",
|
||||||
|
"⛲", "🌁", "🌃", "🌆", "🌇", "🎠", "🎡", "🎢", "🚂",
|
||||||
|
"🚌", "🚍", "🚎", "🚏", "🚐", "🚑", "🚒", "🚓", "🚔", "🚕", "🚖", "🚗", "🚘",
|
||||||
|
"💌", "💎", "🔪", "💈", "🚪", "🚽", "🚿", "🛁", "⌛", "⏳", "⌚", "⏰", "🎈", "🎉",
|
||||||
|
"💤", "💢", "💬", "💭", "♨", "🌀", "🔔", "🔕", "✡", "✝", "🔯", "📛", "🔰", "🔱", "⭕", "✅",
|
||||||
|
"☑", "✔", "✖", "❌", "❎", "➕", "➖", "➗", "➰", "➿", "〽", "✳", "✴", "❇", "‼", "⁉", "❓", "❔", "❕", "❗",
|
||||||
|
"🕛", "🕧", "🕐", "🕜", "🕑", "🕝", "🕒", "🕞", "🕓", "🕟", "🕔", "🕠", "🕕", "🕡",
|
||||||
|
"🕖", "🕢", "🕗", "🕣", "🕘", "🕤", "🕙", "🕥", "🕚", "🕦", "⏱", "⏲", "🕰",
|
||||||
|
"💘", "❤", "💓", "💔", "💕", "💖", "💗", "💙", "💚", "💛", "💜", "💝", "💞", "💟❣",
|
||||||
|
"🍇", "🍈", "🍉", "🍊", "🍋", "🍌", "🍍", "🍎", "🍏", "🍐", "🍑", "🍒", "🍓",
|
||||||
|
]
|
||||||
@@ -2,8 +2,8 @@
|
|||||||
"name" : "ZH-HEALTH",
|
"name" : "ZH-HEALTH",
|
||||||
"appid" : "__UNI__C29473D",
|
"appid" : "__UNI__C29473D",
|
||||||
"description" : "ZH-HEALTH,您手上的健康管理专家",
|
"description" : "ZH-HEALTH,您手上的健康管理专家",
|
||||||
"versionName" : "1.0.7",
|
"versionName" : "1.0.8",
|
||||||
"versionCode" : 107,
|
"versionCode" : 108,
|
||||||
"transformPx" : false,
|
"transformPx" : false,
|
||||||
/* 5+App特有相关 */
|
/* 5+App特有相关 */
|
||||||
"app-plus" : {
|
"app-plus" : {
|
||||||
@@ -22,7 +22,9 @@
|
|||||||
"Payment" : {},
|
"Payment" : {},
|
||||||
"Share" : {},
|
"Share" : {},
|
||||||
"SQLite" : {},
|
"SQLite" : {},
|
||||||
"VideoPlayer" : {}
|
"VideoPlayer" : {},
|
||||||
|
"Geolocation" : {},
|
||||||
|
"Fingerprint" : {}
|
||||||
},
|
},
|
||||||
/* 应用发布信息 */
|
/* 应用发布信息 */
|
||||||
"distribute" : {
|
"distribute" : {
|
||||||
@@ -78,7 +80,17 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"ad" : {},
|
"ad" : {},
|
||||||
"push" : {}
|
"push" : {},
|
||||||
|
"geolocation" : {
|
||||||
|
"amap" : {
|
||||||
|
"__platform__" : [ "android" ],
|
||||||
|
"appkey_ios" : "",
|
||||||
|
"appkey_android" : "05b7f32ca9c897c8b63c505d92cd654b"
|
||||||
|
},
|
||||||
|
"system" : {
|
||||||
|
"__platform__" : [ "android" ]
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"icons" : {
|
"icons" : {
|
||||||
"android" : {
|
"android" : {
|
||||||
|
|||||||
@@ -4,8 +4,6 @@
|
|||||||
"description": "ZH健康",
|
"description": "ZH健康",
|
||||||
"main": "main.js",
|
"main": "main.js",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"bitcore-lib": "^8.25.25",
|
|
||||||
"bitcore-mnemonic": "^8.25.25",
|
|
||||||
"moment": "^2.29.1",
|
"moment": "^2.29.1",
|
||||||
"uni-read-pages": "^1.0.5",
|
"uni-read-pages": "^1.0.5",
|
||||||
"uni-simple-router": "^2.0.7",
|
"uni-simple-router": "^2.0.7",
|
||||||
|
|||||||
118
pages.json
@@ -266,7 +266,7 @@
|
|||||||
"path": "pages/sign/index",
|
"path": "pages/sign/index",
|
||||||
"name": "signIndex",
|
"name": "signIndex",
|
||||||
"style": {
|
"style": {
|
||||||
"navigationBarTitleText": "每日签到",
|
"navigationBarTitleText": "每日打卡",
|
||||||
"navigationBarBackgroundColor": "#FFFFFF"
|
"navigationBarBackgroundColor": "#FFFFFF"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -367,28 +367,16 @@
|
|||||||
"path": "pages/im/index",
|
"path": "pages/im/index",
|
||||||
"name": "IM",
|
"name": "IM",
|
||||||
"style": {
|
"style": {
|
||||||
"navigationBarBackgroundColor": "#FFFFFF",
|
|
||||||
"navigationStyle": "custom"
|
"navigationStyle": "custom"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"path": "pages/im/private/index",
|
"path": "pages/im/private/chat",
|
||||||
"name": "imPrivate",
|
|
||||||
"style": {
|
"style": {
|
||||||
"navigationBarTitleText": "聊天",
|
|
||||||
"navigationBarBackgroundColor": "#F3F6FB",
|
|
||||||
"disableScroll": true,
|
"disableScroll": true,
|
||||||
"app-plus": {
|
"navigationBarTitleText": "聊天",
|
||||||
"titleNView": {
|
"enablePullDownRefresh": false,
|
||||||
"type": "default",
|
"navigationBarBackgroundColor": "#F3F6FB"
|
||||||
"buttons": [{
|
|
||||||
"float": "right",
|
|
||||||
"fontSrc": "/static/iconfont.ttf",
|
|
||||||
"text": "\ue607",
|
|
||||||
"fontSize": "20px"
|
|
||||||
}]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -420,24 +408,21 @@
|
|||||||
"path": "pages/im/friends/pending",
|
"path": "pages/im/friends/pending",
|
||||||
"name": "imFriendsPending",
|
"name": "imFriendsPending",
|
||||||
"style": {
|
"style": {
|
||||||
"navigationBarTitleText": "新朋友",
|
"navigationBarTitleText": "新朋友"
|
||||||
"navigationBarBackgroundColor": "#F3F6FB"
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"path": "pages/im/friends/search",
|
"path": "pages/im/friends/search",
|
||||||
"name": "SearchFriend",
|
"name": "SearchFriend",
|
||||||
"style": {
|
"style": {
|
||||||
"navigationBarTitleText": "好友搜索",
|
"navigationBarTitleText": "好友搜索"
|
||||||
"navigationBarBackgroundColor": "#F3F6FB"
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"path": "pages/im/friends/info",
|
"path": "pages/im/friends/info",
|
||||||
"name": "imFriendsInfo",
|
"name": "imFriendsInfo",
|
||||||
"style": {
|
"style": {
|
||||||
"navigationBarTitleText": "好友资料",
|
"navigationBarTitleText": "用户资料"
|
||||||
"navigationBarBackgroundColor": "#FFFFFF"
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -451,9 +436,84 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"path": "pages/im/group/index",
|
"path": "pages/im/group/index",
|
||||||
"name": "imGroup",
|
"name": "imGroups",
|
||||||
"style": {
|
"style": {
|
||||||
"navigationBarTitleText": "我的群聊"
|
"navigationBarTitleText": "我的群聊",
|
||||||
|
"app-plus": {
|
||||||
|
"titleNView": {
|
||||||
|
"type": "default",
|
||||||
|
"buttons": [{
|
||||||
|
"float": "right",
|
||||||
|
"fontSrc": "/static/iconfont.ttf",
|
||||||
|
"text": "\ue60a",
|
||||||
|
"fontSize": "20px"
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "pages/im/group/chat",
|
||||||
|
"name": "imGroupChat",
|
||||||
|
"style": {
|
||||||
|
"navigationBarTitleText": "群聊",
|
||||||
|
"app-plus": {
|
||||||
|
"titleNView": {
|
||||||
|
"type": "default",
|
||||||
|
"buttons": [{
|
||||||
|
"float": "right",
|
||||||
|
"fontSrc": "/static/iconfont.ttf",
|
||||||
|
"text": "\ue607",
|
||||||
|
"fontSize": "20px"
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "pages/im/group/info",
|
||||||
|
"name": "imGroupInfo",
|
||||||
|
"style": {
|
||||||
|
"navigationBarTitleText": "群信息"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "pages/im/group/create",
|
||||||
|
"name": "imGroupCreate",
|
||||||
|
"style": {
|
||||||
|
"navigationBarTitleText": "创建群聊"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "pages/im/group/users",
|
||||||
|
"name": "imGroupUsers",
|
||||||
|
"style": {
|
||||||
|
"navigationBarTitleText": "群成员"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "pages/im/group/announcement",
|
||||||
|
"name": "imGroupAnnouncement",
|
||||||
|
"style": {
|
||||||
|
"navigationBarTitleText": "群公告",
|
||||||
|
"app-plus": {
|
||||||
|
"titleNView": {
|
||||||
|
"type": "default",
|
||||||
|
"buttons": [{
|
||||||
|
"float": "right",
|
||||||
|
"fontSrc": "/static/iconfont.ttf",
|
||||||
|
"text": "\ue60a",
|
||||||
|
"fontSize": "20px"
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "pages/im/group/announceCreate",
|
||||||
|
"name": "imGroupAnnouncementCreate",
|
||||||
|
"style": {
|
||||||
|
"navigationBarTitleText": "发布群公告"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -566,14 +626,6 @@
|
|||||||
"navigationBarBackgroundColor": "#34CE98",
|
"navigationBarBackgroundColor": "#34CE98",
|
||||||
"navigationBarTextStyle": "white"
|
"navigationBarTextStyle": "white"
|
||||||
}
|
}
|
||||||
}, {
|
|
||||||
"path": "pages/im/private/chat",
|
|
||||||
"style": {
|
|
||||||
"disableScroll": true,
|
|
||||||
"navigationBarTitleText": "聊天",
|
|
||||||
"enablePullDownRefresh": false,
|
|
||||||
"navigationBarBackgroundColor": "#F3F6FB"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"tabBar": {
|
"tabBar": {
|
||||||
|
|||||||
BIN
pages/.DS_Store
vendored
163
pages/im/components/conversationList.vue
Normal file
@@ -0,0 +1,163 @@
|
|||||||
|
<template>
|
||||||
|
<view>
|
||||||
|
<view v-for="(item, index) in conversations" :key="index" :class="['message', { 'is-top': item.isTop }]"
|
||||||
|
:data-item="item" @longpress="onLongPress" @click="toDetail(item)">
|
||||||
|
<message-cell :item="item" />
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class="shade" @click="hidePop" v-show="showPop">
|
||||||
|
<view class="pop" :style="popStyle" :class="{'show':showPop}">
|
||||||
|
<view v-for="(item, index) in popButton" :key="index" @click="pickerMenu" :data-index="index">
|
||||||
|
{{item}}
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import * as RongIMLib from '@/uni_modules/RongCloud-IMWrapper/js_sdk/index'
|
||||||
|
import im from '@/utils/im/index.js'
|
||||||
|
import messageCell from './messageCell'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
props: {
|
||||||
|
conversations: {
|
||||||
|
type: Array,
|
||||||
|
default: function() {
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
components: {
|
||||||
|
messageCell
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
/* 窗口尺寸 */
|
||||||
|
winSize: {},
|
||||||
|
/* 显示操作弹窗 */
|
||||||
|
showPop: false,
|
||||||
|
/* 弹窗按钮列表 */
|
||||||
|
popButton: ['置顶聊天', '删除该聊天'],
|
||||||
|
/* 弹窗定位样式 */
|
||||||
|
popStyle: "",
|
||||||
|
pickedItem: {},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
methods: {
|
||||||
|
// 隐藏功能菜单
|
||||||
|
hidePop() {
|
||||||
|
this.showPop = false
|
||||||
|
this.pickedItem = {}
|
||||||
|
setTimeout(() => {
|
||||||
|
this.showShade = false
|
||||||
|
}, 250)
|
||||||
|
},
|
||||||
|
// 点击会话功能菜单
|
||||||
|
pickerMenu(e) {
|
||||||
|
const index = Number(e.currentTarget.dataset.index)
|
||||||
|
|
||||||
|
if (index == 0) {
|
||||||
|
RongIMLib.setConversationToTop(this.pickedItem.conversationType, this.pickedItem.targetId, !this
|
||||||
|
.pickedItem.isTop)
|
||||||
|
} else {
|
||||||
|
RongIMLib.removeConversation(this.pickedItem.conversationType, this.pickedItem.targetId)
|
||||||
|
RongIMLib.deleteMessages(this.pickedItem.conversationType, this.pickedItem.targetId)
|
||||||
|
}
|
||||||
|
this.$emit('refresh')
|
||||||
|
im.setNotifyBadge()
|
||||||
|
this.hidePop()
|
||||||
|
},
|
||||||
|
// 长按会话,展示功能菜单
|
||||||
|
onLongPress(e) {
|
||||||
|
let [touches, style, item] = [e.touches[0], "", e.currentTarget.dataset.item]
|
||||||
|
|
||||||
|
if (touches.clientY > (this.winSize.height / 2)) {
|
||||||
|
style = `bottom:${this.winSize.height-touches.clientY}px;`
|
||||||
|
} else {
|
||||||
|
style = `top:${touches.clientY}px;`
|
||||||
|
}
|
||||||
|
if (touches.clientX > (this.winSize.witdh / 2)) {
|
||||||
|
style += `right:${this.winSize.witdh-touches.clientX}px`
|
||||||
|
} else {
|
||||||
|
style += `left:${touches.clientX}px`
|
||||||
|
}
|
||||||
|
|
||||||
|
this.popButton[0] = item.isTop ? '取消置顶' : '置顶聊天'
|
||||||
|
this.popStyle = style
|
||||||
|
this.pickedItem = item
|
||||||
|
this.$nextTick(() => {
|
||||||
|
setTimeout(() => {
|
||||||
|
this.showPop = true;
|
||||||
|
}, 10)
|
||||||
|
})
|
||||||
|
},
|
||||||
|
toDetail(item) {
|
||||||
|
if (item.conversationType == 1) {
|
||||||
|
uni.navigateTo({
|
||||||
|
url: '/pages/im/private/chat?targetId=' + item.targetId
|
||||||
|
})
|
||||||
|
} else if (item.conversationType == 3) {
|
||||||
|
uni.navigateTo({
|
||||||
|
url: '/pages/im/group/chat?targetId=' + item.targetId
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
this.hidePop()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.message {
|
||||||
|
background: white;
|
||||||
|
|
||||||
|
&.is-top {
|
||||||
|
background: $window-color;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 遮罩 */
|
||||||
|
.shade {
|
||||||
|
position: fixed;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
|
||||||
|
.pop {
|
||||||
|
position: fixed;
|
||||||
|
z-index: 101;
|
||||||
|
width: 200rpx;
|
||||||
|
box-sizing: border-box;
|
||||||
|
font-size: 28rpx;
|
||||||
|
text-align: left;
|
||||||
|
color: #333;
|
||||||
|
background-color: #fff;
|
||||||
|
box-shadow: 0 0 5px rgba(0, 0, 0, 0.5);
|
||||||
|
line-height: 80rpx;
|
||||||
|
transition: transform 0.15s ease-in-out 0s;
|
||||||
|
user-select: none;
|
||||||
|
-webkit-touch-callout: none;
|
||||||
|
transform: scale(0, 0);
|
||||||
|
|
||||||
|
&.show {
|
||||||
|
transform: scale(1, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
&>view {
|
||||||
|
padding: 0 20rpx;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
white-space: nowrap;
|
||||||
|
user-select: none;
|
||||||
|
-webkit-touch-callout: none;
|
||||||
|
|
||||||
|
&:active {
|
||||||
|
background-color: #f3f3f3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
112
pages/im/components/friendApplyCell.vue
Normal file
@@ -0,0 +1,112 @@
|
|||||||
|
<template>
|
||||||
|
<view class="apply--cell u-border-bottom">
|
||||||
|
<view class="avatar">
|
||||||
|
<u-avatar :src="user.portraitUrl" shape="square" size="46" />
|
||||||
|
</view>
|
||||||
|
<view class="info">
|
||||||
|
<view class="name">
|
||||||
|
{{ user.name }}
|
||||||
|
</view>
|
||||||
|
<view class="message">
|
||||||
|
{{ message.message }}
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class="action">
|
||||||
|
<u-button type="success" size="mini" @click="resolve">通过</u-button>
|
||||||
|
<u-button type="warning" size="mini" @click="reject">拒绝</u-button>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import * as RongIMLib from '@/uni_modules/RongCloud-IMWrapper/js_sdk/index'
|
||||||
|
import {
|
||||||
|
resolveFriend,
|
||||||
|
rejectFriend
|
||||||
|
} from '@/apis/interfaces/im.js'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
props: {
|
||||||
|
message: {
|
||||||
|
type: Object,
|
||||||
|
default: {}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
user() {
|
||||||
|
return JSON.parse(this.message.extra)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
resolve() {
|
||||||
|
resolveFriend(this.message.sourceUserId).then(res => {
|
||||||
|
this.clearMessages()
|
||||||
|
uni.showToast({
|
||||||
|
icon: 'none',
|
||||||
|
title: '通过好友申请'
|
||||||
|
})
|
||||||
|
}).catch(err => {
|
||||||
|
uni.showToast({
|
||||||
|
icon: 'none',
|
||||||
|
title: err.message
|
||||||
|
})
|
||||||
|
})
|
||||||
|
},
|
||||||
|
reject() {
|
||||||
|
uni.showModal({
|
||||||
|
title: '拒绝申请',
|
||||||
|
success: (res) => {
|
||||||
|
if (res.confirm) {
|
||||||
|
rejectFriend(this.message.sourceUserId).then(res => {
|
||||||
|
this.clearMessages()
|
||||||
|
}).catch(err => {
|
||||||
|
uni.showToast({
|
||||||
|
icon: 'none',
|
||||||
|
title: err.message
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
// 不管是通过还是拒绝,都要把相关的信息清理
|
||||||
|
clearMessages() {
|
||||||
|
RongIMLib.deleteMessages(RongIMLib.ConversationType.SYSTEM, this.message.sourceUserId)
|
||||||
|
this.$emit('success')
|
||||||
|
uni.$emit('onContactNotification')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.apply--cell {
|
||||||
|
display: flex;
|
||||||
|
padding: $padding;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
.info {
|
||||||
|
flex: 1;
|
||||||
|
margin-left: $padding;
|
||||||
|
|
||||||
|
.name {
|
||||||
|
font-size: $title-size + 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
.message {
|
||||||
|
color: $text-gray-m;
|
||||||
|
font-size: $title-size-m;
|
||||||
|
margin-top: 10rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.action {
|
||||||
|
justify-content: space-between;
|
||||||
|
|
||||||
|
.u-button+.u-button {
|
||||||
|
margin-top: 10rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -1,15 +1,14 @@
|
|||||||
<template>
|
<template>
|
||||||
<view class="friend-apply">
|
<view class="friend-apply">
|
||||||
<block v-for="item in lists" v-if="lists.length > 0" :key="item.userId">
|
<block v-for="(item, index) in lists" v-if="lists.length > 0" :key="index">
|
||||||
<view class="lists">
|
<view class="lists">
|
||||||
<view class="" style="width: 100rpx;height: 100rpx;">
|
<view class="" style="width: 100rpx;height: 100rpx;">
|
||||||
<u-image class="cover" radius="4" width="100rpx" height="100rpx" :src="item.portraitUrl || require('@/static/user/cover.png')" :lazy-load="true" />
|
<u-avatar :src="JSON.parse(item.latestMessage.extra).portraitUrl" shape="square" size="44" />
|
||||||
</view>
|
</view>
|
||||||
<view class="right">
|
<view class="right">
|
||||||
<view class="title">
|
<view class="title">
|
||||||
<view class="name">{{ item.name }}</view>
|
<view class="name">{{ item.name }}</view>
|
||||||
<view class="des" v-if="isApply">{{ item.address || '这家伙很懒,什么都没有添加~' }}</view>
|
<view class="des">{{ item.latestMessage.message }}</view>
|
||||||
<view class="des" v-else>{{ item.remark || '你好,听说你很优秀想认识~' }}</view>
|
|
||||||
</view>
|
</view>
|
||||||
<view class="agress-btn">
|
<view class="agress-btn">
|
||||||
<span v-if="isAgree" @click="action('agree', item)">通过</span>
|
<span v-if="isAgree" @click="action('agree', item)">通过</span>
|
||||||
@@ -44,8 +43,8 @@ export default {
|
|||||||
default: false
|
default: false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
data() {
|
created() {
|
||||||
return {};
|
console.log(this.lists);
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
action(type, item) {
|
action(type, item) {
|
||||||
85
pages/im/components/messageCell.vue
Normal file
@@ -0,0 +1,85 @@
|
|||||||
|
<template>
|
||||||
|
<view class="message--cell">
|
||||||
|
<view class="avatar">
|
||||||
|
<u-badge max="99" shape="horn" absolute :offset="[-5, -8]" :value="item.unreadMessageCount" />
|
||||||
|
<u-avatar :src="contact(item.targetId).portraitUrl" shape="square" size="44" />
|
||||||
|
</view>
|
||||||
|
<view class="content">
|
||||||
|
<view class="header">
|
||||||
|
<view class="name">{{ contact(item.targetId).name }}</view>
|
||||||
|
<view class="time">{{ item.sentTime|timeCustomCN }}</view>
|
||||||
|
</view>
|
||||||
|
<message-preview class="preview" :msg="item.latestMessage" :conversationType="item.conversationType"
|
||||||
|
:user="item.latestMessage.userInfo" />
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import messagePreview from './messagePreview'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
props: {
|
||||||
|
item: {
|
||||||
|
type: Object,
|
||||||
|
default: function() {
|
||||||
|
return {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
contact() {
|
||||||
|
return function(targetId) {
|
||||||
|
return this.$store.getters.contactInfo(targetId)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
components: {
|
||||||
|
messagePreview
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.message--cell {
|
||||||
|
display: flex;
|
||||||
|
padding: 20rpx 0 0 20rpx;
|
||||||
|
|
||||||
|
.avatar {
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
.u-badge {
|
||||||
|
z-index: 998;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.content {
|
||||||
|
margin-left: 30rpx;
|
||||||
|
box-sizing: border-box;
|
||||||
|
position: relative;
|
||||||
|
flex: 1;
|
||||||
|
|
||||||
|
border-bottom-width: 0.5px !important;
|
||||||
|
border-color: $u-border-color !important;
|
||||||
|
border-bottom-style: solid;
|
||||||
|
|
||||||
|
.header {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
|
||||||
|
.name {
|
||||||
|
font-size: $title-size + 2;
|
||||||
|
color: #454545;
|
||||||
|
color: #454545;
|
||||||
|
}
|
||||||
|
|
||||||
|
.time {
|
||||||
|
font-size: $title-size-sm;
|
||||||
|
color: $text-gray-m;
|
||||||
|
position: absolute;
|
||||||
|
right: 30rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
65
pages/im/components/messagePreview.nvue
Normal file
@@ -0,0 +1,65 @@
|
|||||||
|
<template>
|
||||||
|
<view>
|
||||||
|
<view class="preview" v-if="msg.objectName=='RC:TxtMsg'">
|
||||||
|
<text v-if="conversationType == 3">{{ user.name }}: </text>{{ msg.content || '' }}
|
||||||
|
</view>
|
||||||
|
<view class="preview" v-if="msg.objectName=='RC:HQVCMsg'">
|
||||||
|
<text v-if="conversationType == 3">{{ user.name }}: </text>[语音]
|
||||||
|
</view>
|
||||||
|
<view class="preview" v-if="msg.objectName=='RC:ImgMsg'">
|
||||||
|
<text v-if="conversationType == 3">{{ user.name }}: </text>[图片]
|
||||||
|
</view>
|
||||||
|
<view class="preview" v-if="msg.objectName=='RC:GIFMsg'">
|
||||||
|
<text v-if="conversationType == 3">{{ user.name }}: </text>[表情]
|
||||||
|
</view>
|
||||||
|
<view class="preview" v-if="msg.objectName=='RC:FileMsg'">
|
||||||
|
<text v-if="conversationType == 3">{{ user.name }}: </text>[文件]
|
||||||
|
</view>
|
||||||
|
<view class="preview" v-if="msg.objectName=='RC:LBSMsg'">
|
||||||
|
<text v-if="conversationType == 3">{{ user.name }}: </text>[位置]
|
||||||
|
</view>
|
||||||
|
<view class="preview" v-if="msg.objectName=='RC:AudioMsg'">
|
||||||
|
<text v-if="conversationType == 3">{{ user.name }}: </text>[语音通话]
|
||||||
|
</view>
|
||||||
|
<view class="preview" v-if="msg.objectName=='RC:VideoMsg'">
|
||||||
|
<text v-if="conversationType == 3">{{ user.name }}: </text>[视频通话]
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
props: {
|
||||||
|
msg: {
|
||||||
|
type: Object,
|
||||||
|
default: {}
|
||||||
|
},
|
||||||
|
conversationType: {
|
||||||
|
type: Number,
|
||||||
|
default: 0
|
||||||
|
},
|
||||||
|
user: {
|
||||||
|
type: Object,
|
||||||
|
default: function() {
|
||||||
|
return {
|
||||||
|
name: ''
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.preview {
|
||||||
|
word-break: break-all;
|
||||||
|
color: $text-gray-m;
|
||||||
|
padding-top: $padding - 20;
|
||||||
|
padding-bottom: $padding;
|
||||||
|
font-size: $title-size-m;
|
||||||
|
height: 32rpx;
|
||||||
|
line-height: 32rpx;
|
||||||
|
width: 520rpx;
|
||||||
|
@extend .nowrap;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
83
pages/im/components/sentMessageBar.nvue
Normal file
@@ -0,0 +1,83 @@
|
|||||||
|
<template>
|
||||||
|
<view class="">
|
||||||
|
<!-- footer -->
|
||||||
|
<view class="footer">
|
||||||
|
<view class="msg-type" @click="changeMessageType">
|
||||||
|
<image class="icon" src="@/static/icon/key-icon.png" v-if="chatType === 0" mode="widthFix">
|
||||||
|
</image>
|
||||||
|
<image class="icon" src="@/static/icon/msg-icon.png" v-if="chatType === 1" mode="widthFix">
|
||||||
|
</image>
|
||||||
|
</view>
|
||||||
|
<sent-voice v-if="chatType === 0" :conversationType="conversationType" :targetId="targetId"
|
||||||
|
@success="onSuccess" />
|
||||||
|
<sent-text v-if="chatType === 1" :conversationType="conversationType" :targetId="targetId"
|
||||||
|
@success="onSuccess" />
|
||||||
|
<view class="msg-type msg-popups" @click="showPopups = !showPopups">
|
||||||
|
<image class="icon" src="@/static/icon/popups-icon.png"></image>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<!-- 弹出层 -->
|
||||||
|
<sent-popups :show="showPopups" :conversationType="conversationType" :targetId="targetId"
|
||||||
|
@success="() => {showPopups = false, onSuccess()}"></sent-popups>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import sentText from '../components/sentText'
|
||||||
|
import sentVoice from '../components/sentVoice'
|
||||||
|
import sentPopups from '../components/sentPopups'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
props: {
|
||||||
|
conversationType: {
|
||||||
|
type: Number,
|
||||||
|
default: 0
|
||||||
|
},
|
||||||
|
targetId: {
|
||||||
|
type: String,
|
||||||
|
default: ''
|
||||||
|
}
|
||||||
|
},
|
||||||
|
components: {
|
||||||
|
sentText,
|
||||||
|
sentVoice,
|
||||||
|
sentPopups
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
chatType: 1, // 0 语音,1 文本
|
||||||
|
showPopups: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
// 切换聊天类型,语音/文本
|
||||||
|
changeMessageType() {
|
||||||
|
this.chatType = this.chatType === 1 ? 0 : 1
|
||||||
|
},
|
||||||
|
onSuccess() {
|
||||||
|
this.$emit('onSuccess')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.footer {
|
||||||
|
background: white;
|
||||||
|
padding: 20rpx 30rpx;
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
flex-direction: row;
|
||||||
|
|
||||||
|
.msg-type {
|
||||||
|
width: 70rpx;
|
||||||
|
height: 70rpx;
|
||||||
|
|
||||||
|
.icon {
|
||||||
|
margin: 5rpx;
|
||||||
|
width: 60rpx;
|
||||||
|
height: 60rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
173
pages/im/components/sentPopups.nvue
Normal file
@@ -0,0 +1,173 @@
|
|||||||
|
<template>
|
||||||
|
<view class="sent--popups u-border-top" v-if="show">
|
||||||
|
<view class="item" @click="onPopupsItem('picture')">
|
||||||
|
<image class="icon" src="@/static/icon/popups-icon-00.png" mode="widthFix"></image>
|
||||||
|
<text class="text">相册</text>
|
||||||
|
</view>
|
||||||
|
<view class="item" @click="onPopupsItem('camera')">
|
||||||
|
<image class="icon" src="@/static/icon/popups-icon-01.png" mode="widthFix"></image>
|
||||||
|
<text class="text">拍摄</text>
|
||||||
|
</view>
|
||||||
|
<view class="item" @click="onPopupsItem('video')">
|
||||||
|
<image class="icon" src="@/static/icon/popups-icon-02.png" mode="widthFix"></image>
|
||||||
|
<text class="text">视频通话</text>
|
||||||
|
</view>
|
||||||
|
<view class="item" @click="onPopupsItem('location')">
|
||||||
|
<image class="icon" src="@/static/icon/popups-icon-03.png" mode="widthFix"></image>
|
||||||
|
<text class="text">位置</text>
|
||||||
|
</view>
|
||||||
|
<view class="item" @click="onPopupsItem('redpacket')">
|
||||||
|
<image class="icon" src="@/static/icon/popups-icon-04.png" mode="widthFix"></image>
|
||||||
|
<text class="text">红包</text>
|
||||||
|
</view>
|
||||||
|
<view class="item" @click="onPopupsItem('file')">
|
||||||
|
<image class="icon" src="@/static/icon/popups-icon-05.png" mode="widthFix"></image>
|
||||||
|
<text class="text">文件</text>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<u-action-sheet :actions="callActions" cancelText="取消" @close="callShow = false" @select="singleCall"
|
||||||
|
:show="callShow">
|
||||||
|
</u-action-sheet>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import im from '@/utils/im/index.js'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
callActions: [{
|
||||||
|
type: 0,
|
||||||
|
name: '语音通话'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 1,
|
||||||
|
name: '视频通话'
|
||||||
|
}
|
||||||
|
],
|
||||||
|
callShow: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
props: {
|
||||||
|
show: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
|
},
|
||||||
|
conversationType: {
|
||||||
|
type: Number,
|
||||||
|
default: 0
|
||||||
|
},
|
||||||
|
targetId: {
|
||||||
|
type: String,
|
||||||
|
default: ''
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
user() {
|
||||||
|
return this.$store.getters.sender
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
singleCall(e) {
|
||||||
|
uni.showToast({
|
||||||
|
icon: 'none',
|
||||||
|
title: '功能正在开发中'
|
||||||
|
})
|
||||||
|
// CallLib.startSingleCall(this.targetId, e.type, '');
|
||||||
|
// uni.redirectTo({
|
||||||
|
// url: '/pages/im/private/call?targetId=' + this.targetId + '&mediaType=' + e.type
|
||||||
|
// })
|
||||||
|
},
|
||||||
|
onPopupsItem(type) {
|
||||||
|
switch (type) {
|
||||||
|
case 'picture':
|
||||||
|
uni.chooseImage({
|
||||||
|
count: 9,
|
||||||
|
sourceType: ['album'],
|
||||||
|
success: res => {
|
||||||
|
im.sentImage(this.conversationType, this.targetId, res.tempFilePaths[0],
|
||||||
|
this.user, (
|
||||||
|
res) => {
|
||||||
|
this.success()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
break;
|
||||||
|
case 'camera':
|
||||||
|
uni.chooseImage({
|
||||||
|
sourceType: ['camera'],
|
||||||
|
success: res => {
|
||||||
|
im.sentImage(this.conversationType, this.targetId, res.tempFilePaths[0],
|
||||||
|
this.user, (
|
||||||
|
res) => {
|
||||||
|
this.success()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
break;
|
||||||
|
case 'video':
|
||||||
|
this.callShow = true
|
||||||
|
break;
|
||||||
|
case 'location':
|
||||||
|
uni.showToast({
|
||||||
|
icon: 'none',
|
||||||
|
title: '功能正在开发中'
|
||||||
|
})
|
||||||
|
// uni.chooseLocation({
|
||||||
|
// success: res => {
|
||||||
|
// console.log(res);
|
||||||
|
// this.success()
|
||||||
|
// }
|
||||||
|
// })
|
||||||
|
break;
|
||||||
|
case 'redpacket':
|
||||||
|
uni.showToast({
|
||||||
|
icon: 'none',
|
||||||
|
title: '功能正在开发中'
|
||||||
|
})
|
||||||
|
break;
|
||||||
|
case 'file':
|
||||||
|
uni.showToast({
|
||||||
|
icon: 'none',
|
||||||
|
title: '功能正在开发中'
|
||||||
|
})
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// 处理返回
|
||||||
|
success() {
|
||||||
|
this.$emit('success')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.sent--popups {
|
||||||
|
background: white;
|
||||||
|
padding: 30rpx 15rpx;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
flex-direction: row;
|
||||||
|
|
||||||
|
.item {
|
||||||
|
width: 150rpx;
|
||||||
|
margin: 15rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.text {
|
||||||
|
text-align: center;
|
||||||
|
font-size: 26rpx;
|
||||||
|
color: #555;
|
||||||
|
padding-top: 15rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon {
|
||||||
|
width: 110rpx;
|
||||||
|
height: 110rpx;
|
||||||
|
margin: 0 20rpx;
|
||||||
|
border-radius: 20rpx;
|
||||||
|
background: #F3F6FB;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
84
pages/im/components/sentText.nvue
Normal file
@@ -0,0 +1,84 @@
|
|||||||
|
<template>
|
||||||
|
<view class="sent--text">
|
||||||
|
<input class="input" type="text" @focus="focus" @blur="blur" v-model="inputTxt" confirm-type="send"
|
||||||
|
@confirm="sent" cursor-spacing="10" />
|
||||||
|
<!-- <button class="button" size="mini" :disabled="disabled" @click="sent">发送</button> -->
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import im from '@/utils/im/index.js'
|
||||||
|
import * as RongIMLib from '@/uni_modules/RongCloud-IMWrapper/js_sdk/index'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
props: {
|
||||||
|
conversationType: {
|
||||||
|
type: Number,
|
||||||
|
default: 0
|
||||||
|
},
|
||||||
|
targetId: {
|
||||||
|
type: String,
|
||||||
|
default: ''
|
||||||
|
},
|
||||||
|
inputTxt: {
|
||||||
|
type: String,
|
||||||
|
default: ''
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
disabled() {
|
||||||
|
return this.inputTxt.length === 0
|
||||||
|
},
|
||||||
|
user() {
|
||||||
|
return this.$store.getters.sender
|
||||||
|
}
|
||||||
|
},
|
||||||
|
created() {
|
||||||
|
RongIMLib.getTextMessageDraft(this.conversationType, this.targetId, ({
|
||||||
|
draft
|
||||||
|
}) => {
|
||||||
|
draft ? this.inputTxt = draft : ''
|
||||||
|
})
|
||||||
|
},
|
||||||
|
beforeDestroy() {
|
||||||
|
RongIMLib.saveTextMessageDraft(this.conversationType, this.targetId, this.inputTxt, (res) => {
|
||||||
|
console.log('销毁组件之前,保存草稿信息,但是没有执行', res);
|
||||||
|
})
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
// 发送文本消息
|
||||||
|
sent() {
|
||||||
|
if (!this.disabled) {
|
||||||
|
RongIMLib.clearTextMessageDraft(this.conversationType, this.targetId)
|
||||||
|
im.sentText(this.conversationType, this.targetId, this.inputTxt, this.user, () => {
|
||||||
|
this.$emit('success')
|
||||||
|
this.inputTxt = ''
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
focus() {
|
||||||
|
this.$emit('focus')
|
||||||
|
},
|
||||||
|
blur() {
|
||||||
|
this.$emit('blur')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.sent--text {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
justify-content: space-between;
|
||||||
|
|
||||||
|
.input {
|
||||||
|
background: #F3F6FB;
|
||||||
|
height: 70rpx;
|
||||||
|
width: 500rpx;
|
||||||
|
border-radius: 10rpx;
|
||||||
|
margin-right: 15rpx;
|
||||||
|
padding: 0 20rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
144
pages/im/components/sentVoice.nvue
Normal file
@@ -0,0 +1,144 @@
|
|||||||
|
<template>
|
||||||
|
<view class="send--voice">
|
||||||
|
<view class="voice" hover-class="chat-hover" @touchstart="startRecord" @touchend="stopRecord">
|
||||||
|
<text class="button">按住说话</text>
|
||||||
|
</view>
|
||||||
|
<!-- 录音中提示 -->
|
||||||
|
<view class="modal" v-if="showRecordTip">
|
||||||
|
<image class="icon" src="@/static/icon/record-icon.png" mode="widthFix"></image>
|
||||||
|
<text class="text">录音中 {{recordTime}} s</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import im from '@/utils/im/index.js'
|
||||||
|
import permision from '@/utils/permission.js'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
props: {
|
||||||
|
conversationType: {
|
||||||
|
type: Number,
|
||||||
|
default: 0
|
||||||
|
},
|
||||||
|
targetId: {
|
||||||
|
type: String,
|
||||||
|
default: ''
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
showRecordTip: false,
|
||||||
|
recordTime: 60,
|
||||||
|
interval: 0,
|
||||||
|
maxRecordTime: 60,
|
||||||
|
recorderManager: null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
user() {
|
||||||
|
return this.$store.getters.sender
|
||||||
|
}
|
||||||
|
},
|
||||||
|
created() {
|
||||||
|
this.recorderManager = uni.getRecorderManager()
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
// 检查安卓录制权限
|
||||||
|
async getAndroidPermission() {
|
||||||
|
return await permision.requestAndroidPermission('android.permission.RECORD_AUDIO')
|
||||||
|
},
|
||||||
|
// 录制语音消息
|
||||||
|
startRecord() {
|
||||||
|
this.getAndroidPermission().then(code => {
|
||||||
|
switch (code) {
|
||||||
|
case 1:
|
||||||
|
this.showRecordTip = true
|
||||||
|
this.recorderManager.start()
|
||||||
|
this.interval = setInterval(() => {
|
||||||
|
this.recordTime -= 1
|
||||||
|
if (this.recordTime === 0) {
|
||||||
|
this.stopRecord()
|
||||||
|
}
|
||||||
|
}, 1000)
|
||||||
|
break;
|
||||||
|
case 0:
|
||||||
|
uni.showToast({
|
||||||
|
title: '暂无麦克风权限,请前往应用设置开启麦克风',
|
||||||
|
icon: 'none'
|
||||||
|
})
|
||||||
|
break;
|
||||||
|
case -1:
|
||||||
|
uni.showToast({
|
||||||
|
title: '应用权限错误',
|
||||||
|
icon: 'none'
|
||||||
|
})
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
// 结束录音
|
||||||
|
stopRecord(e) {
|
||||||
|
if (!this.showRecordTip) return
|
||||||
|
this.recorderManager.stop()
|
||||||
|
clearInterval(this.interval)
|
||||||
|
// 监听录音结束
|
||||||
|
this.recorderManager.onStop(res => {
|
||||||
|
im.sentVoice(this.conversationType, this.targetId, res.tempFilePath, (this.maxRecordTime -
|
||||||
|
this
|
||||||
|
.recordTime), this.user, () => {
|
||||||
|
setTimeout(() => {
|
||||||
|
this.$emit('success')
|
||||||
|
}, 500)
|
||||||
|
})
|
||||||
|
this.recordTime = this.maxRecordTime
|
||||||
|
this.showRecordTip = false
|
||||||
|
})
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.send--voice {
|
||||||
|
.voice {
|
||||||
|
background: $window-color;
|
||||||
|
height: 70rpx;
|
||||||
|
line-height: 70rpx;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
width: 500rpx;
|
||||||
|
border-radius: 10rpx;
|
||||||
|
margin-right: 15rpx;
|
||||||
|
|
||||||
|
.button {
|
||||||
|
font-size: 30rpx;
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.modal {
|
||||||
|
background: rgba(0, 0, 0, .6);
|
||||||
|
position: fixed;
|
||||||
|
height: 200rpx;
|
||||||
|
width: 300rpx;
|
||||||
|
border-radius: 10rpx;
|
||||||
|
z-index: 99;
|
||||||
|
top: 550rpx;
|
||||||
|
left: 225rpx;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
|
||||||
|
.icon {
|
||||||
|
width: 88rpx;
|
||||||
|
height: 88rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.text {
|
||||||
|
font-size: 28rpx;
|
||||||
|
color: #FFFFFF;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
73
pages/im/components/showImage.nvue
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
<template>
|
||||||
|
<view class="">
|
||||||
|
<text class="name" v-if="!guest && name">{{ name }}</text>
|
||||||
|
<view class="msg--image" :class="guest ? 'right': 'left'">
|
||||||
|
<image class="img" :src="msg.thumbnail" @click="previewImage" mode="widthFix"></image>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
name: 'showImage',
|
||||||
|
props: {
|
||||||
|
msg: {
|
||||||
|
type: Object,
|
||||||
|
default: () => {
|
||||||
|
return {
|
||||||
|
local: '',
|
||||||
|
remote: '',
|
||||||
|
objectName: '',
|
||||||
|
thumbnail: '',
|
||||||
|
isFull: false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
guest: {
|
||||||
|
type: Boolean,
|
||||||
|
default: true
|
||||||
|
},
|
||||||
|
name: {
|
||||||
|
type: String,
|
||||||
|
default: ''
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
previewImage() {
|
||||||
|
uni.previewImage({
|
||||||
|
urls: [
|
||||||
|
this.msg.remote
|
||||||
|
],
|
||||||
|
current: 1
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.name {
|
||||||
|
font-size: 24rpx;
|
||||||
|
line-height: 34rpx;
|
||||||
|
color: $text-gray-m;
|
||||||
|
}
|
||||||
|
|
||||||
|
.msg--image {
|
||||||
|
padding: 20rpx;
|
||||||
|
|
||||||
|
&.left {
|
||||||
|
border-radius: 0 20rpx 20rpx 20rpx;
|
||||||
|
background: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.right {
|
||||||
|
border-radius: 20rpx 0 20rpx 20rpx;
|
||||||
|
background: #34CE98;
|
||||||
|
}
|
||||||
|
|
||||||
|
.img {
|
||||||
|
width: 150rpx;
|
||||||
|
border-radius: 10rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
54
pages/im/components/showText.nvue
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
<template>
|
||||||
|
<view class="msg--text">
|
||||||
|
<text class="name" v-if="!guest && name">{{ name }}</text>
|
||||||
|
<text class="im--text" :class="guest ? 'right': 'left'">{{ msg.content }}</text>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
name: 'showText',
|
||||||
|
props: {
|
||||||
|
msg: {
|
||||||
|
type: Object,
|
||||||
|
default: {}
|
||||||
|
},
|
||||||
|
name: {
|
||||||
|
type: String,
|
||||||
|
default: ''
|
||||||
|
},
|
||||||
|
guest: {
|
||||||
|
type: Boolean,
|
||||||
|
default: true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.msg--text {
|
||||||
|
.name {
|
||||||
|
font-size: 24rpx;
|
||||||
|
line-height: 34rpx;
|
||||||
|
color: $text-gray-m;
|
||||||
|
}
|
||||||
|
|
||||||
|
.im--text {
|
||||||
|
max-width: 500rpx;
|
||||||
|
padding: 20rpx;
|
||||||
|
line-height: 44rpx;
|
||||||
|
font-size: 32rpx;
|
||||||
|
|
||||||
|
&.left {
|
||||||
|
border-radius: 0 20rpx 20rpx 20rpx;
|
||||||
|
background: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.right {
|
||||||
|
border-radius: 20rpx 0 20rpx 20rpx;
|
||||||
|
background: $main-color;
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -1,9 +1,10 @@
|
|||||||
<template>
|
<template>
|
||||||
<view>
|
<view class="">
|
||||||
<view class="im--audio" :class="guest ? 'right': 'left'" @click="onPlayMsg">
|
<text class="name" v-if="!guest && name">{{ name }}</text>
|
||||||
<image v-if="!guest" class="audio-mp3" src="@/static/icon/audio_green.png" mode="widthFix"></image>
|
<view class="msg--voice" :class="guest ? 'right': 'left'" @click="onPlayMsg">
|
||||||
<text class="audio-text">"{{msg.duration}}"</text>
|
<image v-if="!guest" class="icon" src="@/static/icon/audio_green.png" mode="widthFix"></image>
|
||||||
<image v-if="guest" class="audio-mp3" src="@/static/icon/audio_white.png" mode="widthFix"></image>
|
<text class="duration">{{msg.duration}}"</text>
|
||||||
|
<image v-if="guest" class="icon" src="@/static/icon/audio_white.png" mode="widthFix"></image>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</template>
|
</template>
|
||||||
@@ -23,6 +24,10 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
name: {
|
||||||
|
type: String,
|
||||||
|
default: ''
|
||||||
|
},
|
||||||
guest: {
|
guest: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: true
|
default: true
|
||||||
@@ -57,43 +62,45 @@
|
|||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped lang="scss">
|
||||||
.im--audio {
|
.name {
|
||||||
|
font-size: 24rpx;
|
||||||
|
line-height: 34rpx;
|
||||||
|
color: $text-gray-m;
|
||||||
|
}
|
||||||
|
|
||||||
|
.msg--voice {
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
height: 79rpx;
|
height: 79rpx;
|
||||||
width: 170rpx;
|
width: 170rpx;
|
||||||
padding: 0 20rpx;
|
padding: 0 20rpx;
|
||||||
box-sizing:border-box;
|
box-sizing: border-box;
|
||||||
/* box-sizing: border-box; */
|
|
||||||
}
|
|
||||||
|
|
||||||
,
|
.icon {
|
||||||
.im--audio.left {
|
width: 38rpx;
|
||||||
border-radius: 0 20rpx 20rpx 20rpx;
|
height: 38rpx;
|
||||||
background: white;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
.im--audio.right {
|
&.left {
|
||||||
border-radius: 20rpx 0 20rpx 20rpx;
|
border-radius: 0 20rpx 20rpx 20rpx;
|
||||||
background: #34CE98;
|
background: white;
|
||||||
}
|
|
||||||
|
|
||||||
.audio-mp3 {
|
.duration {
|
||||||
width: 38rpx;
|
color: #333;
|
||||||
height: 38rpx;
|
font-size: 30rpx;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.audio-text {
|
&.right {
|
||||||
font-size: 30rpx;
|
border-radius: 20rpx 0 20rpx 20rpx;
|
||||||
}
|
background: $main-color;
|
||||||
|
|
||||||
.im--audio.left .audio-text {
|
.duration {
|
||||||
color: #333;
|
color: white;
|
||||||
}
|
font-size: 30rpx;
|
||||||
|
}
|
||||||
.im--audio.right .audio-text {
|
}
|
||||||
color: white;
|
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
@@ -1,47 +1,32 @@
|
|||||||
<template>
|
<template>
|
||||||
<view>
|
<view>
|
||||||
<u-index-list :index-list="indexs" inactiveColor="#666" activeColor="#34CE98">
|
<u-index-list :index-list="indexs" inactiveColor="#666" activeColor="#34CE98">
|
||||||
<view>
|
<view class="friend-flex u-border-bottom" @click="toPending">
|
||||||
<view class="friend-flex u-border-bottom" @click="toPending">
|
<u-avatar class="cover" size="40" shape="square" :src="require('@/static/im/im_01.png')"></u-avatar>
|
||||||
<u-avatar class="cover" size="40" shape="square" :src="require('@/static/im/im_01.png')"></u-avatar>
|
<u-badge max="99" absolute :offset="[23, 20]" :value="pendingCount" />
|
||||||
<view class="name">
|
<view class="info">新的朋友</view>
|
||||||
新的朋友 ({{ pendingCount }})
|
</view>
|
||||||
</view>
|
<view class="friend-flex" @click="toGroup">
|
||||||
</view>
|
<u-avatar class="cover" size="40" shape="square" :src="require('@/static/im/im_00.png')"></u-avatar>
|
||||||
<view class="friend-flex" @click="showToast">
|
<view class="info">我的群聊</view>
|
||||||
<u-avatar class="cover" size="40" shape="square" :src="require('@/static/im/im_00.png')"></u-avatar>
|
|
||||||
<view class="name">我的群聊</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
</view>
|
||||||
<block v-if="friends.length > 0">
|
<block v-if="friends.length > 0">
|
||||||
<template v-for="(item, friend) in friends">
|
<u-index-item v-for="(item, fkey) in friends" :key="fkey">
|
||||||
<!-- #ifdef APP-NVUE -->
|
<u-index-anchor :text="indexs[fkey]" bgColor="#F3F6FB" height="20" size="12" color="#666">
|
||||||
<u-index-anchor :text="indexs[friend]" bgColor="#F3F6FB" height="20" size="12" color="#666">
|
|
||||||
</u-index-anchor>
|
</u-index-anchor>
|
||||||
<!-- #endif -->
|
|
||||||
<u-index-item>
|
<view v-for="(friendItem, index) in item" :key="index" class="friend-flex u-border-bottom"
|
||||||
<!-- #ifndef APP-NVUE -->
|
@click="toFriend(friendItem.targetId)">
|
||||||
<u-index-anchor :text="indexs[friend]" bgColor="#F3F6FB" height="20" size="12" color="#666">
|
<u-avatar size="40" shape="square" :src="contact(friendItem.targetId).portraitUrl" />
|
||||||
</u-index-anchor>
|
<view class="info">
|
||||||
<!-- #endif -->
|
<view class="name">{{ contact(friendItem.targetId).name }}</view>
|
||||||
<view v-for="(friendItem, index) in item" :key="friendItem.userId"
|
<view class="address">{{ friendItem.address }}</view>
|
||||||
class="friend-flex u-border-bottom"
|
|
||||||
@click="$Router.push({ name: 'imFriendsInfo', params: { targetId: friendItem.userId } })">
|
|
||||||
<block v-if="friendItem.portraitUrl != ''">
|
|
||||||
<u-avatar class="cover" size="40" shape="square" :src="friendItem.portraitUrl || ''"
|
|
||||||
:default-url="require('@/static/user/cover.png')"></u-avatar>
|
|
||||||
</block>
|
|
||||||
<block v-else>
|
|
||||||
<u-avatar class="cover" size="40" shape="square"
|
|
||||||
:src="require('@/static/user/cover.png')"></u-avatar>
|
|
||||||
</block>
|
|
||||||
<view class="name">{{ friendItem.name }}</view>
|
|
||||||
</view>
|
</view>
|
||||||
</u-index-item>
|
</view>
|
||||||
</template>
|
</u-index-item>
|
||||||
</block>
|
</block>
|
||||||
<block v-else>
|
<block v-else>
|
||||||
<u-empty class="pages-null" mode="data" icon="http://cdn.uviewui.com/uview/empty/data.png" text="暂无好友">
|
<u-empty class="pages-null" mode="data" text="暂无好友">
|
||||||
</u-empty>
|
</u-empty>
|
||||||
</block>
|
</block>
|
||||||
</u-index-list>
|
</u-index-list>
|
||||||
@@ -50,9 +35,9 @@
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
import {
|
import {
|
||||||
getFriends,
|
getFriendsLetter
|
||||||
getPendingCount
|
|
||||||
} from '@/apis/interfaces/im';
|
} from '@/apis/interfaces/im';
|
||||||
|
import * as RongIMLib from '@/uni_modules/RongCloud-IMWrapper/js_sdk/index'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
data() {
|
data() {
|
||||||
@@ -62,22 +47,53 @@
|
|||||||
pendingCount: 0
|
pendingCount: 0
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
onShow() {
|
computed: {
|
||||||
getFriends().then(res => {
|
contact() {
|
||||||
this.indexs = res.indexList
|
return function(targetId) {
|
||||||
this.friends = res.itemArr
|
return this.$store.getters.contactInfo(targetId)
|
||||||
})
|
}
|
||||||
getPendingCount().then(res => {
|
}
|
||||||
console.log(res);
|
},
|
||||||
this.pendingCount = res
|
onLoad() {
|
||||||
|
this.getFriendList()
|
||||||
|
this.checkNewFriendPending()
|
||||||
|
uni.$on('onContactNotification', () => {
|
||||||
|
this.checkNewFriendPending()
|
||||||
|
this.getFriendList()
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
onUnload() {
|
||||||
|
uni.$off('onContactNotification')
|
||||||
|
},
|
||||||
methods: {
|
methods: {
|
||||||
showToast() {
|
getFriendList() {
|
||||||
uni.showToast({
|
getFriendsLetter().then(res => {
|
||||||
title: '群聊功能暂未开放,敬请期待',
|
this.indexs = res.indexList
|
||||||
icon: 'none'
|
this.friends = res.itemArr
|
||||||
});
|
})
|
||||||
|
},
|
||||||
|
checkNewFriendPending() {
|
||||||
|
// 获取是否有新的好友申请
|
||||||
|
RongIMLib.getConversationList([RongIMLib.ConversationType.SYSTEM], 1000, 0, (res) => {
|
||||||
|
if (res.code === 0) {
|
||||||
|
this.pendingCount = res.conversations.filter((item) => {
|
||||||
|
return item.objectName == RongIMLib.ObjectName.ContactNotification
|
||||||
|
}).length
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
toGroup() {
|
||||||
|
uni.navigateTo({
|
||||||
|
url: '/pages/im/group/index',
|
||||||
|
fail(err) {
|
||||||
|
console.log(err);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
toFriend(targetId) {
|
||||||
|
uni.navigateTo({
|
||||||
|
url: '/pages/im/friends/info?targetId=' + targetId
|
||||||
|
})
|
||||||
},
|
},
|
||||||
// 新朋友
|
// 新朋友
|
||||||
toPending() {
|
toPending() {
|
||||||
@@ -108,14 +124,21 @@
|
|||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
|
||||||
// .cover
|
.info {
|
||||||
.name {
|
|
||||||
flex: 1;
|
flex: 1;
|
||||||
padding-left: $padding;
|
margin-left: $padding;
|
||||||
font-size: $title-size + 2;
|
|
||||||
font-size: $title-size + 2;
|
.name {
|
||||||
color: #454545 !important;
|
font-size: $title-size + 2;
|
||||||
@extend .nowrap;
|
font-size: $title-size + 2;
|
||||||
|
color: #454545 !important;
|
||||||
|
@extend .nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.address {
|
||||||
|
color: $text-gray-m;
|
||||||
|
font-size: $title-size-m - 5;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -2,10 +2,11 @@
|
|||||||
<view class="content">
|
<view class="content">
|
||||||
<!-- 用户信息 -->
|
<!-- 用户信息 -->
|
||||||
<view class="info-flex">
|
<view class="info-flex">
|
||||||
<u-avatar :src="userInfo.portraitUrl || require('@/static/user/cover.png')" shape="square" size="50" bg-color="#fff"></u-avatar>
|
<u-avatar :src="userInfo.portraitUrl || require('@/static/user/cover.png')" shape="square" size="50"
|
||||||
|
bg-color="#fff"></u-avatar>
|
||||||
<view class="info-text">
|
<view class="info-text">
|
||||||
<view class="nickname">{{userInfo.name}}</view>
|
<view class="nickname">{{ userInfo.name }}</view>
|
||||||
<view class="address" @longpress="copyAddress">地址:{{userInfo.address}}</view>
|
<view class="address" @longpress="copyAddress">地址:{{ userInfo.address }}</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
<!-- 用户资料 -->
|
<!-- 用户资料 -->
|
||||||
@@ -105,10 +106,11 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
onLoad(e) {
|
onLoad(e) {
|
||||||
console.log(e);
|
|
||||||
this.targetId = e.targetId
|
this.targetId = e.targetId
|
||||||
getFriendInfo(e.targetId).then(res => {
|
getFriendInfo(e.targetId).then(res => {
|
||||||
this.userInfo = res
|
this.userInfo = res
|
||||||
|
// 获取到用户信息之后,去检查一下要不要更新
|
||||||
|
this.$store.dispatch('updateContact', res)
|
||||||
uni.setNavigationBarTitle({
|
uni.setNavigationBarTitle({
|
||||||
title: res.name
|
title: res.name
|
||||||
})
|
})
|
||||||
@@ -125,7 +127,7 @@
|
|||||||
if (code == 0) {
|
if (code == 0) {
|
||||||
this.isTop = conversation.isTop
|
this.isTop = conversation.isTop
|
||||||
}
|
}
|
||||||
});
|
})
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
copyAddress() {
|
copyAddress() {
|
||||||
@@ -141,7 +143,7 @@
|
|||||||
},
|
},
|
||||||
toPrivate() {
|
toPrivate() {
|
||||||
uni.redirectTo({
|
uni.redirectTo({
|
||||||
url: '/pages/im/private/chat?conversationType=1&targetId=' + this.targetId
|
url: '/pages/im/private/chat?targetId=' + this.targetId
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
setRemark() {
|
setRemark() {
|
||||||
@@ -156,7 +158,8 @@
|
|||||||
content: '确认删除后不可恢复',
|
content: '确认删除后不可恢复',
|
||||||
success: e => {
|
success: e => {
|
||||||
if (e.confirm) {
|
if (e.confirm) {
|
||||||
deleteFriend(this.targetId).then(res => {
|
deleteFriend(this.targetId).then(res => {
|
||||||
|
uni.$emit('onContactNotification')
|
||||||
// 删除聊天记录
|
// 删除聊天记录
|
||||||
RongIMLib.deleteMessages(1, this.targetId);
|
RongIMLib.deleteMessages(1, this.targetId);
|
||||||
RongIMLib.removeConversation(1, this.targetId);
|
RongIMLib.removeConversation(1, this.targetId);
|
||||||
@@ -313,14 +316,16 @@
|
|||||||
background: white;
|
background: white;
|
||||||
margin: $margin;
|
margin: $margin;
|
||||||
border-radius: $radius;
|
border-radius: $radius;
|
||||||
.u-border-bottom{
|
|
||||||
|
.u-border-bottom {
|
||||||
border-bottom: solid 1rpx #f9f9f9 !important;
|
border-bottom: solid 1rpx #f9f9f9 !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.item {
|
.item {
|
||||||
line-height: 100rpx;
|
line-height: 100rpx;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
padding:10rpx $padding;
|
padding: 10rpx $padding;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
font-size: $title-size-lg;
|
font-size: $title-size-lg;
|
||||||
|
|
||||||
|
|||||||
@@ -1,11 +1,3 @@
|
|||||||
<!--
|
|
||||||
* @Description:新朋友即新增好友申请列表 可以搜索跳转
|
|
||||||
* @Author: Aimee·Zhang
|
|
||||||
* @Date: 2022-01-24 10:49:15
|
|
||||||
* @LastEditors: Aimee·Zhang
|
|
||||||
* @LastEditTime: 2022-01-25 10:18:26
|
|
||||||
-->
|
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<view class="pending">
|
<view class="pending">
|
||||||
<u-sticky>
|
<u-sticky>
|
||||||
@@ -14,67 +6,42 @@
|
|||||||
:disabled="true" :show-action="false" />
|
:disabled="true" :show-action="false" />
|
||||||
</view>
|
</view>
|
||||||
</u-sticky>
|
</u-sticky>
|
||||||
<block v-if="pedings.length > 0">
|
<view v-for="(item, index) in pendings" :key="index">
|
||||||
<applyFriend :lists="pedings" :isAgree="true" :isReject="false" @action="action" />
|
<apply-cell :message="item.latestMessage" @success="getPendingList" />
|
||||||
</block>
|
|
||||||
<view class="no-lists" v-else>
|
|
||||||
<u-image class="cover" radius="4" width="400rpx" height="400rpx"
|
|
||||||
:src="require('@/static/imgs/no-friend.png')" :lazy-load="true" />
|
|
||||||
<span>暂无申请记录~</span>
|
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import {
|
import * as RongIMLib from '@/uni_modules/RongCloud-IMWrapper/js_sdk/index'
|
||||||
getPedings,
|
import applyCell from '../components/friendApplyCell'
|
||||||
resolveFriend,
|
|
||||||
rejectFriend
|
|
||||||
} from '@/apis/interfaces/im.js'
|
|
||||||
import * as RongIMLib from "@/uni_modules/RongCloud-IMWrapper/js_sdk/index"
|
|
||||||
import applyFriend from '@/components/friend-apply-reject-agree'
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: {
|
components: {
|
||||||
applyFriend
|
applyCell
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
pedings: []
|
pendings: []
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
onLoad() {
|
onLoad() {
|
||||||
this.getPeddingList()
|
this.getPendingList()
|
||||||
|
uni.$on('onContactNotification', this.getPendingList)
|
||||||
|
},
|
||||||
|
onUnload() {
|
||||||
|
uni.$off('onContactNotification')
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
// 操作同意或拒绝
|
getPendingList() {
|
||||||
action(e) {
|
// 获取系统中的好友关系会话列表
|
||||||
let url = e.type === 'agree' ? resolveFriend : rejectFriend
|
RongIMLib.getConversationList([RongIMLib.ConversationType.SYSTEM], 1000, 0, (res) => {
|
||||||
uni.showModal({
|
if (res.code === 0) {
|
||||||
title: e.type === 'agree' ? '通过' : '拒绝',
|
this.pendings = res.conversations.filter((item) => {
|
||||||
content: e.type === 'agree' ? '通过后即可与该用户畅所欲言' : '拒绝后将不会收到该用户发来信息',
|
return item.objectName == RongIMLib.ObjectName.ContactNotification
|
||||||
success: res => {
|
})
|
||||||
if (res.confirm) {
|
|
||||||
url(e.item.userId).then(res => {
|
|
||||||
this.getPeddingList()
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
},
|
|
||||||
getPeddingList() {
|
|
||||||
// 获取系统中的好友关系会话列表
|
|
||||||
// RongIMLib.getConversationList([RongIMLib.ConversationType.SYSTEM], 50, 0, (res) => {
|
|
||||||
// if (res.code === 0) {
|
|
||||||
// this.pedings = res.conversations.filter((item) => {
|
|
||||||
// return item.objectName == RongIMLib.ObjectName.ContactNotification
|
|
||||||
// })
|
|
||||||
// }
|
|
||||||
// })
|
|
||||||
getPedings().then(res => {
|
|
||||||
console.log(res)
|
|
||||||
this.pedings = res
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -31,7 +31,7 @@
|
|||||||
searchFriend,
|
searchFriend,
|
||||||
pedingFriend
|
pedingFriend
|
||||||
} from '@/apis/interfaces/im.js';
|
} from '@/apis/interfaces/im.js';
|
||||||
import applyFriend from '@/components/friend-apply-reject-agree';
|
import applyFriend from '../components/friendApplyList.vue';
|
||||||
export default {
|
export default {
|
||||||
components: {
|
components: {
|
||||||
applyFriend
|
applyFriend
|
||||||
|
|||||||
54
pages/im/group/announceCreate.vue
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
<template>
|
||||||
|
<view class="create">
|
||||||
|
<u--textarea v-model="content" count height="200" maxlength="200" placeholder="请输入公告内容"></u--textarea>
|
||||||
|
|
||||||
|
<u-button type="primary" text="发布" @click="onCreate"></u-button>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import {
|
||||||
|
createGroupAnnouncement
|
||||||
|
} from '@/apis/interfaces/im.js'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
targetId: '',
|
||||||
|
content: ''
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onLoad(e) {
|
||||||
|
this.targetId = e.targetId
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
onCreate() {
|
||||||
|
createGroupAnnouncement(this.targetId, this.content).then(res => {
|
||||||
|
uni.showToast({
|
||||||
|
title: '发布成功',
|
||||||
|
success: () => {
|
||||||
|
setTimeout(() => {
|
||||||
|
uni.navigateBack()
|
||||||
|
}, 1000)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}).catch(err => {
|
||||||
|
uni.showToast({
|
||||||
|
icon: 'none',
|
||||||
|
title: err.message
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.create {
|
||||||
|
padding: $padding;
|
||||||
|
|
||||||
|
.u-button {
|
||||||
|
margin-top: $padding;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
105
pages/im/group/announcement.vue
Normal file
@@ -0,0 +1,105 @@
|
|||||||
|
<template>
|
||||||
|
<view class="announce">
|
||||||
|
<u-skeleton rows="2" :loading="loading" avatar :rows="5">
|
||||||
|
<view v-for="(item,index) in announcements" :key="index">
|
||||||
|
<view class="header">
|
||||||
|
<u-avatar :src="item.user.portraitUrl"></u-avatar>
|
||||||
|
<view class="user">
|
||||||
|
<view class="name">{{ item.user.name }}</view>
|
||||||
|
<view class="time">{{ item.created_at }}</view>
|
||||||
|
</view>
|
||||||
|
<view class="delete" v-if="isAdmin" @click="onDelete(item.announcement_id)">删除</view>
|
||||||
|
</view>
|
||||||
|
<view class="content">{{ item.content }}</view>
|
||||||
|
</view>
|
||||||
|
</u-skeleton>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import {
|
||||||
|
getGroupInfo,
|
||||||
|
getGroupAnnouncements,
|
||||||
|
deleteGroupAnnouncement
|
||||||
|
} from '@/apis/interfaces/im.js'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
targetId: '',
|
||||||
|
announcements: [],
|
||||||
|
loading: true,
|
||||||
|
isAdmin: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onLoad(e) {
|
||||||
|
this.targetId = e.targetId
|
||||||
|
getGroupInfo(this.targetId).then(res => {
|
||||||
|
this.isAdmin = res.group.is_admin
|
||||||
|
})
|
||||||
|
this.initData()
|
||||||
|
},
|
||||||
|
onNavigationBarButtonTap() {
|
||||||
|
if (this.isAdmin) {
|
||||||
|
uni.navigateTo({
|
||||||
|
url: '/pages/im/group/announceCreate?targetId=' + this.targetId
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
uni.showToast({
|
||||||
|
icon: 'none',
|
||||||
|
title: '没有权限'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
initData() {
|
||||||
|
getGroupAnnouncements(this.targetId).then(res => {
|
||||||
|
this.announcements = res
|
||||||
|
console.log(res);
|
||||||
|
this.loading = false
|
||||||
|
})
|
||||||
|
},
|
||||||
|
onDelete(aId) {
|
||||||
|
deleteGroupAnnouncement(this.targetId, aId).then(res => {
|
||||||
|
this.initData()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.announce {
|
||||||
|
padding: $padding;
|
||||||
|
|
||||||
|
.header {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
|
||||||
|
.user {
|
||||||
|
margin-left: $padding;
|
||||||
|
flex: 1;
|
||||||
|
|
||||||
|
.name {
|
||||||
|
line-height: 44rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.time {
|
||||||
|
margin-top: 15rpx;
|
||||||
|
font-size: 24rpx;
|
||||||
|
color: $text-gray-m;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.delete {
|
||||||
|
color: $text-price;
|
||||||
|
font-size: 32rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.content {
|
||||||
|
padding: $padding;
|
||||||
|
font-size: 34rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
186
pages/im/group/chat.nvue
Normal file
@@ -0,0 +1,186 @@
|
|||||||
|
<template>
|
||||||
|
<view class="group--chat">
|
||||||
|
<list class="body" :show-scrollbar="false">
|
||||||
|
<cell class="cell" v-for="(item, index) in messages" :key="index">
|
||||||
|
<view class="cell-item" :class="item.messageDirection == 1 ? 'right' : 'left'">
|
||||||
|
<u-avatar class="avatar" @click="toUser(item)" size="36" shape="square" :src="item.content.userInfo.portraitUrl" />
|
||||||
|
<view class="msg">
|
||||||
|
<show-voice v-if="item.objectName === 'RC:HQVCMsg'" :guest="item.messageDirection == 1"
|
||||||
|
:msg="item.content" :name="item.content.userInfo.name" />
|
||||||
|
<show-image v-if="item.objectName === 'RC:ImgMsg'" :guest="item.messageDirection == 1"
|
||||||
|
:msg="item.content" :name="item.content.userInfo.name" />
|
||||||
|
<show-text v-if="item.objectName === 'RC:TxtMsg'" :guest="item.messageDirection == 1"
|
||||||
|
:msg="item.content" :name="item.content.userInfo.name" />
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</cell>
|
||||||
|
<cell class="cell-footer" ref="chatBottom"></cell>
|
||||||
|
</list>
|
||||||
|
<sent-message-bar :conversationType="conversationType" :targetId="targetId" @onSuccess="getMessageList()" />
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import {
|
||||||
|
timeCustomCN
|
||||||
|
} from '@/utils/filters.js'
|
||||||
|
import * as RongIMLib from '@/uni_modules/RongCloud-IMWrapper/js_sdk/index'
|
||||||
|
import im from '@/utils/im/index.js'
|
||||||
|
import showVoice from '../components/showVoice'
|
||||||
|
import showImage from '../components/showImage'
|
||||||
|
import showText from '../components/showText'
|
||||||
|
import sentMessageBar from '../components/sentMessageBar'
|
||||||
|
|
||||||
|
const ChatList = uni.requireNativePlugin('dom')
|
||||||
|
|
||||||
|
export default {
|
||||||
|
components: {
|
||||||
|
showVoice,
|
||||||
|
showImage,
|
||||||
|
showText,
|
||||||
|
sentMessageBar
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
targetId: '',
|
||||||
|
conversationType: 3,
|
||||||
|
messages: [],
|
||||||
|
groupInfo: {
|
||||||
|
name: ''
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onLoad(e) {
|
||||||
|
this.targetId = e.targetId
|
||||||
|
this.groupInfo = this.$store.getters.contactInfo(this.targetId)
|
||||||
|
uni.setNavigationBarTitle({
|
||||||
|
title: this.groupInfo.name
|
||||||
|
})
|
||||||
|
this.getMessageList()
|
||||||
|
uni.$on('onReceiveMessage', (msg) => {
|
||||||
|
if (msg.targetId == this.targetId) {
|
||||||
|
this.getMessageList()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
onBackPress() {
|
||||||
|
uni.$off('onReceiveMessage')
|
||||||
|
},
|
||||||
|
onNavigationBarButtonTap() {
|
||||||
|
uni.navigateTo({
|
||||||
|
url: '/pages/im/group/info?targetId=' + this.targetId
|
||||||
|
})
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
toUser(item) {
|
||||||
|
console.log(item);
|
||||||
|
uni.navigateTo({
|
||||||
|
url: '/pages/im/friends/info?targetId=' + item.senderUserId
|
||||||
|
})
|
||||||
|
},
|
||||||
|
// 获取消息列表
|
||||||
|
getMessageList() {
|
||||||
|
im.getMessageList(
|
||||||
|
this.conversationType,
|
||||||
|
this.targetId,
|
||||||
|
new Date().getTime(),
|
||||||
|
20,
|
||||||
|
true,
|
||||||
|
(messages) => {
|
||||||
|
this.messages = messages.reverse()
|
||||||
|
this.scrollBottom()
|
||||||
|
})
|
||||||
|
},
|
||||||
|
// 滚动到底部
|
||||||
|
scrollBottom(type) {
|
||||||
|
// 清理当前会话,未读消息数量
|
||||||
|
RongIMLib.clearMessagesUnreadStatus(this.conversationType, this.targetId, new Date().getTime() + 1100)
|
||||||
|
// 发送消息已读状态给对方
|
||||||
|
RongIMLib.sendReadReceiptMessage(this.conversationType, this.targetId, new Date().getTime())
|
||||||
|
// 更新badge提醒数量
|
||||||
|
im.setNotifyBadge()
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
let el = this.$refs.chatBottom
|
||||||
|
ChatList.scrollToElement(el, {
|
||||||
|
offset: 0,
|
||||||
|
animated: false
|
||||||
|
})
|
||||||
|
}, 50)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.group--chat {
|
||||||
|
background: $window-color;
|
||||||
|
flex: 1;
|
||||||
|
|
||||||
|
.body {
|
||||||
|
flex: 1;
|
||||||
|
|
||||||
|
.cell {
|
||||||
|
padding: 10rpx 30rpx;
|
||||||
|
|
||||||
|
.cell-item {
|
||||||
|
width: 690rpx;
|
||||||
|
justify-content: flex-start;
|
||||||
|
|
||||||
|
|
||||||
|
&.left {
|
||||||
|
flex-direction: row;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.right {
|
||||||
|
flex-direction: row-reverse;
|
||||||
|
|
||||||
|
.state {
|
||||||
|
flex-direction: row;
|
||||||
|
justify-content: flex-end;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.avatar {
|
||||||
|
width: 78rpx;
|
||||||
|
height: 78rpx;
|
||||||
|
background-color: white;
|
||||||
|
border-radius: 10rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.msg {
|
||||||
|
margin: 0 20rpx;
|
||||||
|
|
||||||
|
.user {
|
||||||
|
font-size: 18rpx;
|
||||||
|
line-height: 40rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.cell-footer {
|
||||||
|
height: 20rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer {
|
||||||
|
background: white;
|
||||||
|
padding: 20rpx 30rpx;
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
flex-direction: row;
|
||||||
|
|
||||||
|
.msg-type {
|
||||||
|
width: 70rpx;
|
||||||
|
height: 70rpx;
|
||||||
|
|
||||||
|
.icon {
|
||||||
|
margin: 5rpx;
|
||||||
|
width: 60rpx;
|
||||||
|
height: 60rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
48
pages/im/group/create.vue
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
<template>
|
||||||
|
<view>
|
||||||
|
<u--input placeholder="请输入内容" border="surround" v-model="group_name"></u--input>
|
||||||
|
|
||||||
|
<u-button type="primary" text="确定" @click="onCreate"></u-button>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import {
|
||||||
|
createGroup
|
||||||
|
} from '@/apis/interfaces/im.js'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
group_name: '',
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onLoad() {
|
||||||
|
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
onCreate() {
|
||||||
|
console.log('阿斯利康');
|
||||||
|
createGroup({
|
||||||
|
name: this.group_name
|
||||||
|
}).then(res => {
|
||||||
|
console.log(res);
|
||||||
|
uni.showToast({
|
||||||
|
title: '创建成功'
|
||||||
|
})
|
||||||
|
uni.navigateBack()
|
||||||
|
}).catch(err => {
|
||||||
|
console.log(err);
|
||||||
|
uni.showToast({
|
||||||
|
icon: 'none',
|
||||||
|
title: err
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
|
||||||
|
</style>
|
||||||
@@ -1,11 +1,79 @@
|
|||||||
<template>
|
<template>
|
||||||
<view class="">
|
<view>
|
||||||
|
<view v-for="(item, index) in groups" :key="index" class="friend-flex u-border-bottom"
|
||||||
</view>
|
@click="toGroup(item.targetId)">
|
||||||
</template>
|
<u-avatar size="40" shape="square" :src="contact(item.targetId).portraitUrl" />
|
||||||
|
<view class="info">
|
||||||
<script>
|
<view class="name">{{ item.name }}</view>
|
||||||
</script>
|
</view>
|
||||||
|
</view>
|
||||||
<style>
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import {
|
||||||
|
getMyGroups
|
||||||
|
} from '@/apis/interfaces/im.js'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
groups: []
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
contact() {
|
||||||
|
return function(targetId) {
|
||||||
|
return this.$store.getters.contactInfo(targetId)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onNavigationBarButtonTap() {
|
||||||
|
uni.navigateTo({
|
||||||
|
url: 'pages/im/group/create'
|
||||||
|
})
|
||||||
|
},
|
||||||
|
onLoad() {
|
||||||
|
getMyGroups().then((res) => {
|
||||||
|
this.groups = res
|
||||||
|
res.map(item => {
|
||||||
|
this.$store.dispatch('updateContact', item)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
toGroup(targetId) {
|
||||||
|
uni.navigateTo({
|
||||||
|
url: '/pages/im/group/chat?targetId=' + targetId
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
// 好友列表
|
||||||
|
.friend-flex {
|
||||||
|
position: relative;
|
||||||
|
padding: 20rpx $padding;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
.info {
|
||||||
|
flex: 1;
|
||||||
|
margin-left: $padding;
|
||||||
|
|
||||||
|
.name {
|
||||||
|
font-size: $title-size + 2;
|
||||||
|
font-size: $title-size + 2;
|
||||||
|
color: #454545 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.address {
|
||||||
|
color: $text-gray-m;
|
||||||
|
font-size: $title-size-m - 5;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
213
pages/im/group/info.vue
Normal file
@@ -0,0 +1,213 @@
|
|||||||
|
<template>
|
||||||
|
<view class="container">
|
||||||
|
<view class="members u-border-bottom">
|
||||||
|
<view class="users">
|
||||||
|
<view class="user" v-for="(item, index) in members" :key="index" @click="toUser(item)">
|
||||||
|
<u-avatar size="44" shape="square" :src="item.portraitUrl"></u-avatar>
|
||||||
|
<view class="name">{{ item.name }}</view>
|
||||||
|
</view>
|
||||||
|
<view class="user">
|
||||||
|
<u-avatar @click="inviteUser" size="44" shape="square" icon="plus" bg-color="#eeeeee"
|
||||||
|
color="#999999"></u-avatar>
|
||||||
|
<view class="name">邀请用户</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view @click="loadMore" class="loadmore">查看更多群成员</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<u-cell-group class="cells">
|
||||||
|
<u-cell isLink title="群公告" :label="announcement" @click="toAnnouncement"></u-cell>
|
||||||
|
<u-cell title="聊天置顶">
|
||||||
|
<u-switch slot="value" size="20" v-model="isTop" activeColor="#34CE98" @change="setTop"></u-switch>
|
||||||
|
</u-cell>
|
||||||
|
<u-cell title="免打扰">
|
||||||
|
<u-switch slot="value" size="20" v-model="status" activeColor="#34CE98" @change="setStatus"></u-switch>
|
||||||
|
</u-cell>
|
||||||
|
</u-cell-group>
|
||||||
|
|
||||||
|
<u-cell-group class="cells" v-if="group.is_owner">
|
||||||
|
<u-cell isLink title="修改群聊名称" :value="group.name" @click="onGroupName"></u-cell>
|
||||||
|
<u-cell isLink title="修改群头像">
|
||||||
|
<u-avatar slot="value" size="24" shape="square" :src="group.cover"></u-avatar>
|
||||||
|
</u-cell>
|
||||||
|
</u-cell-group>
|
||||||
|
|
||||||
|
<view class="cells actions u-border-top">
|
||||||
|
<view class="action u-border-bottom" @click="onClean">清空聊天记录</view>
|
||||||
|
<view class="action u-border-bottom" v-if="group.is_owner" @click="onDismiss">解散群聊</view>
|
||||||
|
<view class="action u-border-bottom" v-else @click="onQuite">删除并退出</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import {
|
||||||
|
getGroupInfo
|
||||||
|
} from '@/apis/interfaces/im.js'
|
||||||
|
import * as RongIMLib from '@/uni_modules/RongCloud-IMWrapper/js_sdk/index'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
targetId: '',
|
||||||
|
group: {},
|
||||||
|
conversationType: 3,
|
||||||
|
announcement: '',
|
||||||
|
members: [],
|
||||||
|
status: false,
|
||||||
|
isTop: false,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onLoad(e) {
|
||||||
|
this.targetId = e.targetId
|
||||||
|
getGroupInfo(this.targetId).then(res => {
|
||||||
|
this.group = res.group
|
||||||
|
console.log(this.group);
|
||||||
|
this.announcement = res.announcement
|
||||||
|
this.members = res.members
|
||||||
|
})
|
||||||
|
RongIMLib.getConversationNotificationStatus(this.conversationType, this.targetId, ({
|
||||||
|
status
|
||||||
|
}) => {
|
||||||
|
this.status = !Boolean(status)
|
||||||
|
})
|
||||||
|
RongIMLib.getConversation(this.conversationType, this.targetId, ({
|
||||||
|
code,
|
||||||
|
conversation
|
||||||
|
}) => {
|
||||||
|
if (code == 0) {
|
||||||
|
this.isTop = conversation.isTop
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
setStatus() {
|
||||||
|
RongIMLib.setConversationNotificationStatus(this.conversationType, this.targetId, this.status,
|
||||||
|
({
|
||||||
|
status
|
||||||
|
}) => {
|
||||||
|
this.status = !Boolean(status)
|
||||||
|
})
|
||||||
|
},
|
||||||
|
setTop() {
|
||||||
|
RongIMLib.setConversationToTop(this.conversationType, this.targetId, this.isTop, (res) => {
|
||||||
|
RongIMLib.getConversation(this.conversationType, this.targetId, ({
|
||||||
|
conversation
|
||||||
|
}) => {
|
||||||
|
this.isTop = conversation.isTop
|
||||||
|
})
|
||||||
|
})
|
||||||
|
},
|
||||||
|
toUser(item) {
|
||||||
|
uni.navigateTo({
|
||||||
|
url: '/pages/im/friends/info?targetId=' + item.targetId
|
||||||
|
})
|
||||||
|
},
|
||||||
|
inviteUser() {
|
||||||
|
|
||||||
|
},
|
||||||
|
loadMore() {
|
||||||
|
uni.navigateTo({
|
||||||
|
url: '/pages/im/group/users?targetId=' + this.targetId
|
||||||
|
})
|
||||||
|
},
|
||||||
|
toAnnouncement() {
|
||||||
|
uni.navigateTo({
|
||||||
|
url: '/pages/im/group/announcement?targetId=' + this.targetId
|
||||||
|
})
|
||||||
|
},
|
||||||
|
onGroupName() {
|
||||||
|
|
||||||
|
},
|
||||||
|
onClean() {
|
||||||
|
uni.showModal({
|
||||||
|
title: '清空聊天记录',
|
||||||
|
content: '清空聊天记录,只会清空本地的记录,其他成员不会变化',
|
||||||
|
success: (res) => {
|
||||||
|
if (res.confirm) {
|
||||||
|
RongIMLib.deleteMessages(3, this.targetId, () => {
|
||||||
|
uni.showToast({
|
||||||
|
icon: 'none',
|
||||||
|
title: '清空成功'
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
onDismiss() {
|
||||||
|
uni.showToast({
|
||||||
|
icon: 'none',
|
||||||
|
title: '开发中'
|
||||||
|
})
|
||||||
|
},
|
||||||
|
onQuite() {
|
||||||
|
uni.showToast({
|
||||||
|
icon: 'none',
|
||||||
|
title: '开发中'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.container {
|
||||||
|
min-height: 100vh;
|
||||||
|
background: $window-color;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cells {
|
||||||
|
margin-top: $padding;
|
||||||
|
background-color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.members {
|
||||||
|
background-color: white;
|
||||||
|
padding-bottom: 40rpx;
|
||||||
|
|
||||||
|
.users {
|
||||||
|
flex-direction: row;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
display: flex;
|
||||||
|
padding: 20rpx 0;
|
||||||
|
|
||||||
|
.user {
|
||||||
|
width: 126rpx;
|
||||||
|
margin-left: 20rpx;
|
||||||
|
margin-bottom: 20rpx;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
.name {
|
||||||
|
width: 126rpx;
|
||||||
|
text-align: center;
|
||||||
|
font-size: 28rpx;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
white-space: nowrap;
|
||||||
|
word-break: break-word;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.loadmore {
|
||||||
|
font-size: 28rpx;
|
||||||
|
color: $text-gray-m;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.actions {
|
||||||
|
margin-top: $padding;
|
||||||
|
text-align: center;
|
||||||
|
|
||||||
|
.action {
|
||||||
|
padding: $padding;
|
||||||
|
color: $text-price;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
74
pages/im/group/users.vue
Normal file
@@ -0,0 +1,74 @@
|
|||||||
|
<template>
|
||||||
|
<view class="members">
|
||||||
|
<view class="users">
|
||||||
|
<view class="user" v-for="(item, index) in members" :key="index" @click="toUser(item)">
|
||||||
|
<u-avatar size="44" shape="square" :src="item.portraitUrl"></u-avatar>
|
||||||
|
<view class="name">{{ item.name }}</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import {
|
||||||
|
getGroupInfo,
|
||||||
|
getGroupUsers
|
||||||
|
} from '@/apis/interfaces/im.js'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
targetId: '',
|
||||||
|
members: []
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onLoad(e) {
|
||||||
|
this.targetId = e.targetId
|
||||||
|
getGroupInfo(this.targetId).then(res => {
|
||||||
|
|
||||||
|
})
|
||||||
|
getGroupUsers(this.targetId).then(res => {
|
||||||
|
this.members = res
|
||||||
|
})
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
toUser(item) {
|
||||||
|
uni.navigateTo({
|
||||||
|
url: '/pages/im/friends/info?targetId=' + item.targetId
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.members {
|
||||||
|
background-color: white;
|
||||||
|
padding-bottom: 40rpx;
|
||||||
|
|
||||||
|
.users {
|
||||||
|
flex-direction: row;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
display: flex;
|
||||||
|
padding: 20rpx 0;
|
||||||
|
|
||||||
|
.user {
|
||||||
|
width: 126rpx;
|
||||||
|
margin-left: 20rpx;
|
||||||
|
margin-bottom: 20rpx;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
.name {
|
||||||
|
width: 126rpx;
|
||||||
|
text-align: center;
|
||||||
|
font-size: 28rpx;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
white-space: nowrap;
|
||||||
|
word-break: break-word;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -5,56 +5,23 @@
|
|||||||
<view class="custom-header">
|
<view class="custom-header">
|
||||||
<view class="header-flex">
|
<view class="header-flex">
|
||||||
<view class="tabs">
|
<view class="tabs">
|
||||||
<view class="item show">私聊</view>
|
<view class="item active">聊聊</view>
|
||||||
<view class="item" @click="onNav('', {})">群聊</view>
|
|
||||||
</view>
|
</view>
|
||||||
<view class="btns">
|
<view class="btns">
|
||||||
<view class="item" @click="onNav('imFriends', {})">
|
|
||||||
<uni-icons color="#555" custom-prefix="iconfont" type="icon-tuandui" size="22"></uni-icons>
|
|
||||||
</view>
|
|
||||||
<view class="item" @click="scanQrCode">
|
<view class="item" @click="scanQrCode">
|
||||||
<uni-icons color="#555" type="scan" size="22"></uni-icons>
|
<uni-icons color="#555" type="scan" size="22" />
|
||||||
|
</view>
|
||||||
|
<view class="item" @click="toFriendList">
|
||||||
|
<u-badge absolute max="99" :offset="[-5, -5]" :value="hasNewFriends" />
|
||||||
|
<uni-icons color="#555" custom-prefix="iconfont" type="icon-tuandui" size="22" />
|
||||||
</view>
|
</view>
|
||||||
<!-- <view class="item" @click="onNav('', {})">
|
|
||||||
<uni-icons color="#555" custom-prefix="iconfont" type="icon-gengduo2" size="22"></uni-icons>
|
|
||||||
</view> -->
|
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
|
<u-alert type="warning" v-if="connection != 0" description="网络似乎断开了,请检查网络" :show-icon="true" />
|
||||||
<!-- content -->
|
<!-- content -->
|
||||||
<view v-if="$store.state.token != ''">
|
<view v-if="$store.state.token !== ''">
|
||||||
<block v-if="conversations.length < 1">
|
<conversation-list @refresh="getConversationList()" :conversations="conversations" />
|
||||||
<view class="vertical null-list">
|
|
||||||
<u-empty mode="message" textColor="#999" text="暂无好友消息" />
|
|
||||||
</view>
|
|
||||||
</block>
|
|
||||||
<block v-else>
|
|
||||||
<u-alert type="warning" v-if="connection != 0" description="网络似乎断开了" :show-icon="true" />
|
|
||||||
<view v-for="(item, index) in conversations" :key="index" :class="['message', { 'is-top': item.isTop }]"
|
|
||||||
@tap="toDetail(item)" @longpress="onLongPress" :data-item="item">
|
|
||||||
<view class="avatar">
|
|
||||||
<u-badge numberType="ellipsis" max="99" shape="horn" absolute :offset="[-5, -5]"
|
|
||||||
:value="item.unreadMessageCount" />
|
|
||||||
<u-avatar :src="friend(item.targetId).portraitUrl || require('@/static/user/cover.png')"
|
|
||||||
shape="square" size="46" />
|
|
||||||
</view>
|
|
||||||
<view class="content">
|
|
||||||
<view class="header">
|
|
||||||
<view class="name">{{ friend(item.targetId).name || '未知用户' }}</view>
|
|
||||||
<view class="time">{{ item.sentTime|timeCustomCN }}</view>
|
|
||||||
</view>
|
|
||||||
<view class="preview">{{ item.latestMessage.content || '' }}</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
<!-- TODO 长按的弹出框,怎么点击隐藏,没搞明白 -->
|
|
||||||
<view class="shade" @tap="hidePop">
|
|
||||||
<view class="pop" :style="popStyle" :class="{'show':showPop}">
|
|
||||||
<view v-for="(item, index) in popButton" :key="index" @tap="pickerMenu" :data-index="index">
|
|
||||||
{{item}}
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</block>
|
|
||||||
</view>
|
</view>
|
||||||
<!-- 未登录 -->
|
<!-- 未登录 -->
|
||||||
<view v-else class="vertical null-list">
|
<view v-else class="vertical null-list">
|
||||||
@@ -68,113 +35,51 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import * as RongIMLib from "@/uni_modules/RongCloud-IMWrapper/js_sdk/index"
|
import * as RongIMLib from '@/uni_modules/RongCloud-IMWrapper/js_sdk/index'
|
||||||
import im from '@/utils/im/index.js'
|
import im from '@/utils/im/index.js'
|
||||||
import userAuth from '@/public/userAuth'
|
import userAuth from '@/public/userAuth'
|
||||||
import {
|
import conversationList from './components/conversationList'
|
||||||
getImToken
|
|
||||||
} from '@/apis/interfaces/im.js'
|
|
||||||
export default {
|
export default {
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
isShown: true, // 当前页面显示状态
|
|
||||||
conversations: [], // 会话列表
|
conversations: [], // 会话列表
|
||||||
connection: 0,
|
connection: 0,
|
||||||
/* 窗口尺寸 */
|
hasNewFriends: 0
|
||||||
winSize: {},
|
|
||||||
/* 显示操作弹窗 */
|
|
||||||
showPop: false,
|
|
||||||
/* 弹窗按钮列表 */
|
|
||||||
popButton: ['置顶聊天', '删除该聊天'],
|
|
||||||
/* 弹窗定位样式 */
|
|
||||||
popStyle: "",
|
|
||||||
pickedItem: {}
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
components: {
|
||||||
friend() {
|
conversationList
|
||||||
return function(targetId) {
|
|
||||||
return this.$store.getters.userInfo(targetId)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
onLoad() {
|
onLoad() {
|
||||||
uni.$on('onReceiveMessage', (msg) => {
|
// 好友申请数量
|
||||||
this.getConversationList()
|
this.checkNewFriendPending()
|
||||||
})
|
|
||||||
uni.$on('onConnectionStatusChange', (status) => {
|
uni.$on('onConnectionStatusChange', (status) => {
|
||||||
this.connection = status
|
this.connection = status
|
||||||
})
|
})
|
||||||
|
uni.$on('onContactNotification', this.checkNewFriendPending)
|
||||||
},
|
},
|
||||||
onShow() {
|
onShow() {
|
||||||
if (this.$store.state.token !== '') {
|
if (this.$store.state.token !== '') {
|
||||||
this.getConversationList()
|
this.getConversationList()
|
||||||
}
|
}
|
||||||
this.isShown = true
|
// 监听新消息
|
||||||
|
uni.$on('onReceiveMessage', (msg) => {
|
||||||
|
this.getConversationList()
|
||||||
|
})
|
||||||
},
|
},
|
||||||
onHide() {
|
onHide() {
|
||||||
this.isShown = false
|
uni.$off('onReceiveMessage')
|
||||||
},
|
},
|
||||||
onNavigationBarButtonTap(e) {
|
methods: {
|
||||||
if (e.index == 0) {
|
checkNewFriendPending() {
|
||||||
uni.showToast({
|
// 获取是否有新的好友申请
|
||||||
title: '开发中暂未开放,敬请期待',
|
RongIMLib.getConversationList([RongIMLib.ConversationType.SYSTEM], 1000, 0, (res) => {
|
||||||
icon: 'none'
|
if (res.code === 0) {
|
||||||
})
|
this.hasNewFriends = res.conversations.filter((item) => {
|
||||||
}
|
return item.objectName == RongIMLib.ObjectName.ContactNotification
|
||||||
if (e.index == 1) {
|
}).length
|
||||||
if (this.toLogin()) {
|
}
|
||||||
this.$Router.push({
|
|
||||||
name: 'imFriends'
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
// 隐藏功能菜单
|
|
||||||
hidePop() {
|
|
||||||
this.showPop = false
|
|
||||||
this.pickedItem = {}
|
|
||||||
setTimeout(() => {
|
|
||||||
this.showShade = false
|
|
||||||
}, 250)
|
|
||||||
},
|
|
||||||
// 点击会话功能菜单
|
|
||||||
pickerMenu(e) {
|
|
||||||
const index = Number(e.currentTarget.dataset.index)
|
|
||||||
|
|
||||||
if (index == 0) {
|
|
||||||
RongIMLib.setConversationToTop(this.pickedItem.conversationType, this.pickedItem.targetId, !this
|
|
||||||
.pickedItem.isTop)
|
|
||||||
} else {
|
|
||||||
RongIMLib.removeConversation(this.pickedItem.conversationType, this.pickedItem.targetId)
|
|
||||||
}
|
|
||||||
im.setNotifyBadge()
|
|
||||||
this.getConversationList()
|
|
||||||
this.hidePop()
|
|
||||||
},
|
|
||||||
// 长按会话,展示功能菜单
|
|
||||||
onLongPress(e) {
|
|
||||||
let [touches, style, item] = [e.touches[0], "", e.currentTarget.dataset.item]
|
|
||||||
|
|
||||||
if (touches.clientY > (this.winSize.height / 2)) {
|
|
||||||
style = `bottom:${this.winSize.height-touches.clientY}px;`
|
|
||||||
} else {
|
|
||||||
style = `top:${touches.clientY}px;`
|
|
||||||
}
|
|
||||||
if (touches.clientX > (this.winSize.witdh / 2)) {
|
|
||||||
style += `right:${this.winSize.witdh-touches.clientX}px`
|
|
||||||
} else {
|
|
||||||
style += `left:${touches.clientX}px`
|
|
||||||
}
|
|
||||||
|
|
||||||
this.popButton[0] = item.isTop ? '取消置顶' : '置顶聊天'
|
|
||||||
this.popStyle = style
|
|
||||||
this.pickedItem = item
|
|
||||||
this.$nextTick(() => {
|
|
||||||
setTimeout(() => {
|
|
||||||
this.showPop = true;
|
|
||||||
}, 10)
|
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
// 检查登录
|
// 检查登录
|
||||||
@@ -186,41 +91,16 @@
|
|||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
},
|
},
|
||||||
|
// 获取私聊的会话列表
|
||||||
getConversationList() {
|
getConversationList() {
|
||||||
const count = 1000
|
const count = 1000
|
||||||
const timestamp = 0
|
const timestamp = 0
|
||||||
RongIMLib.getConversationList([RongIMLib.ConversationType.PRIVATE], count, timestamp, (res) => {
|
RongIMLib.getConversationList([1, 3], count, timestamp, (res) => {
|
||||||
if (res.code === 0) {
|
if (res.code === 0) {
|
||||||
this.conversations = res.conversations
|
this.conversations = res.conversations
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
// 进入聊天的详情页面,清理未读消息数量
|
|
||||||
toDetail(item) {
|
|
||||||
this.hidePop()
|
|
||||||
uni.navigateTo({
|
|
||||||
url: '/pages/im/private/chat?targetId=' + item.targetId + '&conversationType=' + item
|
|
||||||
.conversationType
|
|
||||||
})
|
|
||||||
|
|
||||||
// url: '/pages/im/private/index?targetId=' + item.targetId + '&conversationType=' + item.conversationType
|
|
||||||
},
|
|
||||||
// 点击按钮
|
|
||||||
onNav(name, params) {
|
|
||||||
if (this.toLogin) {
|
|
||||||
if (name === '') {
|
|
||||||
uni.showToast({
|
|
||||||
title: '开发中,敬请期待',
|
|
||||||
icon: 'none'
|
|
||||||
})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
this.$Router.push({
|
|
||||||
name,
|
|
||||||
params
|
|
||||||
})
|
|
||||||
}
|
|
||||||
},
|
|
||||||
// 调起扫码
|
// 调起扫码
|
||||||
scanQrCode() {
|
scanQrCode() {
|
||||||
uni.scanCode({
|
uni.scanCode({
|
||||||
@@ -233,59 +113,17 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
},
|
||||||
|
toFriendList() {
|
||||||
|
uni.navigateTo({
|
||||||
|
url: '/pages/im/friends/index'
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
// header
|
|
||||||
.custom-header {
|
|
||||||
@extend .ios-top;
|
|
||||||
background: $window-color;
|
|
||||||
position: fixed;
|
|
||||||
top: 0;
|
|
||||||
left: 0;
|
|
||||||
right: 0;
|
|
||||||
z-index: 9999;
|
|
||||||
|
|
||||||
.header-flex {
|
|
||||||
padding: 20rpx $padding;
|
|
||||||
display: flex;
|
|
||||||
justify-content: space-between;
|
|
||||||
height: 60rpx;
|
|
||||||
line-height: 60rpx;
|
|
||||||
|
|
||||||
.tabs {
|
|
||||||
.item {
|
|
||||||
margin-left: $margin;
|
|
||||||
display: inline-block;
|
|
||||||
font-size: $title-size-lg;
|
|
||||||
color: $text-gray;
|
|
||||||
padding: 0 ($padding - 10);
|
|
||||||
border-radius: 30rpx;
|
|
||||||
|
|
||||||
&:first-child {
|
|
||||||
margin: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.show {
|
|
||||||
background: rgba($color: $main-color, $alpha: .1);
|
|
||||||
color: $main-color;
|
|
||||||
font-weight: bold;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.btns {
|
|
||||||
.item {
|
|
||||||
display: inline-block;
|
|
||||||
margin-left: $margin;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// contents
|
// contents
|
||||||
.contents {
|
.contents {
|
||||||
background-color: $window-color;
|
background-color: $window-color;
|
||||||
@@ -293,6 +131,50 @@
|
|||||||
padding-top: 90rpx + 20rpx;
|
padding-top: 90rpx + 20rpx;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
|
|
||||||
|
.custom-header {
|
||||||
|
@extend .ios-top;
|
||||||
|
background: $window-color;
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
z-index: 9999;
|
||||||
|
|
||||||
|
.header-flex {
|
||||||
|
padding: 20rpx $padding;
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
height: 60rpx;
|
||||||
|
line-height: 60rpx;
|
||||||
|
|
||||||
|
.tabs {
|
||||||
|
|
||||||
|
.item {
|
||||||
|
position: relative;
|
||||||
|
display: inline-block;
|
||||||
|
font-size: $title-size-lg;
|
||||||
|
color: $text-gray;
|
||||||
|
padding: 0 ($padding - 10);
|
||||||
|
border-radius: 30rpx;
|
||||||
|
|
||||||
|
&.active {
|
||||||
|
background: rgba($color: $main-color, $alpha: .1);
|
||||||
|
color: $main-color;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.btns {
|
||||||
|
.item {
|
||||||
|
position: relative;
|
||||||
|
display: inline-block;
|
||||||
|
margin-left: $margin;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.null-list {
|
.null-list {
|
||||||
height: 100vh;
|
height: 100vh;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
@@ -308,116 +190,6 @@
|
|||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.message {
|
|
||||||
background: white;
|
|
||||||
padding: 30rpx 0 0 30rpx;
|
|
||||||
position: relative;
|
|
||||||
display: flex;
|
|
||||||
|
|
||||||
|
|
||||||
&.is-top {
|
|
||||||
background: $window-color;
|
|
||||||
border-bottom: #e8e8e8;
|
|
||||||
// background-color: rgba($color: $main-color, $alpha: 0.02);
|
|
||||||
}
|
|
||||||
|
|
||||||
.avatar {
|
|
||||||
position: relative;
|
|
||||||
|
|
||||||
.u-badge {
|
|
||||||
z-index: 998;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.content {
|
|
||||||
margin-left: 30rpx;
|
|
||||||
width: calc(100% - 46px);
|
|
||||||
box-sizing: border-box;
|
|
||||||
border-bottom: solid 1rpx #f3f3f3;
|
|
||||||
position: relative;
|
|
||||||
|
|
||||||
.header {
|
|
||||||
display: flex;
|
|
||||||
justify-content: space-between;
|
|
||||||
|
|
||||||
.name {
|
|
||||||
font-size: $title-size + 2;
|
|
||||||
color: #454545;
|
|
||||||
color: #454545;
|
|
||||||
}
|
|
||||||
|
|
||||||
.time {
|
|
||||||
font-size: $title-size-sm;
|
|
||||||
color: $text-gray-m;
|
|
||||||
position: absolute;
|
|
||||||
right: 30rpx;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.preview {
|
|
||||||
word-break: break-all;
|
|
||||||
color: $text-gray-m;
|
|
||||||
padding-top: $padding - 20;
|
|
||||||
padding-bottom: $padding;
|
|
||||||
font-size: $title-size-m;
|
|
||||||
height: 40rpx;
|
|
||||||
line-height: 40rpx;
|
|
||||||
width: 500rpx;
|
|
||||||
@extend .nowrap;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// .message:not(:last-child) {
|
|
||||||
// &::after {
|
|
||||||
// position: absolute;
|
|
||||||
// left: calc(44px + #{$padding} + 30rpx);
|
|
||||||
// right: 0;
|
|
||||||
// bottom: 0;
|
|
||||||
// content: " ";
|
|
||||||
// height: 1rpx;
|
|
||||||
// background: $border-color;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 遮罩 */
|
|
||||||
.shade {
|
|
||||||
|
|
||||||
.pop {
|
|
||||||
position: fixed;
|
|
||||||
z-index: 101;
|
|
||||||
width: 200rpx;
|
|
||||||
box-sizing: border-box;
|
|
||||||
font-size: 28rpx;
|
|
||||||
text-align: left;
|
|
||||||
color: #333;
|
|
||||||
background-color: #fff;
|
|
||||||
box-shadow: 0 0 5px rgba(0, 0, 0, 0.5);
|
|
||||||
line-height: 80rpx;
|
|
||||||
transition: transform 0.15s ease-in-out 0s;
|
|
||||||
user-select: none;
|
|
||||||
-webkit-touch-callout: none;
|
|
||||||
transform: scale(0, 0);
|
|
||||||
|
|
||||||
&.show {
|
|
||||||
transform: scale(1, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
&>view {
|
|
||||||
padding: 0 20rpx;
|
|
||||||
overflow: hidden;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
white-space: nowrap;
|
|
||||||
user-select: none;
|
|
||||||
-webkit-touch-callout: none;
|
|
||||||
|
|
||||||
&:active {
|
|
||||||
background-color: #f3f3f3;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.u-border-bottom {
|
.u-border-bottom {
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<view class="call-page">
|
<view class="call">
|
||||||
<view class="video">
|
<view class="video">
|
||||||
<RongCloud-Call-RCUniCallView ref="bigVideoView" :style="{width:windowWidth+'px',height:windowHeight+'px'}"
|
<RongCloud-Call-RCUniCallView ref="bigVideoView" :style="{width:windowWidth+'px',height:windowHeight+'px'}"
|
||||||
class="bigVideoView">
|
class="bigVideoView">
|
||||||
@@ -9,9 +9,11 @@
|
|||||||
</view>
|
</view>
|
||||||
|
|
||||||
<view class="status" v-if="!connected || mediaType == 0">
|
<view class="status" v-if="!connected || mediaType == 0">
|
||||||
<view class="call-user">
|
<view class="remote">
|
||||||
<u-avatar v-if="userInfo.portraitUrl" :src="userInfo.portraitUrl" shape="square" size="96" bgColor="#fff" />
|
<u-avatar v-if="userInfo.portraitUrl" :src="userInfo.portraitUrl" shape="square" size="96"
|
||||||
<u-avatar size="80" v-if="!userInfo.portraitUrl" shape="square" :text="userInfo.name ? userInfo.name.substring(0,1) : '未'" font-size="44" randomBgColor />
|
bgColor="#fff" />
|
||||||
|
<u-avatar size="80" v-if="!userInfo.portraitUrl" shape="square"
|
||||||
|
:text="userInfo.name ? userInfo.name.substring(0,1) : '未'" font-size="44" randomBgColor />
|
||||||
<view><text class="nickname">{{userInfo.name}}</text></view>
|
<view><text class="nickname">{{userInfo.name}}</text></view>
|
||||||
<view v-if="remoteRinging"><text class="mediaType">等待对方接听</text></view>
|
<view v-if="remoteRinging"><text class="mediaType">等待对方接听</text></view>
|
||||||
<view v-if="connected"><text class="mediaType">已接通</text></view>
|
<view v-if="connected"><text class="mediaType">已接通</text></view>
|
||||||
@@ -163,85 +165,88 @@
|
|||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped lang="scss">
|
||||||
.call-page {
|
.call {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex: 1;
|
flex: 1;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
position: relative;
|
position: relative;
|
||||||
}
|
|
||||||
|
|
||||||
.bigVideoView {
|
.video {
|
||||||
background: #000;
|
.bigVideoView {
|
||||||
}
|
background: #000;
|
||||||
|
}
|
||||||
|
|
||||||
.smallVideoView {
|
.smallVideoView {
|
||||||
background: blue;
|
background: blue;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
right: 100rpx;
|
right: 100rpx;
|
||||||
top: 100rpx;
|
top: 100rpx;
|
||||||
width: 180rpx;
|
width: 180rpx;
|
||||||
height: 320rpx;
|
height: 320rpx;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.buttons {
|
.status {
|
||||||
position: fixed;
|
flex: 1;
|
||||||
bottom: 100rpx;
|
background: #666;
|
||||||
width: 750rpx;
|
width: 750rpx;
|
||||||
display: flex;
|
position: fixed;
|
||||||
flex-direction: row;
|
bottom: 0;
|
||||||
justify-content: space-around;
|
top: 0;
|
||||||
}
|
|
||||||
|
|
||||||
.btn {
|
.remote {
|
||||||
align-items: center;
|
flex: 1;
|
||||||
}
|
width: 750rpx;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
top: 300rpx;
|
||||||
|
|
||||||
.icon {
|
.mediaType {
|
||||||
background: #34CE98;
|
font-size: 32rpx;
|
||||||
width: 132rpx;
|
color: #aaa;
|
||||||
height: 132rpx;
|
}
|
||||||
border-radius: 50%;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.btn .text {
|
.nickname {
|
||||||
margin-top: 16rpx;
|
margin: 30rpx;
|
||||||
color: #FFFFFF;
|
font-size: 44rpx;
|
||||||
font-size: 32rpx;
|
color: #ffffff;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.icon.hangup {
|
.buttons {
|
||||||
background: #dd524d;
|
position: fixed;
|
||||||
}
|
bottom: 100rpx;
|
||||||
|
width: 750rpx;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
justify-content: space-around;
|
||||||
|
}
|
||||||
|
|
||||||
.status {
|
|
||||||
flex: 1;
|
|
||||||
background: #666;
|
|
||||||
width: 750rpx;
|
|
||||||
position: fixed;
|
|
||||||
bottom: 0;
|
|
||||||
top: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.call-user {
|
.btn {
|
||||||
flex: 1;
|
align-items: center;
|
||||||
width: 750rpx;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
top: 300rpx;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mediaType {
|
&.hangup {
|
||||||
font-size: 32rpx;
|
background: $text-price;
|
||||||
color: #aaa;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
.nickname {
|
.icon {
|
||||||
margin: 30rpx;
|
background: $main-color;
|
||||||
font-size: 44rpx;
|
width: 132rpx;
|
||||||
color: #ffffff;
|
height: 132rpx;
|
||||||
|
border-radius: 50%;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.text {
|
||||||
|
margin-top: 16rpx;
|
||||||
|
color: #FFFFFF;
|
||||||
|
font-size: 32rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -1,21 +1,20 @@
|
|||||||
<template>
|
<template>
|
||||||
<view class="chat">
|
<view class="chat">
|
||||||
<!-- chat -->
|
<!-- chat -->
|
||||||
<list class="chat-scroll" :show-scrollbar="false">
|
<list class="body" :show-scrollbar="false">
|
||||||
<cell class="cell" v-for="(item, index) in messages" :key="index">
|
<cell class="cell" v-for="(item, index) in messages" :key="index">
|
||||||
<view class="cell-time">
|
<view class="time">
|
||||||
<text class="cell-time-text">{{ customCN(item.sentTime) }}</text>
|
<text class="text">{{ customCN(item.sentTime) }}</text>
|
||||||
</view>
|
</view>
|
||||||
<view class="cell-item" :class="item.messageDirection == 1 ? 'right' : 'left'">
|
<view class="cell-item" :class="item.messageDirection == 1 ? 'right' : 'left'">
|
||||||
<image class="active" :src="userInfo.portraitUrl" mode="aspectFill"
|
<u-avatar class="avatar" size="36" shape="square" @click="showUser(targetId, item.messageDirection)" :src="userInfo.portraitUrl" />
|
||||||
@click="showFriend(targetId, item.messageDirection)"></image>
|
|
||||||
<view class="msg">
|
<view class="msg">
|
||||||
<show-voice v-if="item.objectName === 'RC:HQVCMsg'" :guest="item.messageDirection == 1"
|
<show-voice v-if="item.objectName === 'RC:HQVCMsg'" :guest="item.messageDirection == 1"
|
||||||
:msg="item.content"></show-voice>
|
:msg="item.content" />
|
||||||
<show-image v-if="item.objectName === 'RC:ImgMsg'" :guest="item.messageDirection == 1"
|
<show-image v-if="item.objectName === 'RC:ImgMsg'" :guest="item.messageDirection == 1"
|
||||||
:msg="item.content.content"></show-image>
|
:msg="item.content" />
|
||||||
<show-text v-if="item.objectName === 'RC:TxtMsg'" :guest="item.messageDirection == 1"
|
<show-text v-if="item.objectName === 'RC:TxtMsg'" :guest="item.messageDirection == 1"
|
||||||
:msg="item.content.content"></show-text>
|
:msg="item.content" />
|
||||||
<view class="state" v-if="item.messageDirection == 1">
|
<view class="state" v-if="item.messageDirection == 1">
|
||||||
<text class="state-text">{{ item.sentStatus == 50 ? '已读': '未读'}}</text>
|
<text class="state-text">{{ item.sentStatus == 50 ? '已读': '未读'}}</text>
|
||||||
</view>
|
</view>
|
||||||
@@ -24,30 +23,7 @@
|
|||||||
</cell>
|
</cell>
|
||||||
<cell class="cell-footer" ref="chatBottom"></cell>
|
<cell class="cell-footer" ref="chatBottom"></cell>
|
||||||
</list>
|
</list>
|
||||||
<!-- footer -->
|
<sent-message-bar :conversationType="conversationType" :targetId="targetId" @onSuccess="getMessageList()" />
|
||||||
<view class="chat-footer">
|
|
||||||
<view class="msg-type" @click="msgType">
|
|
||||||
<image class="msg-type-icon" src="@/static/icon/key-icon.png" v-if="importTabs === 0" mode="widthFix">
|
|
||||||
</image>
|
|
||||||
<image class="msg-type-icon" src="@/static/icon/msg-icon.png" v-if="importTabs === 1" mode="widthFix">
|
|
||||||
</image>
|
|
||||||
</view>
|
|
||||||
<block v-if="importTabs === 0">
|
|
||||||
<view class="chat-mp3" hover-class="chat-hover" @touchstart="startAudio" @touchend="chendAudio">
|
|
||||||
<text class="chat-mp3-text">按住说话</text>
|
|
||||||
</view>
|
|
||||||
</block>
|
|
||||||
<block v-if="importTabs === 1">
|
|
||||||
<input class="chat-input" type="text" v-model="inputTxt" confirm-type="发送" @confirm="send"
|
|
||||||
cursor-spacing="10" />
|
|
||||||
</block>
|
|
||||||
<text class="chat-push" size="mini" @click="send">发送</text>
|
|
||||||
</view>
|
|
||||||
<!-- 录音中提示 -->
|
|
||||||
<view class="audio-transcribe" v-if="showAudioTranscribe">
|
|
||||||
<image class="audio-transcribe-src" src="@/static/icon/record-icon.png" mode="widthFix"></image>
|
|
||||||
<text class="audio-transcribe-text">录音中 {{transcribeTime}} s</text>
|
|
||||||
</view>
|
|
||||||
</view>
|
</view>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@@ -55,171 +31,94 @@
|
|||||||
import {
|
import {
|
||||||
timeCustomCN
|
timeCustomCN
|
||||||
} from '@/utils/filters.js'
|
} from '@/utils/filters.js'
|
||||||
import * as RongIMLib from "@/uni_modules/RongCloud-IMWrapper/js_sdk/index"
|
import * as RongIMLib from '@/uni_modules/RongCloud-IMWrapper/js_sdk/index'
|
||||||
import im from '@/utils/im/index.js'
|
import im from '@/utils/im/index.js'
|
||||||
import permision from "@/js_sdk/wa-permission/permission.js"
|
import showVoice from '../components/showVoice'
|
||||||
import showVoice from './components/showVoice'
|
import showImage from '../components/showImage'
|
||||||
import showImage from './components/showImage'
|
import showText from '../components/showText'
|
||||||
import showText from './components/showText'
|
import sentMessageBar from '../components/sentMessageBar'
|
||||||
|
|
||||||
var transcribe
|
|
||||||
const recorderManager = uni.getRecorderManager()
|
|
||||||
const ChatList = uni.requireNativePlugin('dom')
|
const ChatList = uni.requireNativePlugin('dom')
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
targetId: '',
|
targetId: '',
|
||||||
inputTxt: '',
|
|
||||||
messages: [],
|
messages: [],
|
||||||
conversationType: 1,
|
conversationType: 1,
|
||||||
userInfo: {
|
userInfo: {
|
||||||
name: '',
|
name: '',
|
||||||
userId: '',
|
userId: '',
|
||||||
portraitUrl: ''
|
portraitUrl: ''
|
||||||
},
|
}
|
||||||
importTabs: 1,
|
|
||||||
showAudioTranscribe: false,
|
|
||||||
transcribeTime: 60,
|
|
||||||
audioContextPaused: true
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
components: {
|
components: {
|
||||||
|
sentMessageBar,
|
||||||
showVoice,
|
showVoice,
|
||||||
showImage,
|
showImage,
|
||||||
showText
|
showText
|
||||||
},
|
},
|
||||||
onLoad(e) {
|
onLoad(e) {
|
||||||
this.targetId = e.targetId
|
this.targetId = e.targetId
|
||||||
this.conversationType = e.conversationType // 会话类型
|
this.userInfo = this.$store.getters.contactInfo(this.targetId)
|
||||||
this.userInfo = this.$store.getters.userInfo(this.targetId)
|
|
||||||
uni.setNavigationBarTitle({
|
uni.setNavigationBarTitle({
|
||||||
title: this.$store.getters.userInfo(this.targetId).name
|
title: this.userInfo.name
|
||||||
})
|
})
|
||||||
|
// 获取消息列表
|
||||||
RongIMLib.clearMessagesUnreadStatus(this.conversationType, this.targetId, new Date().getTime())
|
|
||||||
im.setNotifyBadge()
|
|
||||||
RongIMLib.sendReadReceiptMessage(this.conversationType, this.targetId, new Date().getTime())
|
|
||||||
|
|
||||||
this.getMessageList()
|
this.getMessageList()
|
||||||
|
// 监听消息已读状态
|
||||||
// 监听消息回执
|
uni.$on('onReadReceiptReceived', (data) => {
|
||||||
RongIMLib.addReadReceiptReceivedListener(({
|
|
||||||
data
|
|
||||||
}) => {
|
|
||||||
if (data.targetId == this.targetId) {
|
if (data.targetId == this.targetId) {
|
||||||
this.getMessageList()
|
this.getMessageList()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
// 监听收到新消息,判断是否是当前会话,更新会话内容
|
// 监听收到新消息,判断是否是当前会话,更新会话内容
|
||||||
uni.$on('onReceiveMessage', (msg) => {
|
uni.$on('onReceiveMessage', (msg) => {
|
||||||
if (msg.targetId == this.targetId) {
|
if (msg.targetId == this.targetId) {
|
||||||
RongIMLib.clearMessagesUnreadStatus(msg.conversationType, msg.targetId, msg.sentTime)
|
|
||||||
RongIMLib.sendReadReceiptMessage(msg.conversationType, msg.targetId, msg.sentTime)
|
|
||||||
this.getMessageList()
|
this.getMessageList()
|
||||||
im.setNotifyBadge()
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
beforeDestroy() {
|
onBackPress() {
|
||||||
uni.$off('onReceiveMessage')
|
uni.$off('onReceiveMessage')
|
||||||
},
|
},
|
||||||
onUnload() {
|
|
||||||
RongIMLib.clearReadReceiptReceivedListener()
|
|
||||||
},
|
|
||||||
computed: {
|
|
||||||
disabled() {
|
|
||||||
return this.inputTxt.length == 0
|
|
||||||
}
|
|
||||||
},
|
|
||||||
methods: {
|
methods: {
|
||||||
customCN(val) {
|
customCN(val) {
|
||||||
return timeCustomCN(val)
|
return timeCustomCN(val)
|
||||||
},
|
},
|
||||||
// 检查安卓录制权限
|
|
||||||
async getAndroidPermission() {
|
|
||||||
return await permision.requestAndroidPermission('android.permission.RECORD_AUDIO')
|
|
||||||
},
|
|
||||||
// 切换聊天信息
|
|
||||||
msgType() {
|
|
||||||
this.importTabs = this.importTabs === 1 ? 0 : 1
|
|
||||||
},
|
|
||||||
// 录制语音消息
|
|
||||||
startAudio(e) {
|
|
||||||
this.getAndroidPermission().then(code => {
|
|
||||||
switch (code) {
|
|
||||||
case 1:
|
|
||||||
this.showAudioTranscribe = true
|
|
||||||
recorderManager.start()
|
|
||||||
transcribe = setInterval(() => {
|
|
||||||
this.transcribeTime -= 1
|
|
||||||
if (this.transcribeTime === 0) {
|
|
||||||
this.chendAudio()
|
|
||||||
}
|
|
||||||
}, 1000)
|
|
||||||
break;
|
|
||||||
case 0:
|
|
||||||
uni.showToast({
|
|
||||||
title: '暂无麦克风权限,请前往应用设置开启麦克风',
|
|
||||||
icon: 'none'
|
|
||||||
})
|
|
||||||
break;
|
|
||||||
case -1:
|
|
||||||
uni.showToast({
|
|
||||||
title: '应用权限错误',
|
|
||||||
icon: 'none'
|
|
||||||
})
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
})
|
|
||||||
},
|
|
||||||
// 结束录音
|
|
||||||
chendAudio(e) {
|
|
||||||
if (!this.showAudioTranscribe) return
|
|
||||||
recorderManager.stop()
|
|
||||||
clearInterval(transcribe)
|
|
||||||
// 监听录音结束
|
|
||||||
recorderManager.onStop(res => {
|
|
||||||
im.sentVoice(this.conversationType, this.targetId, res.tempFilePath, (60 - this
|
|
||||||
.transcribeTime), () => {
|
|
||||||
setTimeout(() => {
|
|
||||||
this.getMessageList()
|
|
||||||
}, 500)
|
|
||||||
})
|
|
||||||
this.transcribeTime = 60
|
|
||||||
this.showAudioTranscribe = false
|
|
||||||
})
|
|
||||||
},
|
|
||||||
// 获取消息列表
|
// 获取消息列表
|
||||||
getMessageList() {
|
getMessageList() {
|
||||||
im.getMessageList(this.conversationType, this.targetId, (messages) => {
|
im.getMessageList(
|
||||||
this.messages = messages.reverse()
|
this.conversationType,
|
||||||
this.scrollBottom()
|
this.targetId,
|
||||||
})
|
new Date().getTime(),
|
||||||
|
10,
|
||||||
|
true,
|
||||||
|
(messages) => {
|
||||||
|
this.messages = messages.reverse()
|
||||||
|
this.scrollBottom()
|
||||||
|
})
|
||||||
},
|
},
|
||||||
// 发送文本消息
|
// 展示好友信息, type 1 是自己, 2 是对方
|
||||||
send() {
|
showUser(targetId, type) {
|
||||||
if (this.inputTxt === '') return
|
|
||||||
im.sentText(this.conversationType, this.targetId, this.inputTxt, () => {
|
|
||||||
setTimeout(() => {
|
|
||||||
this.getMessageList()
|
|
||||||
}, 500)
|
|
||||||
this.inputTxt = ''
|
|
||||||
})
|
|
||||||
},
|
|
||||||
// 展示好友信息
|
|
||||||
showFriend(targetId, type) {
|
|
||||||
uni.navigateTo({
|
uni.navigateTo({
|
||||||
url: type === 1 ? '/pages/im/friends/mine?targetId=' + targetId :
|
url: type === 1 ? '/pages/im/friends/mine?targetId=' + targetId :
|
||||||
'/pages/im/friends/info?targetId=' + targetId
|
'/pages/im/friends/info?targetId=' + targetId
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
// 滚动到底部
|
// 滚动到底部
|
||||||
scrollBottom() {
|
scrollBottom(type) {
|
||||||
|
// 清理当前会话,未读消息数量
|
||||||
|
RongIMLib.clearMessagesUnreadStatus(this.conversationType, this.targetId, new Date().getTime() + 1100)
|
||||||
|
// 发送消息已读状态给对方
|
||||||
|
RongIMLib.sendReadReceiptMessage(this.conversationType, this.targetId, new Date().getTime())
|
||||||
|
// 更新badge提醒数量
|
||||||
|
im.setNotifyBadge()
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
let el = this.$refs.chatBottom
|
let el = this.$refs.chatBottom
|
||||||
ChatList.scrollToElement(el, {
|
ChatList.scrollToElement(el, {
|
||||||
|
offset: 0,
|
||||||
animated: false
|
animated: false
|
||||||
})
|
})
|
||||||
}, 50)
|
}, 50)
|
||||||
@@ -228,155 +127,69 @@
|
|||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped lang="scss">
|
||||||
.audio-transcribe {
|
|
||||||
background: rgba(0, 0, 0, .6);
|
|
||||||
position: fixed;
|
|
||||||
height: 200rpx;
|
|
||||||
width: 300rpx;
|
|
||||||
border-radius: 10rpx;
|
|
||||||
z-index: 99;
|
|
||||||
top: 550rpx;
|
|
||||||
left: 225rpx;
|
|
||||||
flex-direction: column;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.audio-transcribe-src {
|
|
||||||
width: 88rpx;
|
|
||||||
height: 88rpx;
|
|
||||||
}
|
|
||||||
|
|
||||||
.audio-transcribe-text {
|
|
||||||
font-size: 28rpx;
|
|
||||||
color: #FFFFFF;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 窗口 */
|
/* 窗口 */
|
||||||
.chat {
|
.chat {
|
||||||
background: #F3F6FB;
|
background: $window-color;
|
||||||
flex: 1;
|
flex: 1;
|
||||||
}
|
|
||||||
|
|
||||||
.chat-scroll {
|
.body {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
}
|
|
||||||
|
|
||||||
.cell {
|
.cell {
|
||||||
padding: 10rpx 30rpx;
|
padding: 10rpx 30rpx;
|
||||||
}
|
|
||||||
|
|
||||||
.cell-time {
|
.time {
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
padding-bottom: 20rpx;
|
padding-bottom: 20rpx;
|
||||||
}
|
|
||||||
|
|
||||||
.cell-time-text {
|
.text {
|
||||||
background: #fff;
|
background: #fff;
|
||||||
font-size: 24rpx;
|
font-size: 24rpx;
|
||||||
color: #666;
|
color: #666;
|
||||||
line-height: 40rpx;
|
line-height: 40rpx;
|
||||||
padding: 0 20rpx;
|
padding: 0 20rpx;
|
||||||
border-radius: 10rpx;
|
border-radius: 10rpx;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.cell-item {
|
.cell-item {
|
||||||
width: 690rpx;
|
width: 690rpx;
|
||||||
justify-content: flex-start;
|
justify-content: flex-start;
|
||||||
}
|
|
||||||
|
|
||||||
.cell-footer {
|
|
||||||
height: 20rpx;
|
|
||||||
}
|
|
||||||
|
|
||||||
.active {
|
&.left {
|
||||||
width: 78rpx;
|
flex-direction: row;
|
||||||
height: 78rpx;
|
}
|
||||||
background-color: white;
|
|
||||||
border-radius: 10rpx;
|
|
||||||
}
|
|
||||||
|
|
||||||
.msg {
|
&.right {
|
||||||
margin: 0 20rpx;
|
flex-direction: row-reverse;
|
||||||
}
|
|
||||||
|
|
||||||
.state {
|
.state {
|
||||||
padding-top: 10rpx;
|
flex-direction: row;
|
||||||
}
|
justify-content: flex-end;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.state-text {
|
.msg {
|
||||||
font-size: 24rpx;
|
margin: 0 20rpx;
|
||||||
color: #666;
|
|
||||||
}
|
|
||||||
|
|
||||||
.cell-item.left {
|
.state {
|
||||||
flex-direction: row;
|
padding-top: 10rpx;
|
||||||
}
|
|
||||||
|
|
||||||
.cell-item.right {
|
.state-text {
|
||||||
flex-direction: row-reverse;
|
font-size: 24rpx;
|
||||||
}
|
color: #666;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.cell-item.right .state {
|
.cell-footer {
|
||||||
flex-direction: row;
|
height: 20rpx;
|
||||||
justify-content: flex-end;
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
/* footer */
|
|
||||||
.chat-footer {
|
|
||||||
background: white;
|
|
||||||
padding: 20rpx 30rpx;
|
|
||||||
display: flex;
|
|
||||||
justify-content: space-between;
|
|
||||||
flex-direction: row;
|
|
||||||
}
|
|
||||||
|
|
||||||
.msg-type {
|
|
||||||
width: 70rpx;
|
|
||||||
height: 70rpx;
|
|
||||||
}
|
|
||||||
|
|
||||||
.msg-type>.msg-type-icon {
|
|
||||||
margin: 5rpx;
|
|
||||||
width: 60rpx;
|
|
||||||
height: 60rpx;
|
|
||||||
}
|
|
||||||
|
|
||||||
.chat-mp3 {
|
|
||||||
background: #F3F6FB;
|
|
||||||
height: 70rpx;
|
|
||||||
line-height: 70rpx;
|
|
||||||
justify-content: center;
|
|
||||||
align-items: center;
|
|
||||||
width: 460rpx;
|
|
||||||
border-radius: 10rpx;
|
|
||||||
margin-right: 15rpx;
|
|
||||||
}
|
|
||||||
|
|
||||||
.chat-mp3-text {
|
|
||||||
font-size: 30rpx;
|
|
||||||
color: #333;
|
|
||||||
}
|
|
||||||
|
|
||||||
.chat-input {
|
|
||||||
background: #F3F6FB;
|
|
||||||
height: 70rpx;
|
|
||||||
width: 460rpx;
|
|
||||||
border-radius: 10rpx;
|
|
||||||
margin-right: 15rpx;
|
|
||||||
padding: 0 20rpx;
|
|
||||||
}
|
|
||||||
|
|
||||||
.chat-push {
|
|
||||||
background: #34CE98;
|
|
||||||
color: white;
|
|
||||||
width: 120rpx;
|
|
||||||
line-height: 70rpx;
|
|
||||||
text-align: center;
|
|
||||||
border-radius: 10rpx;
|
|
||||||
font-size: 30rpx;
|
|
||||||
font-weight: bold;
|
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -1,15 +0,0 @@
|
|||||||
<template>
|
|
||||||
<view>
|
|
||||||
|
|
||||||
</view>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
export default {
|
|
||||||
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style>
|
|
||||||
|
|
||||||
</style>
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
<template>
|
|
||||||
<view>
|
|
||||||
|
|
||||||
</view>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
export default {
|
|
||||||
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style>
|
|
||||||
|
|
||||||
</style>
|
|
||||||
@@ -1,49 +0,0 @@
|
|||||||
<template>
|
|
||||||
<view class="im--img" :class="guest ? 'right': 'left'">
|
|
||||||
<image class="src" :src="msg" @click="openImg" mode="widthFix"></image>
|
|
||||||
</view>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
export default {
|
|
||||||
name: 'showImage',
|
|
||||||
props: {
|
|
||||||
msg: {
|
|
||||||
type: String,
|
|
||||||
default: 'https://images.pexels.com/photos/9024609/pexels-photo-9024609.jpeg'
|
|
||||||
},
|
|
||||||
guest: {
|
|
||||||
type: Boolean,
|
|
||||||
default: true
|
|
||||||
}
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
openImg() {
|
|
||||||
uni.previewImage({
|
|
||||||
urls: [this.msg],
|
|
||||||
current: 1
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style scoped>
|
|
||||||
.im--img {
|
|
||||||
padding: 19rpx;
|
|
||||||
}
|
|
||||||
|
|
||||||
.im--img.left {
|
|
||||||
border-radius: 0 20rpx 20rpx 20rpx;
|
|
||||||
background: white;
|
|
||||||
}
|
|
||||||
|
|
||||||
.im--img.right {
|
|
||||||
border-radius: 20rpx 0 20rpx 20rpx;
|
|
||||||
background: #34CE98;
|
|
||||||
}
|
|
||||||
|
|
||||||
.src {
|
|
||||||
width: 240rpx;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@@ -1,46 +0,0 @@
|
|||||||
<template>
|
|
||||||
<view class="im--box">
|
|
||||||
<text class="im--text" :class="guest ? 'right': 'left'">{{msg}}</text>
|
|
||||||
</view>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
export default {
|
|
||||||
name: 'showText',
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
|
|
||||||
};
|
|
||||||
},
|
|
||||||
props: {
|
|
||||||
msg: {
|
|
||||||
type: String,
|
|
||||||
default: ''
|
|
||||||
},
|
|
||||||
guest: {
|
|
||||||
type: Boolean,
|
|
||||||
default: true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style scoped>
|
|
||||||
.im--text {
|
|
||||||
max-width: 400rpx;
|
|
||||||
padding: 20rpx;
|
|
||||||
font-size: 28rpx;
|
|
||||||
line-height: 40rpx;
|
|
||||||
}
|
|
||||||
|
|
||||||
.im--text.left {
|
|
||||||
border-radius: 0 20rpx 20rpx 20rpx;
|
|
||||||
background: white;
|
|
||||||
}
|
|
||||||
|
|
||||||
.im--text.right {
|
|
||||||
border-radius: 20rpx 0 20rpx 20rpx;
|
|
||||||
background: #34CE98;
|
|
||||||
color: white;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@@ -1,499 +0,0 @@
|
|||||||
<template>
|
|
||||||
<view class="chat-content">
|
|
||||||
<scroll-view class="chat-scrool" :scroll-y="true" :scroll-into-view="scrollIntoID"
|
|
||||||
:scroll-with-animation="false">
|
|
||||||
<!-- 聊天窗口 -->
|
|
||||||
<view class="chat-item" v-for="(item,index) in messages" :key="index">
|
|
||||||
<view class="chat-item-article" :class="item.messageDirection == 1 ? 'right' : 'left'">
|
|
||||||
<view class="chat-msg">
|
|
||||||
<!-- 文字消息 -->
|
|
||||||
<view class="chat-msg-text">{{ item.content.content }}</view>
|
|
||||||
<!-- 语音消息 -->
|
|
||||||
<view class="chat-msg-audio" @click="onPlayMsg()">
|
|
||||||
<image v-if="item.messageDirection == 0" src="@/static/icon/audio_green.png"
|
|
||||||
mode="widthFix"></image>
|
|
||||||
10"
|
|
||||||
<image v-if="item.messageDirection == 1" src="@/static/icon/audio_white.png"
|
|
||||||
mode="widthFix"></image>
|
|
||||||
</view>
|
|
||||||
<!-- 预留一些图片,语音表情包等位置 -->
|
|
||||||
</view>
|
|
||||||
<view class="chat-status" :class="{'hide': item.sentStatus == 50}"
|
|
||||||
v-if="item.messageDirection == 1">{{targetId}}{{ item.sentStatus == 50 ? '已读': '未读'}}</view>
|
|
||||||
<view class="chat-avatar" @click="showFriend(targetId, item.messageDirection)">
|
|
||||||
<u-avatar v-if="item.messageDirection == 2" shape="square" bg-color="#ffffff"
|
|
||||||
:src="userInfo.portraitUrl"></u-avatar>
|
|
||||||
<u-avatar v-else shape="square" bg-color="#ffffff" :src="$store.getters.sender.portraitUrl" />
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
<view class="chat-item-time" :id="'chatId_'+index">
|
|
||||||
<text>{{ item.sentTime|timeCustomCN }}</text>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</scroll-view>
|
|
||||||
|
|
||||||
<view class="chat-footer">
|
|
||||||
<view class="msg-type" @click="msgType">
|
|
||||||
<image src="@/static/icon/key-icon.png" v-if="importTabs === 0" mode="widthFix"></image>
|
|
||||||
<image src="@/static/icon/msg-icon.png" v-if="importTabs === 1" mode="widthFix"></image>
|
|
||||||
</view>
|
|
||||||
<block v-if="importTabs === 0">
|
|
||||||
<button type="default" class="chat-mp3" hover-class="chat-hover" @touchstart="startAudio"
|
|
||||||
@touchend="chendAudio">按住 说话</button>
|
|
||||||
</block>
|
|
||||||
<block v-if="importTabs === 1">
|
|
||||||
<input class="chat-input" type="text" v-model="inputTxt" confirm-type="发送" @confirm="send"
|
|
||||||
cursor-spacing="10" />
|
|
||||||
</block>
|
|
||||||
<button class="chat-push" :disabled="disabled" size="mini" @click="send">发送</button>
|
|
||||||
</view>
|
|
||||||
|
|
||||||
<!-- 录音中提示 -->
|
|
||||||
<view class="audio-transcribe" v-if="showAudioTranscribe">
|
|
||||||
<image src="@/static/icon/record-icon.png" mode="widthFix"></image>
|
|
||||||
<view class="text">录音中 {{transcribeTime}} s</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import * as RongIMLib from "@/uni_modules/RongCloud-IMWrapper/js_sdk/index"
|
|
||||||
import im from '@/utils/im/index.js'
|
|
||||||
import permision from "@/js_sdk/wa-permission/permission.js"
|
|
||||||
|
|
||||||
var transcribe
|
|
||||||
var recorderManager = uni.getRecorderManager()
|
|
||||||
|
|
||||||
export default {
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
targetId: '',
|
|
||||||
scrollIntoID: 'chatID_0',
|
|
||||||
inputTxt: '',
|
|
||||||
messages: [],
|
|
||||||
conversationType: 1,
|
|
||||||
totalCount: 0,
|
|
||||||
userInfo: {
|
|
||||||
name: '',
|
|
||||||
userId: '',
|
|
||||||
portraitUrl: ''
|
|
||||||
},
|
|
||||||
importTabs: 0,
|
|
||||||
showAudioTranscribe: false,
|
|
||||||
transcribeTime: 60,
|
|
||||||
audioSrc: '',
|
|
||||||
audioContextPaused: true
|
|
||||||
}
|
|
||||||
},
|
|
||||||
onLoad(e) {
|
|
||||||
this.targetId = e.targetId
|
|
||||||
this.conversationType = e.conversationType // 会话类型
|
|
||||||
// 消息总数量
|
|
||||||
RongIMLib.getMessageCount(this.conversationType, this.targetId, ({
|
|
||||||
code,
|
|
||||||
count
|
|
||||||
}) => {
|
|
||||||
if (code == 0) {
|
|
||||||
this.totalCount = count
|
|
||||||
}
|
|
||||||
})
|
|
||||||
this.userInfo = this.$store.getters.userInfo(this.targetId)
|
|
||||||
uni.setNavigationBarTitle({
|
|
||||||
title: this.$store.getters.userInfo(this.targetId).name
|
|
||||||
})
|
|
||||||
|
|
||||||
RongIMLib.clearMessagesUnreadStatus(this.conversationType, this.targetId, new Date().getTime())
|
|
||||||
im.setNotifyBadge()
|
|
||||||
RongIMLib.sendReadReceiptMessage(this.conversationType, this.targetId, new Date().getTime())
|
|
||||||
|
|
||||||
this.getMessageList()
|
|
||||||
|
|
||||||
// 监听消息回执
|
|
||||||
RongIMLib.addReadReceiptReceivedListener(({
|
|
||||||
data
|
|
||||||
}) => {
|
|
||||||
if (data.targetId == this.targetId) {
|
|
||||||
this.getMessageList()
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
// 监听录音结束
|
|
||||||
recorderManager.onStop(res => {
|
|
||||||
if (res.tempFilePath) this.audioSrc = res.tempFilePath
|
|
||||||
console.log('------------------获取到了录音的临时路径---------------')
|
|
||||||
console.log(res.tempFilePath)
|
|
||||||
})
|
|
||||||
// 简童收到新消息,判断是否是当前会话,更新会话内容
|
|
||||||
uni.$on('onReceiveMessage', (msg) => {
|
|
||||||
if (msg.targetId == this.targetId) {
|
|
||||||
RongIMLib.clearMessagesUnreadStatus(msg.conversationType, msg.targetId, msg.sentTime)
|
|
||||||
RongIMLib.sendReadReceiptMessage(msg.conversationType, msg.targetId, msg.sentTime)
|
|
||||||
this.getMessageList()
|
|
||||||
im.setNotifyBadge()
|
|
||||||
}
|
|
||||||
})
|
|
||||||
},
|
|
||||||
beforeDestroy() {
|
|
||||||
uni.$off('onReceiveMessage')
|
|
||||||
},
|
|
||||||
onUnload() {
|
|
||||||
RongIMLib.clearReadReceiptReceivedListener()
|
|
||||||
},
|
|
||||||
computed: {
|
|
||||||
disabled() {
|
|
||||||
return this.inputTxt.length == 0
|
|
||||||
}
|
|
||||||
},
|
|
||||||
onNavigationBarButtonTap(e) {
|
|
||||||
if (e.index == 0) {
|
|
||||||
uni.navigateTo({
|
|
||||||
url: '/pages/im/private/setting?targetId=' + this.targetId +
|
|
||||||
'&conversationType=' + this.conversationType,
|
|
||||||
events: {
|
|
||||||
messageClear: () => {
|
|
||||||
this.getMessageList()
|
|
||||||
console.log('聊天消息被清空');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
// 播放语音消息
|
|
||||||
onPlayMsg() {
|
|
||||||
let innerAudioContext = uni.createInnerAudioContext()
|
|
||||||
innerAudioContext.src = this.audioSrc
|
|
||||||
if (this.audioContextPaused) {
|
|
||||||
innerAudioContext.play()
|
|
||||||
this.audioContextPaused = false
|
|
||||||
return
|
|
||||||
}
|
|
||||||
innerAudioContext.stop()
|
|
||||||
innerAudioContext.onStop(resStop => {
|
|
||||||
this.audioContextPaused = true
|
|
||||||
})
|
|
||||||
},
|
|
||||||
// 检查安卓录制权限
|
|
||||||
async getAndroidPermission() {
|
|
||||||
return await permision.requestAndroidPermission('android.permission.RECORD_AUDIO')
|
|
||||||
},
|
|
||||||
// 切换聊天信息
|
|
||||||
msgType() {
|
|
||||||
this.importTabs = this.importTabs === 1 ? 0 : 1
|
|
||||||
},
|
|
||||||
// 录制语音消息
|
|
||||||
startAudio(e) {
|
|
||||||
this.getAndroidPermission().then(code => {
|
|
||||||
switch (code) {
|
|
||||||
case 1:
|
|
||||||
this.showAudioTranscribe = true
|
|
||||||
recorderManager.start()
|
|
||||||
transcribe = setInterval(() => {
|
|
||||||
this.transcribeTime -= 1
|
|
||||||
if (this.transcribeTime === 0) {
|
|
||||||
this.chendAudio()
|
|
||||||
}
|
|
||||||
}, 1000)
|
|
||||||
break;
|
|
||||||
case 0:
|
|
||||||
uni.showToast({
|
|
||||||
title: '暂无麦克风权限,请前往应用设置开启麦克风',
|
|
||||||
icon: 'none'
|
|
||||||
})
|
|
||||||
break;
|
|
||||||
case -1:
|
|
||||||
uni.showToast({
|
|
||||||
title: '应用权限错误',
|
|
||||||
icon: 'none'
|
|
||||||
})
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
})
|
|
||||||
},
|
|
||||||
// 结束录音
|
|
||||||
chendAudio(e) {
|
|
||||||
if (!this.showAudioTranscribe) return
|
|
||||||
recorderManager.stop()
|
|
||||||
clearInterval(transcribe)
|
|
||||||
this.transcribeTime = 60
|
|
||||||
this.showAudioTranscribe = false
|
|
||||||
},
|
|
||||||
getMessageList() {
|
|
||||||
// 获取消息列表
|
|
||||||
const objectNames = [
|
|
||||||
'RC:TxtMsg',
|
|
||||||
'RC:VcMsg',
|
|
||||||
'RC:HQVCMsg',
|
|
||||||
'RC:ImgMsg',
|
|
||||||
'RC:GIFMsg',
|
|
||||||
'RC:ImgTextMsg',
|
|
||||||
'RC:FileMsg',
|
|
||||||
'RC:LBSMsg',
|
|
||||||
'RC:SightMsg',
|
|
||||||
'RC:ReferenceMsg',
|
|
||||||
'RC:CombineMsg'
|
|
||||||
]
|
|
||||||
const timeStamp = new Date().getTime()
|
|
||||||
const count = 20 // 获取的消息数量
|
|
||||||
const isForward = true // 是否向前获取
|
|
||||||
RongIMLib.getHistoryMessagesByTimestamp(this.conversationType, this.targetId, objectNames, timeStamp,
|
|
||||||
count,
|
|
||||||
isForward,
|
|
||||||
({
|
|
||||||
code,
|
|
||||||
messages
|
|
||||||
}) => {
|
|
||||||
if (code === 0) {
|
|
||||||
this.messages = messages.reverse()
|
|
||||||
this.scrollBottom()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)
|
|
||||||
},
|
|
||||||
send() {
|
|
||||||
im.sendMsg(this.conversationType, this.targetId, this.inputTxt, () => {
|
|
||||||
this.getMessageList()
|
|
||||||
this.inputTxt = ''
|
|
||||||
})
|
|
||||||
},
|
|
||||||
showFriend(targetId, type) {
|
|
||||||
this.$Router.push({
|
|
||||||
name: type === 1 ? 'imFriendsMine' : 'imFriendsInfo',
|
|
||||||
params: {
|
|
||||||
targetId
|
|
||||||
}
|
|
||||||
})
|
|
||||||
},
|
|
||||||
scrollBottom() {
|
|
||||||
this.$nextTick(function() {
|
|
||||||
setTimeout(() => {
|
|
||||||
let len = this.messages.length
|
|
||||||
if (len) {
|
|
||||||
if (this.scrollIntoID == "chatId_" + (len - 1)) {
|
|
||||||
this.scrollIntoID = "chatId_" + (len - 2)
|
|
||||||
this.scrollBottom()
|
|
||||||
} else if (this.scrollIntoID == "chatId_" + (len - 2)) {
|
|
||||||
this.scrollIntoID = "chatId_" + (len - 1)
|
|
||||||
} else {
|
|
||||||
this.scrollIntoID = "chatId_" + (len - 1)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
this.scrollIntoID = "chatId_0";
|
|
||||||
}
|
|
||||||
}, 50)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
.chat-content {
|
|
||||||
height: 100vh;
|
|
||||||
background: $window-color;
|
|
||||||
|
|
||||||
.audio-transcribe {
|
|
||||||
background: rgba($color: #000000, $alpha: .6);
|
|
||||||
position: fixed;
|
|
||||||
height: 200rpx;
|
|
||||||
width: 300rpx;
|
|
||||||
border-radius: $radius;
|
|
||||||
color: white;
|
|
||||||
z-index: 99;
|
|
||||||
top: 50%;
|
|
||||||
left: 50%;
|
|
||||||
margin-top: -200rpx;
|
|
||||||
margin-left: -150rpx;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
|
|
||||||
image {
|
|
||||||
width: 88rpx;
|
|
||||||
height: 88rpx;
|
|
||||||
}
|
|
||||||
|
|
||||||
.text {
|
|
||||||
font-size: $title-size-m;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.chat-scrool {
|
|
||||||
height: calc(100vh - 140rpx);
|
|
||||||
box-sizing: border-box;
|
|
||||||
padding-bottom: $padding;
|
|
||||||
|
|
||||||
.chat-item {
|
|
||||||
.chat-item-time {
|
|
||||||
text-align: center;
|
|
||||||
padding: $padding/2 $padding;
|
|
||||||
|
|
||||||
text {
|
|
||||||
background: rgba($color: #000000, $alpha: .2);
|
|
||||||
color: white;
|
|
||||||
font-size: $title-size-sm - 4;
|
|
||||||
line-height: 40rpx;
|
|
||||||
padding: 0 15rpx;
|
|
||||||
display: inline-block;
|
|
||||||
border-radius: $radius-lg;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.chat-item-article {
|
|
||||||
position: relative;
|
|
||||||
padding: 10rpx ($padding + 110) 0;
|
|
||||||
overflow: hidden;
|
|
||||||
min-height: 40px;
|
|
||||||
|
|
||||||
.chat-msg {
|
|
||||||
overflow: hidden;
|
|
||||||
|
|
||||||
.chat-msg-text {
|
|
||||||
display: inline-block;
|
|
||||||
padding: ($padding - 10) $padding;
|
|
||||||
color: $text-color;
|
|
||||||
box-sizing: border-box;
|
|
||||||
font-size: $title-size-lg;
|
|
||||||
}
|
|
||||||
|
|
||||||
.chat-msg-audio {
|
|
||||||
@extend .chat-msg-text;
|
|
||||||
width: 50%;
|
|
||||||
|
|
||||||
image {
|
|
||||||
width: 38rpx;
|
|
||||||
height: 38rpx;
|
|
||||||
margin: 0;
|
|
||||||
vertical-align: middle;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.chat-status {
|
|
||||||
color: $text-gray;
|
|
||||||
font-size: $title-size-sm;
|
|
||||||
text-align: right;
|
|
||||||
|
|
||||||
&.hide {
|
|
||||||
color: $text-gray-m;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.chat-avatar {
|
|
||||||
position: absolute;
|
|
||||||
top: 0;
|
|
||||||
background: white;
|
|
||||||
border-radius: $radius-m;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.left {
|
|
||||||
.chat-avatar {
|
|
||||||
left: $margin;
|
|
||||||
}
|
|
||||||
|
|
||||||
.chat-msg {
|
|
||||||
.chat-msg-text {
|
|
||||||
background-color: white;
|
|
||||||
border-radius: 0 $radius*2 $radius*2 $radius*2;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&.right {
|
|
||||||
.chat-avatar {
|
|
||||||
right: $margin;
|
|
||||||
}
|
|
||||||
|
|
||||||
.chat-msg {
|
|
||||||
text-align: right;
|
|
||||||
|
|
||||||
.chat-msg-text {
|
|
||||||
border-radius: $radius*2 0 $radius*2 $radius*2;
|
|
||||||
background: $main-color;
|
|
||||||
color: white;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.chat-footer {
|
|
||||||
position: fixed;
|
|
||||||
bottom: 0;
|
|
||||||
left: 0;
|
|
||||||
right: 0;
|
|
||||||
height: 140rpx;
|
|
||||||
padding: 20rpx ($padding + 150rpx) 40rpx ($padding + 94rpx);
|
|
||||||
background: white;
|
|
||||||
box-sizing: border-box;
|
|
||||||
z-index: 99;
|
|
||||||
|
|
||||||
.msg-type {
|
|
||||||
position: absolute;
|
|
||||||
top: 20rpx;
|
|
||||||
left: $padding;
|
|
||||||
line-height: 80rpx;
|
|
||||||
|
|
||||||
image {
|
|
||||||
width: 64rpx;
|
|
||||||
height: 64rpx;
|
|
||||||
vertical-align: middle;
|
|
||||||
margin-bottom: 10rpx;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.chat-input {
|
|
||||||
background: $window-color;
|
|
||||||
height: 80rpx;
|
|
||||||
border-radius: $radius-lg;
|
|
||||||
font-size: $title-size-m;
|
|
||||||
padding: 0 $padding;
|
|
||||||
box-sizing: border-box;
|
|
||||||
}
|
|
||||||
|
|
||||||
.chat-mp3 {
|
|
||||||
background: $window-color;
|
|
||||||
line-height: 80rpx;
|
|
||||||
text-align: center;
|
|
||||||
border-radius: $radius-lg;
|
|
||||||
font-weight: bold;
|
|
||||||
color: #333;
|
|
||||||
font-size: $title-size-m;
|
|
||||||
|
|
||||||
&::after {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.chat-hover {
|
|
||||||
opacity: .5;
|
|
||||||
}
|
|
||||||
|
|
||||||
.chat-push[size='mini'] {
|
|
||||||
position: absolute;
|
|
||||||
right: $margin;
|
|
||||||
top: 20rpx;
|
|
||||||
height: 80rpx;
|
|
||||||
line-height: 80rpx;
|
|
||||||
padding: 0;
|
|
||||||
margin: 0;
|
|
||||||
width: 120rpx;
|
|
||||||
background: $main-color;
|
|
||||||
color: white;
|
|
||||||
border-radius: $radius-lg;
|
|
||||||
font-size: $title-size-m;
|
|
||||||
font-weight: bold;
|
|
||||||
|
|
||||||
&[disabled] {
|
|
||||||
background: rgba($color: $main-color, $alpha: .5);
|
|
||||||
}
|
|
||||||
|
|
||||||
&::after {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@@ -4,7 +4,15 @@
|
|||||||
<view class="status-main">
|
<view class="status-main">
|
||||||
<view class="helloe">欢迎使用ZH-HEALTH健康</view>
|
<view class="helloe">欢迎使用ZH-HEALTH健康</view>
|
||||||
<view class="btns">
|
<view class="btns">
|
||||||
<view class="btns-item" @click="onBtn('signIndex')"><image src="@/static/icon/sign-icon.gif" mode="widthFix"></image></view>
|
<!-- 打卡图标gif -->
|
||||||
|
<!-- <view class="btns-item" @click="$Router.push({name: 'signIndex'})"><image src="@/static/icon/sign-icon.gif" mode="widthFix"></image></view> -->
|
||||||
|
<view class="btns-clock" @click="$Router.push({name: 'signIndex'})">
|
||||||
|
<image src="@/static/icon/clock_icon.png" mode="widthFix"></image>
|
||||||
|
<view class="btns-clock-text">
|
||||||
|
打卡
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
<view class="btns-item show" @click="onBtn('noticeIndex')"><uni-icons custom-prefix="iconfont" type="icon-pinglun" size="25"></uni-icons></view>
|
<view class="btns-item show" @click="onBtn('noticeIndex')"><uni-icons custom-prefix="iconfont" type="icon-pinglun" size="25"></uni-icons></view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
@@ -101,12 +109,29 @@
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
.helloe {
|
.helloe {
|
||||||
line-height: 100rpx;
|
line-height: 100rpx;
|
||||||
font-size: $title-size + 10;
|
font-size: $title-size + 4;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
}
|
}
|
||||||
.btns {
|
.btns {
|
||||||
margin-left: $margin;
|
margin-left: $margin;
|
||||||
display: flex;
|
display: flex;
|
||||||
|
.btns-clock {
|
||||||
|
color: #885100;
|
||||||
|
height: 50rpx;
|
||||||
|
font-size: $title-size-sm - 2;
|
||||||
|
border-radius: 40rpx;
|
||||||
|
display: flex;
|
||||||
|
background-image: linear-gradient(to right, #fce938, #ffce36);
|
||||||
|
image {
|
||||||
|
width: 48rpx;
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
.btns-clock-text {
|
||||||
|
line-height: 50rpx;
|
||||||
|
font-weight: 600;
|
||||||
|
padding: 0 20rpx 0 8rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
.btns-item {
|
.btns-item {
|
||||||
position: relative;
|
position: relative;
|
||||||
text-align: right;
|
text-align: right;
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
<view class="number">
|
<view class="number">
|
||||||
<text>{{ dateData.total }}</text>天
|
<text>{{ dateData.total }}</text>天
|
||||||
</view>
|
</view>
|
||||||
本月签到
|
本月打卡
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
<view class="label">
|
<view class="label">
|
||||||
@@ -18,7 +18,7 @@
|
|||||||
<view class="number">
|
<view class="number">
|
||||||
<text>{{ dateData.continue }}</text>天
|
<text>{{ dateData.continue }}</text>天
|
||||||
</view>
|
</view>
|
||||||
累计签到
|
累计打卡
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
@@ -50,25 +50,28 @@
|
|||||||
六
|
六
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
<view class="day" v-for="(item, index) in dateArr">
|
<view class="day" v-for="(item, index) in dateArr" :key="index">
|
||||||
<view class="day-label" v-for="(items, index) in item">
|
<view class="day-label" v-for="(items, index) in item" :key="index">
|
||||||
<view class="label-block" :class="{active : items.isSign}" v-if="!items.isHidden">{{ items.isSign ? '签' : items.date }}</view>
|
<view class="label-block" :class="{active : items.isSign}" v-if="!items.isHidden">
|
||||||
|
<uni-icons v-if="items.isSign" class="search-icon" custom-prefix="iconfont" type="icon-dui" color="#ffffff" size="18"></uni-icons>
|
||||||
|
<block v-else>{{ items.date }}</block>
|
||||||
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
<view class="signBtn">
|
<view class="signBtn">
|
||||||
<view class="btn" @click="signClick" :class="{active : dateData.isSign}">
|
<view class="btn" @click="signClick" :class="{active : dateData.isSign}">
|
||||||
{{ dateData.isSign ? '当日已签' : '立即签到'}}
|
{{ dateData.isSign ? '今日已打卡' : '今日打卡'}}
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
<view class="tipsText">
|
<view class="tipsText">
|
||||||
ZH大健康用户签到
|
ZH大健康用户打卡
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { date, sign } from '@/apis/interfaces/sign'
|
import { date, sign } from '@/apis/interfaces/sign'
|
||||||
export default {
|
export default {
|
||||||
@@ -112,9 +115,9 @@
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
page {
|
page {
|
||||||
background: $window-color;
|
background: $window-color;
|
||||||
@@ -174,7 +177,9 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
.signDate {
|
.signDate {
|
||||||
padding: $padding;
|
padding: $padding;
|
||||||
|
border-radius: $radius-m;
|
||||||
|
background-color: white;
|
||||||
.date {
|
.date {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
font-size: $title-size + 6;
|
font-size: $title-size + 6;
|
||||||
@@ -209,6 +214,12 @@
|
|||||||
height: 56rpx;
|
height: 56rpx;
|
||||||
line-height: 56rpx;
|
line-height: 56rpx;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
|
position: relative;
|
||||||
|
.label-icon {
|
||||||
|
position: absolute;
|
||||||
|
left: 10rpx;
|
||||||
|
top: 0;
|
||||||
|
}
|
||||||
&.active {
|
&.active {
|
||||||
background-color: $main-color;
|
background-color: $main-color;
|
||||||
color: white;
|
color: white;
|
||||||
@@ -232,7 +243,8 @@
|
|||||||
color: $text-gray;
|
color: $text-gray;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.tipsText {
|
.tipsText {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
@@ -241,4 +253,4 @@
|
|||||||
color: $text-gray-m;
|
color: $text-gray-m;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
color: $text-gray-m;
|
</style>
|
||||||
|
|||||||
@@ -155,12 +155,10 @@
|
|||||||
if (this.$store.state.token === '') return;
|
if (this.$store.state.token === '') return;
|
||||||
info()
|
info()
|
||||||
.then(res => {
|
.then(res => {
|
||||||
console.log(res);
|
|
||||||
uni.setNavigationBarTitle({
|
uni.setNavigationBarTitle({
|
||||||
title: res.nickname
|
title: res.nickname
|
||||||
});
|
});
|
||||||
this.userInfo = res;
|
this.userInfo = res;
|
||||||
console.log(res);
|
|
||||||
})
|
})
|
||||||
.catch(err => {
|
.catch(err => {
|
||||||
uni.showToast({
|
uni.showToast({
|
||||||
|
|||||||
@@ -1,64 +1,68 @@
|
|||||||
<template>
|
<template>
|
||||||
<view class="content vertical">
|
<view class="content vertical">
|
||||||
<!-- logo -->
|
<!-- logo -->
|
||||||
<image class="logo" src="@/static/wallet/logo.png" mode="widthFix"></image>
|
<image class="logo" src="@/static/wallet/logo.png" mode="widthFix"></image>
|
||||||
<!-- 副标题 -->
|
<!-- 副标题 -->
|
||||||
<view class="sub-title">激活您的ZH健康钱包获取钱包地址,地址可以理解为您的个人银行卡卡号</view>
|
<view class="sub-title">激活您的ZH健康钱包获取钱包地址,地址可以理解为您的个人银行卡卡号</view>
|
||||||
<!-- 按钮 -->
|
<!-- 按钮 -->
|
||||||
<view class="wallet-btn" @click="$Router.replace({name: 'WalletCreate'})">激活钱包</view>
|
<view class="wallet-btn" @click="$Router.replace({name: 'WalletCreate'})">激活钱包</view>
|
||||||
</view>
|
</view>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
export default {
|
export default {
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
page {
|
page {
|
||||||
background-color: white;
|
background-color: white;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
.content{
|
.content {
|
||||||
position: relative;
|
position: relative;
|
||||||
height: 100vh;
|
height: 100vh;
|
||||||
padding: 0 15vw;
|
padding: 0 15vw;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
.logo{
|
|
||||||
width: 138rpx;
|
.logo {
|
||||||
vertical-align: top;
|
width: 138rpx;
|
||||||
margin-bottom: 20vh;
|
vertical-align: top;
|
||||||
}
|
margin-bottom: 20vh;
|
||||||
.sub-title{
|
}
|
||||||
font-size: $title-size-m;
|
|
||||||
color: $text-gray;
|
.sub-title {
|
||||||
}
|
font-size: $title-size-m;
|
||||||
.wallet-btn{
|
color: $text-gray;
|
||||||
width: 100%;
|
}
|
||||||
background-color: $main-color;
|
|
||||||
height: 90rpx;
|
.wallet-btn {
|
||||||
line-height: 90rpx;
|
width: 100%;
|
||||||
margin-top: $margin * 2;
|
background-color: $main-color;
|
||||||
border-radius: $radius-lg;
|
height: 90rpx;
|
||||||
color: white;
|
line-height: 90rpx;
|
||||||
font-weight: bold;
|
margin-top: $margin * 2;
|
||||||
font-size: $title-size;
|
border-radius: $radius-lg;
|
||||||
&.hollow{
|
color: white;
|
||||||
background-color: white;
|
font-weight: bold;
|
||||||
color: $main-color;
|
font-size: $title-size;
|
||||||
border:solid 2rpx $main-color;
|
|
||||||
box-sizing: border-box;
|
&.hollow {
|
||||||
}
|
background-color: white;
|
||||||
}
|
color: $main-color;
|
||||||
}
|
border: solid 2rpx $main-color;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -1,187 +1,193 @@
|
|||||||
<template>
|
<template>
|
||||||
<view>
|
<view>
|
||||||
<!-- 设置钱包密码 -->
|
<!-- 设置钱包密码 -->
|
||||||
<view class="password">
|
<view class="password">
|
||||||
<view class="prompt">请设置6位数字密码,建议不要使用连续的数字</view>
|
<view class="prompt">请设置6位数字密码,建议不要使用连续的数字</view>
|
||||||
<view class="group">
|
<view class="group">
|
||||||
<view class="inputs" @click="onShowKet('password')">
|
<view class="inputs" @click="onShowKet('password')">
|
||||||
<block v-if="password.length > 0">
|
<block v-if="password.length > 0">
|
||||||
<text v-for="item in password.length" :key="item">•</text>
|
<text v-for="item in password.length" :key="item">•</text>
|
||||||
</block>
|
</block>
|
||||||
<block v-if="keyShow && valKye === 'password'">
|
<block v-if="keyShow && valKye === 'password'">
|
||||||
<text class="flicker-animation">|</text>
|
<text class="flicker-animation">|</text>
|
||||||
</block>
|
</block>
|
||||||
<block v-else>
|
<block v-else>
|
||||||
<text v-if="password.length === 0" class="placeholder">请设置密码</text>
|
<text v-if="password.length === 0" class="placeholder">请设置密码</text>
|
||||||
</block>
|
</block>
|
||||||
</view>
|
</view>
|
||||||
<view class="inputs" :class="{'hide': verify === ''}" @click="onShowKet('verify')">
|
<view class="inputs" :class="{'hide': verify === ''}" @click="onShowKet('verify')">
|
||||||
<block v-if="verify.length > 0">
|
<block v-if="verify.length > 0">
|
||||||
<text v-for="item in verify.length" :key="item">•</text>
|
<text v-for="item in verify.length" :key="item">•</text>
|
||||||
</block>
|
</block>
|
||||||
<block v-if="keyShow && valKye === 'verify'">
|
<block v-if="keyShow && valKye === 'verify'">
|
||||||
<text class="flicker-animation">|</text>
|
<text class="flicker-animation">|</text>
|
||||||
</block>
|
</block>
|
||||||
<block v-else>
|
<block v-else>
|
||||||
<text v-if="verify.length === 0" class="placeholder">请确认密码</text>
|
<text v-if="verify.length === 0" class="placeholder">请确认密码</text>
|
||||||
</block>
|
</block>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
<!-- key键盘 -->
|
<!-- key键盘 -->
|
||||||
<u-keyboard
|
<u-keyboard mode="number" random dotDisabled :overlay="false" :show="keyShow" :showCancel="false"
|
||||||
mode="number"
|
@change="keyValChange" @backspace="keyValBackspace" @confirm="keyShow = false"></u-keyboard>
|
||||||
random
|
<!-- 按钮 -->
|
||||||
dotDisabled
|
<view class="buttons">
|
||||||
:overlay="false"
|
<button type="default" form-type="submit" @click="createWallet">确认激活</button>
|
||||||
:show="keyShow"
|
</view>
|
||||||
:showCancel="false"
|
</view>
|
||||||
@change="keyValChange"
|
</template>
|
||||||
@backspace="keyValBackspace"
|
|
||||||
@confirm="keyShow = false"
|
<script>
|
||||||
></u-keyboard>
|
import {
|
||||||
<!-- 按钮 -->
|
security
|
||||||
<view class="buttons">
|
} from '@/apis/interfaces/wallet';
|
||||||
<button type="default" form-type="submit" @click="createWallet">确认激活</button>
|
export default {
|
||||||
</view>
|
data() {
|
||||||
</view>
|
return {
|
||||||
</template>
|
password: '',
|
||||||
|
verify: '',
|
||||||
<script>
|
valKye: '',
|
||||||
import { security } from '@/apis/interfaces/wallet';
|
keyShow: false
|
||||||
export default {
|
};
|
||||||
data() {
|
},
|
||||||
return {
|
methods: {
|
||||||
password: '',
|
// 唤起key
|
||||||
verify : '',
|
onShowKet(key) {
|
||||||
valKye : '',
|
this.valKye = key
|
||||||
keyShow : false
|
this.keyShow = true
|
||||||
};
|
},
|
||||||
},
|
// 键盘输入
|
||||||
methods: {
|
keyValChange(e) {
|
||||||
// 唤起key
|
if (this[this.valKye].length >= 6) return
|
||||||
onShowKet(key){
|
this[this.valKye] += e
|
||||||
this.valKye = key
|
},
|
||||||
this.keyShow = true
|
// 键盘删除
|
||||||
},
|
keyValBackspace(e) {
|
||||||
// 键盘输入
|
if (this[this.valKye].length) this[this.valKye] = this[this.valKye].substr(0, this[this.valKye].length -
|
||||||
keyValChange(e){
|
1)
|
||||||
if(this[this.valKye].length >= 6) return
|
},
|
||||||
this[this.valKye] += e
|
// 激活钱包
|
||||||
},
|
createWallet() {
|
||||||
// 键盘删除
|
if (this.password === '' || this.verify === '') {
|
||||||
keyValBackspace(e){
|
uni.showToast({
|
||||||
if(this[this.valKye].length) this[this.valKye] = this[this.valKye].substr(0, this[this.valKye].length - 1)
|
icon: 'none',
|
||||||
},
|
title: '请设置密码'
|
||||||
// 激活钱包
|
});
|
||||||
createWallet() {
|
return;
|
||||||
if (this.password === '' || this.verify === '') {
|
}
|
||||||
uni.showToast({
|
if (this.password !== this.verify) {
|
||||||
icon: 'none',
|
uni.showToast({
|
||||||
title: '请设置密码'
|
icon: 'none',
|
||||||
});
|
title: '两次输入密码不一致'
|
||||||
return;
|
});
|
||||||
}
|
return;
|
||||||
if (this.password !== this.verify) {
|
}
|
||||||
uni.showToast({
|
|
||||||
icon: 'none',
|
security({
|
||||||
title: '两次输入密码不一致'
|
code: Number(this.password)
|
||||||
});
|
}).then(res => {
|
||||||
return;
|
this.$Router.replace({
|
||||||
}
|
name: 'WalletProperty'
|
||||||
|
})
|
||||||
security({
|
}).catch(err => {
|
||||||
code: Number(this.password)
|
uni.showToast({
|
||||||
}).then(res => {
|
icon: 'none',
|
||||||
this.$Router.replace({
|
title: err.message
|
||||||
name: 'WalletProperty'
|
});
|
||||||
})
|
});
|
||||||
}).catch(err => {
|
}
|
||||||
uni.showToast({
|
}
|
||||||
icon: 'none',
|
};
|
||||||
title: err.message
|
</script>
|
||||||
});
|
|
||||||
});
|
<style>
|
||||||
}
|
.flicker-animation {
|
||||||
}
|
animation: flicker .8s infinite;
|
||||||
};
|
}
|
||||||
</script>
|
|
||||||
|
@keyframes flicker {
|
||||||
<style>
|
0% {
|
||||||
.flicker-animation{
|
opacity: 0;
|
||||||
animation: flicker .8s infinite;
|
}
|
||||||
}
|
|
||||||
@keyframes flicker{
|
100 {
|
||||||
0%{opacity: 0;}
|
opacity: 1;
|
||||||
100{opacity: 1;}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
// 副标题
|
// 副标题
|
||||||
.sub-title {
|
.sub-title {
|
||||||
color: $text-gray;
|
color: $text-gray;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
margin: $margin * 2 $margin;
|
margin: $margin * 2 $margin;
|
||||||
font-size: $title-size-m;
|
font-size: $title-size-m;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 设置密码
|
// 设置密码
|
||||||
.password {
|
.password {
|
||||||
padding: 0 $padding * 2;
|
padding: 0 $padding * 2;
|
||||||
.prompt {
|
|
||||||
margin-top: $margin * 2;
|
.prompt {
|
||||||
font-size: $title-size-m;
|
margin-top: $margin * 2;
|
||||||
color: $main-color;
|
font-size: $title-size-m;
|
||||||
text-align: center;
|
color: $main-color;
|
||||||
}
|
text-align: center;
|
||||||
|
}
|
||||||
.group {
|
|
||||||
padding-top: $padding;
|
.group {
|
||||||
.inputs {
|
padding-top: $padding;
|
||||||
padding: 10rpx $padding + 10;
|
|
||||||
margin-top: $margin;
|
.inputs {
|
||||||
border-radius: $radius-m;
|
padding: 10rpx $padding + 10;
|
||||||
background-color: $window-color;
|
margin-top: $margin;
|
||||||
height: 70rpx;
|
border-radius: $radius-m;
|
||||||
line-height: 70rpx;
|
background-color: $window-color;
|
||||||
font-size: $title-size-lg;
|
height: 70rpx;
|
||||||
text-align: center;
|
line-height: 70rpx;
|
||||||
text{
|
font-size: $title-size-lg;
|
||||||
padding: 0 10rpx;
|
text-align: center;
|
||||||
text-align: center;
|
|
||||||
}
|
text {
|
||||||
.placeholder{
|
padding: 0 10rpx;
|
||||||
color: $text-gray;
|
text-align: center;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
.placeholder {
|
||||||
}
|
color: $text-gray;
|
||||||
|
}
|
||||||
// 按钮
|
}
|
||||||
.buttons {
|
}
|
||||||
padding: $padding * 2;
|
}
|
||||||
.text {
|
|
||||||
text-align: center;
|
// 按钮
|
||||||
line-height: 90rpx;
|
.buttons {
|
||||||
height: 90rpx;
|
padding: $padding * 2;
|
||||||
margin-bottom: $margin * 2;
|
|
||||||
font-size: $title-size-lg;
|
.text {
|
||||||
color: $main-color;
|
text-align: center;
|
||||||
font-weight: bold;
|
line-height: 90rpx;
|
||||||
}
|
height: 90rpx;
|
||||||
|
margin-bottom: $margin * 2;
|
||||||
button {
|
font-size: $title-size-lg;
|
||||||
height: 90rpx;
|
color: $main-color;
|
||||||
line-height: 90rpx;
|
font-weight: bold;
|
||||||
background-color: $main-color;
|
}
|
||||||
border-radius: $radius-m;
|
|
||||||
color: white;
|
button {
|
||||||
font-weight: bold;
|
height: 90rpx;
|
||||||
font-size: $title-size;
|
line-height: 90rpx;
|
||||||
&::after{
|
background-color: $main-color;
|
||||||
display: none;
|
border-radius: $radius-m;
|
||||||
}
|
color: white;
|
||||||
}
|
font-weight: bold;
|
||||||
}
|
font-size: $title-size;
|
||||||
|
|
||||||
|
&::after {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -1,112 +1,122 @@
|
|||||||
<template>
|
<template>
|
||||||
<view>
|
<view>
|
||||||
<!-- 提示信息 -->
|
<!-- 提示信息 -->
|
||||||
<view class="prompt">请按照顺序记录并确保正确备份助记词</view>
|
<view class="prompt">请按照顺序记录并确保正确备份助记词</view>
|
||||||
<!-- 助记词 -->
|
<!-- 助记词 -->
|
||||||
<ul class="mnemonic">
|
<ul class="mnemonic">
|
||||||
<li v-for="(item, index) in mnemonic" :key="index">{{item}}</li>
|
<li v-for="(item, index) in mnemonic" :key="index">{{item}}</li>
|
||||||
</ul>
|
</ul>
|
||||||
<!-- 按钮 -->
|
<!-- 按钮 -->
|
||||||
<view class="buttons">
|
<view class="buttons">
|
||||||
<view class="text">注:助记词是用户账户的唯一标识,不能分享给他人,掌握该助记词即可控制该账户与钱包</view>
|
<view class="text">注:助记词是用户账户的唯一标识,不能分享给他人,掌握该助记词即可控制该账户与钱包</view>
|
||||||
<!-- <button type="default" @click="goto">验证助记词</button> -->
|
<!-- <button type="default" @click="goto">验证助记词</button> -->
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { seed } from "@/apis/interfaces/wallet"
|
import {
|
||||||
export default {
|
seed
|
||||||
data() {
|
} from "@/apis/interfaces/wallet"
|
||||||
return {
|
export default {
|
||||||
mnemonic: []
|
data() {
|
||||||
}
|
return {
|
||||||
},
|
mnemonic: []
|
||||||
mounted() {
|
}
|
||||||
seed({
|
},
|
||||||
code: this.$Route.query.password
|
mounted() {
|
||||||
}).then(res => {
|
seed({
|
||||||
this.mnemonic = res.seed.split(' ')
|
code: this.$Route.query.password
|
||||||
}).catch(err => {
|
}).then(res => {
|
||||||
uni.showToast({
|
this.mnemonic = res.seed.split(' ')
|
||||||
icon: 'none',
|
}).catch(err => {
|
||||||
title: err.message
|
uni.showToast({
|
||||||
})
|
icon: 'none',
|
||||||
})
|
title: err.message
|
||||||
},
|
})
|
||||||
methods: {
|
})
|
||||||
goto(){
|
},
|
||||||
this.$Router.replace({
|
methods: {
|
||||||
name: 'WalletValidation',
|
goto() {
|
||||||
params: {
|
this.$Router.replace({
|
||||||
seed: this.mnemonic,
|
name: 'WalletValidation',
|
||||||
sign: this.sign
|
params: {
|
||||||
}
|
seed: this.mnemonic,
|
||||||
})
|
sign: this.sign
|
||||||
}
|
}
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
</script>
|
}
|
||||||
|
}
|
||||||
<style lang="scss" scoped>
|
</script>
|
||||||
// 提示信息
|
|
||||||
.prompt{
|
<style lang="scss" scoped>
|
||||||
color: $text-gray;
|
// 提示信息
|
||||||
text-align: center;
|
.prompt {
|
||||||
line-height: 90rpx;
|
color: $text-gray;
|
||||||
font-size: $title-size-m;
|
text-align: center;
|
||||||
}
|
line-height: 90rpx;
|
||||||
// 跳过
|
font-size: $title-size-m;
|
||||||
.skip{
|
}
|
||||||
padding: $padding * 2;
|
|
||||||
text-align: center;
|
// 跳过
|
||||||
color: $text-gray;
|
.skip {
|
||||||
navigator{
|
padding: $padding * 2;
|
||||||
color: $main-color;
|
text-align: center;
|
||||||
margin-left: $margin/2;
|
color: $text-gray;
|
||||||
display: inline-block;
|
|
||||||
}
|
navigator {
|
||||||
}
|
color: $main-color;
|
||||||
// 助记词
|
margin-left: $margin/2;
|
||||||
.mnemonic{
|
display: inline-block;
|
||||||
margin: $margin $margin * 2;
|
}
|
||||||
border-radius: $radius-m;
|
}
|
||||||
box-shadow: 0 0 4rpx 4rpx rgba($color: $text-color, $alpha: .02);
|
|
||||||
background-color: white;
|
// 助记词
|
||||||
padding: $padding;
|
.mnemonic {
|
||||||
list-style: none;
|
margin: $margin $margin * 2;
|
||||||
display: flex;
|
border-radius: $radius-m;
|
||||||
flex-wrap: wrap;
|
box-shadow: 0 0 4rpx 4rpx rgba($color: $text-color, $alpha: .02);
|
||||||
li{
|
background-color: white;
|
||||||
text-align: center;
|
padding: $padding;
|
||||||
height: 58rpx;
|
list-style: none;
|
||||||
padding: 0 $padding/2;
|
display: flex;
|
||||||
line-height: 58rpx;
|
flex-wrap: wrap;
|
||||||
margin: $margin / 2;
|
|
||||||
color: $text-color;
|
li {
|
||||||
background: rgba($color: $border-color, $alpha: .4);
|
text-align: center;
|
||||||
}
|
height: 58rpx;
|
||||||
}
|
padding: 0 $padding/2;
|
||||||
// 按钮
|
line-height: 58rpx;
|
||||||
.buttons{
|
margin: $margin / 2;
|
||||||
padding: $padding $padding * 2;
|
color: $text-color;
|
||||||
.text{
|
background: rgba($color: $border-color, $alpha: .4);
|
||||||
text-align: center;
|
}
|
||||||
margin-bottom: $margin * 2;
|
}
|
||||||
font-size: $title-size-m;
|
|
||||||
color: $text-price;
|
// 按钮
|
||||||
}
|
.buttons {
|
||||||
button{
|
padding: $padding $padding * 2;
|
||||||
height: 90rpx;
|
|
||||||
line-height: 90rpx;
|
.text {
|
||||||
background-color: $main-color;
|
text-align: center;
|
||||||
border-radius: $radius-lg;
|
margin-bottom: $margin * 2;
|
||||||
color: white;
|
font-size: $title-size-m;
|
||||||
font-weight: bold;
|
color: $text-price;
|
||||||
font-size: $title-size;
|
}
|
||||||
&::after{
|
|
||||||
display: none;
|
button {
|
||||||
}
|
height: 90rpx;
|
||||||
}
|
line-height: 90rpx;
|
||||||
}
|
background-color: $main-color;
|
||||||
|
border-radius: $radius-lg;
|
||||||
|
color: white;
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: $title-size;
|
||||||
|
|
||||||
|
&::after {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -1,119 +1,130 @@
|
|||||||
<template>
|
<template>
|
||||||
<view>
|
<view>
|
||||||
<!-- 私钥 -->
|
<!-- 私钥 -->
|
||||||
<view class="keys">
|
<view class="keys">
|
||||||
<view class="title">您的ZH托管钱包</view>
|
<view class="title">您的ZH托管钱包</view>
|
||||||
<view class="key">{{key || '-'}}</view>
|
<view class="key">{{key || '-'}}</view>
|
||||||
<view class="copykey" @click="copykey">复制我的私钥</view>
|
<view class="copykey" @click="copykey">复制我的私钥</view>
|
||||||
</view>
|
</view>
|
||||||
<!-- 疑问 -->
|
<!-- 疑问 -->
|
||||||
<view class="doubt" v-if="rules.length > 0">
|
<view class="doubt" v-if="rules.length > 0">
|
||||||
<view class="doubt-item" v-for="(item, index) in rules" :key="index">
|
<view class="doubt-item" v-for="(item, index) in rules" :key="index">
|
||||||
<view class="title">{{item.title || '-'}}</view>
|
<view class="title">{{item.title || '-'}}</view>
|
||||||
<view class="content">{{item.description || '-'}}</view>
|
<view class="content">{{item.description || '-'}}</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
<!-- 免责说明 -->
|
<!-- 免责说明 -->
|
||||||
<!-- <view class="liability">
|
<!-- <view class="liability">
|
||||||
<navigator url="/pages/wallet/cmsWithDraw">免责条款</navigator>
|
<navigator url="/pages/wallet/cmsWithDraw">免责条款</navigator>
|
||||||
</view> -->
|
</view> -->
|
||||||
</view>
|
</view>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { privatekey, keyrules } from '@/apis/interfaces/wallet'
|
import {
|
||||||
export default {
|
privatekey,
|
||||||
data() {
|
keyrules
|
||||||
return {
|
} from '@/apis/interfaces/wallet'
|
||||||
key: "",
|
export default {
|
||||||
rules: [
|
data() {
|
||||||
{
|
return {
|
||||||
title: "什么是托管钱包?",
|
key: "",
|
||||||
description: "托管钱包顾名思义就是用户把私钥和数字资产委托给其他机构管理,也就是就是通过中心化的方式安全管理并保存资产,本质上是与区块链所追求的去中心化相背离的。"
|
rules: [{
|
||||||
},
|
title: "什么是托管钱包?",
|
||||||
{
|
description: "托管钱包顾名思义就是用户把私钥和数字资产委托给其他机构管理,也就是就是通过中心化的方式安全管理并保存资产,本质上是与区块链所追求的去中心化相背离的。"
|
||||||
title: "什么是钱包私钥?",
|
},
|
||||||
description: "作为管理和使用加密货币最关键的东西,私钥对所有数字货币用户而言具有所有权,拥有私钥才能支配相应的加密资产。"
|
{
|
||||||
}
|
title: "什么是钱包私钥?",
|
||||||
]
|
description: "作为管理和使用加密货币最关键的东西,私钥对所有数字货币用户而言具有所有权,拥有私钥才能支配相应的加密资产。"
|
||||||
};
|
}
|
||||||
},
|
]
|
||||||
mounted() {
|
};
|
||||||
privatekey(this.$Route.query.password).then(res => {
|
},
|
||||||
this.key = res.private_key
|
mounted() {
|
||||||
}).catch(err => {
|
privatekey(this.$Route.query.password).then(res => {
|
||||||
uni.showToast({
|
this.key = res.private_key
|
||||||
title: err.message,
|
}).catch(err => {
|
||||||
icon : 'none'
|
uni.showToast({
|
||||||
})
|
title: err.message,
|
||||||
})
|
icon: 'none'
|
||||||
},
|
})
|
||||||
methods:{
|
})
|
||||||
copykey(){
|
},
|
||||||
uni.setClipboardData({
|
methods: {
|
||||||
data: this.key
|
copykey() {
|
||||||
})
|
uni.setClipboardData({
|
||||||
}
|
data: this.key
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
</script>
|
}
|
||||||
|
}
|
||||||
<style lang="scss">
|
</script>
|
||||||
.keys{
|
|
||||||
margin: $margin * 2;
|
<style lang="scss">
|
||||||
background: white;
|
.keys {
|
||||||
padding: $padding * 2;
|
margin: $margin * 2;
|
||||||
box-shadow: 0 0 4rpx 4rpx rgba($color: #000000, $alpha: .02);
|
background: white;
|
||||||
border-radius: $radius;
|
padding: $padding * 2;
|
||||||
.title{
|
box-shadow: 0 0 4rpx 4rpx rgba($color: #000000, $alpha: .02);
|
||||||
text-align: center;
|
border-radius: $radius;
|
||||||
font-weight: bold;
|
|
||||||
font-size: $title-size + 4;
|
.title {
|
||||||
color: $text-color;
|
text-align: center;
|
||||||
}
|
font-weight: bold;
|
||||||
.key{
|
font-size: $title-size + 4;
|
||||||
padding: $padding * 2 0;
|
color: $text-color;
|
||||||
text-align: center;
|
}
|
||||||
color: $main-color;
|
|
||||||
word-wrap: break-word;
|
.key {
|
||||||
}
|
padding: $padding * 2 0;
|
||||||
.copykey{
|
text-align: center;
|
||||||
background-color: $main-color;
|
color: $main-color;
|
||||||
color: white;
|
word-wrap: break-word;
|
||||||
height: 95rpx;
|
}
|
||||||
line-height: 95rpx;
|
|
||||||
text-align: center;
|
.copykey {
|
||||||
font-size: $title-size;
|
background-color: $main-color;
|
||||||
border-radius: $radius-m;
|
color: white;
|
||||||
font-weight: bold;
|
height: 95rpx;
|
||||||
}
|
line-height: 95rpx;
|
||||||
}
|
text-align: center;
|
||||||
.doubt{
|
font-size: $title-size;
|
||||||
margin: $margin $margin * 2;
|
border-radius: $radius-m;
|
||||||
.doubt-item{
|
font-weight: bold;
|
||||||
padding: $padding 0;
|
}
|
||||||
.title{
|
}
|
||||||
font-weight: bold;
|
|
||||||
color: $text-color;
|
.doubt {
|
||||||
line-height: 50rpx;
|
margin: $margin $margin * 2;
|
||||||
font-size: $title-size + 2;
|
|
||||||
}
|
.doubt-item {
|
||||||
.content{
|
padding: $padding 0;
|
||||||
color: $text-gray;
|
|
||||||
font-size: $title-size-m;
|
.title {
|
||||||
line-height: 40rpx;
|
font-weight: bold;
|
||||||
}
|
color: $text-color;
|
||||||
}
|
line-height: 50rpx;
|
||||||
}
|
font-size: $title-size + 2;
|
||||||
.liability{
|
}
|
||||||
text-align: center;
|
|
||||||
color: $text-gray;
|
.content {
|
||||||
@extend .ios-bottom;
|
color: $text-gray;
|
||||||
navigator{
|
font-size: $title-size-m;
|
||||||
font-size: $title-size-sm;
|
line-height: 40rpx;
|
||||||
display: inline-block;
|
}
|
||||||
line-height: 90rpx;
|
}
|
||||||
padding: 0 ($padding * 2);
|
}
|
||||||
}
|
|
||||||
}
|
.liability {
|
||||||
|
text-align: center;
|
||||||
|
color: $text-gray;
|
||||||
|
@extend .ios-bottom;
|
||||||
|
|
||||||
|
navigator {
|
||||||
|
font-size: $title-size-sm;
|
||||||
|
display: inline-block;
|
||||||
|
line-height: 90rpx;
|
||||||
|
padding: 0 ($padding * 2);
|
||||||
|
}
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -1,359 +1,386 @@
|
|||||||
<template>
|
<template>
|
||||||
<view>
|
<view>
|
||||||
<view class="propery">
|
<view class="propery">
|
||||||
<view class="propery-content">
|
<view class="propery-content">
|
||||||
<view class="currency">钱包余额</view>
|
<view class="currency">钱包余额</view>
|
||||||
<view class="balance">{{ balance.balance || '0' }}</view>
|
<view class="balance">{{ balance.balance || '0' }}</view>
|
||||||
<view class="frozen">{{ balance.frozen || '0' }} 冻结中</view>
|
<view class="frozen">{{ balance.frozen || '0' }} 冻结中</view>
|
||||||
<view class="balance-flex">
|
<view class="balance-flex">
|
||||||
<view class="balance-flex-item" @click="showAddress">区块链地址</view>
|
<view class="balance-flex-item" @click="showAddress">区块链地址</view>
|
||||||
<view class="balance-flex-item" @click="showPrivatekey('privatekey')">我的私钥</view>
|
<view class="balance-flex-item" @click="showPrivatekey('privatekey')">我的私钥</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
<!-- 账户记录 -->
|
<!-- 账户记录 -->
|
||||||
<view class="record">
|
<view class="record">
|
||||||
<view class="record-tabs">
|
<view class="record-tabs">
|
||||||
<view class="tabs-item" :class="logsType === 0 ? 'show': ''" @click="onLogsType(0)">全部</view>
|
<view class="tabs-item" :class="logsType === 0 ? 'show': ''" @click="onLogsType(0)">全部</view>
|
||||||
<view class="tabs-item" :class="logsType === 2 ? 'show': ''" @click="onLogsType(2)">收入</view>
|
<view class="tabs-item" :class="logsType === 2 ? 'show': ''" @click="onLogsType(2)">收入</view>
|
||||||
<view class="tabs-item" :class="logsType === 1 ? 'show': ''" @click="onLogsType(1)">支出</view>
|
<view class="tabs-item" :class="logsType === 1 ? 'show': ''" @click="onLogsType(1)">支出</view>
|
||||||
</view>
|
</view>
|
||||||
<record :list="logs" />
|
<record :list="logs" />
|
||||||
<!-- ios安全距离 -->
|
<!-- ios安全距离 -->
|
||||||
<view class="ios-bottom"></view>
|
<view class="ios-bottom"></view>
|
||||||
</view>
|
</view>
|
||||||
<!-- 钱包密码 -->
|
<!-- 钱包密码 -->
|
||||||
<u-popup :show="passwordShow" @close="resetPassword" mode="center" round="10" borderRadius="10">
|
<u-popup :show="passwordShow" @close="resetPassword" mode="center" round="10" borderRadius="10">
|
||||||
<view class="validationPassword">
|
<view class="validationPassword">
|
||||||
<view class="from">
|
<view class="from">
|
||||||
<view class="title">验证钱包密码</view>
|
<view class="title">验证钱包密码</view>
|
||||||
<view class="inputs">
|
<view class="inputs">
|
||||||
<text v-for="item in password.length" :key="item">•</text>
|
<text v-for="item in password.length" :key="item">•</text>
|
||||||
<text class="flicker-animation">|</text>
|
<text class="flicker-animation">|</text>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</u-popup>
|
</u-popup>
|
||||||
<!-- key -->
|
<!-- key -->
|
||||||
<u-keyboard
|
<u-keyboard mode="number" random dotDisabled :overlay="false" :show="passwordShow" confirmText="验证"
|
||||||
mode="number"
|
@change="keyValChange" @backspace="keyValBackspace" @confirm="payPassword('confirm', passwordPages)"
|
||||||
random
|
@cancel="passwordShow = false"></u-keyboard>
|
||||||
dotDisabled
|
</view>
|
||||||
:overlay="false"
|
|
||||||
:show="passwordShow"
|
|
||||||
confirmText="验证"
|
|
||||||
@change="keyValChange"
|
|
||||||
@backspace="keyValBackspace"
|
|
||||||
@confirm="payPassword('confirm', passwordPages)"
|
|
||||||
@cancel="passwordShow = false"
|
|
||||||
></u-keyboard>
|
|
||||||
</view>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import record from '@/components/property/record'
|
import record from '@/components/property/record'
|
||||||
import { sum, logs, securityCheck } from '@/apis/interfaces/wallet'
|
import {
|
||||||
export default {
|
sum,
|
||||||
components: {
|
logs,
|
||||||
record
|
securityCheck
|
||||||
},
|
} from '@/apis/interfaces/wallet'
|
||||||
data() {
|
export default {
|
||||||
return {
|
components: {
|
||||||
balance : {},
|
record
|
||||||
logs : [],
|
},
|
||||||
logsType : 0,
|
data() {
|
||||||
password : '',
|
return {
|
||||||
passwordShow : false,
|
balance: {},
|
||||||
passwordPages: ''
|
logs: [],
|
||||||
};
|
logsType: 0,
|
||||||
},
|
password: '',
|
||||||
onShow() {
|
passwordShow: false,
|
||||||
Promise.all([
|
passwordPages: ''
|
||||||
sum(),
|
};
|
||||||
logs()
|
},
|
||||||
]).then(res => {
|
onShow() {
|
||||||
this.balance = res[0]
|
Promise.all([
|
||||||
this.logs = res[1]
|
sum(),
|
||||||
}).catch(err => {
|
logs()
|
||||||
uni.showToast({
|
]).then(res => {
|
||||||
icon: 'none',
|
this.balance = res[0]
|
||||||
title: err.message
|
this.logs = res[1]
|
||||||
})
|
}).catch(err => {
|
||||||
})
|
uni.showToast({
|
||||||
},
|
icon: 'none',
|
||||||
methods: {
|
title: err.message
|
||||||
// 键盘输入
|
})
|
||||||
keyValChange(e){
|
})
|
||||||
if(this.password.length >= 6) return
|
},
|
||||||
this.password += e
|
methods: {
|
||||||
},
|
// 键盘输入
|
||||||
// 键盘删除
|
keyValChange(e) {
|
||||||
keyValBackspace(e){
|
if (this.password.length >= 6) return
|
||||||
if(this.password.length) this.password = this.password.substr(0, this.password.length - 1)
|
this.password += e
|
||||||
},
|
},
|
||||||
// 弹出私钥
|
// 键盘删除
|
||||||
showPrivatekey(pages){
|
keyValBackspace(e) {
|
||||||
this.passwordShow = true
|
if (this.password.length) this.password = this.password.substr(0, this.password.length - 1)
|
||||||
this.passwordPages = pages
|
},
|
||||||
},
|
// 弹出私钥
|
||||||
// 重置密码
|
showPrivatekey(pages) {
|
||||||
resetPassword(){
|
this.passwordShow = true
|
||||||
this.passwordShow = false
|
this.passwordPages = pages
|
||||||
this.password = ''
|
},
|
||||||
},
|
// 重置密码
|
||||||
// 验证私钥
|
resetPassword() {
|
||||||
payPassword(type){
|
this.passwordShow = false
|
||||||
if(type === 'confirm'){
|
this.password = ''
|
||||||
if(this.password === '') {
|
},
|
||||||
uni.showToast({
|
// 验证私钥
|
||||||
title: '请输入安全密码',
|
payPassword(type) {
|
||||||
icon : 'none'
|
if (type === 'confirm') {
|
||||||
})
|
if (this.password === '') {
|
||||||
return
|
uni.showToast({
|
||||||
}
|
title: '请输入安全密码',
|
||||||
securityCheck(this.password).then(res => {
|
icon: 'none'
|
||||||
switch (this.passwordPages){
|
})
|
||||||
case 'privatekey':
|
return
|
||||||
this.$Router.push({name:'WalletPrivatekey', params: {password: this.password}})
|
}
|
||||||
break;
|
securityCheck(this.password).then(res => {
|
||||||
case 'ResetPassword':
|
switch (this.passwordPages) {
|
||||||
this.$Router.push({name:'ResetPassword', params: {password: this.password}})
|
case 'privatekey':
|
||||||
break;
|
this.$Router.push({
|
||||||
case 'WalletMnemonic':
|
name: 'WalletPrivatekey',
|
||||||
this.$Router.push({name:'WalletMnemonic', params: {password: this.password}})
|
params: {
|
||||||
break;
|
password: this.password
|
||||||
}
|
}
|
||||||
this.resetPassword()
|
})
|
||||||
}).catch(err => {
|
break;
|
||||||
uni.showToast({
|
case 'ResetPassword':
|
||||||
title: err.message,
|
this.$Router.push({
|
||||||
icon: 'none',
|
name: 'ResetPassword',
|
||||||
})
|
params: {
|
||||||
})
|
password: this.password
|
||||||
return
|
}
|
||||||
}
|
})
|
||||||
this.$refs.showPassword.close()
|
break;
|
||||||
},
|
case 'WalletMnemonic':
|
||||||
// 交易记录
|
this.$Router.push({
|
||||||
onLogsType(index) {
|
name: 'WalletMnemonic',
|
||||||
if (this.logsType === index) return
|
params: {
|
||||||
this.logsType = index
|
password: this.password
|
||||||
this.logs = []
|
}
|
||||||
logs({
|
})
|
||||||
flag: this.logsType
|
break;
|
||||||
}).then(res => {
|
}
|
||||||
this.logs = res
|
this.resetPassword()
|
||||||
})
|
}).catch(err => {
|
||||||
},
|
uni.showToast({
|
||||||
// 区块地址
|
title: err.message,
|
||||||
showAddress() {
|
icon: 'none',
|
||||||
uni.showModal({
|
})
|
||||||
title: '我的区块链地址',
|
})
|
||||||
content: this.balance.address,
|
return
|
||||||
cancelText: '复制',
|
}
|
||||||
cancelColor: '#009B69',
|
this.$refs.showPassword.close()
|
||||||
success: (res) => {
|
},
|
||||||
if (res.cancel) {
|
// 交易记录
|
||||||
uni.setClipboardData({
|
onLogsType(index) {
|
||||||
data: this.balance.address
|
if (this.logsType === index) return
|
||||||
})
|
this.logsType = index
|
||||||
}
|
this.logs = []
|
||||||
}
|
logs({
|
||||||
})
|
flag: this.logsType
|
||||||
}
|
}).then(res => {
|
||||||
},
|
this.logs = res
|
||||||
onNavigationBarButtonTap(e) {
|
})
|
||||||
if (e.index === 0) {
|
},
|
||||||
uni.showActionSheet({
|
// 区块地址
|
||||||
itemList: ['导出助记词', '修改密码'],
|
showAddress() {
|
||||||
success: (res) => {
|
uni.showModal({
|
||||||
switch (res.tapIndex) {
|
title: '我的区块链地址',
|
||||||
case 0:
|
content: this.balance.address,
|
||||||
this.showPrivatekey('WalletMnemonic')
|
cancelText: '复制',
|
||||||
break;
|
cancelColor: '#009B69',
|
||||||
case 1:
|
success: (res) => {
|
||||||
this.showPrivatekey('ResetPassword')
|
if (res.cancel) {
|
||||||
break;
|
uni.setClipboardData({
|
||||||
}
|
data: this.balance.address
|
||||||
uni.hideLoading()
|
})
|
||||||
}
|
}
|
||||||
})
|
}
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
</script>
|
onNavigationBarButtonTap(e) {
|
||||||
|
if (e.index === 0) {
|
||||||
<style>
|
uni.showActionSheet({
|
||||||
.flicker-animation{
|
itemList: ['导出助记词', '修改密码'],
|
||||||
animation: flicker .8s infinite;
|
success: (res) => {
|
||||||
}
|
switch (res.tapIndex) {
|
||||||
@keyframes flicker{
|
case 0:
|
||||||
0%{opacity: 0;}
|
this.showPrivatekey('WalletMnemonic')
|
||||||
100{opacity: 1;}
|
break;
|
||||||
}
|
case 1:
|
||||||
|
this.showPrivatekey('ResetPassword')
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
uni.hideLoading()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.flicker-animation {
|
||||||
|
animation: flicker .8s infinite;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes flicker {
|
||||||
|
0% {
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
100 {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
// 验证密码弹出层
|
// 验证密码弹出层
|
||||||
.validationPassword{
|
.validationPassword {
|
||||||
width: 80vw;
|
width: 80vw;
|
||||||
.from{
|
|
||||||
padding: $padding*2;
|
|
||||||
text-align: center;
|
|
||||||
.title{
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
font-weight: bold;
|
|
||||||
font-size: $title-size;
|
|
||||||
padding-bottom: $padding;
|
|
||||||
}
|
|
||||||
// input{
|
|
||||||
// background: $window-color;
|
|
||||||
// height: 90rpx;
|
|
||||||
// left: 90rpx;
|
|
||||||
// font-size: $title-size-lg;
|
|
||||||
// border-radius: 45rpx;
|
|
||||||
// }
|
|
||||||
.inputs {
|
|
||||||
background-color: $window-color;
|
|
||||||
height: 90rpx;
|
|
||||||
line-height: 90rpx;
|
|
||||||
border-radius: 45rpx;
|
|
||||||
font-size: $title-size-lg;
|
|
||||||
text-align: center;
|
|
||||||
text{
|
|
||||||
padding: 0 10rpx;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
.placeholder{
|
|
||||||
color: $text-gray;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.buttons{
|
|
||||||
text-align: center;
|
|
||||||
padding: 0 $padding*2;
|
|
||||||
.button{
|
|
||||||
height: 90rpx;
|
|
||||||
line-height: 90rpx;
|
|
||||||
margin-bottom: $margin;
|
|
||||||
&.cancel{
|
|
||||||
color: $text-gray;
|
|
||||||
}
|
|
||||||
&.confirm{
|
|
||||||
color: white;
|
|
||||||
background: $main-color;
|
|
||||||
border-radius: 45rpx;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//
|
|
||||||
//
|
|
||||||
}
|
|
||||||
// 账户
|
|
||||||
.propery {
|
|
||||||
position: relative;
|
|
||||||
padding-top: var(--status-bar-height);
|
|
||||||
background-image: linear-gradient(to right, $main-color, #22aa98);
|
|
||||||
|
|
||||||
&::before {
|
.from {
|
||||||
position: absolute;
|
padding: $padding*2;
|
||||||
left: 0;
|
text-align: center;
|
||||||
top: 0;
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
content: " ";
|
|
||||||
// background-image: url(@/static/background/wallet-back.png);
|
|
||||||
background-size: 100%;
|
|
||||||
background-repeat: no-repeat;
|
|
||||||
}
|
|
||||||
|
|
||||||
.propery-content {
|
.title {
|
||||||
position: relative;
|
display: flex;
|
||||||
z-index: 1;
|
flex-direction: column;
|
||||||
padding: $padding * 5 $padding * 2;
|
align-items: center;
|
||||||
text-align: center;
|
justify-content: center;
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: $title-size;
|
||||||
|
padding-bottom: $padding;
|
||||||
|
}
|
||||||
|
|
||||||
.currency {
|
// input{
|
||||||
font-size: $title-size-m;
|
// background: $window-color;
|
||||||
color: rgba($color: white, $alpha: .8);
|
// height: 90rpx;
|
||||||
}
|
// left: 90rpx;
|
||||||
|
// font-size: $title-size-lg;
|
||||||
|
// border-radius: 45rpx;
|
||||||
|
// }
|
||||||
|
.inputs {
|
||||||
|
background-color: $window-color;
|
||||||
|
height: 90rpx;
|
||||||
|
line-height: 90rpx;
|
||||||
|
border-radius: 45rpx;
|
||||||
|
font-size: $title-size-lg;
|
||||||
|
text-align: center;
|
||||||
|
|
||||||
.balance {
|
text {
|
||||||
font-size: $title-size * 2;
|
padding: 0 10rpx;
|
||||||
padding: ($padding / 2) 0;
|
text-align: center;
|
||||||
color: white;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
.frozen {
|
.placeholder {
|
||||||
background: rgba($color: #000000, $alpha: .1);
|
color: $text-gray;
|
||||||
color: rgba($color: white, $alpha: .7);
|
}
|
||||||
display: inline-block;
|
}
|
||||||
padding: 0 $padding;
|
}
|
||||||
font-size: $title-size-m;
|
|
||||||
height: 50rpx;
|
|
||||||
line-height: 50rpx;
|
|
||||||
border-radius: $radius-m;
|
|
||||||
border: solid 1rpx rgba($color: white, $alpha: .4)
|
|
||||||
}
|
|
||||||
|
|
||||||
.balance-flex {
|
.buttons {
|
||||||
display: flex;
|
text-align: center;
|
||||||
justify-content: center;
|
padding: 0 $padding*2;
|
||||||
margin-top: $margin * 3;
|
|
||||||
|
|
||||||
.balance-flex-item {
|
.button {
|
||||||
background-color: white;
|
height: 90rpx;
|
||||||
width: 200rpx;
|
line-height: 90rpx;
|
||||||
height: 75rpx;
|
margin-bottom: $margin;
|
||||||
line-height: 75rpx;
|
|
||||||
color: $main-color;
|
|
||||||
margin: 0 $margin;
|
|
||||||
border-radius: $radius-m;
|
|
||||||
font-size: $title-size-lg;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 记录
|
&.cancel {
|
||||||
.record {
|
color: $text-gray;
|
||||||
background-color: white;
|
}
|
||||||
border-radius: $radius $radius 0 0;
|
|
||||||
padding: $padding ($padding * 2);
|
|
||||||
margin-top: -$margin;
|
|
||||||
position: relative;
|
|
||||||
z-index: 2;
|
|
||||||
|
|
||||||
.record-tabs {
|
&.confirm {
|
||||||
display: flex;
|
color: white;
|
||||||
justify-content: space-around;
|
background: $main-color;
|
||||||
font-weight: bold;
|
border-radius: 45rpx;
|
||||||
font-size: $title-size;
|
}
|
||||||
color: $text-gray;
|
}
|
||||||
line-height: 70rpx;
|
}
|
||||||
margin-bottom: $margin;
|
|
||||||
|
|
||||||
.tabs-item {
|
//
|
||||||
position: relative;
|
//
|
||||||
padding: 0 $padding;
|
}
|
||||||
|
|
||||||
&.show {
|
// 账户
|
||||||
color: $main-color;
|
.propery {
|
||||||
|
position: relative;
|
||||||
|
padding-top: var(--status-bar-height);
|
||||||
|
background-image: linear-gradient(to right, $main-color, #22aa98);
|
||||||
|
|
||||||
&::before {
|
&::before {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
bottom: 0;
|
left: 0;
|
||||||
left: $padding;
|
top: 0;
|
||||||
right: $padding;
|
width: 100%;
|
||||||
height: 4rpx;
|
height: 100%;
|
||||||
content: " ";
|
content: " ";
|
||||||
background-color: $main-color;
|
// background-image: url(@/static/background/wallet-back.png);
|
||||||
}
|
background-size: 100%;
|
||||||
}
|
background-repeat: no-repeat;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
.propery-content {
|
||||||
|
position: relative;
|
||||||
|
z-index: 1;
|
||||||
|
padding: $padding * 5 $padding * 2;
|
||||||
|
text-align: center;
|
||||||
|
|
||||||
|
.currency {
|
||||||
|
font-size: $title-size-m;
|
||||||
|
color: rgba($color: white, $alpha: .8);
|
||||||
|
}
|
||||||
|
|
||||||
|
.balance {
|
||||||
|
font-size: $title-size * 2;
|
||||||
|
padding: ($padding / 2) 0;
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.frozen {
|
||||||
|
background: rgba($color: #000000, $alpha: .1);
|
||||||
|
color: rgba($color: white, $alpha: .7);
|
||||||
|
display: inline-block;
|
||||||
|
padding: 0 $padding;
|
||||||
|
font-size: $title-size-m;
|
||||||
|
height: 50rpx;
|
||||||
|
line-height: 50rpx;
|
||||||
|
border-radius: $radius-m;
|
||||||
|
border: solid 1rpx rgba($color: white, $alpha: .4)
|
||||||
|
}
|
||||||
|
|
||||||
|
.balance-flex {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
margin-top: $margin * 3;
|
||||||
|
|
||||||
|
.balance-flex-item {
|
||||||
|
background-color: white;
|
||||||
|
width: 200rpx;
|
||||||
|
height: 75rpx;
|
||||||
|
line-height: 75rpx;
|
||||||
|
color: $main-color;
|
||||||
|
margin: 0 $margin;
|
||||||
|
border-radius: $radius-m;
|
||||||
|
font-size: $title-size-lg;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 记录
|
||||||
|
.record {
|
||||||
|
background-color: white;
|
||||||
|
border-radius: $radius $radius 0 0;
|
||||||
|
padding: $padding ($padding * 2);
|
||||||
|
margin-top: -$margin;
|
||||||
|
position: relative;
|
||||||
|
z-index: 2;
|
||||||
|
|
||||||
|
.record-tabs {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-around;
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: $title-size;
|
||||||
|
color: $text-gray;
|
||||||
|
line-height: 70rpx;
|
||||||
|
margin-bottom: $margin;
|
||||||
|
|
||||||
|
.tabs-item {
|
||||||
|
position: relative;
|
||||||
|
padding: 0 $padding;
|
||||||
|
|
||||||
|
&.show {
|
||||||
|
color: $main-color;
|
||||||
|
|
||||||
|
&::before {
|
||||||
|
position: absolute;
|
||||||
|
bottom: 0;
|
||||||
|
left: $padding;
|
||||||
|
right: $padding;
|
||||||
|
height: 4rpx;
|
||||||
|
content: " ";
|
||||||
|
background-color: $main-color;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -1,198 +1,203 @@
|
|||||||
<template>
|
<template>
|
||||||
<view>
|
<view>
|
||||||
<!-- 设置钱包密码 -->
|
<!-- 设置钱包密码 -->
|
||||||
<view class="password">
|
<view class="password">
|
||||||
<view class="prompt">请设置6位数字密码,建议不要使用连续的数字</view>
|
<view class="prompt">请设置6位数字密码,建议不要使用连续的数字</view>
|
||||||
<view class="group">
|
<view class="group">
|
||||||
<view class="inputs" @click="onShowKet('password')">
|
<view class="inputs" @click="onShowKet('password')">
|
||||||
<block v-if="password.length > 0">
|
<block v-if="password.length > 0">
|
||||||
<text v-for="item in password.length" :key="item">•</text>
|
<text v-for="item in password.length" :key="item">•</text>
|
||||||
</block>
|
</block>
|
||||||
<block v-if="keyShow && valKye === 'password'">
|
<block v-if="keyShow && valKye === 'password'">
|
||||||
<text class="flicker-animation">|</text>
|
<text class="flicker-animation">|</text>
|
||||||
</block>
|
</block>
|
||||||
<block v-else>
|
<block v-else>
|
||||||
<text v-if="password.length === 0" class="placeholder">请设置密码</text>
|
<text v-if="password.length === 0" class="placeholder">请设置密码</text>
|
||||||
</block>
|
</block>
|
||||||
</view>
|
</view>
|
||||||
<view class="inputs" :class="{'hide': verify === ''}" @click="onShowKet('verify')">
|
<view class="inputs" :class="{'hide': verify === ''}" @click="onShowKet('verify')">
|
||||||
<block v-if="verify.length > 0">
|
<block v-if="verify.length > 0">
|
||||||
<text v-for="item in verify.length" :key="item">•</text>
|
<text v-for="item in verify.length" :key="item">•</text>
|
||||||
</block>
|
</block>
|
||||||
<block v-if="keyShow && valKye === 'verify'">
|
<block v-if="keyShow && valKye === 'verify'">
|
||||||
<text class="flicker-animation">|</text>
|
<text class="flicker-animation">|</text>
|
||||||
</block>
|
</block>
|
||||||
<block v-else>
|
<block v-else>
|
||||||
<text v-if="verify.length === 0" class="placeholder">请确认密码</text>
|
<text v-if="verify.length === 0" class="placeholder">请确认密码</text>
|
||||||
</block>
|
</block>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
<!-- key键盘 -->
|
<!-- key键盘 -->
|
||||||
<u-keyboard
|
<u-keyboard mode="number" random dotDisabled :overlay="false" :show="keyShow" :showCancel="false"
|
||||||
mode="number"
|
@change="keyValChange" @backspace="keyValBackspace" @confirm="keyShow = false"></u-keyboard>
|
||||||
random
|
<!-- 按钮 -->
|
||||||
dotDisabled
|
<view class="buttons">
|
||||||
:overlay="false"
|
<button type="default" form-type="submit" @click="createWallet">确认修改</button>
|
||||||
:show="keyShow"
|
</view>
|
||||||
:showCancel="false"
|
</view>
|
||||||
@change="keyValChange"
|
|
||||||
@backspace="keyValBackspace"
|
|
||||||
@confirm="keyShow = false"
|
|
||||||
></u-keyboard>
|
|
||||||
<!-- 按钮 -->
|
|
||||||
<view class="buttons">
|
|
||||||
<button type="default" form-type="submit" @click="createWallet">确认修改</button>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { securityReset } from '@/apis/interfaces/wallet'
|
import {
|
||||||
export default {
|
securityReset
|
||||||
data() {
|
} from '@/apis/interfaces/wallet'
|
||||||
return {
|
export default {
|
||||||
password: '',
|
data() {
|
||||||
verify: '',
|
return {
|
||||||
oldPassword: '',
|
password: '',
|
||||||
|
verify: '',
|
||||||
valKye : '',
|
oldPassword: '',
|
||||||
keyShow : false
|
valKye: '',
|
||||||
}
|
keyShow: false
|
||||||
},
|
}
|
||||||
onLoad() {
|
},
|
||||||
this.oldPassword = this.$Route.query.password
|
onLoad() {
|
||||||
},
|
this.oldPassword = this.$Route.query.password
|
||||||
methods: {
|
},
|
||||||
// 唤起key
|
methods: {
|
||||||
onShowKet(key){
|
// 唤起key
|
||||||
this.valKye = key
|
onShowKet(key) {
|
||||||
this.keyShow = true
|
this.valKye = key
|
||||||
},
|
this.keyShow = true
|
||||||
// 键盘输入
|
},
|
||||||
keyValChange(e){
|
// 键盘输入
|
||||||
if(this[this.valKye].length >= 6) return
|
keyValChange(e) {
|
||||||
this[this.valKye] += e
|
if (this[this.valKye].length >= 6) return
|
||||||
},
|
this[this.valKye] += e
|
||||||
// 键盘删除
|
},
|
||||||
keyValBackspace(e){
|
// 键盘删除
|
||||||
if(this[this.valKye].length) this[this.valKye] = this[this.valKye].substr(0, this[this.valKye].length - 1)
|
keyValBackspace(e) {
|
||||||
},
|
if (this[this.valKye].length) this[this.valKye] = this[this.valKye].substr(0, this[this.valKye].length -
|
||||||
// 修改密码
|
1)
|
||||||
createWallet() {
|
},
|
||||||
if (this.password === '' || this.verify === '') {
|
// 修改密码
|
||||||
uni.showToast({
|
createWallet() {
|
||||||
icon: 'none',
|
if (this.password === '' || this.verify === '') {
|
||||||
title: '请设置密码'
|
uni.showToast({
|
||||||
})
|
icon: 'none',
|
||||||
return
|
title: '请设置密码'
|
||||||
}
|
})
|
||||||
if (this.password !== this.verify) {
|
return
|
||||||
uni.showToast({
|
}
|
||||||
icon: 'none',
|
if (this.password !== this.verify) {
|
||||||
title: '两次输入密码不一致'
|
uni.showToast({
|
||||||
})
|
icon: 'none',
|
||||||
return
|
title: '两次输入密码不一致'
|
||||||
}
|
})
|
||||||
securityReset({
|
return
|
||||||
new_code: this.password,
|
}
|
||||||
code: this.oldPassword
|
securityReset({
|
||||||
}).then(res => {
|
new_code: this.password,
|
||||||
uni.showModal({
|
code: this.oldPassword
|
||||||
title: '提示',
|
}).then(res => {
|
||||||
content: '密码已重置',
|
uni.showModal({
|
||||||
showCancel:false,
|
title: '提示',
|
||||||
success: res=> {
|
content: '密码已重置',
|
||||||
uni.navigateBack()
|
showCancel: false,
|
||||||
}
|
success: res => {
|
||||||
})
|
uni.navigateBack()
|
||||||
}).catch(err => {
|
}
|
||||||
uni.showToast({
|
})
|
||||||
icon: 'none',
|
}).catch(err => {
|
||||||
title: err.message
|
uni.showToast({
|
||||||
})
|
icon: 'none',
|
||||||
})
|
title: err.message
|
||||||
}
|
})
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
</script>
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
<style>
|
|
||||||
.flicker-animation{
|
|
||||||
animation: flicker .8s infinite;
|
<style>
|
||||||
}
|
.flicker-animation {
|
||||||
@keyframes flicker{
|
animation: flicker .8s infinite;
|
||||||
0%{opacity: 0;}
|
}
|
||||||
100{opacity: 1;}
|
|
||||||
}
|
@keyframes flicker {
|
||||||
|
0% {
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
100 {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
// 副标题
|
// 副标题
|
||||||
.sub-title {
|
.sub-title {
|
||||||
color: $text-gray;
|
color: $text-gray;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
margin: $margin * 2 $margin;
|
margin: $margin * 2 $margin;
|
||||||
font-size: $title-size-m;
|
font-size: $title-size-m;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 设置密码
|
// 设置密码
|
||||||
.password {
|
.password {
|
||||||
padding: 0 $padding * 2;
|
padding: 0 $padding * 2;
|
||||||
.prompt {
|
|
||||||
margin-top: $margin * 2;
|
.prompt {
|
||||||
font-size: $title-size-m;
|
margin-top: $margin * 2;
|
||||||
color: $main-color;
|
font-size: $title-size-m;
|
||||||
text-align: center;
|
color: $main-color;
|
||||||
}
|
text-align: center;
|
||||||
|
}
|
||||||
.group {
|
|
||||||
padding-top: $padding;
|
.group {
|
||||||
.inputs {
|
padding-top: $padding;
|
||||||
padding: 10rpx $padding + 10;
|
|
||||||
margin-top: $margin;
|
.inputs {
|
||||||
border-radius: $radius-m;
|
padding: 10rpx $padding + 10;
|
||||||
background-color: $window-color;
|
margin-top: $margin;
|
||||||
height: 70rpx;
|
border-radius: $radius-m;
|
||||||
line-height: 70rpx;
|
background-color: $window-color;
|
||||||
font-size: $title-size-lg;
|
height: 70rpx;
|
||||||
text-align: center;
|
line-height: 70rpx;
|
||||||
text{
|
font-size: $title-size-lg;
|
||||||
padding: 0 10rpx;
|
text-align: center;
|
||||||
text-align: center;
|
|
||||||
}
|
text {
|
||||||
.placeholder{
|
padding: 0 10rpx;
|
||||||
color: $text-gray;
|
text-align: center;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
.placeholder {
|
||||||
}
|
color: $text-gray;
|
||||||
|
}
|
||||||
// 按钮
|
}
|
||||||
.buttons {
|
}
|
||||||
padding: $padding * 2;
|
}
|
||||||
.text {
|
|
||||||
text-align: center;
|
// 按钮
|
||||||
line-height: 90rpx;
|
.buttons {
|
||||||
height: 90rpx;
|
padding: $padding * 2;
|
||||||
margin-bottom: $margin * 2;
|
|
||||||
font-size: $title-size-lg;
|
.text {
|
||||||
color: $main-color;
|
text-align: center;
|
||||||
font-weight: bold;
|
line-height: 90rpx;
|
||||||
}
|
height: 90rpx;
|
||||||
|
margin-bottom: $margin * 2;
|
||||||
button {
|
font-size: $title-size-lg;
|
||||||
height: 90rpx;
|
color: $main-color;
|
||||||
line-height: 90rpx;
|
font-weight: bold;
|
||||||
background-color: $main-color;
|
}
|
||||||
border-radius: $radius-m;
|
|
||||||
color: white;
|
button {
|
||||||
font-weight: bold;
|
height: 90rpx;
|
||||||
font-size: $title-size;
|
line-height: 90rpx;
|
||||||
&::after{
|
background-color: $main-color;
|
||||||
display: none;
|
border-radius: $radius-m;
|
||||||
}
|
color: white;
|
||||||
}
|
font-weight: bold;
|
||||||
}
|
font-size: $title-size;
|
||||||
|
|
||||||
|
&::after {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -1,170 +1,178 @@
|
|||||||
<template>
|
<template>
|
||||||
<view>
|
<view>
|
||||||
<!-- 提示信息 -->
|
<!-- 提示信息 -->
|
||||||
<view class="prompt">
|
<view class="prompt">
|
||||||
验证您的钱包助记词
|
验证您的钱包助记词
|
||||||
</view>
|
</view>
|
||||||
<!-- 助记词 -->
|
<!-- 助记词 -->
|
||||||
<view class="mnemonic">
|
<view class="mnemonic">
|
||||||
<view
|
<view class="item" v-for="(item, index) in validation" :key="index" :class="item === null ? 'hide': ''"
|
||||||
class="item"
|
@click="onKeys('removeKey', index)">{{ item }}</view>
|
||||||
v-for="(item, index) in validation"
|
</view>
|
||||||
:key="index"
|
<!-- 选择助记词 -->
|
||||||
:class="item === null ? 'hide': ''"
|
<block v-if="mnemonic.length > 0">
|
||||||
@click="onKeys('removeKey', index)"
|
<view class="mnemonic-title">
|
||||||
>{{ item }}</view>
|
按顺序填写助记词
|
||||||
</view>
|
</view>
|
||||||
<!-- 选择助记词 -->
|
<view class="mnemonic-select">
|
||||||
<block v-if="mnemonic.length > 0">
|
<view class="item" v-for="(item, index) in mnemonic" :key="index" @click="onKeys('addKey', index)">
|
||||||
<view class="mnemonic-title">
|
{{ item }}</view>
|
||||||
按顺序填写助记词
|
</view>
|
||||||
</view>
|
</block>
|
||||||
<view class="mnemonic-select">
|
<!-- 按钮 -->
|
||||||
<view class="item" v-for="(item, index) in mnemonic" :key="index" @click="onKeys('addKey', index)">{{ item }}</view>
|
<view class="buttons">
|
||||||
</view>
|
<button type="default" @click="verifyMnemonic">验证</button>
|
||||||
</block>
|
</view>
|
||||||
<!-- 按钮 -->
|
</view>
|
||||||
<view class="buttons">
|
</template>
|
||||||
<button type="default" @click="verifyMnemonic">验证</button>
|
|
||||||
</view>
|
<script>
|
||||||
</view>
|
import {
|
||||||
</template>
|
hash
|
||||||
|
} from "@/apis/interfaces/wallet"
|
||||||
<script>
|
export default {
|
||||||
import { hash } from "../../apis/interfaces/wallet"
|
data() {
|
||||||
export default {
|
return {
|
||||||
data() {
|
validation: new Array(12).fill(null), // 验证key
|
||||||
return {
|
mnemonic: [], // 助记词key
|
||||||
validation : new Array(12).fill(null), // 验证key
|
sign: '', // 助记词校验签名
|
||||||
mnemonic : [], // 助记词key
|
seedString: '', // 助记词原词
|
||||||
sign : '', // 助记词校验签名
|
}
|
||||||
seedString : '', // 助记词原词
|
},
|
||||||
}
|
mounted() {
|
||||||
},
|
let seed = this.$Route.query.seed.split(',')
|
||||||
mounted() {
|
seed.sort(() => {
|
||||||
let seed = this.$Route.query.seed.split(',')
|
return Math.random() - .5
|
||||||
seed.sort(() => {
|
});
|
||||||
return Math.random() - .5
|
console.log(seed)
|
||||||
});
|
// this.mnemonic = seed
|
||||||
console.log(seed)
|
// this.sign = this.$Route.query.sign
|
||||||
// this.mnemonic = seed
|
// this.seedString = this.$Route.query.seed
|
||||||
// this.sign = this.$Route.query.sign
|
},
|
||||||
// this.seedString = this.$Route.query.seed
|
methods: {
|
||||||
},
|
// 填写助记词
|
||||||
methods: {
|
onKeys(type, index) {
|
||||||
// 填写助记词
|
if (type === 'addKey') {
|
||||||
onKeys(type, index){
|
this.$set(this.validation, this.validation.findIndex(val => val === null), this.mnemonic[index])
|
||||||
if(type === 'addKey') {
|
this.$delete(this.mnemonic, index)
|
||||||
this.$set(this.validation, this.validation.findIndex(val => val === null), this.mnemonic[index])
|
return
|
||||||
this.$delete(this.mnemonic, index)
|
}
|
||||||
return
|
if (type === 'removeKey' && this.validation[index] !== null) {
|
||||||
}
|
this.mnemonic.push(this.validation[index])
|
||||||
if(type === 'removeKey' && this.validation[index] !== null) {
|
this.$delete(this.validation, index)
|
||||||
this.mnemonic.push(this.validation[index])
|
this.validation.push(null)
|
||||||
this.$delete(this.validation, index)
|
}
|
||||||
this.validation.push(null)
|
},
|
||||||
}
|
// 验证助记词
|
||||||
},
|
verifyMnemonic() {
|
||||||
// 验证助记词
|
if (this.validation.findIndex(val => val === null) > -1) {
|
||||||
verifyMnemonic(){
|
uni.showToast({
|
||||||
if(this.validation.findIndex(val => val === null) > -1){
|
title: '请完整填写助记词',
|
||||||
uni.showToast({
|
icon: 'none'
|
||||||
title: '请完整填写助记词',
|
})
|
||||||
icon : 'none'
|
return
|
||||||
})
|
}
|
||||||
return
|
let seed = this.validation.toString().replace(/,/g, ',')
|
||||||
}
|
if (this.seedString !== seed) {
|
||||||
let seed = this.validation.toString().replace(/,/g, ',')
|
uni.showToast({
|
||||||
if (this.seedString !== seed) {
|
title: '验证失败,请确认您的助记词',
|
||||||
uni.showToast({
|
icon: 'none'
|
||||||
title: '验证失败,请确认您的助记词',
|
})
|
||||||
icon : 'none'
|
return
|
||||||
})
|
}
|
||||||
return
|
uni.redirectTo({
|
||||||
}
|
url: './create'
|
||||||
uni.redirectTo({
|
})
|
||||||
url: './create'
|
}
|
||||||
})
|
}
|
||||||
}
|
}
|
||||||
}
|
</script>
|
||||||
}
|
|
||||||
</script>
|
<style lang="scss" scoped>
|
||||||
|
// 提示信息
|
||||||
<style lang="scss" scoped>
|
.prompt {
|
||||||
// 提示信息
|
color: $text-gray;
|
||||||
.prompt{
|
text-align: center;
|
||||||
color: $text-gray;
|
line-height: 90rpx;
|
||||||
text-align: center;
|
font-size: $title-size-m;
|
||||||
line-height: 90rpx;
|
}
|
||||||
font-size: $title-size-m;
|
|
||||||
}
|
// 选择助记词
|
||||||
// 选择助记词
|
.mnemonic-title {
|
||||||
.mnemonic-title{
|
padding-top: $padding * 2;
|
||||||
padding-top: $padding * 2;
|
margin: 0 $margin * 2;
|
||||||
margin: 0 $margin * 2;
|
font-size: $title-size-m;
|
||||||
font-size: $title-size-m;
|
color: $main-color;
|
||||||
color: $main-color;
|
}
|
||||||
}
|
|
||||||
.mnemonic-select{
|
.mnemonic-select {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
padding: $padding $padding + $padding / 2;
|
padding: $padding $padding + $padding / 2;
|
||||||
.item{
|
|
||||||
background-color: white;
|
.item {
|
||||||
line-height: 68rpx;
|
background-color: white;
|
||||||
height: 68rpx;
|
line-height: 68rpx;
|
||||||
width: 68rpx;
|
height: 68rpx;
|
||||||
text-align: center;
|
width: 68rpx;
|
||||||
margin: $margin / 2;
|
text-align: center;
|
||||||
border-radius: $radius-m;
|
margin: $margin / 2;
|
||||||
box-shadow: 0 0 4rpx 4rpx rgba($color: $text-color, $alpha: .02);
|
border-radius: $radius-m;
|
||||||
}
|
box-shadow: 0 0 4rpx 4rpx rgba($color: $text-color, $alpha: .02);
|
||||||
}
|
}
|
||||||
// 助记词
|
}
|
||||||
.mnemonic{
|
|
||||||
margin: $margin ($margin * 2);
|
// 助记词
|
||||||
border-radius: $radius-m;
|
.mnemonic {
|
||||||
box-shadow: 0 0 4rpx 4rpx rgba($color: $text-color, $alpha: .02);
|
margin: $margin ($margin * 2);
|
||||||
background-color: white;
|
border-radius: $radius-m;
|
||||||
padding: $padding;
|
box-shadow: 0 0 4rpx 4rpx rgba($color: $text-color, $alpha: .02);
|
||||||
display: flex;
|
background-color: white;
|
||||||
flex-wrap: wrap;
|
padding: $padding;
|
||||||
align-items: flex-start;
|
display: flex;
|
||||||
.item{
|
flex-wrap: wrap;
|
||||||
background: rgba($color: $border-color, $alpha: .4);
|
align-items: flex-start;
|
||||||
min-width: 58rpx;
|
|
||||||
height: 58rpx;
|
.item {
|
||||||
line-height: 58rpx;
|
background: rgba($color: $border-color, $alpha: .4);
|
||||||
text-align: center;
|
min-width: 58rpx;
|
||||||
color: $text-color;
|
height: 58rpx;
|
||||||
margin: $margin / 2;
|
line-height: 58rpx;
|
||||||
&.hide{
|
text-align: center;
|
||||||
border:dashed 1px $border-color;
|
color: $text-color;
|
||||||
box-sizing: border-box;
|
margin: $margin / 2;
|
||||||
background-color: white;
|
|
||||||
}
|
&.hide {
|
||||||
}
|
border: dashed 1px $border-color;
|
||||||
}
|
box-sizing: border-box;
|
||||||
// 按钮
|
background-color: white;
|
||||||
.buttons{
|
}
|
||||||
padding: $padding $padding * 2;
|
}
|
||||||
.text{
|
}
|
||||||
text-align: center;
|
|
||||||
margin-bottom: $margin * 2;
|
// 按钮
|
||||||
font-size: $title-size-lg;
|
.buttons {
|
||||||
color: $text-price;
|
padding: $padding $padding * 2;
|
||||||
}
|
|
||||||
button{
|
.text {
|
||||||
height: 90rpx;
|
text-align: center;
|
||||||
line-height: 90rpx;
|
margin-bottom: $margin * 2;
|
||||||
background-color: $main-color;
|
font-size: $title-size-lg;
|
||||||
border-radius: $radius-lg;
|
color: $text-price;
|
||||||
color: white;
|
}
|
||||||
font-weight: bold;
|
|
||||||
font-size: $title-size;
|
button {
|
||||||
&[disabled]{
|
height: 90rpx;
|
||||||
background: rgba($color: $main-color, $alpha: .8);
|
line-height: 90rpx;
|
||||||
}
|
background-color: $main-color;
|
||||||
}
|
border-radius: $radius-lg;
|
||||||
}
|
color: white;
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: $title-size;
|
||||||
|
|
||||||
|
&[disabled] {
|
||||||
|
background: rgba($color: $main-color, $alpha: .8);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -4,16 +4,16 @@ import {
|
|||||||
} from 'uni-simple-router';
|
} from 'uni-simple-router';
|
||||||
import store from '@/store/index'
|
import store from '@/store/index'
|
||||||
|
|
||||||
// #ifdef APP-NVUE
|
// CALL 页面,必须是nvue,但是NVUE 不支持webpack的 ROUTES 注入
|
||||||
// CALL 页面,必须是nvue,但是NVUE 不支持webpack的 ROUTES 注入
|
|
||||||
// https://github.com/SilurianYang/uni-read-pages/issues/20
|
// https://github.com/SilurianYang/uni-read-pages/issues/20
|
||||||
|
// #ifdef APP-NVUE
|
||||||
const ROUTES = [{
|
const ROUTES = [{
|
||||||
'path': '/pages/im/private/call',
|
"path": "/pages/im/private/call"
|
||||||
'name': 'imPrivateCall'
|
}, {
|
||||||
},{
|
"path": "/pages/im/private/chat"
|
||||||
'path': '/pages/im/private/chat',
|
}, {
|
||||||
'name': 'imPrivateChat'
|
"path": "/pages/im/group/chat"
|
||||||
}]
|
}];
|
||||||
// #endif
|
// #endif
|
||||||
|
|
||||||
const router = createRouter({
|
const router = createRouter({
|
||||||
|
|||||||
BIN
static/.DS_Store
vendored
BIN
static/icon/clock_icon.png
Normal file
|
After Width: | Height: | Size: 3.3 KiB |
BIN
static/icon/popups-icon-00.png
Normal file
|
After Width: | Height: | Size: 3.5 KiB |
BIN
static/icon/popups-icon-01.png
Normal file
|
After Width: | Height: | Size: 3.2 KiB |
BIN
static/icon/popups-icon-02.png
Normal file
|
After Width: | Height: | Size: 2.9 KiB |
BIN
static/icon/popups-icon-03.png
Normal file
|
After Width: | Height: | Size: 3.0 KiB |
BIN
static/icon/popups-icon-04.png
Normal file
|
After Width: | Height: | Size: 3.1 KiB |
BIN
static/icon/popups-icon-05.png
Normal file
|
After Width: | Height: | Size: 2.9 KiB |
BIN
static/icon/popups-icon.png
Normal file
|
After Width: | Height: | Size: 5.1 KiB |
@@ -1,6 +1,6 @@
|
|||||||
@font-face {
|
@font-face {
|
||||||
font-family: "iconfont"; /* Project id 2869797 */
|
font-family: "iconfont"; /* Project id 2869797 */
|
||||||
src: url('@/static/iconfont.ttf') format('truetype');
|
src: url('@/static/iconfont.ttf') format('truetype'),
|
||||||
}
|
}
|
||||||
|
|
||||||
.iconfont {
|
.iconfont {
|
||||||
@@ -11,6 +11,14 @@
|
|||||||
-moz-osx-font-smoothing: grayscale;
|
-moz-osx-font-smoothing: grayscale;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.icon-jia:before {
|
||||||
|
content: "\e60a";
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon-dui:before {
|
||||||
|
content: "\e609";
|
||||||
|
}
|
||||||
|
|
||||||
.icon-gengduo2:before {
|
.icon-gengduo2:before {
|
||||||
content: "\e608";
|
content: "\e608";
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,98 +2,138 @@ import im from "@/utils/im/index.js"
|
|||||||
|
|
||||||
export default {
|
export default {
|
||||||
state: {
|
state: {
|
||||||
friends: {},
|
contacts: {},
|
||||||
sender: {},
|
myInfo: {}
|
||||||
},
|
},
|
||||||
getters: {
|
getters: {
|
||||||
friends(state) {
|
contacts(state) {
|
||||||
return state.friends
|
return state.contacts
|
||||||
},
|
},
|
||||||
userInfo: (state) => (targetId) => {
|
contactInfo: (state) => (targetId) => {
|
||||||
if (state.friends[targetId]) {
|
if (state.contacts[targetId]) {
|
||||||
return state.friends[targetId]
|
const info = state.contacts[targetId]
|
||||||
|
|
||||||
|
return {
|
||||||
|
name: info.name,
|
||||||
|
hash: info.hash,
|
||||||
|
portraitUrl: info.localAvatar ? info.localAvatar : require('@/static/user/cover.png')
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
console.log('没找到,死循环了,得处理 todo', targetId);
|
|
||||||
// im.syncUserInfo(targetId)
|
|
||||||
return {
|
return {
|
||||||
name: '',
|
name: '',
|
||||||
address: '',
|
|
||||||
hash: '',
|
hash: '',
|
||||||
portraitUrl: ''
|
portraitUrl: ''
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
hasUser: (state) => (targetId) => {
|
// 联系人是否存在
|
||||||
return Boolean(state.friends[targetId])
|
contactIsExist: (state) => (targetId) => {
|
||||||
|
return Boolean(state.contacts[targetId])
|
||||||
},
|
},
|
||||||
sender(state) {
|
sender(state) {
|
||||||
return state.sender
|
return state.myInfo
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
mutations: {
|
mutations: {
|
||||||
updateFriends(state, userInfo) {
|
updateContactInfo(state, contactInfo) {
|
||||||
Vue.set(state.friends, userInfo.userId, userInfo)
|
Vue.set(state.contacts, contactInfo.targetId, contactInfo)
|
||||||
},
|
},
|
||||||
SET_state_sender(state, userInfo) {
|
setSenderInfo(state, contactInfo) {
|
||||||
state.sender = userInfo
|
state.myInfo = {
|
||||||
|
userId: contactInfo.targetId,
|
||||||
|
name: contactInfo.name,
|
||||||
|
portraitUrl: contactInfo.portraitUrl
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
actions: {
|
actions: {
|
||||||
setSenderInfo({
|
setSenderInfo({
|
||||||
commit
|
commit
|
||||||
}, userInfo) {
|
}, contactInfo) {
|
||||||
commit('SET_state_sender', userInfo)
|
commit('setSenderInfo', contactInfo)
|
||||||
},
|
},
|
||||||
updateFriends({
|
// 载入好友信息
|
||||||
|
launchContact({
|
||||||
commit
|
commit
|
||||||
}, userInfo) {
|
}, data) {
|
||||||
commit('updateFriends', userInfo)
|
commit('updateContactInfo', data)
|
||||||
const model = uni.model.friendModel
|
},
|
||||||
model.find('userId=' + userInfo.userId, (err, user) => {
|
// 更新好友信息,这个时候要校验hash值了
|
||||||
if (!err && user.length == 0) {
|
updateContact({
|
||||||
saveAvatar(userInfo, (savedFilePath) => {
|
commit,
|
||||||
model.insert({
|
dispatch
|
||||||
userId: userInfo.userId,
|
}, contactInfo) {
|
||||||
name: userInfo.name,
|
const model = uni.model.contactModel
|
||||||
hash: userInfo.hash,
|
model.find('targetId="' + contactInfo.targetId + '"', (err, result) => {
|
||||||
address: userInfo.address,
|
if (result.length == 0) {
|
||||||
portraitUrl: savedFilePath,
|
// 没有数据,直接新增一条
|
||||||
}, (err, result) => {})
|
dispatch('initContact', contactInfo)
|
||||||
userInfo.portraitUrl = savedFilePath
|
} else if (contactInfo.hash != result[0].hash) {
|
||||||
commit('updateFriends', userInfo)
|
commit('updateContactInfo', contactInfo)
|
||||||
})
|
if (contactInfo.portraitUrl && contactInfo.portraitUrl != result[0].portraitUrl) {
|
||||||
} else if (!err && user[0].hash != userInfo.hash) {
|
saveAvatar(contactInfo, (savedFilePath) => {
|
||||||
saveAvatar(userInfo, (savedFilePath) => {
|
const info = {
|
||||||
model.update('userId=' + userInfo.userId, {
|
targetId: contactInfo.targetId,
|
||||||
name: userInfo.name,
|
name: contactInfo.name,
|
||||||
hash: userInfo.hash,
|
hash: contactInfo.hash,
|
||||||
portraitUrl: savedFilePath,
|
portraitUrl: contactInfo.portraitUrl,
|
||||||
}, (err, result) => {})
|
localAvatar: savedFilePath
|
||||||
userInfo.portraitUrl = savedFilePath
|
}
|
||||||
commit('updateFriends', userInfo)
|
model.update('targetId=' + contactInfo.targetId, info, (err, res) => {})
|
||||||
})
|
commit('updateContactInfo', info)
|
||||||
} else if (!err && user[0].portraitUrl.length > 50) {
|
})
|
||||||
saveAvatar(userInfo, (savedFilePath) => {
|
} else {
|
||||||
model.update('userId=' + userInfo.userId, {
|
const info = {
|
||||||
name: userInfo.name,
|
targetId: contactInfo.targetId,
|
||||||
hash: userInfo.hash,
|
name: contactInfo.name,
|
||||||
portraitUrl: savedFilePath,
|
hash: contactInfo.hash,
|
||||||
}, (err, result) => {})
|
portraitUrl: contactInfo.portraitUrl,
|
||||||
|
localAvatar: result[0].localAvatar
|
||||||
userInfo.portraitUrl = savedFilePath
|
}
|
||||||
commit('updateFriends', userInfo)
|
model.update('targetId="' + contactInfo.targetId + '"', info, (err, res) => {})
|
||||||
})
|
}
|
||||||
} else {
|
} else {}
|
||||||
console.log('不用操作', user[0]);
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
|
},
|
||||||
|
// 初始化好友信息
|
||||||
|
initContact({
|
||||||
|
commit
|
||||||
|
}, contactInfo) {
|
||||||
|
// 将好友信息保存到vuex的内存中,方便立即使用
|
||||||
|
commit('updateContactInfo', contactInfo)
|
||||||
|
const model = uni.model.contactModel
|
||||||
|
// 用户头像,是否需要下载到本地
|
||||||
|
if (contactInfo.portraitUrl) {
|
||||||
|
saveAvatar(contactInfo, (savedFilePath) => {
|
||||||
|
const info = {
|
||||||
|
targetId: contactInfo.targetId,
|
||||||
|
name: contactInfo.name,
|
||||||
|
hash: contactInfo.hash,
|
||||||
|
portraitUrl: contactInfo.portraitUrl,
|
||||||
|
localAvatar: savedFilePath
|
||||||
|
}
|
||||||
|
model.insert(info, (err, res) => {})
|
||||||
|
// 保存头像后,更新信息
|
||||||
|
commit('updateContactInfo', info)
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
// 直接将信息,写入数据库
|
||||||
|
const info = {
|
||||||
|
targetId: contactInfo.targetId,
|
||||||
|
name: contactInfo.name,
|
||||||
|
hash: contactInfo.hash,
|
||||||
|
portraitUrl: contactInfo.portraitUrl,
|
||||||
|
localAvatar: ''
|
||||||
|
}
|
||||||
|
model.insert(info, (err, res) => {})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const saveAvatar = (userInfo, callback) => {
|
const saveAvatar = (contactInfo, callback) => {
|
||||||
uni.downloadFile({
|
uni.downloadFile({
|
||||||
url: userInfo.portraitUrl,
|
url: contactInfo.portraitUrl,
|
||||||
success: ({
|
success: ({
|
||||||
tempFilePath
|
tempFilePath
|
||||||
}) => {
|
}) => {
|
||||||
@@ -106,8 +146,6 @@ const saveAvatar = (userInfo, callback) => {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
fail: (err) => {
|
fail: (err) => {}
|
||||||
console.log('头像保存失败', err);
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
16
utils/im/data.js
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
// 获取新好友申请数量
|
||||||
|
const getPendingCount = (callback) => {
|
||||||
|
RongIMLib.getConversationList([RongIMLib.ConversationType.SYSTEM], 100, 0, (res) => {
|
||||||
|
if (res.code === 0) {
|
||||||
|
const pendingCount = res.conversations.filter((item) => {
|
||||||
|
return item.objectName == RongIMLib.ObjectName.ContactNotification
|
||||||
|
}).length
|
||||||
|
|
||||||
|
callback(pendingCount)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
export default {
|
||||||
|
getPendingCount
|
||||||
|
}
|
||||||
@@ -1,23 +0,0 @@
|
|||||||
[{
|
|
||||||
"objectName": "RC:TxtMsg",
|
|
||||||
"receivedTime": 1643080237399,
|
|
||||||
"extra": "",
|
|
||||||
"messageUId": "BUFC-3FSU-OLE4-I31K",
|
|
||||||
"conversationType": 1,
|
|
||||||
"messageDirection": 2,
|
|
||||||
"senderUserId": "10041",
|
|
||||||
"content": {
|
|
||||||
"content": "你好,这是 1710 条消息条消息条消息条消息条消息条消息条消息条消息条消息0.97796900 1642741562",
|
|
||||||
"objectName": "RC:TxtMsg",
|
|
||||||
"userInfo": {
|
|
||||||
"userId": "10041",
|
|
||||||
"name": "我是eth",
|
|
||||||
"portraitUrl": "http://storage.zh.shangkelian.cn/images/2022/01/12/3d2a103386df6822db7e5290272e8bc2.png"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"targetId": "10041",
|
|
||||||
"sentTime": 1642741563003,
|
|
||||||
"messageId": 2,
|
|
||||||
"receivedStatus": 1,
|
|
||||||
"sentStatus": 30
|
|
||||||
}]
|
|
||||||
@@ -2,6 +2,7 @@ import * as RongIMLib from '@/uni_modules/RongCloud-IMWrapper/js_sdk/index'
|
|||||||
import * as CallLib from '@/uni_modules/RongCloud-CallWrapper/lib/index'
|
import * as CallLib from '@/uni_modules/RongCloud-CallWrapper/lib/index'
|
||||||
import store from '@/store/index.js'
|
import store from '@/store/index.js'
|
||||||
import message from './message.js'
|
import message from './message.js'
|
||||||
|
import listeners from './listeners.js'
|
||||||
import {
|
import {
|
||||||
getFriends,
|
getFriends,
|
||||||
getUserInfo,
|
getUserInfo,
|
||||||
@@ -10,7 +11,7 @@ import {
|
|||||||
|
|
||||||
const initIm = (KEY) => {
|
const initIm = (KEY) => {
|
||||||
RongIMLib.init(KEY)
|
RongIMLib.init(KEY)
|
||||||
CallLib.init()
|
// CallLib.init()
|
||||||
addListeners()
|
addListeners()
|
||||||
// 初始化的时候 自动链接
|
// 初始化的时候 自动链接
|
||||||
if (store.getters.getToken !== '') {
|
if (store.getters.getToken !== '') {
|
||||||
@@ -47,25 +48,37 @@ const setNotifyBadge = () => {
|
|||||||
/**
|
/**
|
||||||
* 连接IM服务
|
* 连接IM服务
|
||||||
* @param {string} token token
|
* @param {string} token token
|
||||||
* @param {object} userInfo {userId: string, name: string, portraitUrl: string}
|
* @param {object} userInfo {targetId: string, name: string, portraitUrl: string}
|
||||||
*/
|
*/
|
||||||
const connect = (token, userInfo, callback) => {
|
const connect = (token, userInfo, callback) => {
|
||||||
RongIMLib.connect(token, res => {
|
RongIMLib.connect(token, res => {
|
||||||
console.log('连接结果', res);
|
|
||||||
|
|
||||||
callback(res)
|
callback(res)
|
||||||
})
|
// 更新个人信息
|
||||||
|
store.dispatch('setSenderInfo', userInfo)
|
||||||
|
// 设置未读消息数量
|
||||||
|
setNotifyBadge()
|
||||||
|
// 首次运行获取好友列表
|
||||||
|
const FK = 'IFT_' + userInfo.targetId
|
||||||
|
|
||||||
store.dispatch('setSenderInfo', userInfo)
|
uni.getStorage({
|
||||||
|
key: FK,
|
||||||
setNotifyBadge()
|
success: () => {
|
||||||
|
const model = uni.model.contactModel
|
||||||
const model = uni.model.friendModel
|
model.find((err, results) => {
|
||||||
|
results.map(item => {
|
||||||
model.find((err, results) => {
|
store.dispatch('launchContact', item)
|
||||||
console.log('好友列表', results);
|
})
|
||||||
results.map(item => {
|
})
|
||||||
store.dispatch('updateFriends', item)
|
},
|
||||||
|
fail: () => {
|
||||||
|
// 程序是首次运行,初始化加载好友信息
|
||||||
|
getFriends().then(res => {
|
||||||
|
res.map(item => {
|
||||||
|
store.dispatch('initContact', item)
|
||||||
|
})
|
||||||
|
uni.setStorageSync(FK, userInfo.targetId)
|
||||||
|
})
|
||||||
|
}
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -102,63 +115,88 @@ const notifyMsgTypes = [
|
|||||||
function inArray(search, array) {
|
function inArray(search, array) {
|
||||||
for (var i in array) {
|
for (var i in array) {
|
||||||
if (array[i] == search) {
|
if (array[i] == search) {
|
||||||
return true;
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
const addListeners = () => {
|
const addListeners = () => {
|
||||||
// 添加连接状态监听函数
|
// 添加连接状态监听函数
|
||||||
RongIMLib.addConnectionStatusListener((res) => {
|
RongIMLib.addConnectionStatusListener((res) => {
|
||||||
console.log('连接状态监听', res.data.status);
|
console.log('连接状态监听', res.data.status)
|
||||||
uni.$emit('onConnectionStatusChange', res.data.status)
|
uni.$emit('onConnectionStatusChange', res.data.status)
|
||||||
})
|
})
|
||||||
// 添加消息监听函数
|
// 添加消息监听函数
|
||||||
RongIMLib.addReceiveMessageListener((res) => {
|
RongIMLib.addReceiveMessageListener((res) => {
|
||||||
console.log('收到消息', res.data.message);
|
|
||||||
const message = res.data.message
|
const message = res.data.message
|
||||||
|
console.log('收到消息', message)
|
||||||
if (inArray(message.objectName, notifyMsgTypes)) {
|
if (inArray(message.objectName, notifyMsgTypes)) {
|
||||||
console.log('new Message');
|
if (!store.getters.contactIsExist(message.targetId)) {
|
||||||
|
getUserInfo(message.targetId).then(res => {
|
||||||
|
store.dispatch('initContact', res)
|
||||||
|
}).catch(err => {
|
||||||
|
console.log('ERR', err)
|
||||||
|
})
|
||||||
|
}
|
||||||
newMessage(message)
|
newMessage(message)
|
||||||
|
} else if (message.objectName === RongIMLib.ObjectName.ProfileNotification) {
|
||||||
|
store.dispatch('updateContact', JSON.parse(message.content.data))
|
||||||
|
// 调用完更新之后,删除这条消息
|
||||||
|
RongIMLib.deleteMessagesByIds([message.messageId], ({
|
||||||
|
code
|
||||||
|
}) => {
|
||||||
|
console.log('消息删除结果', code)
|
||||||
|
})
|
||||||
|
} else if (message.objectName === RongIMLib.ObjectName.ContactNotification) {
|
||||||
|
// 触发一个新好友的通知事件
|
||||||
|
uni.$emit('onContactNotification', message.content)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
// 音视频通话相关的
|
|
||||||
// 监听通话呼入
|
// 监听消息回执
|
||||||
CallLib.onCallReceived(({
|
RongIMLib.addReadReceiptReceivedListener(({
|
||||||
data
|
data
|
||||||
}) => {
|
}) => {
|
||||||
uni.navigateTo({
|
uni.$emit('onReadReceiptReceived', data)
|
||||||
url: '/pages/im/private/call?targetId=' + data.targetId + '&mediaType=' +
|
|
||||||
data.mediaType
|
|
||||||
})
|
|
||||||
})
|
|
||||||
// 通话建立成功
|
|
||||||
CallLib.onCallConnected(() => {
|
|
||||||
uni.$emit('onCallConnected');
|
|
||||||
})
|
|
||||||
// 外呼
|
|
||||||
CallLib.onCallOutgoing((res) => {
|
|
||||||
uni.$emit('onCallOutgoing');
|
|
||||||
})
|
|
||||||
// 远端响铃
|
|
||||||
CallLib.onRemoteUserRinging((res) => {
|
|
||||||
uni.$emit('onRemoteUserRinging');
|
|
||||||
})
|
|
||||||
// 远端加入
|
|
||||||
CallLib.onRemoteUserJoined((res) => {
|
|
||||||
uni.$emit('onRemoteUserJoined');
|
|
||||||
})
|
|
||||||
// 断开链接
|
|
||||||
CallLib.onCallDisconnected((res) => {
|
|
||||||
console.log('断开链接', res);
|
|
||||||
uni.$emit('onCallDisconnected');
|
|
||||||
})
|
|
||||||
// 远端挂断
|
|
||||||
CallLib.onRemoteUserLeft((res) => {
|
|
||||||
console.log('远端离开', res);
|
|
||||||
uni.$emit('onRemoteUserLeft');
|
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// 音视频通话相关的
|
||||||
|
// 监听通话呼入
|
||||||
|
// CallLib.onCallReceived(({
|
||||||
|
// data
|
||||||
|
// }) => {
|
||||||
|
// uni.navigateTo({
|
||||||
|
// url: '/pages/im/private/call?targetId=' + data.targetId + '&mediaType=' +
|
||||||
|
// data.mediaType
|
||||||
|
// })
|
||||||
|
// })
|
||||||
|
// // 通话建立成功
|
||||||
|
// CallLib.onCallConnected(() => {
|
||||||
|
// uni.$emit('onCallConnected')
|
||||||
|
// })
|
||||||
|
// // 外呼
|
||||||
|
// CallLib.onCallOutgoing((res) => {
|
||||||
|
// uni.$emit('onCallOutgoing')
|
||||||
|
// })
|
||||||
|
// // 远端响铃
|
||||||
|
// CallLib.onRemoteUserRinging((res) => {
|
||||||
|
// uni.$emit('onRemoteUserRinging')
|
||||||
|
// })
|
||||||
|
// // 远端加入
|
||||||
|
// CallLib.onRemoteUserJoined((res) => {
|
||||||
|
// uni.$emit('onRemoteUserJoined')
|
||||||
|
// })
|
||||||
|
// // 断开链接
|
||||||
|
// CallLib.onCallDisconnected((res) => {
|
||||||
|
// console.log('断开链接', res)
|
||||||
|
// uni.$emit('onCallDisconnected')
|
||||||
|
// })
|
||||||
|
// // 远端挂断
|
||||||
|
// CallLib.onRemoteUserLeft((res) => {
|
||||||
|
// console.log('远端离开', res)
|
||||||
|
// uni.$emit('onRemoteUserLeft')
|
||||||
|
// })
|
||||||
}
|
}
|
||||||
|
|
||||||
// 维护消息列表,检查是否需要通知声音,设置新消息提醒的数量
|
// 维护消息列表,检查是否需要通知声音,设置新消息提醒的数量
|
||||||
@@ -168,25 +206,14 @@ const newMessage = (msg) => {
|
|||||||
status
|
status
|
||||||
}) => {
|
}) => {
|
||||||
if (code === 0) {
|
if (code === 0) {
|
||||||
if (status) {
|
if (status) {
|
||||||
|
uni.vibrateLong()
|
||||||
triTone()
|
triTone()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
|
||||||
|
|
||||||
setNotifyBadge()
|
|
||||||
|
|
||||||
if (!store.getters.hasUser(msg.targetId)) {
|
|
||||||
syncUserInfo(msg.targetId)
|
|
||||||
}
|
|
||||||
|
|
||||||
uni.$emit('onReceiveMessage', msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
function syncUserInfo(targetId) {
|
|
||||||
getUserInfo(targetId).then(res => {
|
|
||||||
store.dispatch('updateFriends', res)
|
|
||||||
})
|
})
|
||||||
|
setNotifyBadge()
|
||||||
|
uni.$emit('onReceiveMessage', msg)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 播放状态
|
// 播放状态
|
||||||
@@ -201,29 +228,15 @@ const triTone = () => {
|
|||||||
tipState = true
|
tipState = true
|
||||||
})
|
})
|
||||||
innerAudioContext.onEnded(() => {
|
innerAudioContext.onEnded(() => {
|
||||||
tipState = false
|
tipState = false
|
||||||
innerAudioContext.destroy()
|
innerAudioContext.destroy()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 同步好友信息,保存头像地址等
|
|
||||||
*/
|
|
||||||
const syncFriends = () => {
|
|
||||||
getFriends().then(res => {
|
|
||||||
res.map(item => {
|
|
||||||
console.log('item', item);
|
|
||||||
store.dispatch('updateFriends', item)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
initIm,
|
initIm,
|
||||||
connect,
|
connect,
|
||||||
setNotifyBadge,
|
setNotifyBadge,
|
||||||
syncFriends,
|
|
||||||
syncUserInfo,
|
|
||||||
...message
|
...message
|
||||||
}
|
}
|
||||||
|
|||||||
0
utils/im/listeners.js
Normal file
@@ -1,8 +1,9 @@
|
|||||||
import store from '@/store/index.js'
|
import store from '@/store/index.js'
|
||||||
|
|
||||||
import * as RongIMLib from '@/uni_modules/RongCloud-IMWrapper/js_sdk/index'
|
import * as RongIMLib from '@/uni_modules/RongCloud-IMWrapper/js_sdk/index'
|
||||||
|
|
||||||
const getMessageList = (conversationType, targetId, callback) => {
|
const getMessageList = (conversationType, targetId, timeStamp, count, isForward, callback) => {
|
||||||
// 获取消息列表
|
// 获取消息列表 https://doc.rongcloud.cn/imserver/server/v1/message/objectname#objectName
|
||||||
const objectNames = [
|
const objectNames = [
|
||||||
'RC:TxtMsg',
|
'RC:TxtMsg',
|
||||||
'RC:VcMsg',
|
'RC:VcMsg',
|
||||||
@@ -16,10 +17,12 @@ const getMessageList = (conversationType, targetId, callback) => {
|
|||||||
'RC:ReferenceMsg',
|
'RC:ReferenceMsg',
|
||||||
'RC:CombineMsg'
|
'RC:CombineMsg'
|
||||||
]
|
]
|
||||||
const timeStamp = new Date().getTime()
|
|
||||||
const count = 10 // 获取的消息数量
|
RongIMLib.getHistoryMessagesByTimestamp(
|
||||||
const isForward = true // 是否向前获取
|
conversationType,
|
||||||
RongIMLib.getHistoryMessagesByTimestamp(conversationType, targetId, objectNames, timeStamp,
|
targetId,
|
||||||
|
objectNames,
|
||||||
|
timeStamp + 1000,
|
||||||
count,
|
count,
|
||||||
isForward,
|
isForward,
|
||||||
({
|
({
|
||||||
@@ -45,27 +48,28 @@ const getMessageList = (conversationType, targetId, callback) => {
|
|||||||
* @param {string} content 消息内容
|
* @param {string} content 消息内容
|
||||||
* @param {function} callback 回调函数
|
* @param {function} callback 回调函数
|
||||||
*/
|
*/
|
||||||
const sentText = (conversationType, targetId, content, callback) => {
|
const sentText = (conversationType, targetId, content, user, callback) => {
|
||||||
console.log('发送');
|
|
||||||
const msg = {
|
const msg = {
|
||||||
conversationType: conversationType,
|
conversationType: conversationType,
|
||||||
targetId: String(targetId),
|
targetId: String(targetId),
|
||||||
content: {
|
content: {
|
||||||
objectName: 'RC:TxtMsg',
|
objectName: 'RC:TxtMsg',
|
||||||
content: content,
|
content: content,
|
||||||
user: store.getters.sender
|
userInfo: user
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
RongIMLib.sendMessage(msg, ({
|
RongIMLib.sendMessage(msg, ({
|
||||||
code,
|
code,
|
||||||
messageId
|
messageId
|
||||||
}) => {
|
}) => {
|
||||||
if (code === 0) {
|
if (code === 0) {
|
||||||
callback(messageId)
|
callback(messageId)
|
||||||
} else {
|
} else {
|
||||||
|
console.log('发送失败', msg);
|
||||||
uni.showToast({
|
uni.showToast({
|
||||||
icon: 'none',
|
icon: 'none',
|
||||||
title: '发送失败'
|
title: '发送失败' + code
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@@ -79,14 +83,15 @@ const sentText = (conversationType, targetId, content, callback) => {
|
|||||||
* @param {integer} time 录音时长
|
* @param {integer} time 录音时长
|
||||||
* @param {function} callback 录音时长
|
* @param {function} callback 录音时长
|
||||||
*/
|
*/
|
||||||
const sentVoice = (conversationType, targetId, voiceUrl, time, callback) => {
|
const sentVoice = (conversationType, targetId, voiceUrl, time, user, callback) => {
|
||||||
const msg = {
|
const msg = {
|
||||||
conversationType: conversationType,
|
conversationType: conversationType,
|
||||||
targetId: String(targetId),
|
targetId: String(targetId),
|
||||||
content: {
|
content: {
|
||||||
objectName: 'RC:HQVCMsg',
|
objectName: 'RC:HQVCMsg',
|
||||||
local: 'file:///' + plus.io.convertLocalFileSystemURL(voiceUrl),
|
local: 'file:///' + plus.io.convertLocalFileSystemURL(voiceUrl),
|
||||||
duration: time
|
duration: time,
|
||||||
|
userInfo: user
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
RongIMLib.sendMediaMessage(msg, {
|
RongIMLib.sendMediaMessage(msg, {
|
||||||
@@ -105,14 +110,14 @@ const sentVoice = (conversationType, targetId, voiceUrl, time, callback) => {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
const sentImage = (conversationType, targetId, imageUrl, time, callback) => {
|
const sentImage = (conversationType, targetId, imageUrl, user, callback) => {
|
||||||
const msg = {
|
const msg = {
|
||||||
conversationType: conversationType,
|
conversationType: conversationType,
|
||||||
targetId: String(targetId),
|
targetId: String(targetId),
|
||||||
content: {
|
content: {
|
||||||
objectName: 'RC:ImgMsg',
|
objectName: 'RC:ImgMsg',
|
||||||
local: 'file:///' + plus.io.convertLocalFileSystemURL(imageUrl),
|
local: 'file:///' + plus.io.convertLocalFileSystemURL(imageUrl),
|
||||||
duration: time
|
userInfo: user
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
RongIMLib.sendMediaMessage(msg, {
|
RongIMLib.sendMediaMessage(msg, {
|
||||||
|
|||||||
@@ -2,21 +2,21 @@ import {
|
|||||||
usqlite
|
usqlite
|
||||||
} from '@/uni_modules/onemue-USQLite/js_sdk/usqlite.js'
|
} from '@/uni_modules/onemue-USQLite/js_sdk/usqlite.js'
|
||||||
|
|
||||||
const friendModel = usqlite.model('friends', {
|
const contactModel = usqlite.model('contacts', {
|
||||||
userId: {
|
targetId: {
|
||||||
type: String,
|
type: String,
|
||||||
primaryKey: true,
|
primaryKey: true,
|
||||||
unique: true
|
unique: true
|
||||||
},
|
},
|
||||||
name: String,
|
name: String,
|
||||||
address: String,
|
|
||||||
hash: {
|
hash: {
|
||||||
type: String,
|
type: String,
|
||||||
unique: true
|
unique: true
|
||||||
},
|
},
|
||||||
portraitUrl: String
|
portraitUrl: String,
|
||||||
})
|
localAvatar: String
|
||||||
|
})
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
friendModel
|
contactModel
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,51 +0,0 @@
|
|||||||
{
|
|
||||||
"type": "Engine:OnCallReceived",
|
|
||||||
"module": "RongCloud-Call-RCUniCall",
|
|
||||||
"data": {
|
|
||||||
"endTime": 0,
|
|
||||||
"users": [{
|
|
||||||
"userId": "10051",
|
|
||||||
"enableCamera": false,
|
|
||||||
"mediaId": "420111350",
|
|
||||||
"mediaType": 1,
|
|
||||||
"userType": 0,
|
|
||||||
"enableMicrophone": false
|
|
||||||
}, {
|
|
||||||
"userId": "10047",
|
|
||||||
"enableCamera": false,
|
|
||||||
"mediaType": 1,
|
|
||||||
"userType": 0,
|
|
||||||
"enableMicrophone": false
|
|
||||||
}],
|
|
||||||
"inviter": {
|
|
||||||
"userId": "10051",
|
|
||||||
"enableCamera": false,
|
|
||||||
"mediaId": "420111350",
|
|
||||||
"mediaType": 1,
|
|
||||||
"userType": 0,
|
|
||||||
"enableMicrophone": false
|
|
||||||
},
|
|
||||||
"caller": {
|
|
||||||
"userId": "10051",
|
|
||||||
"enableCamera": false,
|
|
||||||
"mediaId": "420111350",
|
|
||||||
"mediaType": 1,
|
|
||||||
"userType": 0,
|
|
||||||
"enableMicrophone": false
|
|
||||||
},
|
|
||||||
"connectedTime": 0,
|
|
||||||
"extra": "",
|
|
||||||
"startTime": 0,
|
|
||||||
"mediaType": 1,
|
|
||||||
"callId": "c28cb9d8-6581-474c-bfa5-9872a4824b65",
|
|
||||||
"targetId": "10051",
|
|
||||||
"callType": 0,
|
|
||||||
"mine": {
|
|
||||||
"userId": "10047",
|
|
||||||
"enableCamera": false,
|
|
||||||
"mediaType": 1,
|
|
||||||
"userType": 0,
|
|
||||||
"enableMicrophone": false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,51 +0,0 @@
|
|||||||
{
|
|
||||||
"type": "Engine:OnCallReceived",
|
|
||||||
"module": "RongCloud-Call-RCUniCall",
|
|
||||||
"data": {
|
|
||||||
"endTime": 0,
|
|
||||||
"users": [{
|
|
||||||
"userId": "10051",
|
|
||||||
"enableCamera": false,
|
|
||||||
"mediaId": "420068630",
|
|
||||||
"mediaType": 0,
|
|
||||||
"userType": 0,
|
|
||||||
"enableMicrophone": false
|
|
||||||
}, {
|
|
||||||
"userId": "10047",
|
|
||||||
"enableCamera": true,
|
|
||||||
"mediaType": 0,
|
|
||||||
"userType": 0,
|
|
||||||
"enableMicrophone": false
|
|
||||||
}],
|
|
||||||
"inviter": {
|
|
||||||
"userId": "10051",
|
|
||||||
"enableCamera": false,
|
|
||||||
"mediaId": "420068630",
|
|
||||||
"mediaType": 0,
|
|
||||||
"userType": 0,
|
|
||||||
"enableMicrophone": false
|
|
||||||
},
|
|
||||||
"caller": {
|
|
||||||
"userId": "10051",
|
|
||||||
"enableCamera": false,
|
|
||||||
"mediaId": "420068630",
|
|
||||||
"mediaType": 0,
|
|
||||||
"userType": 0,
|
|
||||||
"enableMicrophone": false
|
|
||||||
},
|
|
||||||
"connectedTime": 0,
|
|
||||||
"extra": "",
|
|
||||||
"startTime": 0,
|
|
||||||
"mediaType": 0,
|
|
||||||
"callId": "1a1462b8-b63b-40a9-bf95-963e810ac49a",
|
|
||||||
"targetId": "10051",
|
|
||||||
"callType": 0,
|
|
||||||
"mine": {
|
|
||||||
"userId": "10047",
|
|
||||||
"enableCamera": true,
|
|
||||||
"mediaType": 0,
|
|
||||||
"userType": 0,
|
|
||||||
"enableMicrophone": false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
388
utils/index.js
@@ -1,221 +1,183 @@
|
|||||||
import sha1 from './sha1.js'
|
import env from './conf/env.js'
|
||||||
import env from './conf/env.js'
|
|
||||||
import * as RongIMLib from '@rongcloud/imlib-uni'
|
|
||||||
export default {
|
export default {
|
||||||
checkPhone: (phone) => {
|
checkPhone: (phone) => {
|
||||||
let re = /^[0-9]+.?[0-9]*/;
|
let re = /^[0-9]+.?[0-9]*/;
|
||||||
if (phone.length === 11) {
|
if (phone.length === 11) {
|
||||||
return re.test(phone)
|
return re.test(phone)
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
},
|
},
|
||||||
jumpUrl(path) {
|
jumpUrl(path) {
|
||||||
uni.navigateTo({
|
uni.navigateTo({
|
||||||
url: path
|
url: path
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
connectIM() {
|
handleTimeCustom(val) {
|
||||||
if(uni.getStorageSync('userInfo')) {
|
val = this.timeStamp(val, 'Y-m-d H:i:s')
|
||||||
let userInfo = JSON.parse(uni.getStorageSync('userInfo'));
|
let currentDate = new Date();
|
||||||
const im = getApp().globalData.im;
|
let currentD = currentDate.getDate();
|
||||||
im.connect({
|
let currentYear = currentDate.getFullYear();
|
||||||
token: userInfo.rongimToken
|
let currentMonth = currentDate.getMonth() + 1;
|
||||||
}).then(user => {
|
let date = val.substring(0, 19);
|
||||||
console.log('IM链接成功, 链接用户 id 为: ', user.id);
|
date = date.replace(/-/g, '/');
|
||||||
}).catch(error => {
|
let valDate = new Date(date);
|
||||||
uni.hideLoading();
|
let valD = valDate.getDate();
|
||||||
console.log('IM链接失败: ', error.code, error.msg);
|
let valYear = valDate.getFullYear();
|
||||||
});
|
let valMonth = valDate.getMonth() + 1;
|
||||||
}
|
// 判断是否属于今天,计算时分
|
||||||
},
|
let difftime = (currentDate - valDate) / 1000;
|
||||||
handleTimeCustom(val) {
|
let hour = valDate.getHours();
|
||||||
val = this.timeStamp(val, 'Y-m-d H:i:s')
|
hour = hour > 9 ? hour : '0' + hour;
|
||||||
let currentDate = new Date();
|
let minute = valDate.getMinutes();
|
||||||
let currentD = currentDate.getDate();
|
minute = minute > 9 ? minute : '0' + minute;
|
||||||
let currentYear = currentDate.getFullYear();
|
if (currentYear === valYear && currentMonth === valMonth && currentD === valD) {
|
||||||
let currentMonth = currentDate.getMonth() + 1;
|
return hour + ':' + minute;
|
||||||
let date = val.substring(0,19);
|
} else {
|
||||||
date = date.replace(/-/g,'/');
|
// 计算天
|
||||||
let valDate = new Date(date);
|
if (currentYear === valYear && currentMonth === valMonth && currentD !== valD) {
|
||||||
let valD = valDate.getDate();
|
return valMonth + '月' + valD + '日 ' + hour + '时' + minute;
|
||||||
let valYear = valDate.getFullYear();
|
} else {
|
||||||
let valMonth = valDate.getMonth() + 1;
|
return valYear + '年' + valMonth + '月' + valD + '日 ' + hour + ':' + minute;
|
||||||
// 判断是否属于今天,计算时分
|
}
|
||||||
let difftime = (currentDate - valDate) / 1000;
|
|
||||||
let hour = valDate.getHours();
|
|
||||||
hour = hour > 9 ? hour : '0' + hour;
|
|
||||||
let minute = valDate.getMinutes();
|
|
||||||
minute = minute > 9 ? minute : '0' + minute;
|
|
||||||
if(currentYear === valYear && currentMonth === valMonth && currentD === valD) {
|
|
||||||
return hour + ':' + minute;
|
|
||||||
} else {
|
|
||||||
// 计算天
|
|
||||||
if(currentYear === valYear && currentMonth === valMonth && currentD !== valD) {
|
|
||||||
return valMonth + '月' + valD + '日 ' + hour + '时' + minute;
|
|
||||||
} else {
|
|
||||||
return valYear + '年' + valMonth + '月' + valD + '日 ' + hour + ':' + minute;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
},
|
|
||||||
handleTimeCustomCN(val) {
|
|
||||||
val = this.timeStamp(val, 'Y-m-d H:i:s')
|
|
||||||
console.log(val, '时间0000000');
|
|
||||||
let currentDate = new Date();
|
|
||||||
let currentD = currentDate.getDate();
|
|
||||||
let currentYear = currentDate.getFullYear();
|
|
||||||
let currentMonth = currentDate.getMonth() + 1;
|
|
||||||
let date = val.substring(0,19);
|
|
||||||
date = date.replace(/-/g,'/');
|
|
||||||
let valDate = new Date(date);
|
|
||||||
let valD = valDate.getDate();
|
|
||||||
let valYear = valDate.getFullYear();
|
|
||||||
let valMonth = valDate.getMonth() + 1;
|
|
||||||
// 判断是否属于今天,计算时分
|
|
||||||
let difftime = (currentDate - valDate) / 1000;
|
|
||||||
if(currentYear === valYear && currentMonth === valMonth && currentD === valD) {
|
|
||||||
let minute = parseInt(difftime % 3600 / 60);
|
|
||||||
if(minute <= 60) {
|
|
||||||
return minute === 0 ? '刚刚' : minute + '分钟前';
|
|
||||||
} else {
|
|
||||||
return (minute * 60).toFixed(0) + '小时前';
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// 计算天
|
|
||||||
if(currentYear === valYear && currentMonth === valMonth && currentD - 1 === valD) {
|
|
||||||
return '昨天';
|
|
||||||
} else {
|
|
||||||
let days = Math.abs(currentDate.getTime() - valDate.getTime())/(1000*60*60*24);
|
|
||||||
return Math.ceil(days) + '天前';
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
},
|
|
||||||
timeStamp(timestamp, formats) {
|
|
||||||
/*
|
|
||||||
** 时间戳转换成指定格式日期
|
|
||||||
** eg.
|
|
||||||
** dateFormat(11111111111111, 'Y年m月d日 H时i分')
|
|
||||||
** → "2322年02月06日 03时45分"
|
|
||||||
*/
|
|
||||||
// formats格式包括
|
|
||||||
// 1. Y-m-d
|
|
||||||
// 2. Y-m-d H:i:s
|
|
||||||
// 3. Y年m月d日
|
|
||||||
// 4. Y年m月d日 H时i分
|
|
||||||
formats = formats || 'Y-m-d';
|
|
||||||
|
|
||||||
var zero = function(value) {
|
}
|
||||||
if (value < 10) {
|
},
|
||||||
return '0' + value;
|
handleTimeCustomCN(val) {
|
||||||
}
|
val = this.timeStamp(val, 'Y-m-d H:i:s')
|
||||||
return value;
|
console.log(val, '时间0000000');
|
||||||
};
|
let currentDate = new Date();
|
||||||
var myDate = timestamp ? new Date(timestamp) : new Date();
|
let currentD = currentDate.getDate();
|
||||||
|
let currentYear = currentDate.getFullYear();
|
||||||
|
let currentMonth = currentDate.getMonth() + 1;
|
||||||
|
let date = val.substring(0, 19);
|
||||||
|
date = date.replace(/-/g, '/');
|
||||||
|
let valDate = new Date(date);
|
||||||
|
let valD = valDate.getDate();
|
||||||
|
let valYear = valDate.getFullYear();
|
||||||
|
let valMonth = valDate.getMonth() + 1;
|
||||||
|
// 判断是否属于今天,计算时分
|
||||||
|
let difftime = (currentDate - valDate) / 1000;
|
||||||
|
if (currentYear === valYear && currentMonth === valMonth && currentD === valD) {
|
||||||
|
let minute = parseInt(difftime % 3600 / 60);
|
||||||
|
if (minute <= 60) {
|
||||||
|
return minute === 0 ? '刚刚' : minute + '分钟前';
|
||||||
|
} else {
|
||||||
|
return (minute * 60).toFixed(0) + '小时前';
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// 计算天
|
||||||
|
if (currentYear === valYear && currentMonth === valMonth && currentD - 1 === valD) {
|
||||||
|
return '昨天';
|
||||||
|
} else {
|
||||||
|
let days = Math.abs(currentDate.getTime() - valDate.getTime()) / (1000 * 60 * 60 * 24);
|
||||||
|
return Math.ceil(days) + '天前';
|
||||||
|
}
|
||||||
|
|
||||||
var year = myDate.getFullYear();
|
}
|
||||||
var month = zero(myDate.getMonth() + 1);
|
},
|
||||||
var day = zero(myDate.getDate());
|
timeStamp(timestamp, formats) {
|
||||||
|
/*
|
||||||
|
** 时间戳转换成指定格式日期
|
||||||
|
** eg.
|
||||||
|
** dateFormat(11111111111111, 'Y年m月d日 H时i分')
|
||||||
|
** → "2322年02月06日 03时45分"
|
||||||
|
*/
|
||||||
|
// formats格式包括
|
||||||
|
// 1. Y-m-d
|
||||||
|
// 2. Y-m-d H:i:s
|
||||||
|
// 3. Y年m月d日
|
||||||
|
// 4. Y年m月d日 H时i分
|
||||||
|
formats = formats || 'Y-m-d';
|
||||||
|
|
||||||
var hour = zero(myDate.getHours());
|
var zero = function(value) {
|
||||||
var minite = zero(myDate.getMinutes());
|
if (value < 10) {
|
||||||
var second = zero(myDate.getSeconds());
|
return '0' + value;
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
};
|
||||||
|
var myDate = timestamp ? new Date(timestamp) : new Date();
|
||||||
|
|
||||||
return formats.replace(/Y|m|d|H|i|s/ig, function(matches) {
|
var year = myDate.getFullYear();
|
||||||
return ({
|
var month = zero(myDate.getMonth() + 1);
|
||||||
Y: year,
|
var day = zero(myDate.getDate());
|
||||||
m: month,
|
|
||||||
d: day,
|
|
||||||
H: hour,
|
|
||||||
i: minite,
|
|
||||||
s: second
|
|
||||||
})[matches];
|
|
||||||
});
|
|
||||||
},
|
|
||||||
// 时间字符串转换中文时间
|
|
||||||
timeToDate(str) {
|
|
||||||
let date = str.substring(0, 19);
|
|
||||||
date = date.replace(/-/g, '/');
|
|
||||||
date = new Date(str);
|
|
||||||
let dateObj = {
|
|
||||||
year: date.getFullYear(),
|
|
||||||
month: date.getMonth() + 1,
|
|
||||||
day: date.getDate(),
|
|
||||||
hour: date.getHours(),
|
|
||||||
minute: date.getMinutes(),
|
|
||||||
second: date.getSeconds()
|
|
||||||
}
|
|
||||||
let string = dateObj.year + '年' + dateObj.month + '月' + dateObj.day + '日 ' + dateObj.hour + '时' + dateObj
|
|
||||||
.minute + '分';
|
|
||||||
return string
|
|
||||||
},
|
|
||||||
getAge(strAge) {
|
|
||||||
let birArr = strAge.split("-");
|
|
||||||
let birYear = birArr[0];
|
|
||||||
let birMonth = birArr[1];
|
|
||||||
let birDay = birArr[2];
|
|
||||||
|
|
||||||
d = new Date();
|
var hour = zero(myDate.getHours());
|
||||||
let nowYear = d.getFullYear();
|
var minite = zero(myDate.getMinutes());
|
||||||
let nowMonth = d.getMonth() + 1; //记得加1
|
var second = zero(myDate.getSeconds());
|
||||||
let nowDay = d.getDate();
|
|
||||||
let returnAge;
|
|
||||||
|
|
||||||
if (birArr == null) {
|
return formats.replace(/Y|m|d|H|i|s/ig, function(matches) {
|
||||||
return false
|
return ({
|
||||||
};
|
Y: year,
|
||||||
let d = new Date(birYear, birMonth - 1, birDay);
|
m: month,
|
||||||
if (d.getFullYear() == birYear && (d.getMonth() + 1) == birMonth && d.getDate() == birDay) {
|
d: day,
|
||||||
if (nowYear == birYear) {
|
H: hour,
|
||||||
returnAge = 0;
|
i: minite,
|
||||||
} else {
|
s: second
|
||||||
let ageDiff = nowYear - birYear;
|
})[matches];
|
||||||
if (ageDiff > 0) {
|
});
|
||||||
if (nowMonth == birMonth) {
|
},
|
||||||
let dayDiff = nowDay - birDay;
|
// 时间字符串转换中文时间
|
||||||
if (dayDiff < 0) {
|
timeToDate(str) {
|
||||||
returnAge = ageDiff - 1;
|
let date = str.substring(0, 19);
|
||||||
} else {
|
date = date.replace(/-/g, '/');
|
||||||
returnAge = ageDiff;
|
date = new Date(str);
|
||||||
}
|
let dateObj = {
|
||||||
} else {
|
year: date.getFullYear(),
|
||||||
let monthDiff = nowMonth - birMonth;
|
month: date.getMonth() + 1,
|
||||||
if (monthDiff < 0) {
|
day: date.getDate(),
|
||||||
returnAge = ageDiff - 1;
|
hour: date.getHours(),
|
||||||
} else {
|
minute: date.getMinutes(),
|
||||||
returnAge = ageDiff;
|
second: date.getSeconds()
|
||||||
}
|
}
|
||||||
}
|
let string = dateObj.year + '年' + dateObj.month + '月' + dateObj.day + '日 ' + dateObj.hour + '时' + dateObj
|
||||||
} else {
|
.minute + '分';
|
||||||
return "出生日期晚于今天,数据有误"; //返回-1 表示出生日期输入错误 晚于今天
|
return string
|
||||||
}
|
},
|
||||||
}
|
getAge(strAge) {
|
||||||
return returnAge;
|
let birArr = strAge.split("-");
|
||||||
} else {
|
let birYear = birArr[0];
|
||||||
return ("输入的日期格式错误!");
|
let birMonth = birArr[1];
|
||||||
}
|
let birDay = birArr[2];
|
||||||
},
|
|
||||||
getImUserInfo(targetId) {
|
d = new Date();
|
||||||
return new Promise((resolve, reject) => {
|
let nowYear = d.getFullYear();
|
||||||
const Nonce = Date.now();
|
let nowMonth = d.getMonth() + 1; //记得加1
|
||||||
const Timestamp = Date.now() * 1000;
|
let nowDay = d.getDate();
|
||||||
uni.request({
|
let returnAge;
|
||||||
url: 'https://api2-cn.ronghub.com/user/info.json', //仅为示例,并非真实接口地址。
|
|
||||||
data: {
|
if (birArr == null) {
|
||||||
userId: targetId
|
return false
|
||||||
},
|
};
|
||||||
method: 'POST',
|
let d = new Date(birYear, birMonth - 1, birDay);
|
||||||
header: {
|
if (d.getFullYear() == birYear && (d.getMonth() + 1) == birMonth && d.getDate() == birDay) {
|
||||||
'Content-Type': 'application/x-www-form-urlencoded',
|
if (nowYear == birYear) {
|
||||||
'App-Key': '你的key',
|
returnAge = 0;
|
||||||
'Nonce': Nonce,
|
} else {
|
||||||
'Timestamp': Timestamp,
|
let ageDiff = nowYear - birYear;
|
||||||
'Signature': sha1(env.IMsecret + Nonce + Timestamp)
|
if (ageDiff > 0) {
|
||||||
},
|
if (nowMonth == birMonth) {
|
||||||
success: (res) => {
|
let dayDiff = nowDay - birDay;
|
||||||
resolve(res.data)
|
if (dayDiff < 0) {
|
||||||
}
|
returnAge = ageDiff - 1;
|
||||||
});
|
} else {
|
||||||
})
|
returnAge = ageDiff;
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
let monthDiff = nowMonth - birMonth;
|
||||||
|
if (monthDiff < 0) {
|
||||||
|
returnAge = ageDiff - 1;
|
||||||
|
} else {
|
||||||
|
returnAge = ageDiff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return "出生日期晚于今天,数据有误"; //返回-1 表示出生日期输入错误 晚于今天
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return returnAge;
|
||||||
|
} else {
|
||||||
|
return ("输入的日期格式错误!");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,50 +0,0 @@
|
|||||||
function encodeUTF8(s) {
|
|
||||||
var i, r = [], c, x;
|
|
||||||
for (i = 0; i < s.length; i++)
|
|
||||||
if ((c = s.charCodeAt(i)) < 0x80) r.push(c);
|
|
||||||
else if (c < 0x800) r.push(0xC0 + (c >> 6 & 0x1F), 0x80 + (c & 0x3F));
|
|
||||||
else {
|
|
||||||
if ((x = c ^ 0xD800) >> 10 == 0) //对四字节UTF-16转换为Unicode
|
|
||||||
c = (x << 10) + (s.charCodeAt(++i) ^ 0xDC00) + 0x10000,
|
|
||||||
r.push(0xF0 + (c >> 18 & 0x7), 0x80 + (c >> 12 & 0x3F));
|
|
||||||
else r.push(0xE0 + (c >> 12 & 0xF));
|
|
||||||
r.push(0x80 + (c >> 6 & 0x3F), 0x80 + (c & 0x3F));
|
|
||||||
};
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 字符串加密成 hex 字符串
|
|
||||||
function sha1(s) {
|
|
||||||
var data = new Uint8Array(encodeUTF8(s))
|
|
||||||
var i, j, t;
|
|
||||||
var l = ((data.length + 8) >>> 6 << 4) + 16, s = new Uint8Array(l << 2);
|
|
||||||
s.set(new Uint8Array(data.buffer)), s = new Uint32Array(s.buffer);
|
|
||||||
for (t = new DataView(s.buffer), i = 0; i < l; i++)s[i] = t.getUint32(i << 2);
|
|
||||||
s[data.length >> 2] |= 0x80 << (24 - (data.length & 3) * 8);
|
|
||||||
s[l - 1] = data.length << 3;
|
|
||||||
var w = [], f = [
|
|
||||||
function () { return m[1] & m[2] | ~m[1] & m[3]; },
|
|
||||||
function () { return m[1] ^ m[2] ^ m[3]; },
|
|
||||||
function () { return m[1] & m[2] | m[1] & m[3] | m[2] & m[3]; },
|
|
||||||
function () { return m[1] ^ m[2] ^ m[3]; }
|
|
||||||
], rol = function (n, c) { return n << c | n >>> (32 - c); },
|
|
||||||
k = [1518500249, 1859775393, -1894007588, -899497514],
|
|
||||||
m = [1732584193, -271733879, null, null, -1009589776];
|
|
||||||
m[2] = ~m[0], m[3] = ~m[1];
|
|
||||||
for (i = 0; i < s.length; i += 16) {
|
|
||||||
var o = m.slice(0);
|
|
||||||
for (j = 0; j < 80; j++)
|
|
||||||
w[j] = j < 16 ? s[i + j] : rol(w[j - 3] ^ w[j - 8] ^ w[j - 14] ^ w[j - 16], 1),
|
|
||||||
t = rol(m[0], 5) + f[j / 20 | 0]() + m[4] + w[j] + k[j / 20 | 0] | 0,
|
|
||||||
m[1] = rol(m[1], 30), m.pop(), m.unshift(t);
|
|
||||||
for (j = 0; j < 5; j++)m[j] = m[j] + o[j] | 0;
|
|
||||||
};
|
|
||||||
t = new DataView(new Uint32Array(m).buffer);
|
|
||||||
for (var i = 0; i < 5; i++)m[i] = t.getUint32(i << 2);
|
|
||||||
|
|
||||||
var hex = Array.prototype.map.call(new Uint8Array(new Uint32Array(m).buffer), function (e) {
|
|
||||||
return (e < 16 ? "0" : "") + e.toString(16);
|
|
||||||
}).join("");
|
|
||||||
return hex;
|
|
||||||
}
|
|
||||||
export default sha1
|
|
||||||
126
wallet/Wallet.js
@@ -1,126 +0,0 @@
|
|||||||
import Bitcore from "bitcore-lib"
|
|
||||||
import Mnemonic from "bitcore-mnemonic"
|
|
||||||
import secp256k1 from 'secp256k1'
|
|
||||||
import {
|
|
||||||
Address,
|
|
||||||
pubToAddress,
|
|
||||||
toBuffer,
|
|
||||||
toChecksumAddress,
|
|
||||||
intToBuffer
|
|
||||||
} from 'ethereumjs-util'
|
|
||||||
import coinType from './networks.js'
|
|
||||||
import basex from 'base-x'
|
|
||||||
|
|
||||||
export default class Wallet {
|
|
||||||
|
|
||||||
static coinType = coinType
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 生成助记词
|
|
||||||
* @param {Object} lang
|
|
||||||
*/
|
|
||||||
static generateMnemonic(lang) {
|
|
||||||
if (lang) {
|
|
||||||
return (new Mnemonic(this.getLanguage(lang))).toString();
|
|
||||||
} else {
|
|
||||||
return (new Mnemonic()).toString();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 验证助记词
|
|
||||||
* @param {Object} code
|
|
||||||
* @param {Object} lang
|
|
||||||
*/
|
|
||||||
static validMnemonic(code, lang) {
|
|
||||||
if (lang) {
|
|
||||||
return Mnemonic.isValid(code, this.getLanguage(lang));
|
|
||||||
} else {
|
|
||||||
return Mnemonic.isValid(code);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取助记词字典
|
|
||||||
* @param {Object} lang
|
|
||||||
*/
|
|
||||||
static getLanguage(lang) {
|
|
||||||
return Mnemonic.Words[lang]
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 转成硬钱包私钥
|
|
||||||
* @param {Object} code
|
|
||||||
*/
|
|
||||||
static toHDPrivateKey(code) {
|
|
||||||
return (new Mnemonic(code)).toHDPrivateKey()
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 验证地址是否合法
|
|
||||||
* @param {Object} addr
|
|
||||||
*/
|
|
||||||
static isValidAddress(addr) {
|
|
||||||
return Bitcore.Address.isValid(addr)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 硬钱包私钥转成对应网络的 地址 和 私钥
|
|
||||||
* @param {Object} hdPrivateKey
|
|
||||||
* @param {Object} type
|
|
||||||
*/
|
|
||||||
static HDPrivateKeyToAddress(hdPrivateKey, type) {
|
|
||||||
const derived = hdPrivateKey.derive("m/44'/" + type.type + "'/0'/0/0");
|
|
||||||
if (type.type === 195) {
|
|
||||||
const ethAddr = this.getEthereumAddress(derived)
|
|
||||||
const addressBuffer = Buffer.concat([intToBuffer(0x41), ethAddr.buf], 21)
|
|
||||||
return {
|
|
||||||
address: Bitcore.encoding.Base58Check.encode(addressBuffer),
|
|
||||||
public_key: derived.privateKey.publicKey.toString(),
|
|
||||||
private_key: derived.privateKey.toString()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (type.type === 144) {
|
|
||||||
let addr = derived.privateKey.toAddress(type.network).toString()
|
|
||||||
let deco = Bitcore.encoding.Base58.decode(addr)
|
|
||||||
|
|
||||||
return {
|
|
||||||
address: basex('rpshnaf39wBUDNEGHJKLM4PQRST7VWXYZ2bcdeCg65jkm8oFqi1tuvAxyz').encode(deco),
|
|
||||||
public_key: derived.privateKey.publicKey.toString(),
|
|
||||||
private_key: derived.privateKey.toString()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (this.networkIsEthereum(type)) {
|
|
||||||
return {
|
|
||||||
address: toChecksumAddress(this.getEthereumAddress(derived).toString()),
|
|
||||||
public_key: derived.privateKey.publicKey.toString(),
|
|
||||||
private_key: derived.privateKey.toString()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return {
|
|
||||||
address: derived.privateKey.toAddress(type.network).toString(),
|
|
||||||
public_key: derived.privateKey.publicKey.toString(),
|
|
||||||
private_key: derived.privateKey.toString()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 以太坊地址格式转换
|
|
||||||
* @param {Object} derived
|
|
||||||
*/
|
|
||||||
static getEthereumAddress(derived) {
|
|
||||||
const publicKey = derived.hdPublicKey.publicKey.toBuffer()
|
|
||||||
const ethPublicKey = secp256k1.publicKeyConvert(publicKey, false)
|
|
||||||
.slice(1)
|
|
||||||
return Address.fromPublicKey(toBuffer(ethPublicKey))
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 是否是以太坊网络
|
|
||||||
* @param {Object} type
|
|
||||||
*/
|
|
||||||
static networkIsEthereum(type) {
|
|
||||||
return type.isEthereum
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,29 +0,0 @@
|
|||||||
import {
|
|
||||||
Wallet
|
|
||||||
} from "./Wallet.js"
|
|
||||||
|
|
||||||
const code = Wallet.generateMnemonic(this.defaultLanguage)
|
|
||||||
this.mnemonicCode = code
|
|
||||||
const hdPrivateKey = Wallet.toHDPrivateKey(this.mnemonicCode)
|
|
||||||
// const derived = hdPrivateKey.derive("m/44'/61'/0'/0/0");
|
|
||||||
// const publicKey = derived.hdPublicKey.publicKey.toBuffer()
|
|
||||||
// const ethPublicKey = secp256k1.publicKeyConvert(publicKey, false)
|
|
||||||
// .slice(1)
|
|
||||||
|
|
||||||
// const ethAddr = Address.fromPublicKey(toBuffer(ethPublicKey)).toString();
|
|
||||||
|
|
||||||
// console.log(toChecksumAddress(ethAddr));
|
|
||||||
|
|
||||||
// console.log(Address.fromPrivateKey(hdPrivateKey.hdPublicKey.publicKey.toBuffer()));
|
|
||||||
|
|
||||||
var addr = []
|
|
||||||
for (var i in this.coinType) {
|
|
||||||
let whk = Wallet.HDPrivateKeyToAddress(hdPrivateKey, i)
|
|
||||||
let parmas = {
|
|
||||||
name: this.coinType[i],
|
|
||||||
address: whk.address,
|
|
||||||
private_key: whk.private_key,
|
|
||||||
}
|
|
||||||
addr.push(parmas)
|
|
||||||
}
|
|
||||||
this.address = addr
|
|
||||||
@@ -1,24 +0,0 @@
|
|||||||
import store from "@/store/index.js"
|
|
||||||
|
|
||||||
const USE_SOTER_AUTH_KEY = 'USE_SOTER_AUTH_KEY'
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 初始化配置
|
|
||||||
*/
|
|
||||||
const initWalletConfigs = () => {
|
|
||||||
// 生物识别
|
|
||||||
const USE_SOTER = Boolean(uni.getStorageSync(USE_SOTER_AUTH_KEY))
|
|
||||||
store.dispatch('wallet/setSoterAuth', USE_SOTER)
|
|
||||||
// 获取默认钱包
|
|
||||||
}
|
|
||||||
|
|
||||||
const setSoterAuthStatus = (opt) => {
|
|
||||||
uni.setStorageSync(USE_SOTER_AUTH_KEY, opt)
|
|
||||||
store.dispatch('wallet/setSoterAuth', opt)
|
|
||||||
}
|
|
||||||
|
|
||||||
export default {
|
|
||||||
USE_SOTER_AUTH_KEY,
|
|
||||||
setSoterAuthStatus,
|
|
||||||
initWalletConfigs
|
|
||||||
}
|
|
||||||
@@ -1,209 +0,0 @@
|
|||||||
import Bitcore from "bitcore-lib"
|
|
||||||
|
|
||||||
export default [{
|
|
||||||
type: 0,
|
|
||||||
name: '比特币',
|
|
||||||
symbol: 'BTC',
|
|
||||||
code: 'btc',
|
|
||||||
isEthereum: false,
|
|
||||||
network: Bitcore.Networks.mainnet
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: 60,
|
|
||||||
name: '以太坊',
|
|
||||||
symbol: 'ETH',
|
|
||||||
code: 'eth',
|
|
||||||
isEthereum: true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: 61,
|
|
||||||
name: '以太经典',
|
|
||||||
symbol: 'ETC',
|
|
||||||
code: 'etc',
|
|
||||||
isEthereum: true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: 60,
|
|
||||||
name: '赤子心',
|
|
||||||
symbol: 'CZX',
|
|
||||||
code: 'eth_0x3a2a239b1bdaae768ffa06314d523e88e98d4d1f',
|
|
||||||
isEthereum: true
|
|
||||||
},
|
|
||||||
// {
|
|
||||||
// type: 2,
|
|
||||||
// name: '莱特币',
|
|
||||||
// symbol: 'LTC',
|
|
||||||
// isEthereum: false,
|
|
||||||
// network: Bitcore.Networks.add({
|
|
||||||
// name: 'LTC',
|
|
||||||
// alias: 'LTC',
|
|
||||||
// pubkeyhash: 0x30,
|
|
||||||
// privatekey: 0x32,
|
|
||||||
// scripthash: 0xb0,
|
|
||||||
// bech32prefix: 'ltc',
|
|
||||||
// xpubkey: 0x019da462,
|
|
||||||
// xprivkey: 0x019d9cfe,
|
|
||||||
// networkMagic: 0xdbb6c0fb
|
|
||||||
// })
|
|
||||||
// },
|
|
||||||
{
|
|
||||||
type: 3,
|
|
||||||
name: '狗狗币',
|
|
||||||
symbol: 'DOGE',
|
|
||||||
code: 'doge',
|
|
||||||
isEthereum: false,
|
|
||||||
network: Bitcore.Networks.add({
|
|
||||||
name: 'DOGE',
|
|
||||||
alias: 'DOGE',
|
|
||||||
pubkeyhash: 0x1e,
|
|
||||||
privatekey: 0x16,
|
|
||||||
scripthash: 0x9e,
|
|
||||||
bech32prefix: 'doge',
|
|
||||||
xpubkey: 0x02facafd,
|
|
||||||
xprivkey: 0x02fac398,
|
|
||||||
networkMagic: 0xc0c0c0c0
|
|
||||||
})
|
|
||||||
},
|
|
||||||
|
|
||||||
// {
|
|
||||||
// type: 133,
|
|
||||||
// name: '零币',
|
|
||||||
// symbol: 'ZEC',
|
|
||||||
// isEthereum: false,
|
|
||||||
// network: Bitcore.Networks.add({
|
|
||||||
// name: 'ZEC',
|
|
||||||
// alias: 'ZEC',
|
|
||||||
// pubkeyhash: 0x1e,
|
|
||||||
// privatekey: 0x16,
|
|
||||||
// scripthash: 0x9e,
|
|
||||||
// bech32prefix: 'doge',
|
|
||||||
// xpubkey: 0x02facafd,
|
|
||||||
// xprivkey: 0x02fac398,
|
|
||||||
// networkMagic: 0xc0c0c0c0
|
|
||||||
// })
|
|
||||||
// },
|
|
||||||
// {
|
|
||||||
// type: 144,
|
|
||||||
// name: 'XPR - 瑞波币',
|
|
||||||
// symbol: 'XPR',
|
|
||||||
// isEthereum: false,
|
|
||||||
// network: Bitcore.Networks.add({
|
|
||||||
// name: 'XPR',
|
|
||||||
// alias: 'XPR',
|
|
||||||
// pubkeyhash: 0x1e,
|
|
||||||
// privatekey: 0x16,
|
|
||||||
// scripthash: 0x9e,
|
|
||||||
// bech32prefix: 'doge',
|
|
||||||
// xpubkey: 0x02facafd,
|
|
||||||
// xprivkey: 0x02fac398,
|
|
||||||
// networkMagic: 0xc0c0c0c0
|
|
||||||
// })
|
|
||||||
// },
|
|
||||||
// {
|
|
||||||
// type: 145,
|
|
||||||
// name: '比特现金',
|
|
||||||
// symbol: 'BCH',
|
|
||||||
// isEthereum: false,
|
|
||||||
// network: Bitcore.Networks.add({
|
|
||||||
// name: 'BCH',
|
|
||||||
// alias: 'BCH',
|
|
||||||
// pubkeyhash: 0x00,
|
|
||||||
// privatekey: 0x05,
|
|
||||||
// scripthash: 0x80,
|
|
||||||
// bech32prefix: 'bitcoincash',
|
|
||||||
// xpubkey: 0x0488b21e,
|
|
||||||
// xprivkey: 0x0488ade4,
|
|
||||||
// networkMagic: 0xd9b4bef9
|
|
||||||
// })
|
|
||||||
// },
|
|
||||||
// {
|
|
||||||
// type: 195,
|
|
||||||
// name: '波场',
|
|
||||||
// symbol: 'TRX',
|
|
||||||
// isEthereum: false,
|
|
||||||
// network: Bitcore.Networks.add({
|
|
||||||
// name: 'TRX',
|
|
||||||
// alias: 'TRX',
|
|
||||||
// pubkeyhash: 0x41,
|
|
||||||
// privatekey: 0x05,
|
|
||||||
// scripthash: 0x80,
|
|
||||||
// bech32prefix: '',
|
|
||||||
// xpubkey: 0x0488b21e,
|
|
||||||
// xprivkey: 0x0488ade4
|
|
||||||
// })
|
|
||||||
// },
|
|
||||||
{
|
|
||||||
type: 195,
|
|
||||||
name: 'USDT(TRC20)',
|
|
||||||
symbol: 'USDT',
|
|
||||||
code: 'trx_TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t',
|
|
||||||
isEthereum: false,
|
|
||||||
network: Bitcore.Networks.add({
|
|
||||||
name: 'USDT',
|
|
||||||
alias: 'USDT',
|
|
||||||
pubkeyhash: 0x41,
|
|
||||||
privatekey: 0x05,
|
|
||||||
scripthash: 0x80,
|
|
||||||
bech32prefix: '',
|
|
||||||
xpubkey: 0x0488b21e,
|
|
||||||
xprivkey: 0x0488ade4
|
|
||||||
})
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: 195,
|
|
||||||
name: 'USDT(ERC20)',
|
|
||||||
symbol: 'USDT',
|
|
||||||
code: 'eth_0xdac17f958d2ee523a2206206994597c13d831ec7',
|
|
||||||
isEthereum: true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: 0,
|
|
||||||
name: 'USDT(OMNI)',
|
|
||||||
symbol: 'USDT',
|
|
||||||
code: 'usdt',
|
|
||||||
isEthereum: false,
|
|
||||||
network: Bitcore.Networks.mainnet
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: 13107,
|
|
||||||
name: '比特元',
|
|
||||||
symbol: 'BTY',
|
|
||||||
code: 'bty',
|
|
||||||
isEthereum: false,
|
|
||||||
network: Bitcore.Networks.add({
|
|
||||||
name: 'BTY',
|
|
||||||
alias: 'BTY',
|
|
||||||
pubkeyhash: 0x00,
|
|
||||||
privatekey: 0x05,
|
|
||||||
scripthash: 0x80,
|
|
||||||
bech32prefix: 'bityuan',
|
|
||||||
xpubkey: 0x0488b21e,
|
|
||||||
xprivkey: 0x0488ade4,
|
|
||||||
networkMagic: 0xd9b4bef9
|
|
||||||
})
|
|
||||||
},
|
|
||||||
// {
|
|
||||||
// type: 60,
|
|
||||||
// name: '元链',
|
|
||||||
// symbol: 'YCC',
|
|
||||||
// isEthereum: true
|
|
||||||
// },
|
|
||||||
{
|
|
||||||
type: 13107,
|
|
||||||
name: 'JZC',
|
|
||||||
symbol: 'JZC',
|
|
||||||
code: 'bty',
|
|
||||||
isEthereum: false,
|
|
||||||
network: Bitcore.Networks.add({
|
|
||||||
name: 'JZC',
|
|
||||||
alias: 'JZC',
|
|
||||||
pubkeyhash: 0x00,
|
|
||||||
privatekey: 0x05,
|
|
||||||
scripthash: 0x80,
|
|
||||||
bech32prefix: 'bityuan',
|
|
||||||
xpubkey: 0x0488b21e,
|
|
||||||
xprivkey: 0x0488ade4,
|
|
||||||
networkMagic: 0xd9b4bef9
|
|
||||||
})
|
|
||||||
}
|
|
||||||
]
|
|
||||||
207
yarn.lock
@@ -2,194 +2,27 @@
|
|||||||
# yarn lockfile v1
|
# yarn lockfile v1
|
||||||
|
|
||||||
|
|
||||||
"base-x@^3.0.2":
|
moment@^2.29.1:
|
||||||
"integrity" "sha512-H7JU6iBHTal1gp56aKoaa//YUxEaAOUiydvrV/pILqIHXTtqxSkATOnDA2u+jZ/61sD+L/412+7kzXRtWukhpQ=="
|
version "2.29.1"
|
||||||
"resolved" "https://registry.npmjs.org/base-x/-/base-x-3.0.9.tgz"
|
resolved "https://registry.npmjs.org/moment/-/moment-2.29.1.tgz"
|
||||||
"version" "3.0.9"
|
integrity sha512-kHmoybcPV8Sqy59DwNDY3Jefr64lK/by/da0ViFcuA4DH0vQg5Q6Ze5VimxkfQNSC+Mls/Kx53s7TjP1RhFEDQ==
|
||||||
dependencies:
|
|
||||||
"safe-buffer" "^5.0.1"
|
|
||||||
|
|
||||||
"bech32@=2.0.0":
|
uni-read-pages@^1.0.5:
|
||||||
"integrity" "sha512-LcknSilhIGatDAsY1ak2I8VtGaHNhgMSYVxFrGLXv+xLHytaKZKcaUJJUE7qmBr7h33o5YQwP55pMI0xmkpJwg=="
|
version "1.0.5"
|
||||||
"resolved" "https://registry.npmjs.org/bech32/-/bech32-2.0.0.tgz"
|
resolved "https://registry.npmjs.org/uni-read-pages/-/uni-read-pages-1.0.5.tgz"
|
||||||
"version" "2.0.0"
|
integrity sha512-GkrrZ0LX0vn9R5k6RKEi0Ez3Q3e2vUpjXQ8Z6/K/d28KudI9ajqgt8WEjQFlG5EPm1K6uTArN8LlqmZTEixDUA==
|
||||||
|
|
||||||
"bigi@^1.1.0", "bigi@^1.4.2":
|
uni-simple-router@^2.0.7:
|
||||||
"integrity" "sha1-nGZalfiLiwj8Bc/XMfVhhZ1yWCU="
|
version "2.0.7"
|
||||||
"resolved" "https://registry.npmjs.org/bigi/-/bigi-1.4.2.tgz"
|
resolved "https://registry.npmjs.org/uni-simple-router/-/uni-simple-router-2.0.7.tgz"
|
||||||
"version" "1.4.2"
|
integrity sha512-8FKv5dw7Eoonm0gkO8udprrxzin0fNUI0+AvIphFkFRH5ZmP5ZWJ2pvnWzb2NiiqQSECTSU5VSB7HhvOSwD5eA==
|
||||||
|
|
||||||
"bip-schnorr@=0.6.4":
|
uview-ui@^2.0.19:
|
||||||
"integrity" "sha512-dNKw7Lea8B0wMIN4OjEmOk/Z5qUGqoPDY0P2QttLqGk1hmDPytLWW8PR5Pb6Vxy6CprcdEgfJpOjUu+ONQveyg=="
|
version "2.0.19"
|
||||||
"resolved" "https://registry.npmjs.org/bip-schnorr/-/bip-schnorr-0.6.4.tgz"
|
resolved "https://registry.npmjs.org/uview-ui/-/uview-ui-2.0.19.tgz"
|
||||||
"version" "0.6.4"
|
integrity sha512-ddZiaP7R9wsUxMzAuhuXgh5OswgCm2lKuulTqjnRXFr0uUWsgL1iBifU3GbOwpwP0LtTHKJOo9rYv1LP0WXmzA==
|
||||||
dependencies:
|
|
||||||
"bigi" "^1.4.2"
|
|
||||||
"ecurve" "^1.0.6"
|
|
||||||
"js-sha256" "^0.9.0"
|
|
||||||
"randombytes" "^2.1.0"
|
|
||||||
"safe-buffer" "^5.2.1"
|
|
||||||
|
|
||||||
"bitcore-lib@^8.25.25":
|
vuex@^3.6.2:
|
||||||
"integrity" "sha512-H6qNCVl4M8/MglXhvc04mmeus1d6nrmqTJGQ+xezJLvL7hs7R3dyBPtOqSP3YSw0iq/GWspMd8f5OOlyXVipJQ=="
|
version "3.6.2"
|
||||||
"resolved" "https://registry.npmjs.org/bitcore-lib/-/bitcore-lib-8.25.25.tgz"
|
resolved "https://registry.npmjs.org/vuex/-/vuex-3.6.2.tgz"
|
||||||
"version" "8.25.25"
|
integrity sha512-ETW44IqCgBpVomy520DT5jf8n0zoCac+sxWnn+hMe/CzaSejb/eVw2YToiXYX+Ex/AuHHia28vWTq4goAexFbw==
|
||||||
dependencies:
|
|
||||||
"bech32" "=2.0.0"
|
|
||||||
"bip-schnorr" "=0.6.4"
|
|
||||||
"bn.js" "=4.11.8"
|
|
||||||
"bs58" "^4.0.1"
|
|
||||||
"buffer-compare" "=1.1.1"
|
|
||||||
"elliptic" "^6.5.3"
|
|
||||||
"inherits" "=2.0.1"
|
|
||||||
"lodash" "^4.17.20"
|
|
||||||
|
|
||||||
"bitcore-mnemonic@^8.25.25":
|
|
||||||
"integrity" "sha512-7HvRxHrmd+Rh0Ohl0SEDMKQBAM+FoevXbCFnxGju6H+uZjtWMOToHA8vUg0+B91pfEMjdt9mQVB/wSA8GMqnCA=="
|
|
||||||
"resolved" "https://registry.npmjs.org/bitcore-mnemonic/-/bitcore-mnemonic-8.25.25.tgz"
|
|
||||||
"version" "8.25.25"
|
|
||||||
dependencies:
|
|
||||||
"bitcore-lib" "^8.25.25"
|
|
||||||
"unorm" "^1.4.1"
|
|
||||||
|
|
||||||
"bn.js@^4.11.9":
|
|
||||||
"integrity" "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA=="
|
|
||||||
"resolved" "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz"
|
|
||||||
"version" "4.12.0"
|
|
||||||
|
|
||||||
"bn.js@=4.11.8":
|
|
||||||
"integrity" "sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA=="
|
|
||||||
"resolved" "https://registry.npmjs.org/bn.js/-/bn.js-4.11.8.tgz"
|
|
||||||
"version" "4.11.8"
|
|
||||||
|
|
||||||
"brorand@^1.1.0":
|
|
||||||
"integrity" "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8="
|
|
||||||
"resolved" "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz"
|
|
||||||
"version" "1.1.0"
|
|
||||||
|
|
||||||
"bs58@^4.0.1":
|
|
||||||
"integrity" "sha1-vhYedsNU9veIrkBx9j806MTwpCo="
|
|
||||||
"resolved" "https://registry.npmjs.org/bs58/-/bs58-4.0.1.tgz"
|
|
||||||
"version" "4.0.1"
|
|
||||||
dependencies:
|
|
||||||
"base-x" "^3.0.2"
|
|
||||||
|
|
||||||
"buffer-compare@=1.1.1":
|
|
||||||
"integrity" "sha1-W+e+hTr4kZjR9N3AkNHWakiu9ZY="
|
|
||||||
"resolved" "https://registry.npmjs.org/buffer-compare/-/buffer-compare-1.1.1.tgz"
|
|
||||||
"version" "1.1.1"
|
|
||||||
|
|
||||||
"ecurve@^1.0.6":
|
|
||||||
"integrity" "sha512-/BzEjNfiSuB7jIWKcS/z8FK9jNjmEWvUV2YZ4RLSmcDtP7Lq0m6FvDuSnJpBlDpGRpfRQeTLGLBI8H+kEv0r+w=="
|
|
||||||
"resolved" "https://registry.npmjs.org/ecurve/-/ecurve-1.0.6.tgz"
|
|
||||||
"version" "1.0.6"
|
|
||||||
dependencies:
|
|
||||||
"bigi" "^1.1.0"
|
|
||||||
"safe-buffer" "^5.0.1"
|
|
||||||
|
|
||||||
"elliptic@^6.5.3":
|
|
||||||
"integrity" "sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ=="
|
|
||||||
"resolved" "https://registry.npmjs.org/elliptic/-/elliptic-6.5.4.tgz"
|
|
||||||
"version" "6.5.4"
|
|
||||||
dependencies:
|
|
||||||
"bn.js" "^4.11.9"
|
|
||||||
"brorand" "^1.1.0"
|
|
||||||
"hash.js" "^1.0.0"
|
|
||||||
"hmac-drbg" "^1.0.1"
|
|
||||||
"inherits" "^2.0.4"
|
|
||||||
"minimalistic-assert" "^1.0.1"
|
|
||||||
"minimalistic-crypto-utils" "^1.0.1"
|
|
||||||
|
|
||||||
"hash.js@^1.0.0", "hash.js@^1.0.3":
|
|
||||||
"integrity" "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA=="
|
|
||||||
"resolved" "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz"
|
|
||||||
"version" "1.1.7"
|
|
||||||
dependencies:
|
|
||||||
"inherits" "^2.0.3"
|
|
||||||
"minimalistic-assert" "^1.0.1"
|
|
||||||
|
|
||||||
"hmac-drbg@^1.0.1":
|
|
||||||
"integrity" "sha1-0nRXAQJabHdabFRXk+1QL8DGSaE="
|
|
||||||
"resolved" "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz"
|
|
||||||
"version" "1.0.1"
|
|
||||||
dependencies:
|
|
||||||
"hash.js" "^1.0.3"
|
|
||||||
"minimalistic-assert" "^1.0.0"
|
|
||||||
"minimalistic-crypto-utils" "^1.0.1"
|
|
||||||
|
|
||||||
"inherits@^2.0.3":
|
|
||||||
"integrity" "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
|
|
||||||
"resolved" "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz"
|
|
||||||
"version" "2.0.4"
|
|
||||||
|
|
||||||
"inherits@^2.0.4":
|
|
||||||
"integrity" "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
|
|
||||||
"resolved" "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz"
|
|
||||||
"version" "2.0.4"
|
|
||||||
|
|
||||||
"inherits@=2.0.1":
|
|
||||||
"integrity" "sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE="
|
|
||||||
"resolved" "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz"
|
|
||||||
"version" "2.0.1"
|
|
||||||
|
|
||||||
"js-sha256@^0.9.0":
|
|
||||||
"integrity" "sha512-sga3MHh9sgQN2+pJ9VYZ+1LPwXOxuBJBA5nrR5/ofPfuiJBE2hnjsaN8se8JznOmGLN2p49Pe5U/ttafcs/apA=="
|
|
||||||
"resolved" "https://registry.npmjs.org/js-sha256/-/js-sha256-0.9.0.tgz"
|
|
||||||
"version" "0.9.0"
|
|
||||||
|
|
||||||
"lodash@^4.17.20":
|
|
||||||
"integrity" "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="
|
|
||||||
"resolved" "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz"
|
|
||||||
"version" "4.17.21"
|
|
||||||
|
|
||||||
"minimalistic-assert@^1.0.0", "minimalistic-assert@^1.0.1":
|
|
||||||
"integrity" "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A=="
|
|
||||||
"resolved" "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz"
|
|
||||||
"version" "1.0.1"
|
|
||||||
|
|
||||||
"minimalistic-crypto-utils@^1.0.1":
|
|
||||||
"integrity" "sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo="
|
|
||||||
"resolved" "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz"
|
|
||||||
"version" "1.0.1"
|
|
||||||
|
|
||||||
"moment@^2.29.1":
|
|
||||||
"integrity" "sha512-kHmoybcPV8Sqy59DwNDY3Jefr64lK/by/da0ViFcuA4DH0vQg5Q6Ze5VimxkfQNSC+Mls/Kx53s7TjP1RhFEDQ=="
|
|
||||||
"resolved" "https://registry.npmjs.org/moment/-/moment-2.29.1.tgz"
|
|
||||||
"version" "2.29.1"
|
|
||||||
|
|
||||||
"randombytes@^2.1.0":
|
|
||||||
"integrity" "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ=="
|
|
||||||
"resolved" "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz"
|
|
||||||
"version" "2.1.0"
|
|
||||||
dependencies:
|
|
||||||
"safe-buffer" "^5.1.0"
|
|
||||||
|
|
||||||
"safe-buffer@^5.0.1", "safe-buffer@^5.1.0", "safe-buffer@^5.2.1":
|
|
||||||
"integrity" "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ=="
|
|
||||||
"resolved" "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz"
|
|
||||||
"version" "5.2.1"
|
|
||||||
|
|
||||||
"uni-read-pages@^1.0.5":
|
|
||||||
"integrity" "sha512-GkrrZ0LX0vn9R5k6RKEi0Ez3Q3e2vUpjXQ8Z6/K/d28KudI9ajqgt8WEjQFlG5EPm1K6uTArN8LlqmZTEixDUA=="
|
|
||||||
"resolved" "https://registry.npmjs.org/uni-read-pages/-/uni-read-pages-1.0.5.tgz"
|
|
||||||
"version" "1.0.5"
|
|
||||||
|
|
||||||
"uni-simple-router@^2.0.7":
|
|
||||||
"integrity" "sha512-8FKv5dw7Eoonm0gkO8udprrxzin0fNUI0+AvIphFkFRH5ZmP5ZWJ2pvnWzb2NiiqQSECTSU5VSB7HhvOSwD5eA=="
|
|
||||||
"resolved" "https://registry.npmjs.org/uni-simple-router/-/uni-simple-router-2.0.7.tgz"
|
|
||||||
"version" "2.0.7"
|
|
||||||
|
|
||||||
"unorm@^1.4.1":
|
|
||||||
"integrity" "sha512-b2/KCUlYZUeA7JFUuRJZPUtr4gZvBh7tavtv4fvk4+KV9pfGiR6CQAQAWl49ZpR3ts2dk4FYkP7EIgDJoiOLDA=="
|
|
||||||
"resolved" "https://registry.npmjs.org/unorm/-/unorm-1.6.0.tgz"
|
|
||||||
"version" "1.6.0"
|
|
||||||
|
|
||||||
"uview-ui@^2.0.19":
|
|
||||||
"integrity" "sha512-ddZiaP7R9wsUxMzAuhuXgh5OswgCm2lKuulTqjnRXFr0uUWsgL1iBifU3GbOwpwP0LtTHKJOo9rYv1LP0WXmzA=="
|
|
||||||
"resolved" "https://registry.npmjs.org/uview-ui/-/uview-ui-2.0.19.tgz"
|
|
||||||
"version" "2.0.19"
|
|
||||||
|
|
||||||
"vuex@^3.6.2":
|
|
||||||
"integrity" "sha512-ETW44IqCgBpVomy520DT5jf8n0zoCac+sxWnn+hMe/CzaSejb/eVw2YToiXYX+Ex/AuHHia28vWTq4goAexFbw=="
|
|
||||||
"resolved" "https://registry.npmjs.org/vuex/-/vuex-3.6.2.tgz"
|
|
||||||
"version" "3.6.2"
|
|
||||||
|
|||||||