This commit is contained in:
2025-11-25 05:36:02 +08:00
parent 8e036cc171
commit b10e4b4336
65 changed files with 2672 additions and 2270 deletions
+55 -132
View File
@@ -1,29 +1,16 @@
<script> <script>
import { import {mapGetters,mapActions} from "vuex";
mapGetters, import IMSDK, {IMMethods,MessageType,SessionType,} from "openim-uniapp-polyfill";
mapActions
} from "vuex";
import IMSDK, {
IMMethods,
MessageType,
SessionType,
} from "openim-uniapp-polyfill";
import config from "./common/config"; import config from "./common/config";
import { import {getDbDir,toastWithCallback} from "@/util/common.js";
getDbDir, import {conversationSort} from "@/util/imCommon";
toastWithCallback import {checkUpgrade} from "@/api/login.js"
} from "@/util/common.js"; import {PageEvents,UpdateMessageTypes} from "@/constant";
import {
conversationSort
} from "@/util/imCommon";
import {
PageEvents,
UpdateMessageTypes
} from "@/constant";
export default { export default {
onLaunch: function() { onLaunch: function() {
console.log("App Launch"); console.log("App Launch");
this.checkUpdate();
this.setGlobalIMlistener(); this.setGlobalIMlistener();
this.tryLogin(); this.tryLogin();
// #ifdef H5 // #ifdef H5
@@ -101,15 +88,11 @@
}); });
// sync // sync
const syncStartHandler = ({ const syncStartHandler = ({data}) => {
data
}) => {
this.$store.commit("user/SET_IS_SYNCING", true); this.$store.commit("user/SET_IS_SYNCING", true);
this.$store.commit("user/SET_REINSTALL", data); this.$store.commit("user/SET_REINSTALL", data);
}; };
const syncProgressHandler = ({ const syncProgressHandler = ({data}) => {
data
}) => {
this.$store.commit("user/SET_PROGRESS", data); this.$store.commit("user/SET_PROGRESS", data);
}; };
const syncFinishHandler = () => { const syncFinishHandler = () => {
@@ -133,9 +116,7 @@
IMSDK.subscribe(IMSDK.IMEvents.OnSyncServerProgress, syncProgressHandler); IMSDK.subscribe(IMSDK.IMEvents.OnSyncServerProgress, syncProgressHandler);
// self // self
const selfInfoUpdateHandler = ({ const selfInfoUpdateHandler = ({data}) => {
data
}) => {
this.$store.commit("user/SET_SELF_INFO", { this.$store.commit("user/SET_SELF_INFO", {
...this.storeSelfInfo, ...this.storeSelfInfo,
...data, ...data,
@@ -145,9 +126,7 @@
IMSDK.subscribe(IMSDK.IMEvents.OnSelfInfoUpdated, selfInfoUpdateHandler); IMSDK.subscribe(IMSDK.IMEvents.OnSelfInfoUpdated, selfInfoUpdateHandler);
// message // message
const newMessagesHandler = ({ const newMessagesHandler = ({data}) => {
data
}) => {
if (this.storeIsSyncing) { if (this.storeIsSyncing) {
return; return;
} }
@@ -157,9 +136,7 @@
IMSDK.subscribe(IMSDK.IMEvents.OnRecvNewMessages, newMessagesHandler); IMSDK.subscribe(IMSDK.IMEvents.OnRecvNewMessages, newMessagesHandler);
// friend // friend
const friendInfoChangeHandler = ({ const friendInfoChangeHandler = ({data}) => {
data
}) => {
uni.$emit(IMSDK.IMEvents.OnFriendInfoChanged, { uni.$emit(IMSDK.IMEvents.OnFriendInfoChanged, {
data data
}); });
@@ -167,36 +144,25 @@
friendInfo: data, friendInfo: data,
}); });
}; };
const friendAddedHandler = ({ const friendAddedHandler = ({data}) => {
data
}) => {
this.pushNewFriend(data); this.pushNewFriend(data);
}; };
const friendDeletedHander = ({ const friendDeletedHander = ({data}) => {
data
}) => {
this.updateFriendInfo({ this.updateFriendInfo({
friendInfo: data, friendInfo: data,
isRemove: true, isRemove: true,
}); });
}; };
IMSDK.subscribe( IMSDK.subscribe(IMSDK.IMEvents.OnFriendInfoChanged,friendInfoChangeHandler);
IMSDK.IMEvents.OnFriendInfoChanged,
friendInfoChangeHandler
);
IMSDK.subscribe(IMSDK.IMEvents.OnFriendAdded, friendAddedHandler); IMSDK.subscribe(IMSDK.IMEvents.OnFriendAdded, friendAddedHandler);
IMSDK.subscribe(IMSDK.IMEvents.OnFriendDeleted, friendDeletedHander); IMSDK.subscribe(IMSDK.IMEvents.OnFriendDeleted, friendDeletedHander);
// blacklist // blacklist
const blackAddedHandler = ({ const blackAddedHandler = ({data}) => {
data
}) => {
this.pushNewBlack(data); this.pushNewBlack(data);
}; };
const blackDeletedHandler = ({ const blackDeletedHandler = ({data}) => {
data
}) => {
this.updateBlackInfo({ this.updateBlackInfo({
blackInfo: data, blackInfo: data,
isRemove: true, isRemove: true,
@@ -207,58 +173,34 @@
IMSDK.subscribe(IMSDK.IMEvents.OnBlackDeleted, blackDeletedHandler); IMSDK.subscribe(IMSDK.IMEvents.OnBlackDeleted, blackDeletedHandler);
// group // group
const joinedGroupAddedHandler = ({ const joinedGroupAddedHandler = ({data}) => {
data
}) => {
this.pushNewGroup(data); this.pushNewGroup(data);
}; };
const joinedGroupDeletedHandler = ({ const joinedGroupDeletedHandler = ({data}) => {
data
}) => {
this.updateGroupInfo({ this.updateGroupInfo({
groupInfo: data, groupInfo: data,
isRemove: true, isRemove: true,
}); });
}; };
const groupInfoChangedHandler = ({ const groupInfoChangedHandler = ({data}) => {
data
}) => {
this.updateGroupInfo({ this.updateGroupInfo({
groupInfo: data, groupInfo: data,
}); });
}; };
const groupMemberInfoChangedHandler = ({ const groupMemberInfoChangedHandler = ({data}) => {
data uni.$emit(IMSDK.IMEvents.OnGroupMemberInfoChanged, {data});
}) => {
uni.$emit(IMSDK.IMEvents.OnGroupMemberInfoChanged, {
data
});
if (data.groupID === this.storeCurrentConversation?.groupID) { if (data.groupID === this.storeCurrentConversation?.groupID) {
this.updateCurrentMemberInGroup(data); this.updateCurrentMemberInGroup(data);
} }
}; };
IMSDK.subscribe( IMSDK.subscribe(IMSDK.IMEvents.OnJoinedGroupAdded,joinedGroupAddedHandler);
IMSDK.IMEvents.OnJoinedGroupAdded, IMSDK.subscribe(IMSDK.IMEvents.OnJoinedGroupDeleted,joinedGroupDeletedHandler);
joinedGroupAddedHandler IMSDK.subscribe(IMSDK.IMEvents.OnGroupInfoChanged,groupInfoChangedHandler);
); IMSDK.subscribe(IMSDK.IMEvents.OnGroupMemberInfoChanged,groupMemberInfoChangedHandler);
IMSDK.subscribe(
IMSDK.IMEvents.OnJoinedGroupDeleted,
joinedGroupDeletedHandler
);
IMSDK.subscribe(
IMSDK.IMEvents.OnGroupInfoChanged,
groupInfoChangedHandler
);
IMSDK.subscribe(
IMSDK.IMEvents.OnGroupMemberInfoChanged,
groupMemberInfoChangedHandler
);
// application // application
const friendApplicationNumHandler = ({ const friendApplicationNumHandler = ({data}) => {
data
}) => {
const isRecv = data.toUserID === this.storeCurrentUserID; const isRecv = data.toUserID === this.storeCurrentUserID;
if (isRecv) { if (isRecv) {
this.pushNewRecvFriendApplition(data); this.pushNewRecvFriendApplition(data);
@@ -266,9 +208,7 @@
this.pushNewSentFriendApplition(data); this.pushNewSentFriendApplition(data);
} }
}; };
const friendApplicationAccessHandler = ({ const friendApplicationAccessHandler = ({data}) => {
data
}) => {
const isRecv = data.toUserID === this.storeCurrentUserID; const isRecv = data.toUserID === this.storeCurrentUserID;
if (isRecv) { if (isRecv) {
this.updateRecvFriendApplition({ this.updateRecvFriendApplition({
@@ -280,9 +220,7 @@
}); });
} }
}; };
const groupApplicationNumHandler = ({ const groupApplicationNumHandler = ({data}) => {
data
}) => {
const isRecv = data.userID !== this.storeCurrentUserID; const isRecv = data.userID !== this.storeCurrentUserID;
if (isRecv) { if (isRecv) {
this.pushNewRecvGroupApplition(data); this.pushNewRecvGroupApplition(data);
@@ -290,9 +228,7 @@
this.pushNewSentGroupApplition(data); this.pushNewSentGroupApplition(data);
} }
}; };
const groupApplicationAccessHandler = ({ const groupApplicationAccessHandler = ({data}) => {
data
}) => {
const isRecv = data.userID !== this.storeCurrentUserID; const isRecv = data.userID !== this.storeCurrentUserID;
if (isRecv) { if (isRecv) {
this.updateRecvGroupApplition({ this.updateRecvGroupApplition({
@@ -305,43 +241,21 @@
} }
}; };
IMSDK.subscribe( IMSDK.subscribe(IMSDK.IMEvents.OnFriendApplicationAdded,friendApplicationNumHandler);
IMSDK.IMEvents.OnFriendApplicationAdded, IMSDK.subscribe(IMSDK.IMEvents.OnFriendApplicationAccepted,friendApplicationAccessHandler);
friendApplicationNumHandler IMSDK.subscribe(IMSDK.IMEvents.OnFriendApplicationRejected,friendApplicationAccessHandler);
); IMSDK.subscribe(IMSDK.IMEvents.OnGroupApplicationAdded,groupApplicationNumHandler);
IMSDK.subscribe( IMSDK.subscribe(IMSDK.IMEvents.OnGroupApplicationAccepted,groupApplicationAccessHandler);
IMSDK.IMEvents.OnFriendApplicationAccepted, IMSDK.subscribe(IMSDK.IMEvents.OnGroupApplicationRejected,groupApplicationAccessHandler);
friendApplicationAccessHandler
);
IMSDK.subscribe(
IMSDK.IMEvents.OnFriendApplicationRejected,
friendApplicationAccessHandler
);
IMSDK.subscribe(
IMSDK.IMEvents.OnGroupApplicationAdded,
groupApplicationNumHandler
);
IMSDK.subscribe(
IMSDK.IMEvents.OnGroupApplicationAccepted,
groupApplicationAccessHandler
);
IMSDK.subscribe(
IMSDK.IMEvents.OnGroupApplicationRejected,
groupApplicationAccessHandler
);
// conversation // conversation
const totalUnreadCountChangedHandler = ({ const totalUnreadCountChangedHandler = ({data}) => {
data
}) => {
if (this.storeIsSyncing) { if (this.storeIsSyncing) {
return; return;
} }
this.$store.commit("conversation/SET_UNREAD_COUNT", data); this.$store.commit("conversation/SET_UNREAD_COUNT", data);
}; };
const newConversationHandler = ({ const newConversationHandler = ({data}) => {
data
}) => {
if (this.storeIsSyncing) { if (this.storeIsSyncing) {
return; return;
} }
@@ -351,9 +265,7 @@
conversationSort(result) conversationSort(result)
); );
}; };
const conversationChangedHandler = ({ const conversationChangedHandler = ({data}) => {
data
}) => {
if (this.storeIsSyncing) { if (this.storeIsSyncing) {
return; return;
} }
@@ -421,17 +333,14 @@
uni.$u.toast("初始化IMSDK失败!"); uni.$u.toast("初始化IMSDK失败!");
return; return;
} }
const status = await IMSDK.asyncApi( const status = await IMSDK.asyncApi(IMSDK.IMMethods.GetLoginStatus,IMSDK.uuid());
IMSDK.IMMethods.GetLoginStatus,
IMSDK.uuid()
);
if (status === 3) { if (status === 3) {
initStore(); initStore();
return; return;
} }
const IMToken = uni.getStorageSync("IMToken"); const IMToken = uni.getStorageSync("IMToken");
const IMUserID = uni.getStorageSync("IMUserID"); const IMUserID = uni.getStorageSync("IMUserID")+'';
if (IMToken && IMUserID) { if (IMToken && IMUserID) {
IMSDK.asyncApi(IMSDK.IMMethods.Login, IMSDK.uuid(), { IMSDK.asyncApi(IMSDK.IMMethods.Login, IMSDK.uuid(), {
userID: IMUserID, userID: IMUserID,
@@ -494,6 +403,20 @@
this.storeCurrentConversation.conversationID this.storeCurrentConversation.conversationID
); );
}, },
// 验证是否升级
checkUpdate() {
let system = uni.getSystemInfoSync()
plus.runtime.getProperty(plus.runtime.appid, function(inf) {
checkUpgrade({version:system.appVersion,platform:system.platform,version_wgt:inf.versionCode}).then(res=>{
let skip_version = uni.getStorageSync('skip_version')
if(res && res.version!=skip_version){
uni.$emit('closeWebview')
this.setShow(this.current, false)
router('/pages/common/upgrade?model=' + JSON.stringify(res), '', 'fade-in')
}
})
})
},
}, },
}; };
</script> </script>
+45 -7
View File
@@ -1,6 +1,9 @@
// 登录 // 登录
export const businessConfig = (params) => export const businessConfig = (params) =>
uni.$u?.http.post("/common/init", JSON.stringify(params)); uni.$u?.http.post("/common/init", JSON.stringify(params));
// 验证是否升级
export const checkUpgrade = (params) =>
uni.$u?.http.post("/common/checkUpgrade", JSON.stringify(params));
export const businessLogin = (params) => export const businessLogin = (params) =>
uni.$u?.http.post("/common/login", JSON.stringify(params)); uni.$u?.http.post("/common/login", JSON.stringify(params));
export const businessSendSms = (params) => export const businessSendSms = (params) =>
@@ -28,9 +31,8 @@ export const businessModify = (params) =>
export const businessInfoUpdate = (params) => export const businessInfoUpdate = (params) =>
uni.$u?.http.post( uni.$u?.http.post(
"/user/profile", "/user/profile",
JSON.stringify({ JSON.stringify({ ...params, }),
...params, {
}), {
header: { header: {
token: uni.getStorageSync("BusinessToken"), token: uni.getStorageSync("BusinessToken"),
}, },
@@ -39,9 +41,8 @@ export const businessInfoUpdate = (params) =>
export const businessGetUserInfo = (userID) => export const businessGetUserInfo = (userID) =>
uni.$u?.http.post( uni.$u?.http.post(
"/user/find", "/user/find",
JSON.stringify({ JSON.stringify({ userIDs: [userID], }),
userIDs: [userID], {
}), {
header: { header: {
token: uni.getStorageSync("BusinessToken"), token: uni.getStorageSync("BusinessToken"),
}, },
@@ -76,4 +77,41 @@ export const businessSearchUser = (keyword,searchtype) =>
token: uni.getStorageSync("BusinessToken"), token: uni.getStorageSync("BusinessToken"),
}, },
} }
); );
export const getArticle = (id,type) =>
uni.$u?.http.post(
"/article/detail",
JSON.stringify({
id,
type:(type? type : 'id')
}), {
header: {
token: uni.getStorageSync("BusinessToken"),
},
}
);
export const getFriendCircle = (page=1,limit=10) =>{
uni.$u?.http.get(
"/friend_circle/list",
JSON.stringify({
limit:limit,
page:page
}),
{
header: {
token: uni.getStorageSync("BusinessToken"),
},
}
);
}
export const getFriendCircleNewcount = () =>{
uni.$u?.http.get(
"/friend_circle/newcount",
JSON.stringify({}),
{
header: {
token: uni.getStorageSync("BusinessToken"),
},
}
);
}
+1 -1
View File
@@ -7,7 +7,7 @@ const BASE_DOMAIN = 'www.axzc.xyz'
// const CHAT_URL = `https://${BASE_DOMAIN}/chat` // const CHAT_URL = `https://${BASE_DOMAIN}/chat`
// const API_URL = `https://${BASE_DOMAIN}/api` // const API_URL = `https://${BASE_DOMAIN}/api`
// const WS_URL = `wss://${BASE_DOMAIN}/msg_gateway` // const WS_URL = `wss://${BASE_DOMAIN}/msg_gateway`
const CHAT_URL = `http://${BASE_DOMAIN}:8585/api` const CHAT_URL = `http://${BASE_DOMAIN}/api`
const API_URL = `http://${BASE_DOMAIN}/imapi` const API_URL = `http://${BASE_DOMAIN}/imapi`
const WS_URL = `ws://${BASE_DOMAIN}/ws` const WS_URL = `ws://${BASE_DOMAIN}/ws`
+45 -49
View File
@@ -1,59 +1,55 @@
<template> <template>
<view class="selected_item"> <view class="selected_item">
<view class="left_info"> <view class="left_info">
<my-avatar <my-avatar :src="source.faceURL" :desc="source.nickname || source.showName"
:src="source.faceURL" :isGroup="Boolean(source.groupID)" size="42" />
:desc="source.nickname || source.showName" <text>{{ source.nickname || source.groupName || source.showName }}</text>
:isGroup="Boolean(source.groupID)" </view>
size="42" <view>
/> <u-button @click="action" plain text="移除" type="primary" />
<text>{{ source.nickname || source.groupName || source.showName }}</text> </view>
</view> </view>
<view>
<u-button @click="action" plain text="移除" type="primary" />
</view>
</view>
</template> </template>
<script> <script>
import MyAvatar from "@/components/MyAvatar/index.vue"; import MyAvatar from "@/components/MyAvatar/index.vue";
export default { export default {
name: "", name: "",
components: { components: {
MyAvatar, MyAvatar,
}, },
props: { props: {
source: Object, source: Object,
}, },
data() { data() {
return {}; return {};
}, },
methods: { methods: {
action() { action() {
this.$emit("removeItem"); this.$emit("removeItem");
}, },
}, },
mounted() { mounted() {
console.log(this.source); console.log(this.source);
}, },
}; };
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.selected_item { .selected_item {
@include btwBox(); @include btwBox();
padding: 20rpx 0; padding: 20rpx 0;
.left_info { .left_info {
@include vCenterBox(); @include vCenterBox();
.u-avatar { .u-avatar {
margin-right: 24rpx; margin-right: 24rpx;
} }
} }
.u-button { .u-button {
height: 48rpx; height: 48rpx;
} }
} }
</style> </style>
+114 -127
View File
@@ -1,143 +1,130 @@
<template> <template>
<view class="member_checked_desc"> <view class="member_checked_desc">
<view @click="showSelected = true" class="left_info"> <view @click="showSelected = true" class="left_info">
<view class="select_num"> <view class="select_num">
<text class="text">{{ `已选择(${choosedData.length})` }}</text> <text class="text">{{ `已选择(${choosedData.length})` }}</text>
<u-icon name="arrow-up" size="14" color="#007aff" /> <u-icon name="arrow-up" size="14" color="#007aff" />
</view> </view>
<view class="select_list">{{ selectedStr }}</view> <view class="select_list">{{ selectedStr }}</view>
</view> </view>
<view class=""> <view class="">
<u-button <u-button :loading="comfirmLoading" @click="clickComfirm" :disabled="choosedData.length === 0"
:loading="comfirmLoading" type="primary"
@click="clickComfirm" :text="isRemove? '移除': `确定(${choosedData.length}${maxLength > 0 ? `/${maxLength}` : ``})`" />
:disabled="choosedData.length === 0" <u-popup round="24" :show="showSelected" mode="bottom" @close="close">
type="primary" <view class="selected_container">
:text=" <view class="top_desc">
isRemove <text>{{ `已选择(${choosedData.length})` }}</text>
? '移除' <text @click="close" class="comfirm_text">确认</text>
: `确定(${choosedData.length}${ </view>
maxLength > 0 ? `/${maxLength}` : `` <u-list class="selected_list">
})` <u-list-item v-for="item in choosedData" :key="item.userID || item.groupID">
" <selected-member @removeItem="removeItem(item)" :source="item" />
/> </u-list-item>
<u-popup round="24" :show="showSelected" mode="bottom" @close="close"> </u-list>
<view class="selected_container"> </view>
<view class="top_desc"> </u-popup>
<text>{{ `已选择(${choosedData.length})` }}</text> </view>
<text @click="close" class="comfirm_text">确认</text> </view>
</view>
<u-list class="selected_list">
<u-list-item
v-for="item in choosedData"
:key="item.userID || item.groupID"
>
<selected-member @removeItem="removeItem(item)" :source="item" />
</u-list-item>
</u-list>
</view>
</u-popup>
</view>
</view>
</template> </template>
<script> <script>
import SelectedMember from "./SelectedMember.vue"; import SelectedMember from "./SelectedMember.vue";
export default { export default {
name: "ChooseIndexFooter", name: "ChooseIndexFooter",
components: { components: {
SelectedMember, SelectedMember,
}, },
props: { props: {
isRemove: Boolean, isRemove: Boolean,
choosedData: Array, choosedData: Array,
comfirmLoading: Boolean, comfirmLoading: Boolean,
maxLength: Number, maxLength: Number,
}, },
data() { data() {
return { return {
showSelected: false, showSelected: false,
showConfirmModal: false, showConfirmModal: false,
}; };
}, },
computed: { computed: {
selectedStr() { selectedStr() {
return this.choosedData return this.choosedData
.map((item) => item.nickname || item.showName || item.groupName) .map((item) => item.nickname || item.showName || item.groupName)
.join("、"); .join("、");
}, },
}, },
methods: { methods: {
close() { close() {
this.showSelected = false; this.showSelected = false;
}, },
removeItem(item) { removeItem(item) {
this.$emit("removeItem", item); this.$emit("removeItem", item);
}, },
clickComfirm() { clickComfirm() {
this.$emit("confirm"); this.$emit("confirm");
}, },
}, },
}; };
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.member_checked_desc { .member_checked_desc {
@include btwBox(); @include btwBox();
background-color: #fff; background-color: #fff;
align-items: flex-start; align-items: flex-start;
padding: 24rpx 44rpx 0; padding: 24rpx 44rpx 0;
height: 60px; height: 60px;
max-height: 60px; max-height: 60px;
box-shadow: 0px -1px 4px 1px rgba(0, 0, 0, 0.04); box-shadow: 0px -1px 4px 1px rgba(0, 0, 0, 0.04);
.left_info { .left_info {
@include colBox(false); @include colBox(false);
.select_num { .select_num {
display: flex; display: flex;
align-items: center; align-items: center;
color: $uni-color-primary; color: $uni-color-primary;
} }
.select_list { .select_list {
font-size: 24rpx; font-size: 24rpx;
color: #8e9ab0; color: #8e9ab0;
overflow: hidden; overflow: hidden;
white-space: nowrap; white-space: nowrap;
text-overflow: ellipsis; text-overflow: ellipsis;
max-width: 50vw; max-width: 50vw;
} }
.text { .text {
font-size: 30rpx; font-size: 30rpx;
margin-right: 24rpx; margin-right: 24rpx;
} }
} }
.u-button { .u-button {
background-color: #0089ff; background-color: #0089ff;
height: 40px; height: 40px;
margin: 0; margin: 0;
} }
} }
.selected_container { .selected_container {
padding: 44rpx; padding: 44rpx;
.top_desc { .top_desc {
@include btwBox(); @include btwBox();
margin-bottom: 20rpx; margin-bottom: 20rpx;
.comfirm_text { .comfirm_text {
color: $uni-color-primary; color: $uni-color-primary;
margin-right: 24rpx; margin-right: 24rpx;
} }
} }
.selected_list { .selected_list {
height: 60vh !important; height: 60vh !important;
overflow-y: auto; overflow-y: auto;
} }
} }
</style> </style>
+69 -83
View File
@@ -1,91 +1,77 @@
<template> <template>
<u-index-list <u-index-list @scrolltolower="scrolltolower" class="user_list" :style="{ height: height }" :index-list="indexList">
@scrolltolower="scrolltolower" <template v-for="(item, index) in itemArr">
class="user_list" <u-index-item :key="index">
:style="{ height: height }" <u-index-anchor class="user_anchor" :text="indexList[index]"></u-index-anchor>
:index-list="indexList" <user-item @itemClick="itemClick" @updateCheck="updateCheck"
> :checked="checkedIDList.includes(cell.userID)" :disabled="disabledIDList.includes(cell.userID)"
<template v-for="(item, index) in itemArr"> :checkVisible="showCheck" v-for="cell in item" :item="cell" :key="cell.userID" />
<u-index-item :key="index"> </u-index-item>
<u-index-anchor </template>
class="user_anchor" </u-index-list>
:text="indexList[index]"
></u-index-anchor>
<user-item
@itemClick="itemClick"
@updateCheck="updateCheck"
:checked="checkedIDList.includes(cell.userID)"
:disabled="disabledIDList.includes(cell.userID)"
:checkVisible="showCheck"
v-for="cell in item"
:item="cell"
:key="cell.userID"
/>
</u-index-item>
</template>
</u-index-list>
</template> </template>
<script> <script>
import UserItem from "../UserItem/index.vue"; import UserItem from "../UserItem/index.vue";
export default { export default {
name: "ChooseIndexList", name: "ChooseIndexList",
components: { components: {
UserItem, UserItem,
}, },
props: { props: {
height: { height: {
type: String, type: String,
default: "0px", default: "0px",
}, },
indexList: { indexList: {
type: Array, type: Array,
default: () => [], default: () => [],
}, },
itemArr: { itemArr: {
type: Array, type: Array,
default: () => [], default: () => [],
}, },
checkedIDList: { checkedIDList: {
type: Array, type: Array,
default: () => [], default: () => [],
}, },
disabledIDList: { disabledIDList: {
type: Array, type: Array,
default: () => [], default: () => [],
}, },
showCheck: { showCheck: {
type: Boolean, type: Boolean,
default: false, default: false,
}, },
}, },
data() { data() {
return {}; return {};
}, },
methods: { methods: {
itemClick(item) { itemClick(item) {
this.$emit("itemClick", item); this.$emit("itemClick", item);
}, },
updateCheck(item) { updateCheck(item) {
this.$emit("updateCheck", item); this.$emit("updateCheck", item);
}, },
scrolltolower() { scrolltolower() {
this.$emit("scrolltolower"); this.$emit("scrolltolower");
}, },
}, },
}; };
</script> </script>
<style scoped lang="scss"> <style scoped lang="scss">
.user_list { .user_list {
flex: 1; flex: 1;
::v-deep uni-scroll-view {
max-height: 100% !important;
}
}
.user_anchor { ::v-deep uni-scroll-view {
background-color: #f8f8f8 !important; max-height: 100% !important;
border: none !important; }
} }
</style>
.user_anchor {
background-color: #f8f8f8 !important;
border: none !important;
}
</style>
+27 -23
View File
@@ -1,42 +1,46 @@
export const ChatingFooterActionTypes = { export const ChatingFooterActionTypes = {
Album: "Album", Album: "Album",
Camera: "Camera",
Video: "Video",
Voice: "Voice",
Location: "Location",
}; };
export const ContactMenuTypes = { export const ContactMenuTypes = {
NewFriend: "NewFriend", NewFriend: "NewFriend",
NewGroup: "NewGroup", NewGroup: "NewGroup",
MyFriend: "MyFriend", MyFriend: "MyFriend",
MyGroup: "MyGroup", MyGroup: "MyGroup",
}; };
export const GroupMemberListTypes = { export const GroupMemberListTypes = {
Preview: "Preview", Preview: "Preview",
Transfer: "Transfer", Transfer: "Transfer",
Kickout: "Kickout", Kickout: "Kickout",
}; };
export const ContactChooseTypes = { export const ContactChooseTypes = {
Invite: "Invite", Invite: "Invite",
GetList: "GetList", GetList: "GetList",
}; };
export const UpdateMessageTypes = { export const UpdateMessageTypes = {
Overall: "Overall", Overall: "Overall",
KeyWords: "KeyWords", KeyWords: "KeyWords",
}; };
export const SmsUserFor = { export const SmsUserFor = {
Register: 1, Register: 1,
Reset: 2, Reset: 2,
Login: 3, Login: 3,
}; };
export const CustomMessageStatus = { export const CustomMessageStatus = {
Success: "success", Success: "success",
Cancel: "cancel", Cancel: "cancel",
Canceled: "canceled", Canceled: "canceled",
Refuse: "refuse", Refuse: "refuse",
Refused: "refused", Refused: "refused",
Timeout: "timeout", Timeout: "timeout",
AccessByOther: "accessByOther", AccessByOther: "accessByOther",
}; };
+4 -4
View File
@@ -1,5 +1,5 @@
export const PageEvents = { export const PageEvents = {
GlobalToast: "GlobalToast", GlobalToast: "GlobalToast",
ScrollToBottom: "ScrollToBottom", ScrollToBottom: "ScrollToBottom",
RtcCall: "RtcCall" RtcCall: "RtcCall"
}; };
+40 -40
View File
@@ -1,51 +1,51 @@
import { MessageType } from "openim-uniapp-polyfill"; import {MessageType} from "openim-uniapp-polyfill";
export const CustomType = { export const CustomType = {
VideoCall: "c100", VideoCall: "c100",
VoiceCall: "c101", VoiceCall: "c101",
Call: 901, Call: 901,
MassMsg: 903, MassMsg: 903,
}; };
export const Platform = { export const Platform = {
1: 'iOS', 1: 'iOS',
2: 'Android', 2: 'Android',
3: 'PC', 3: 'PC',
4: 'PC', 4: 'PC',
5: 'Web' 5: 'Web'
}; };
export const noticeMessageTypes = [ export const noticeMessageTypes = [
MessageType.RevokeMessage, MessageType.RevokeMessage,
MessageType.FriendAdded, MessageType.FriendAdded,
MessageType.GroupCreated, MessageType.GroupCreated,
MessageType.GroupInfoUpdated, MessageType.GroupInfoUpdated,
MessageType.MemberQuit, MessageType.MemberQuit,
MessageType.GroupOwnerTransferred, MessageType.GroupOwnerTransferred,
MessageType.MemberKicked, MessageType.MemberKicked,
MessageType.MemberInvited, MessageType.MemberInvited,
MessageType.MemberEnter, MessageType.MemberEnter,
MessageType.GroupDismissed, MessageType.GroupDismissed,
MessageType.GroupMemberMuted, MessageType.GroupMemberMuted,
MessageType.GroupMuted, MessageType.GroupMuted,
MessageType.GroupCancelMuted, MessageType.GroupCancelMuted,
MessageType.GroupMemberCancelMuted, MessageType.GroupMemberCancelMuted,
MessageType.GroupNameUpdated, MessageType.GroupNameUpdated,
MessageType.BurnMessageChange, MessageType.BurnMessageChange,
]; ];
export const GroupSystemMessageTypes = [ export const GroupSystemMessageTypes = [
MessageType.GroupCreated, MessageType.GroupCreated,
MessageType.GroupInfoUpdated, MessageType.GroupInfoUpdated,
MessageType.MemberQuit, MessageType.MemberQuit,
MessageType.GroupOwnerTransferred, MessageType.GroupOwnerTransferred,
MessageType.MemberKicked, MessageType.MemberKicked,
MessageType.MemberInvited, MessageType.MemberInvited,
MessageType.MemberEnter, MessageType.MemberEnter,
MessageType.GroupDismissed, MessageType.GroupDismissed,
MessageType.GroupMemberMuted, MessageType.GroupMemberMuted,
MessageType.GroupMuted, MessageType.GroupMuted,
MessageType.GroupCancelMuted, MessageType.GroupCancelMuted,
MessageType.GroupMemberCancelMuted, MessageType.GroupMemberCancelMuted,
MessageType.GroupNameUpdated MessageType.GroupNameUpdated
]; ];
+17 -4
View File
@@ -1,5 +1,5 @@
{ {
"name" : "IM-UCB", "name" : "探探",
"appid" : "__UNI__F0A946D", "appid" : "__UNI__F0A946D",
"description" : "", "description" : "",
"versionName" : "3.3.4", "versionName" : "3.3.4",
@@ -21,7 +21,10 @@
"Camera" : {}, "Camera" : {},
"Record" : {}, "Record" : {},
"Geolocation" : {}, "Geolocation" : {},
"Maps" : {} "Maps" : {},
"Fingerprint" : {},
"Contacts" : {},
"Barcode" : {}
}, },
"distribute" : { "distribute" : {
"android" : { "android" : {
@@ -66,8 +69,18 @@
}, },
"sdkConfigs" : { "sdkConfigs" : {
"ad" : {}, "ad" : {},
"geolocation" : {}, "geolocation" : {
"maps" : {}, "system" : {
"__platform__" : [ "ios", "android" ]
}
},
"maps" : {
"amap" : {
"name" : "amap_18926034082bYRO97pz",
"appkey_ios" : "cfc7b531b60382598b4aac7944415fba",
"appkey_android" : "e431515e99e69fc1b6edb674e3487f1a"
}
},
"share" : {}, "share" : {},
"statics" : {}, "statics" : {},
"speech" : {} "speech" : {}
+2 -1
View File
@@ -1,11 +1,12 @@
{ {
"dependencies": { "dependencies": {
"@openim/client-sdk": "^0.0.11-ahpha.1",
"date-fns": "^2.30.0", "date-fns": "^2.30.0",
"dayjs": "^1.11.6", "dayjs": "^1.11.6",
"image-tools": "^1.4.0", "image-tools": "^1.4.0",
"md5": "^2.3.0", "md5": "^2.3.0",
"@openim/client-sdk": "^0.0.11-ahpha.1",
"openim-uniapp-polyfill": "^1.4.1", "openim-uniapp-polyfill": "^1.4.1",
"qrcode": "^1.5.4",
"uuid": "^9.0.0" "uuid": "^9.0.0"
} }
} }
+38 -14
View File
@@ -245,37 +245,61 @@
"navigationBarTitleText": "", "navigationBarTitleText": "",
"enablePullDownRefresh": false "enablePullDownRefresh": false
} }
},
{
"path": "pages/common/upgrade",
"style": {
"navigationBarTitleText": ""
}
},
{
"path": "pages/common/article",
"style": {
"navigationBarTitleText": ""
}
},
{
"path": "pages/common/webview",
"style": {
"navigationBarTitleText": ""
}
},
{
"path": "pages/workbench/friend-circle/friend-circle",
"style": {
"navigationBarTitleText": ""
}
} }
], ],
"tabBar": { "tabBar": {
"color": "#8E9AB0", "color": "#171717",
"selectedColor": "#0089FF", "selectedColor": "#07c160",
"borderStyle": "black", "borderStyle": "#f4f4f4",
"backgroundColor": "#ffffff", "backgroundColor": "#f4f4f4",
"height": "55px", "height": "55px",
"list": [{ "list": [{
"pagePath": "pages/conversation/conversationList/index", "pagePath": "pages/conversation/conversationList/index",
"iconPath": "./static/images/tabbar_conversation.png", "iconPath": "./static/images/tabbar/conversation.png",
"selectedIconPath": "static/images/tabbar_conversation_active.png", "selectedIconPath": "static/images/tabbar/conversation_active.png",
"text": "OpenIM" "text": "消息"
}, },
{ {
"pagePath": "pages/contact/index/index", "pagePath": "pages/contact/index/index",
"iconPath": "./static/images/tabbar_contacts.png", "iconPath": "./static/images/tabbar/contacts.png",
"selectedIconPath": "static/images/tabbar_contacts_active.png", "selectedIconPath": "static/images/tabbar/contacts_active.png",
"text": "通讯录" "text": "通讯录"
}, },
{ {
"pagePath": "pages/workbench/index/index", "pagePath": "pages/workbench/index/index",
"iconPath": "./static/images/tabbar_workbench.png", "iconPath": "./static/images/tabbar/workbench.png",
"selectedIconPath": "static/images/tabbar_workbench_active.png", "selectedIconPath": "static/images/tabbar/workbench_active.png",
"text": "发现" "text": "发现"
}, },
{ {
"pagePath": "pages/profile/index/index", "pagePath": "pages/profile/index/index",
"iconPath": "./static/images/tabbar_profile.png", "iconPath": "./static/images/tabbar/profile.png",
"selectedIconPath": "static/images/tabbar_profile_active.png", "selectedIconPath": "static/images/tabbar/profile_active.png",
"text": "我" "text": "我"
} }
] ]
}, },
+61
View File
@@ -0,0 +1,61 @@
<template>
<view class="n-ps-all-base">
<uv-parse v-if="content" :content="content"></uv-parse>
<view class="n-flex-row" v-if="showButton" :style="{marginTop:'100rpx'}">
<uv-button class="n-flex-1 n-ms-base" v-for="(item, idx) in buttonList" :key="idx" @click="switchButton(idx, item)" :text="item.title" :icon="'/static/image/' + item.value + '.png'" :plain="current==idx" :color="current==idx ? item.color:'#f8f8f8'" :customStyle="{height:'80rpx'}" :customTextStyle="{color:current==idx ? item.color:'#333333',marginLeft:'20rpx'}" shape="circle" color="#f8f8f8" throttleTime="1000"></uv-button>
</view>
<uv-empty :show="empty" icon="/static/image/empty.png" text="暂无数据~" width="200" marginTop="100"></uv-empty>
</view>
</template>
<script>
import {getArticle} from '@/api/login.js'
export default {
data() {
return {
empty: false,
content: '',
current: null,
questionId: 0,
showButton: false,
buttonList: [
{title:'未解决', value:'unresolved', color:'#fc3463'},
{title:'已解决', value:'resolved', color:'#5ac725'}
]
}
},
onLoad(evt) {
if(evt.type=='config') this.setConfig(evt)
if(evt.type=='question') this.setQuestion(evt)
uni.setNavigationBarTitle({title:evt.title})
},
methods: {
// 设置配置内容
setConfig(evt) {
let config = getApp().globalData.config
if(evt.name && config[evt.name]){
this.content = config[evt.name]
}else{
this.empty = true
}
},
// 设置问题内容
setQuestion(evt) {
this.content = evt.content
this.questionId = evt.id
this.showButton = true
},
// 切换按钮
switchButton(idx, item) {
this.current = idx
getArticle({id:this.questionId,type:item.value})
}
}
}
</script>
<style>
</style>
+242 -256
View File
@@ -1,281 +1,267 @@
<template> <template>
<view class="contact_choose_container"> <view class="contact_choose_container">
<custom-nav-bar title="联系人" /> <custom-nav-bar title="联系人" />
<view class="search_bar_wrap"> <view class="search_bar_wrap">
<u-search <u-search shape="square" placeholder="搜索" :showAction="false" v-model="keyword" />
shape="square" </view>
placeholder="搜索"
:showAction="false"
v-model="keyword"
/>
</view>
<view class="tab_container"> <view class="tab_container">
<template v-if="activeTab === 0"> <template v-if="activeTab === 0">
<setting-item <setting-item @click="tabChange(tabs[0].idx)" :title="tabs[0].title" :border="false" />
@click="tabChange(tabs[0].idx)"
:title="tabs[0].title"
:border="false"
/>
<view class="tab_pane"></view> <view class="tab_pane"></view>
</template> </template>
<template v-else> <template v-else>
<view class="tab_pane" v-show="activeTab === 1"> <view class="tab_pane" v-show="activeTab === 1">
<choose-index-list <choose-index-list @updateCheck="updateCheckedUser" :indexList="getChooseData.indexList"
@updateCheck="updateCheckedUser" :itemArr="getChooseData.dataList" :checkedIDList="checkedUserIDList"
:indexList="getChooseData.indexList" :disabledIDList="disabledUserIDList" :showCheck="true" />
:itemArr="getChooseData.dataList" </view>
:checkedIDList="checkedUserIDList" </template>
:disabledIDList="disabledUserIDList" </view>
:showCheck="true" <choose-index-footer :comfirmLoading="comfirmLoading" @removeItem="updateCheckedUserOrGroup" @confirm="confirm"
/> :choosedData="getCheckedInfo" />
</view> </view>
</template>
</view>
<choose-index-footer
:comfirmLoading="comfirmLoading"
@removeItem="updateCheckedUserOrGroup"
@confirm="confirm"
:choosedData="getCheckedInfo"
/>
</view>
</template> </template>
<script> <script>
import { mapGetters } from "vuex"; import {mapGetters} from "vuex";
import { ContactChooseTypes } from "@/constant"; import {ContactChooseTypes} from "@/constant";
import { formatChooseData, toastWithCallback } from "@/util/common"; import {formatChooseData,toastWithCallback} from "@/util/common";
import IMSDK from "openim-uniapp-polyfill"; import IMSDK from "openim-uniapp-polyfill";
import CustomNavBar from "@/components/CustomNavBar/index.vue"; import CustomNavBar from "@/components/CustomNavBar/index.vue";
import UserItem from "@/components/UserItem/index.vue"; import UserItem from "@/components/UserItem/index.vue";
import ChooseIndexList from "@/components/ChooseIndexList/index.vue"; import ChooseIndexList from "@/components/ChooseIndexList/index.vue";
import ChooseIndexFooter from "@/components/ChooseIndexFooter/index.vue"; import ChooseIndexFooter from "@/components/ChooseIndexFooter/index.vue";
import SettingItem from "@/components/SettingItem/index.vue"; import SettingItem from "@/components/SettingItem/index.vue";
export default { export default {
components: { components: {
CustomNavBar, CustomNavBar,
UserItem, UserItem,
ChooseIndexList, ChooseIndexList,
ChooseIndexFooter, ChooseIndexFooter,
SettingItem, SettingItem,
}, },
data() { data() {
return { return {
keyword: "", keyword: "",
type: ContactChooseTypes.Card, type: ContactChooseTypes.Card,
activeTab: 0, activeTab: 0,
groupID: "", groupID: "",
checkedUserIDList: [], checkedUserIDList: [],
disabledUserIDList: [], disabledUserIDList: [],
comfirmLoading: false, comfirmLoading: false,
tabs: [ tabs: [
{ {
idx: 1, idx: 1,
title: "我的好友", title: "我的好友",
}, },
], ],
}; };
}, },
computed: { computed: {
...mapGetters([ ...mapGetters([
"storeFriendList", "storeFriendList",
"storeCurrentConversation", "storeCurrentConversation",
"storeCurrentUserID", "storeCurrentUserID",
"storeConversationList", "storeConversationList",
]), ]),
getChooseData() { getChooseData() {
if (this.keyword) { if (this.keyword) {
return { return {
indexList: ["#"], indexList: ["#"],
dataList: [ dataList: [
this.storeFriendList.filter( this.storeFriendList.filter(
(friend) => (friend) =>
friend.nickname.includes(this.keyword) || friend.nickname.includes(this.keyword) ||
friend.remark.includes(this.keyword) friend.remark.includes(this.keyword)
), ),
], ],
}; };
} }
return formatChooseData(this.storeFriendList); return formatChooseData(this.storeFriendList);
}, },
getCheckedInfo() { getCheckedInfo() {
const tmpUserIDList = [...this.checkedUserIDList]; const tmpUserIDList = [...this.checkedUserIDList];
const checkedFriends = this.storeFriendList.filter((friend) => { const checkedFriends = this.storeFriendList.filter((friend) => {
const idx = tmpUserIDList.findIndex( const idx = tmpUserIDList.findIndex(
(userID) => userID === friend.userID (userID) => userID === friend.userID
); );
if (idx > -1) { if (idx > -1) {
tmpUserIDList.splice(idx, 1); tmpUserIDList.splice(idx, 1);
} }
return idx > -1; return idx > -1;
}); });
return [...checkedFriends]; return [...checkedFriends];
}, },
}, },
onLoad(options) { onLoad(options) {
const { const {groupID,type,checkedUserIDList,} = options;
groupID, console.log(this.storeFriendList);
type, this.type = type;
checkedUserIDList, this.groupID = groupID;
} = options; this.checkedUserIDList = checkedUserIDList ?
this.type = type; JSON.parse(checkedUserIDList) :
this.groupID = groupID; [];
this.checkedUserIDList = checkedUserIDList if (this.type === ContactChooseTypes.Invite) {
? JSON.parse(checkedUserIDList) this.checkDisabledUser();
: []; }
if (this.type === ContactChooseTypes.Invite) { },
this.checkDisabledUser(); methods: {
} checkDisabledUser() {
}, const friendIDList = this.storeFriendList.map((friend) => friend.userID);
methods: { IMSDK.asyncApi("getUsersInGroup", IMSDK.uuid(), {
checkDisabledUser() { groupID: this.groupID,
const friendIDList = this.storeFriendList.map((friend) => friend.userID); userIDList: friendIDList,
IMSDK.asyncApi("getUsersInGroup", IMSDK.uuid(), { }).then(({
groupID: this.groupID, data
userIDList: friendIDList, }) => {
}).then(({ data }) => { this.disabledUserIDList = data;
this.disabledUserIDList = data; });
}); },
}, tabChange(idx) {
tabChange(idx) { this.keyword = "";
this.keyword = ""; this.activeTab = idx;
this.activeTab = idx; },
}, updateCheckedUserOrGroup(item) {
updateCheckedUserOrGroup(item) { if (item.userID) {
if (item.userID) { this.updateCheckedUser(item);
this.updateCheckedUser(item); }
} },
}, updateCheckedUser({
updateCheckedUser({ userID }) { userID
if (this.checkedUserIDList.includes(userID)) { }) {
const idx = this.checkedUserIDList.findIndex((item) => item === userID); if (this.checkedUserIDList.includes(userID)) {
const tmpArr = [...this.checkedUserIDList]; const idx = this.checkedUserIDList.findIndex((item) => item === userID);
tmpArr.splice(idx, 1); const tmpArr = [...this.checkedUserIDList];
this.checkedUserIDList = [...tmpArr]; tmpArr.splice(idx, 1);
} else { this.checkedUserIDList = [...tmpArr];
this.checkedUserIDList = [...this.checkedUserIDList, userID]; } else {
} this.checkedUserIDList = [...this.checkedUserIDList, userID];
}, }
confirm() { },
if (this.activeTab) { confirm() {
this.activeTab = 0; if (this.activeTab) {
return; this.activeTab = 0;
} return;
this.comfirmLoading = true; }
if (this.type === ContactChooseTypes.GetList) { this.comfirmLoading = true;
let pages = getCurrentPages(); if (this.type === ContactChooseTypes.GetList) {
let prevPage = pages[pages.length - 2]; let pages = getCurrentPages();
prevPage.$vm.getCheckedUsers(this.getCheckedInfo); let prevPage = pages[pages.length - 2];
this.comfirmLoading = false; prevPage.$vm.getCheckedUsers(this.getCheckedInfo);
this.comfirmLoading = false;
uni.navigateBack({ uni.navigateBack({
delta: 1, delta: 1,
}); });
return; return;
} }
if (this.type === ContactChooseTypes.Invite) { if (this.type === ContactChooseTypes.Invite) {
IMSDK.asyncApi(IMSDK.IMMethods.InviteUserToGroup, IMSDK.uuid(), { IMSDK.asyncApi(IMSDK.IMMethods.InviteUserToGroup, IMSDK.uuid(), {
groupID: this.groupID, groupID: this.groupID,
reason: "", reason: "",
userIDList: this.getCheckedInfo.map((user) => user.userID), userIDList: this.getCheckedInfo.map((user) => user.userID),
}) })
.then(() => { .then(() => {
toastWithCallback("操作成功", () => uni.navigateBack()); toastWithCallback("操作成功", () => uni.navigateBack());
this.comfirmLoading = false; this.comfirmLoading = false;
}) })
.catch(() => toastWithCallback("操作失败")); .catch(() => toastWithCallback("操作失败"));
return; return;
} }
this.comfirmLoading = false; this.comfirmLoading = false;
}, },
}, },
onBackPress() { onBackPress() {
if (this.activeTab) { if (this.activeTab) {
this.activeTab = 0; this.activeTab = 0;
return true; return true;
} }
return false; return false;
}, },
}; };
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
::v-deep.u-popup { ::v-deep.u-popup {
flex: none; flex: none;
} }
.contact_choose_container {
height: 100vh;
display: flex;
flex-direction: column;
.search_bar_wrap {
height: 34px;
padding: 12px 22px;
}
.tab_container { .contact_choose_container {
@include colBox(false); height: 100vh;
flex: 1; display: flex;
overflow: hidden; flex-direction: column;
.setting_item { .search_bar_wrap {
padding: 32rpx 36rpx; height: 34px;
} padding: 12px 22px;
}
.title { .tab_container {
height: 60rpx; @include colBox(false);
display: flex; flex: 1;
justify-content: start; overflow: hidden;
align-items: center;
// padding: 16rpx 8rpx;
background: #f8f9fa;
color: #8e9ab0;
font-size: 24rpx;
}
.tabs_bar { .setting_item {
@include vCenterBox(); padding: 32rpx 36rpx;
justify-content: space-evenly; }
.tab_item { .title {
@include colBox(false); height: 60rpx;
align-items: center; display: flex;
justify-content: start;
align-items: center;
// padding: 16rpx 8rpx;
background: #f8f9fa;
color: #8e9ab0;
font-size: 24rpx;
}
image { .tabs_bar {
width: 50px; @include vCenterBox();
height: 50px; justify-content: space-evenly;
}
}
}
.tab_pane { .tab_item {
display: flex; @include colBox(false);
flex-direction: column; align-items: center;
flex: 1;
overflow: hidden;
.member_list { image {
flex: 1; width: 50px;
height: 80% !important; height: 50px;
::v-deepuni-scroll-view { }
max-height: 100% !important; }
} }
}
.user_list { .tab_pane {
height: 100% !important; display: flex;
} flex-direction: column;
flex: 1;
overflow: hidden;
.member_anchor { .member_list {
background-color: #f8f8f8 !important; flex: 1;
border: none !important; height: 80% !important;
}
} ::v-deepuni-scroll-view {
} max-height: 100% !important;
} }
</style> }
.user_list {
height: 100% !important;
}
.member_anchor {
background-color: #f8f8f8 !important;
border: none !important;
}
}
}
}
</style>
+4 -2
View File
@@ -86,6 +86,7 @@
); );
info = data[0]; info = data[0];
} }
console.log(info)
if (info) { if (info) {
uni.navigateTo({ uni.navigateTo({
url: `/pages/common/groupCard/index?sourceInfo=${JSON.stringify(info,)}`, url: `/pages/common/groupCard/index?sourceInfo=${JSON.stringify(info,)}`,
@@ -103,7 +104,7 @@
const {data} = await IMSDK.asyncApi( const {data} = await IMSDK.asyncApi(
IMSDK.IMMethods.GetUsersInfo, IMSDK.IMMethods.GetUsersInfo,
IMSDK.uuid(), IMSDK.uuid(),
[res.data[0].id], [res.data[0].id+''],
); );
const imData = data[0]; const imData = data[0];
@@ -111,9 +112,9 @@
...imData, ...imData,
...res.data[0], ...res.data[0],
}; };
console.log(info)
} }
} }
console.log(info)
if (info) { if (info) {
uni.navigateTo({ uni.navigateTo({
url: `/pages/common/userCard/index?sourceInfo=${JSON.stringify(info,)}`, url: `/pages/common/userCard/index?sourceInfo=${JSON.stringify(info,)}`,
@@ -123,6 +124,7 @@
} }
} }
} catch (e) { } catch (e) {
console.log(e);
//TODO handle the exception //TODO handle the exception
} }
this.searching = false; this.searching = false;
+103 -111
View File
@@ -1,125 +1,117 @@
<template> <template>
<view class="request_join_container"> <view class="request_join_container">
<custom-nav-bar :title="isGroup ? '群聊验证' : '好友验证'"> <custom-nav-bar :title="isGroup ? '群聊验证' : '好友验证'">
<view class="top_right_btn" slot="more"> <view class="top_right_btn" slot="more">
<u-button @click="sendRequest" text="发送" type="primary"></u-button> <u-button @click="sendRequest" text="发送" type="primary"></u-button>
</view> </view>
</custom-nav-bar> </custom-nav-bar>
<text class="title">{{ `发送${isGroup ? "入群" : "好友"}申请` }}</text> <text class="title">{{ `发送${isGroup ? "入群" : "好友"}申请` }}</text>
<view class="input_container"> <view class="input_container">
<u--textarea <u--textarea height="120" v-model="reason" border="none" placeholder="请输入内容" maxlength="20" count>
height="120" </u--textarea>
v-model="reason" </view>
border="none" </view>
placeholder="请输入内容"
maxlength="20"
count
>
</u--textarea>
</view>
</view>
</template> </template>
<script> <script>
import IMSDK, { GroupJoinSource } from "openim-uniapp-polyfill"; import IMSDK, {GroupJoinSource} from "openim-uniapp-polyfill";
import CustomNavBar from "@/components/CustomNavBar/index.vue"; import CustomNavBar from "@/components/CustomNavBar/index.vue";
import { navigateToDesignatedConversation } from "@/util/imCommon"; import {navigateToDesignatedConversation} from "@/util/imCommon";
export default { export default {
components: { components: {
CustomNavBar, CustomNavBar,
}, },
data() { data() {
return { return {
reason: "", reason: "",
sourceID: "", sourceID: "",
isGroup: false, isGroup: false,
isScan: false, isScan: false,
notNeedVerification: false, notNeedVerification: false,
sessionType: 0, sessionType: 0,
}; };
}, },
onLoad(options) { onLoad(options) {
const { isGroup, sourceID, isScan, notNeedVerification, sessionType } = const {isGroup,sourceID,isScan,notNeedVerification,sessionType} = options;
options; this.isGroup = JSON.parse(isGroup);
this.isGroup = JSON.parse(isGroup); this.isScan = JSON.parse(isScan);
this.isScan = JSON.parse(isScan); this.sourceID = sourceID;
this.sourceID = sourceID; this.notNeedVerification = JSON.parse(notNeedVerification);
this.notNeedVerification = JSON.parse(notNeedVerification); this.sessionType = sessionType ?? 0;
this.sessionType = sessionType ?? 0; },
}, methods: {
methods: { sendRequest() {
sendRequest() { let func;
let func; if (this.isGroup) {
if (this.isGroup) { const joinSource = this.isScan ?
const joinSource = this.isScan GroupJoinSource.QrCode :
? GroupJoinSource.QrCode GroupJoinSource.Search;
: GroupJoinSource.Search; func = IMSDK.asyncApi(IMSDK.IMMethods.JoinGroup, IMSDK.uuid(), {
func = IMSDK.asyncApi(IMSDK.IMMethods.JoinGroup, IMSDK.uuid(), { groupID: this.sourceID,
groupID: this.sourceID, reqMsg: this.reason,
reqMsg: this.reason, joinSource,
joinSource, });
}); } else {
} else { func = IMSDK.asyncApi(IMSDK.IMMethods.AddFriend, IMSDK.uuid(), {
func = IMSDK.asyncApi(IMSDK.IMMethods.AddFriend, IMSDK.uuid(), { toUserID: this.sourceID,
toUserID: this.sourceID, reqMsg: this.reason,
reqMsg: this.reason, });
}); }
} func
func .then(() => {
.then(() => { uni.$u.toast(this.notNeedVerification ? "你已加入该群" : "发送成功");
uni.$u.toast(this.notNeedVerification ? "你已加入该群" : "发送成功"); setTimeout(() => {
setTimeout(() => { if (this.notNeedVerification) {
if (this.notNeedVerification) { navigateToDesignatedConversation(
navigateToDesignatedConversation( this.sourceID,
this.sourceID, Number(this.sessionType),
Number(this.sessionType), ).catch(() => this.showToast("获取会话信息失败"));
).catch(() => this.showToast("获取会话信息失败")); } else {
} else { uni.navigateBack();
uni.navigateBack(); }
} }, 1000);
}, 1000); })
}) .catch((err) => {
.catch((err) => { console.log(err);
console.log(err); uni.$u.toast(err.errMsg || "发送失败");
uni.$u.toast("发送失败"); });
}); },
}, showToast(message) {
showToast(message) { this.$refs.uToast.show({
this.$refs.uToast.show({ message,
message, });
}); },
}, },
}, };
};
</script> </script>
<style lang="scss"> <style lang="scss">
.request_join_container { .request_join_container {
@include colBox(false); @include colBox(false);
height: 100vh; height: 100vh;
background-color: #f6f6f6; background-color: #f6f6f6;
.top_right_btn { .top_right_btn {
margin-right: 44rpx; margin-right: 44rpx;
.u-button { .u-button {
height: 48rpx; height: 48rpx;
} }
} }
.title { .title {
font-size: 28rpx; font-size: 28rpx;
color: #999; color: #999;
margin: 24rpx 44rpx; margin: 24rpx 44rpx;
} }
.input_container { .input_container {
::v-deep.u-textarea { ::v-deep.u-textarea {
padding: 24rpx 44rpx !important; padding: 24rpx 44rpx !important;
} }
} }
} }
</style> </style>
+110
View File
@@ -0,0 +1,110 @@
<template>
<view class="m-shade n-flex-1 n-align-center n-justify-center">
<view :style="{width:'580rpx'}">
<image src="/static/image/upgrade.png" mode="widthFix"></image>
<view class="n-ps-all-ll n-ms-top-ll n-position-absolute">
<text class="n-size-mm n-weight-7 n-color-inverse">发现新版本</text>
<text class="n-size-base n-ms-top-ss n-color-inverse">V{{model.version}}</text>
</view>
<view class="n-ps-all-l n-radius-lb-base" :style="{backgroundColor:'#f3f3f3',borderRadius:'0 0 16rpx 16rpx'}">
<view :style="{height:'300rpx'}">
<scroll-view class="n-flex-1" :show-scrollbar="false" scroll-y>
<rich-text class="n-size-s" :nodes="model.content" :style="{lineHeight:'26rpx'}"></rich-text>
</scroll-view>
</view>
<view class="n-height-base n-justify-center">
<view v-if="progress">
<uv-line-progress :percentage="value" activeColor="#fc3463"></uv-line-progress>
</view>
<view class="n-flex-row" v-else>
<uv-button class="n-flex-1 n-ms-right-ll" v-if="model.force==0" @click="cancel" :customStyle="{backgroundColor:'#f3f3f3'}" text="暂不更新" color="#fc3463" shape="circle" throttleTime="1000" plain></uv-button>
<uv-button class="n-flex-1" @click="upgrade" text="立即更新" color="#fc3463" shape="circle" throttleTime="1000"></uv-button>
</view>
</view>
</view>
</view>
</view>
</template>
<script>
export default {
data() {
return {
value: 0,
model: {
force: 1,
version: '1.0.0',
content: ''
},
progress: false,
download: false
}
},
onLoad(evt) {
if(evt.model){
this.model = {...this.model, ...JSON.parse(evt.model)}
}
},
onBackPress() {
if(this.model.force==1){
return true
}
},
methods: {
// 取消更新
cancel() {
uni.navigateBack()
uni.setStorageSync('skip_version', this.model.version)
},
// 立即更新
upgrade(){
// 检测更新方式
if(this.model.type==0 || this.model.type==1){
this.downloadUpdate()
}else{
plus.runtime.openURL(this.model.source_text)
}
},
// 下载更新
downloadUpdate() {
if(!this.download){
this.progress = true
this.download = true
// 下载安装包
const download = uni.downloadFile({
url: this.model.source_text,
success: result=>{
// 自动安装软件
plus.runtime.install(result.tempFilePath, {force:true}, ()=>{
// 防止强制更新无法关闭界面
this.model.force = 0
if(this.model.type==1){
uni.showToast({
title:'更新成功,软件重启'
})
setTimeout(()=>{ plus.runtime.restart() }, 1500)
}
})
},
fail: error=>{
uni.showToast({
title:'下载失败,请检查您的网络情况'
})
}
})
// 监听下载进度
download.onProgressUpdate(result=>{
this.value = result.progress
})
}
}
}
}
</script>
<style>
.m-shade{
background-color: rgba(0, 0, 0, 0.1);
}
</style>
+24 -14
View File
@@ -15,7 +15,11 @@
<u-button type="primary" icon="man-add" text="添加"></u-button> <u-button type="primary" icon="man-add" text="添加"></u-button>
</view> </view>
</view> </view>
<view class="info_row">
<user-info-row-item lable="性别" :content="getGender" />
<user-info-row-item lable="生日" :content="getBirth" />
<user-info-row-item lable="个性签名" :content="sourceUserInfo.bio" />
</view>
<view v-if="isFriend" class="info_row"> <view v-if="isFriend" class="info_row">
<user-info-row-item @click="toMoreInfo" lable="个人资料" arrow /> <user-info-row-item @click="toMoreInfo" lable="个人资料" arrow />
</view> </view>
@@ -31,21 +35,14 @@
</template> </template>
<script> <script>
import { import {mapGetters} from "vuex";
mapGetters import {navigateToDesignatedConversation} from "@/util/imCommon";
} from "vuex"; import IMSDK, {SessionType,} from "openim-uniapp-polyfill";
import {
navigateToDesignatedConversation
} from "@/util/imCommon";
import IMSDK, {
SessionType,
} from "openim-uniapp-polyfill";
import MyAvatar from "@/components/MyAvatar/index.vue"; import MyAvatar from "@/components/MyAvatar/index.vue";
import CustomNavBar from "@/components/CustomNavBar/index.vue"; import CustomNavBar from "@/components/CustomNavBar/index.vue";
import UserInfoRowItem from "./components/UserInfoRowItem.vue"; import UserInfoRowItem from "./components/UserInfoRowItem.vue";
import { import {businessSearchUserInfo} from "@/api/login";
businessSearchUserInfo import dayjs from "dayjs";
} from "@/api/login";
export default { export default {
components: { components: {
@@ -67,6 +64,19 @@
"storeFriendList", "storeFriendList",
"storeSelfInfo", "storeSelfInfo",
]), ]),
getGender() {
if (this.sourceUserInfo.sex === 0) {
return "保密";
}
if (this.sourceUserInfo.sex === 1) {
return "男";
}
return "女";
},
getBirth() {
const birth = this.sourceUserInfo.birthday ?? 0;
return dayjs(birth).format("YYYY-MM-DD");
},
isFriend() { isFriend() {
return ( return (
this.storeFriendList.findIndex( this.storeFriendList.findIndex(
@@ -142,7 +152,7 @@
} = await IMSDK.asyncApi( } = await IMSDK.asyncApi(
IMSDK.IMMethods.GetUsersInfo, IMSDK.IMMethods.GetUsersInfo,
IMSDK.uuid(), IMSDK.uuid(),
[this.sourceID], [this.sourceID+''],
); );
const imData = data[0]?.friendInfo ?? data[0]?.publicInfo ?? {}; const imData = data[0]?.friendInfo ?? data[0]?.publicInfo ?? {};
info = { info = {
+33
View File
@@ -0,0 +1,33 @@
<template>
<web-view :src="linkUrl"></web-view>
</template>
<script>
export default {
data() {
return {
linkUrl: "",
};
},
onShow() {
this.linkUrl = 'https://doc.rentsoft.cn/'
},
onReady() {
// #ifdef APP-PLUS
setTimeout(() => {
this.$scope
.$getAppWebview()
.children()[0]
.setStyle({
top: uni.getWindowInfo().statusBarHeight,
height: uni.getWindowInfo().safeArea.height,
});
});
// #endif
},
};
</script>
<style>
</style>
+60 -60
View File
@@ -1,74 +1,74 @@
<template> <template>
<view class="action_item" @click="onClick"> <view class="action_item" @click="onClick">
<slot name="icon"> <slot name="icon">
<view class="action_icon"> <view class="action_icon">
<image :src="action.icon" mode=""></image> <image :src="action.icon" mode=""></image>
</view> </view>
</slot> </slot>
<view class="action_details"> <view class="action_details">
<text class="title">{{ action.title }}</text> <text class="title">{{ action.title }}</text>
<text class="desc">{{ action.desc }}</text> <text class="desc">{{ action.desc }}</text>
<view class="bottom_line"></view> <view class="bottom_line"></view>
</view> </view>
</view> </view>
</template> </template>
<script> <script>
export default { export default {
name: "", name: "",
props: { props: {
action: Object, action: Object,
}, },
data() { data() {
return {}; return {};
}, },
methods: { methods: {
onClick() { onClick() {
this.$emit("click", this.action); this.$emit("click", this.action);
}, },
}, },
}; };
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.action_item { .action_item {
@include vCenterBox(); @include vCenterBox();
padding: 24rpx 44rpx; padding: 24rpx 44rpx;
.action_icon { .action_icon {
width: 30px; width: 30px;
height: 30px; height: 30px;
image { image {
max-width: 100%; max-width: 100%;
max-height: 100%; max-height: 100%;
} }
} }
.action_details { .action_details {
@include colBox(false); @include colBox(false);
margin-left: 48rpx; margin-left: 48rpx;
width: 100%; width: 100%;
position: relative; position: relative;
.title { .title {
font-weight: 500; font-weight: 500;
padding-bottom: 12rpx; padding-bottom: 12rpx;
} }
.desc { .desc {
font-size: 24rpx; font-size: 24rpx;
color: #999; color: #999;
} }
.bottom_line { .bottom_line {
height: 1px; height: 1px;
width: 100%; width: 100%;
background-color: #f0f0f0; background-color: #f0f0f0;
position: absolute; position: absolute;
bottom: -24rpx; bottom: -24rpx;
} }
} }
} }
</style> </style>
+80 -90
View File
@@ -1,101 +1,91 @@
<template> <template>
<view class="contact_add_container"> <view class="contact_add_container">
<custom-nav-bar title="添加" /> <custom-nav-bar title="添加" />
<view class="action_row"> <view class="action_row">
<action-item <action-item @click="friendAction(item)" v-for="item in friendActionMenus" :action="item" :key="'f_'+item.idx" />
@click="friendAction(item)" <action-item @click="groupAction(item)" v-for="item in groupActionMenus" :action="item" :key="'g_'+item.idx" />
v-for="item in friendActionMenus" </view>
:action="item" </view>
:key="item.idx"
/>
<action-item
@click="groupAction(item)"
v-for="item in groupActionMenus"
:action="item"
:key="item.idx"
/>
</view>
</view>
</template> </template>
<script> <script>
import CustomNavBar from "@/components/CustomNavBar/index.vue"; import CustomNavBar from "@/components/CustomNavBar/index.vue";
import ActionItem from "./ActionItem.vue"; import ActionItem from "./ActionItem.vue";
export default { export default {
components: { components: {
CustomNavBar, CustomNavBar,
ActionItem, ActionItem,
}, },
data() { data() {
return { return {
groupActionMenus: [ groupActionMenus: [
{ {
idx: 0, idx: 0,
title: "创建群聊", title: "创建群聊",
desc: "创建群聊,全面使用OpenIM", desc: "创建群聊,全面使用OpenIM",
icon: require("static/images/contact_add_create_group.png"), icon: require("static/images/contact_add_create_group.png"),
}, },
{ {
idx: 1, idx: 1,
title: "添加群聊", title: "添加群聊",
desc: "向管理员或团队成员询问ID", desc: "向管理员或团队成员询问ID",
icon: require("static/images/contact_add_join_group.png"), icon: require("static/images/contact_add_join_group.png"),
}, },
], ],
friendActionMenus: [ friendActionMenus: [
{ {
idx: 0, idx: 0,
title: "添加好友", title: "添加好友",
desc: "通过手机号/ID号/搜索添加", desc: "通过手机号/ID号/搜索添加",
icon: require("static/images/contact_add_search_user.png"), icon: require("static/images/contact_add_search_user.png"),
}, },
], ],
}; };
}, },
methods: { methods: {
groupAction({ idx }) { groupAction({idx}) {
if (idx === 0) { if (idx === 0) {
uni.navigateTo({ uni.navigateTo({
url: `/pages/common/createGroup/index`, url: `/pages/common/createGroup/index`,
}); });
} else { } else {
uni.navigateTo({ uni.navigateTo({
url: "/pages/contact/switchJoinGroup/index", url: "/pages/contact/switchJoinGroup/index",
}); });
} }
}, },
friendAction({ idx }) { friendAction({idx}) {
if (!idx) { if (!idx) {
uni.navigateTo({ uni.navigateTo({
url: "/pages/common/searchUserOrGroup/index?isSearchGroup=false", url: "/pages/common/searchUserOrGroup/index?isSearchGroup=false",
}); });
} }
}, },
}, },
}; };
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.contact_add_container { .contact_add_container {
height: 100vh; height: 100vh;
background-color: #f8f8f8; background-color: #f8f8f8;
.desc_title { .desc_title {
font-size: 24rpx; font-size: 24rpx;
color: #999; color: #999;
padding: 24rpx 44rpx; padding: 24rpx 44rpx;
} }
.action_row { .action_row {
margin-top: 24rpx; margin-top: 24rpx;
background-color: #fff; background-color: #fff;
.action_item:last-child { .action_item:last-child {
.bottom_line { .bottom_line {
height: 0; height: 0;
} }
} }
} }
} }
</style> </style>
@@ -1,80 +1,112 @@
<template> <template>
<view class="chat_action_bar"> <view class="chat_action_bar">
<u-row class="action_row"> <u-row class="action_row">
<u-col <u-col v-for="item in actionList" :key="item.idx" @click="actionClick(item)" span="3">
v-for="item in actionList" <view class="action_item">
:key="item.idx" <image :src="item.icon" alt="" srcset="" />
@click="actionClick(item)" <text class="action_item_title">{{ item.title }}</text>
span="3" </view>
> </u-col>
<view class="action_item"> </u-row>
<image :src="item.icon" alt="" srcset="" /> </view>
<text class="action_item_title">{{ item.title }}</text>
</view>
</u-col>
</u-row>
</view>
</template> </template>
<script> <script>
import { import {ChatingFooterActionTypes,} from "@/constant";
ChatingFooterActionTypes,
} from "@/constant";
export default { export default {
components: {}, components: {},
data() { data() {
return { return {
actionList: [ actionList: [
{ {
idx: 0, idx: 0,
type: ChatingFooterActionTypes.Album, type: ChatingFooterActionTypes.Album,
title: "相册", title: "照片",
icon: require("static/images/chating_action_image.png"), icon: require("static/images/chating_action_image.png"),
} },
], {
}; idx: 1,
}, type: ChatingFooterActionTypes.Camera,
methods: { title: "拍摄",
async actionClick(action) { icon: require("static/images/chating_action_image.png"),
switch (action.type) { },
case ChatingFooterActionTypes.Album: {
this.$emit("prepareMediaMessage", action.type); idx: 2,
break; type: ChatingFooterActionTypes.Video,
default: title: "视频通话",
break; icon: require("static/images/chating_action_image.png"),
} },
}, {
}, idx: 3,
}; type: ChatingFooterActionTypes.Location,
title: "位置",
icon: require("static/images/chating_action_image.png"),
},
// {
// idx: 0,
// type: ChatingFooterActionTypes.Album,
// title: "红包",
// icon: require("static/images/chating_action_image.png"),
// },
// {
// idx: 0,
// type: ChatingFooterActionTypes.Album,
// title: "转账",
// icon: require("static/images/chating_action_image.png"),
// }
],
};
},
methods: {
async actionClick(action) {
switch (action.type) {
case ChatingFooterActionTypes.Video:
this.$emit("prepareMediaMessage", action.type);
break;
case ChatingFooterActionTypes.Album:
this.$emit("prepareMediaMessage", action.type);
break;
case ChatingFooterActionTypes.Camera:
this.$emit("prepareMediaMessage", action.type);
break;
case ChatingFooterActionTypes.Location:
this.$emit("prepareMediaMessage", action.type);
break;
default:
break;
}
},
},
};
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.chat_action_bar { .chat_action_bar {
position: relative; position: relative;
background: #f0f2f6; background: #f0f2f6;
padding: 24rpx 36rpx; padding: 24rpx 36rpx;
.action_row { .action_row {
flex-wrap: wrap; flex-wrap: wrap;
margin-bottom: 24rpx; margin-bottom: 24rpx;
} }
.action_item { .action_item {
@include centerBox(); @include centerBox();
flex-direction: column; flex-direction: column;
margin-top: 24rpx; margin-top: 24rpx;
image { image {
width: 96rpx; width: 96rpx;
height: 96rpx; height: 96rpx;
} }
&_title { &_title {
font-size: 24rpx; font-size: 24rpx;
color: #999; color: #999;
margin-top: 6rpx; margin-top: 6rpx;
} }
} }
} }
</style> </style>
@@ -25,40 +25,26 @@
</template> </template>
<script> <script>
import { import {mapGetters,mapActions} from "vuex";
mapGetters, import {getPurePath,html2Text} from "@/util/common";
mapActions import {offlinePushInfo} from "@/util/imCommon";
} from "vuex"; import {ChatingFooterActionTypes,UpdateMessageTypes,} from "@/constant";
import { import IMSDK, {IMMethods,MessageStatus,MessageType,} from "openim-uniapp-polyfill";
getPurePath,
html2Text
} from "@/util/common";
import {
offlinePushInfo
} from "@/util/imCommon";
import {
ChatingFooterActionTypes,
UpdateMessageTypes,
} from "@/constant";
import IMSDK, {
IMMethods,
MessageStatus,
MessageType,
} from "openim-uniapp-polyfill";
import UParse from "@/components/gaoyia-parse/parse.vue"; import UParse from "@/components/gaoyia-parse/parse.vue";
import CustomEditor from "./CustomEditor.vue"; import CustomEditor from "./CustomEditor.vue";
import ChatingActionBar from "./ChatingActionBar.vue"; import ChatingActionBar from "./ChatingActionBar.vue";
const needClearTypes = [MessageType.TextMessage]; const needClearTypes = [MessageType.TextMessage];
const albumChoose = [{ const rtcChoose = [
name: "图片", {
type: ChatingFooterActionTypes.Album, name: "视频通话",
type: ChatingFooterActionTypes.Video,
idx: 0, idx: 0,
}, },
{ {
name: "拍照", name: "语言通话",
type: ChatingFooterActionTypes.Camera, type: ChatingFooterActionTypes.Voice,
idx: 1, idx: 1,
}, },
]; ];
@@ -133,23 +119,19 @@
message, message,
offlinePushInfo, offlinePushInfo,
}) })
.then(({ .then(({data}) => {
data
}) => {
this.updateOneMessage({ this.updateOneMessage({
message: data, message: data,
isSuccess: true, isSuccess: true,
}); });
}) })
.catch(({ .catch(({data,errCode,errMsg}) => {
data, uni.$u.toast(errMsg);
errCode,
errMsg
}) => {
this.updateOneMessage({ this.updateOneMessage({
message: data, message: data,
type: UpdateMessageTypes.KeyWords, type: UpdateMessageTypes.KeyWords,
keyWords: [{ keyWords: [
{
key: "status", key: "status",
value: MessageStatus.Failed, value: MessageStatus.Failed,
}, },
@@ -186,14 +168,62 @@
this.inputHtml = e.detail.html; this.inputHtml = e.detail.html;
}, },
prepareMediaMessage(type) { prepareMediaMessage(type) {
if (type === ChatingFooterActionTypes.Album) { console.log(type)
this.actionSheetMenu = [...albumChoose]; if (type === ChatingFooterActionTypes.Video) {
this.actionSheetMenu = [...rtcChoose];
this.showActionSheet = true;
}
if (type === ChatingFooterActionTypes.Album) {
this.chooseOrShotImage(["album"]).then((paths) =>
this.batchCreateImageMesage(paths)
);
}
if (type === ChatingFooterActionTypes.Camera) {
this.chooseOrShotImage(["camera"]).then((paths) =>
this.batchCreateImageMesage(paths)
);
}
if (type === ChatingFooterActionTypes.Location) {
uni.chooseLocation({
complete(res) {
console.log(res);
},
fail(res) {
console.log(res);
}
//latitude:1,
//longitude:1,
})
} }
this.showActionSheet = true;
}, },
// from comp // from comp
batchCreateImageMesage(paths) { batchCreateImageMesage(paths) {
/*
createAdvancedTextMessage
createTextAtMessage
createLocationMessage
createTextMessage
createCustomMessage
createQuoteMessage
createAdvancedQuoteMessage
createCardMessage
createImageMessage
createImageMessage
createImageMessageByURL
createSoundMessage
createSoundMessageFromFullPath
createSoundMessageByURL
createVideoMessage
createVideoMessageFromFullPath
createVideoMessageByURL
createFileMessage
createFileMessageFromFullPath
createFileMessageByURL
createMergerMessage
createFaceMessage
createForwardMessage
*/
paths.forEach(async (path) => { paths.forEach(async (path) => {
const message = await IMSDK.asyncApi( const message = await IMSDK.asyncApi(
IMMethods.CreateImageMessageFromFullPath, IMMethods.CreateImageMessageFromFullPath,
@@ -203,17 +233,19 @@
this.sendMessage(message); this.sendMessage(message);
}); });
}, },
selectClick({ selectClick({idx}) {
idx
}) {
if (idx === 0) { if (idx === 0) {
this.chooseOrShotImage(["album"]).then((paths) => uni.$u.toast('根据相关政策,暂时禁用视频通话');
this.batchCreateImageMesage(paths) //发送视频通话
); // this.chooseOrShotImage(["album"]).then((paths) =>
// this.batchCreateImageMesage(paths)
// );
} else { } else {
this.chooseOrShotImage(["camera"]).then((paths) => uni.$u.toast('根据相关政策,暂时禁用音频通话');
this.batchCreateImageMesage(paths) //发送音频通话
); // this.chooseOrShotImage(["camera"]).then((paths) =>
// this.batchCreateImageMesage(paths)
// );
} }
}, },
chooseOrShotImage(sourceType) { chooseOrShotImage(sourceType) {
@@ -222,9 +254,7 @@
count: 9, count: 9,
sizeType: ["compressed"], sizeType: ["compressed"],
sourceType, sourceType,
success: function({ success: function({tempFilePaths}) {
tempFilePaths
}) {
resolve(tempFilePaths); resolve(tempFilePaths);
}, },
fail: function(err) { fail: function(err) {
@@ -236,9 +266,7 @@
}, },
// keyboard // keyboard
keyboardChangeHander({ keyboardChangeHander({height}) {
height
}) {
if (height > 0) { if (height > 0) {
if (this.actionBarVisible) { if (this.actionBarVisible) {
this.actionBarVisible = false; this.actionBarVisible = false;
@@ -1,329 +1,301 @@
<template> <template>
<view class="chat_header"> <view class="chat_header">
<view class="self_info"> <view class="self_info">
<my-avatar <my-avatar :src="storeSelfInfo.faceURL" :desc="storeSelfInfo.nickname" size="46" />
:src="storeSelfInfo.faceURL" <view class="self_info_desc">
:desc="storeSelfInfo.nickname" <view class="user_state">
size="46" <text class="nickname">{{ storeSelfInfo.nickname }}</text>
/> <view v-if="!storeReinstall">
<view class="self_info_desc"> <view class="tag" v-if="storeIsSyncing">
<view class="user_state"> <img class="loading" style="height: 24rpx; width: 24rpx" src="static/images/loading.png"
<text class="nickname">{{ storeSelfInfo.nickname }}</text> alt="" />
<view v-if="!storeReinstall"> <text class="status">同步中</text>
<view class="tag" v-if="storeIsSyncing"> </view>
<img <view class="tag" v-if="connectStart == 0">
class="loading" <img class="loading" style="height: 24rpx; width: 24rpx" src="static/images/loading.png"
style="height: 24rpx; width: 24rpx" alt="" />
src="static/images/loading.png" <text class="status">连接中</text>
alt="" </view>
/> <view class="err-tag" v-if="connectStart == -1">
<text class="status">同步中</text> <img style="height: 24rpx; width: 24rpx" src="static/images/sync_error.png" alt="" />
</view> <text class="status">连接失败</text>
<view class="tag" v-if="connectStart == 0"> </view>
<img </view>
class="loading" </view>
style="height: 24rpx; width: 24rpx" </view>
src="static/images/loading.png" </view>
alt="" <view class="right_action">
/> <view class="call_icon"> </view>
<text class="status">连接中</text> <view @click="showMore" class="more_icon">
</view> <image src="@/static/images/common_circle_add.png"></image>
<view class="err-tag" v-if="connectStart == -1"> </view>
<img <u-overlay :show="moreMenuVisible" @click="moreMenuVisible = false" opacity="0">
style="height: 24rpx; width: 24rpx" <view :style="{ top: popMenuPosition.top, right: popMenuPosition.right }" class="more_menu">
src="static/images/sync_error.png" <view @click="clickMenu(item)" v-for="item in moreMenus" :key="item.idx" class="menu_item">
alt="" <image :src="item.icon" mode=""></image>
/> <text>{{ item.title }}</text>
<text class="status">连接失败</text> </view>
</view> </view>
</view> </u-overlay>
</view> </view>
</view> </view>
</view>
<view class="right_action">
<view class="call_icon"> </view>
<view @click="showMore" class="more_icon">
<image src="@/static/images/common_circle_add.png"></image>
</view>
<u-overlay
:show="moreMenuVisible"
@click="moreMenuVisible = false"
opacity="0"
>
<view
:style="{ top: popMenuPosition.top, right: popMenuPosition.right }"
class="more_menu"
>
<view
@click="clickMenu(item)"
v-for="item in moreMenus"
:key="item.idx"
class="menu_item"
>
<image :src="item.icon" mode=""></image>
<text>{{ item.title }}</text>
</view>
</view>
</u-overlay>
</view>
</view>
</template> </template>
<script> <script>
import { mapGetters } from "vuex"; import {
import MyAvatar from "@/components/MyAvatar/index.vue"; mapGetters
import IMSDK from "openim-uniapp-polyfill"; } from "vuex";
export default { import MyAvatar from "@/components/MyAvatar/index.vue";
name: "ChatHeader", import IMSDK from "openim-uniapp-polyfill";
components: { export default {
MyAvatar, name: "ChatHeader",
}, components: {
props: {}, MyAvatar,
data() { },
return { props: {},
connectStart: -2, data() {
moreMenuVisible: false, return {
popMenuPosition: { connectStart: -2,
top: 0, moreMenuVisible: false,
right: 0, popMenuPosition: {
}, top: 0,
moreMenus: [ right: 0,
{ },
idx: 1, moreMenus: [{
title: "添加好友", idx: 1,
icon: require("static/images/more_add_friend.png"), title: "添加好友",
}, icon: require("static/images/more_add_friend.png"),
{ },
idx: 2, {
title: "添加群聊", idx: 2,
icon: require("static/images/more_add_group.png"), title: "添加群聊",
}, icon: require("static/images/more_add_group.png"),
{ },
idx: 3, {
title: "创建群聊", idx: 3,
icon: require("static/images/more_create_group.png"), title: "创建群聊",
}, icon: require("static/images/more_create_group.png"),
], },
}; ],
}, };
computed: { },
...mapGetters(["storeSelfInfo", "storeIsSyncing", "storeReinstall"]), computed: {
}, ...mapGetters(["storeSelfInfo", "storeIsSyncing", "storeReinstall"]),
mounted() { },
this.subscribeAll(); mounted() {
}, this.subscribeAll();
beforeDestroy() { },
this.unsubscribeAll(); beforeDestroy() {
}, this.unsubscribeAll();
methods: { },
setStateStart() { methods: {
this.connectStart = 0; setStateStart() {
}, this.connectStart = 0;
setStateSuccess() { },
this.connectStart = 1; setStateSuccess() {
}, this.connectStart = 1;
setStateError() { },
this.connectStart = -1; setStateError() {
}, this.connectStart = -1;
subscribeAll() { },
IMSDK.subscribe(IMSDK.IMEvents.OnConnecting, this.setStateStart); subscribeAll() {
IMSDK.subscribe(IMSDK.IMEvents.OnConnectSuccess, this.setStateSuccess); IMSDK.subscribe(IMSDK.IMEvents.OnConnecting, this.setStateStart);
IMSDK.subscribe(IMSDK.IMEvents.OnConnectFailed, this.setStateError); IMSDK.subscribe(IMSDK.IMEvents.OnConnectSuccess, this.setStateSuccess);
}, IMSDK.subscribe(IMSDK.IMEvents.OnConnectFailed, this.setStateError);
unsubscribeAll() { },
IMSDK.unsubscribe(IMSDK.IMEvents.OnConnecting, this.setStateStart); unsubscribeAll() {
IMSDK.unsubscribe(IMSDK.IMEvents.OnConnectSuccess, this.setStateSuccess); IMSDK.unsubscribe(IMSDK.IMEvents.OnConnecting, this.setStateStart);
IMSDK.unsubscribe(IMSDK.IMEvents.OnConnectFailed, this.setStateError); IMSDK.unsubscribe(IMSDK.IMEvents.OnConnectSuccess, this.setStateSuccess);
}, IMSDK.unsubscribe(IMSDK.IMEvents.OnConnectFailed, this.setStateError);
clickMenu({ idx }) { },
switch (idx) { clickMenu({idx}) {
case 1: switch (idx) {
case 2: case 1:
uni.navigateTo({ case 2:
url: `/pages/common/searchUserOrGroup/index?isSearchGroup=${ uni.navigateTo({
idx === 2 url: `/pages/common/searchUserOrGroup/index?isSearchGroup=${idx === 2}`,
}`, });
}); break;
break; case 3:
case 3: uni.navigateTo({
uni.navigateTo({ url: `/pages/common/createGroup/index`,
url: `/pages/common/createGroup/index`, });
}); break;
break; default:
default: break;
break; }
} },
}, async showMore() {
async showMore() { const {right,bottom} = await this.getEl(".more_icon");
const { right, bottom } = await this.getEl(".more_icon"); this.popMenuPosition.right =
this.popMenuPosition.right = uni.getWindowInfo().windowWidth - right + "px";
uni.getWindowInfo().windowWidth - right + "px"; this.popMenuPosition.top = bottom + "px";
this.popMenuPosition.top = bottom + "px"; this.moreMenuVisible = true;
this.moreMenuVisible = true; },
}, getEl(el) {
getEl(el) { return new Promise((resolve) => {
return new Promise((resolve) => { const query = uni.createSelectorQuery().in(this);
const query = uni.createSelectorQuery().in(this); query
query .select(el)
.select(el) .boundingClientRect((data) => {
.boundingClientRect((data) => { // 存在data,且存在宽和高,视为渲染完毕
// 存在data,且存在宽和高,视为渲染完毕 resolve(data);
resolve(data); })
}) .exec();
.exec(); });
}); },
}, },
}, };
};
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
@keyframes loading { @keyframes loading {
0% { 0% {
transform: rotate(0deg); transform: rotate(0deg);
} }
100% { 100% {
transform: rotate(360deg); transform: rotate(360deg);
} }
} }
.chat_header { .chat_header {
@include btwBox(); @include btwBox();
padding: 36rpx 44rpx; padding: 36rpx 44rpx;
margin-top: var(--status-bar-height); margin-top: var(--status-bar-height);
.self_info { .self_info {
@include btwBox(); @include btwBox();
&_desc { &_desc {
@include colBox(true); @include colBox(true);
margin-left: 24rpx; margin-left: 24rpx;
color: $uni-text-color; color: $uni-text-color;
.company { .company {
@include nomalEllipsis(); @include nomalEllipsis();
font-size: 24rpx; font-size: 24rpx;
margin-bottom: 10rpx; margin-bottom: 10rpx;
max-width: 300rpx; max-width: 300rpx;
} }
.user_state { .user_state {
@include vCenterBox(); @include vCenterBox();
.nickname { .nickname {
@include nomalEllipsis(); @include nomalEllipsis();
font-size: 26rpx; font-size: 26rpx;
max-width: 240rpx; max-width: 240rpx;
} }
.err-tag { .err-tag {
display: flex; display: flex;
justify-content: center; justify-content: center;
align-items: center; align-items: center;
width: 152rpx; width: 152rpx;
height: 44rpx; height: 44rpx;
background: #ffe1dd; background: #ffe1dd;
border-radius: 12rpx 12rpx 12rpx 12rpx; border-radius: 12rpx 12rpx 12rpx 12rpx;
margin-left: 8rpx; margin-left: 8rpx;
.status {
font-size: 24rpx;
margin-left: 8rpx;
font-weight: 400;
color: #ff381f;
}
}
.tag { .status {
display: flex; font-size: 24rpx;
justify-content: center; margin-left: 8rpx;
align-items: center; font-weight: 400;
width: 152rpx; color: #ff381f;
height: 44rpx; }
background: #f2f8ff; }
border-radius: 12rpx 12rpx 12rpx 12rpx;
margin-left: 8rpx;
.loading { .tag {
animation: loading 1.5s infinite; display: flex;
} justify-content: center;
align-items: center;
width: 152rpx;
height: 44rpx;
background: #f2f8ff;
border-radius: 12rpx 12rpx 12rpx 12rpx;
margin-left: 8rpx;
.status { .loading {
font-size: 24rpx; animation: loading 1.5s infinite;
margin-left: 8rpx; }
font-weight: 400;
color: #0089ff;
}
}
.online_state { .status {
@include vCenterBox(); font-size: 24rpx;
margin-left: 24rpx; margin-left: 8rpx;
font-size: 24rpx; font-weight: 400;
color: #0089ff;
}
}
.dot { .online_state {
background-color: #10cc64; @include vCenterBox();
width: 12rpx; margin-left: 24rpx;
height: 12rpx; font-size: 24rpx;
border-radius: 50%;
margin-right: 12rpx;
}
}
}
}
}
.right_action { .dot {
display: flex; background-color: #10cc64;
position: relative; width: 12rpx;
height: 12rpx;
border-radius: 50%;
margin-right: 12rpx;
}
}
}
}
}
.call_icon { .right_action {
margin-right: 24rpx; display: flex;
position: relative;
image { .call_icon {
width: 56rpx; margin-right: 24rpx;
height: 56rpx;
}
}
.more_icon { image {
image { width: 56rpx;
width: 56rpx; height: 56rpx;
height: 56rpx; }
} }
}
.more_menu { .more_icon {
position: absolute; image {
// bottom: 0; width: 56rpx;
// left: 100%; height: 56rpx;
z-index: 999; }
// transform: translate(-100%, 100%); }
box-shadow: 0px 0px 6px 2px rgba(0, 0, 0, 0.16);
width: max-content;
border-radius: 12rpx;
background-color: #fff;
.menu_item { .more_menu {
display: flex; position: absolute;
justify-content: flex-start; // bottom: 0;
align-items: center; // left: 100%;
padding: 20rpx 24rpx; z-index: 999;
font-size: 28rpx; // transform: translate(-100%, 100%);
color: $uni-text-color; box-shadow: 0px 0px 6px 2px rgba(0, 0, 0, 0.16);
border-bottom: 1px solid #f0f0f0; width: max-content;
border-radius: 12rpx;
background-color: #fff;
image { .menu_item {
width: 24px; display: flex;
height: 24px; justify-content: flex-start;
margin-right: 24rpx; align-items: center;
} padding: 20rpx 24rpx;
font-size: 28rpx;
color: $uni-text-color;
border-bottom: 1px solid #f0f0f0;
&:last-child { image {
border: none; width: 24px;
} height: 24px;
} margin-right: 24rpx;
} }
}
} &:last-child {
</style> border: none;
}
}
}
}
}
</style>
@@ -1,34 +1,31 @@
<template> <template>
<view @tap.prevent="clickConversationItem" class="conversation_item"> <view @tap.prevent="clickConversationItem" :class="['conversation_item',source.isPinned?'pinned' : '']">
<view class="pinned" v-if="source.isPinned"></view>
<view class="left_info"> <view class="left_info">
<my-avatar :isGroup="isGroup" :isNotify="isNotify" :src="source.faceURL" :desc="source.showName" <my-avatar :isGroup="isGroup" :isNotify="isNotify" :src="source.faceURL" :desc="source.showName"
size="46" /> size="46" />
<view class="details"> <view class="details">
<text class="conversation_name">{{ source.showName }}</text> <view class="title">
<text class="conversation_name">
{{ source.showName }}
</text>
<view class="right_desc">
<text class="send_time">{{ latestMessageTime }}</text>
<u-badge max="99" :value="source.unreadCount"></u-badge>
</view>
</view>
<view class="lastest_msg_wrap"> <view class="lastest_msg_wrap">
<text class="lastest_msg_content">{{ latestMessage }}</text> <text class="lastest_msg_content">{{ latestMessage }}</text>
</view> </view>
</view> </view>
</view> </view>
<view class="right_desc">
<text class="send_time">{{ latestMessageTime }}</text>
<u-badge max="99" :value="source.unreadCount"></u-badge>
</view>
</view> </view>
</template> </template>
<script> <script>
import { import {SessionType,} from "openim-uniapp-polyfill";
SessionType,
} from "openim-uniapp-polyfill";
import MyAvatar from "@/components/MyAvatar/index.vue"; import MyAvatar from "@/components/MyAvatar/index.vue";
import UParse from "@/components/gaoyia-parse/parse.vue"; import UParse from "@/components/gaoyia-parse/parse.vue";
import { import {getConversationContent,formatConversionTime,prepareConversationState,} from "@/util/imCommon";
getConversationContent,
formatConversionTime,
prepareConversationState,
} from "@/util/imCommon";
export default { export default {
components: { components: {
@@ -81,6 +78,9 @@
flex-direction: row; flex-direction: row;
padding: 12rpx 44rpx 20rpx; padding: 12rpx 44rpx 20rpx;
position: relative; position: relative;
&.pinned{
background-color: #ededed;
}
&_active { &_active {
background-color: #f3f3f3; background-color: #f3f3f3;
@@ -88,17 +88,41 @@
.left_info { .left_info {
@include btwBox(); @include btwBox();
flex:1;
.details { .details {
@include colBox(true); @include colBox(true);
flex:1;
margin-left: 24rpx; margin-left: 24rpx;
height: 46px; height: 46px;
color: $uni-text-color; color: $uni-text-color;
border-bottom: 1px solid #eee;
padding-bottom:20rpx;
.title{
@include btwBox();
.conversation_name {
@include nomalEllipsis();
max-width: 40vw;
font-size: 32rpx;
font-weight: 500;
}
.conversation_name { .right_desc {
@include nomalEllipsis(); @include colBox(true);
max-width: 40vw; align-items: flex-end;
font-size: 28rpx; width: max-content;
justify-content: space-between;
.send_time {
width: max-content;
font-size: 24rpx;
color: #999;
}
.u-badge {
width: fit-content;
}
}
} }
.lastest_msg_wrap { .lastest_msg_wrap {
@@ -125,32 +149,5 @@
} }
} }
} }
.right_desc {
@include colBox(true);
align-items: flex-end;
width: max-content;
justify-content: space-between;
height: 46px;
.send_time {
width: max-content;
font-size: 24rpx;
color: #999;
}
.u-badge {
width: fit-content;
}
}
.pinned {
position: absolute;
top: 0;
right: 24rpx;
width: 17rpx;
height: 17rpx;
background-image: linear-gradient(to bottom left, #314ffe 50%, white 50%);
}
} }
</style> </style>
+15 -21
View File
@@ -7,10 +7,10 @@
</view> </view>
<u-tabs :list="list" :current="active" @click="click"></u-tabs> <u-tabs :list="list" :current="active" @click="click"></u-tabs>
<u-form class="loginForm" labelPosition="top" :model="loginInfo" :labelStyle="{ <u-form class="loginForm" labelPosition="top" :model="loginInfo" :labelStyle="{
fontSize: '14px', fontSize: '14px',
marginTop: '20rpx', marginTop: '20rpx',
width: 'max-content', width: 'max-content',
}" ref="loginForm"> }" ref="loginForm">
<u-form-item v-if="active === 0" label="" prop="phoneNumber"> <u-form-item v-if="active === 0" label="" prop="phoneNumber">
<u-input v-model="loginInfo.phoneNumber" border="surround" placeholder="请输入手机号码" clearable> <u-input v-model="loginInfo.phoneNumber" border="surround" placeholder="请输入手机号码" clearable>
<view slot="prefix" class="phoneNumber_areacode" @click="showPicker"> <view slot="prefix" class="phoneNumber_areacode" @click="showPicker">
@@ -53,7 +53,7 @@
<view class="action_bar"> <view class="action_bar">
<text>还没有账号<text class="register" @click="toRegisterOrForget(true)">立即注册</text></text> <text>还没有账号<text class="register" @click="toRegisterOrForget(true)">立即注册</text></text>
<text style="margin-bottom: 16rpx" @click="copy">{{ v }}</text> <text style="margin-bottom: 16rpx" @click="copy">{{ appversion }}</text>
</view> </view>
</view> </view>
</template> </template>
@@ -62,7 +62,6 @@
import { mapGetters } from "vuex"; import { mapGetters } from "vuex";
import { v4 as uuidv4 } from "uuid"; import { v4 as uuidv4 } from "uuid";
import md5 from "md5"; import md5 from "md5";
import { version } from '@/common/config'
import { businessLogin, businessSendSms } from "@/api/login"; import { businessLogin, businessSendSms } from "@/api/login";
import AreaPicker from "@/components/AreaPicker"; import AreaPicker from "@/components/AreaPicker";
import { checkLoginError } from "@/util/common"; import { checkLoginError } from "@/util/common";
@@ -89,6 +88,7 @@
areaCode: "86", areaCode: "86",
verificationCode: "", verificationCode: "",
}, },
appversion:0,
eying: false, eying: false,
loading: false, loading: false,
count: 0, count: 0,
@@ -97,12 +97,7 @@
}; };
}, },
computed: { computed: {
...mapGetters([ ...mapGetters(["config"]),
"config",
]),
v() {
return this.config.name+' '+version
},
canLogin() { canLogin() {
return ( return (
(this.loginInfo.phoneNumber || this.loginInfo.email) && (this.loginInfo.phoneNumber || this.loginInfo.email) &&
@@ -111,16 +106,18 @@
}, },
}, },
onLoad(options) { onLoad(options) {
const _this = this;
plus.runtime.getProperty(plus.runtime.appid,(inf) => {
console.log(inf);
_this.appversion = inf.version
});
// if(options.isRedirect){ // if(options.isRedirect){
// plus.navigator.closeSplashscreen(); // plus.navigator.closeSplashscreen();
// } // }
this.version = version
this.init(); this.init();
}, },
methods: { methods: {
click({ click({index}) {
index
}) {
this.active = index; this.active = index;
}, },
copy() { copy() {
@@ -164,14 +161,11 @@
email: this.loginInfo.email, email: this.loginInfo.email,
areaCode: `+${this.loginInfo.areaCode}`, areaCode: `+${this.loginInfo.areaCode}`,
password: this.isPwdLogin ? md5(this.loginInfo.password) : "", password: this.isPwdLogin ? md5(this.loginInfo.password) : "",
platform: uni.$u.os() === "ios" ? 1 : 2, platform: uni.$u.os(),
type: this.active === 0 ? 'mobile' : 'email', type: this.active === 0 ? 'mobile' : 'email',
code: this.loginInfo.verificationCode, code: this.loginInfo.verificationCode,
}); });
const { const {imToken,userID} = data;
imToken,
userID
} = data;
await IMSDK.asyncApi(IMSDK.IMMethods.Login, uuidv4(), { await IMSDK.asyncApi(IMSDK.IMMethods.Login, uuidv4(), {
userID, userID,
token: imToken, token: imToken,
+1 -1
View File
@@ -106,7 +106,7 @@
areaCode: `+${this.userInfo.areaCode}`, areaCode: `+${this.userInfo.areaCode}`,
code: this.codeValue, code: this.codeValue,
password: this.formData.password, password: this.formData.password,
platform: uni.$u.os() === "ios" ? 1 : 2, platform: uni.$u.os(),
operationID: Date.now() + "", operationID: Date.now() + "",
}; };
businessReset(options) businessReset(options)
+12 -15
View File
@@ -27,7 +27,7 @@
</u-form> </u-form>
<view class="btn"> <view class="btn">
<u-button :loading="loading" type="primary" @click="doNext"> <u-button :loading="loading" type="primary" @click="doNext">
进入OpenIM 进入{{config.name}}
</u-button> </u-button>
</view> </view>
</view> </view>
@@ -36,12 +36,9 @@
<script> <script>
import md5 from "md5"; import md5 from "md5";
import MyAvatar from "@/components/MyAvatar/index.vue"; import MyAvatar from "@/components/MyAvatar/index.vue";
import { import { mapGetters } from "vuex";
businessRegister import { businessRegister } from "@/api/login";
} from "@/api/login"; import { checkLoginError } from "@/util/common";
import {
checkLoginError
} from "@/util/common";
export default { export default {
components: { components: {
MyAvatar, MyAvatar,
@@ -100,19 +97,19 @@
}, },
}; };
}, },
computed:{
...mapGetters(["config"]),
},
onLoad(options) { onLoad(options) {
const { const {userInfo,codeValue} = options;
userInfo,
codeValue
} = options;
this.userInfo = { this.userInfo = {
...this.userInfo, ...this.userInfo,
...JSON.parse(userInfo), ...JSON.parse(userInfo),
}; };
this.codeValue = codeValue; this.codeValue = codeValue;
if(process.env.NODE_ENV == 'development'){ if(process.env.NODE_ENV == 'development'){
this.userInfo.email = "commiu@outlook.com"; //this.userInfo.email = "commiu@outlook.com";
this.userInfo.nickname = "commiu"; this.userInfo.nickname = "";
this.userInfo.password = "qwe123"; this.userInfo.password = "qwe123";
this.userInfo.confirmPassword = "qwe123"; this.userInfo.confirmPassword = "qwe123";
} }
@@ -135,12 +132,12 @@
this.loading = true; this.loading = true;
const options = { const options = {
code: this.codeValue, code: this.codeValue,
platform: uni.$u.os() === "ios" ? 1 : 2, platform: uni.$u.os(),
autoLogin: true, autoLogin: true,
...this.userInfo, ...this.userInfo,
areaCode: `+${this.userInfo.areaCode}`, areaCode: `+${this.userInfo.areaCode}`,
password: md5(this.userInfo.password), password: md5(this.userInfo.password),
mobile: `+${this.userInfo.phoneNumber}`, mobile: this.userInfo.phoneNumber
}; };
try { try {
await businessRegister(options); await businessRegister(options);
+157 -132
View File
@@ -1,144 +1,169 @@
<template> <template>
<view class="page_container"> <view class="page_container">
<custom-nav-bar title="关于我们" /> <custom-nav-bar title="关于我们" />
<view class="logo_area"> <view class="logo_area">
<image src="@/static/images/about_logo.png" mode=""></image> <image src="@/static/images/about_logo.png" mode=""></image>
<view>{{ v }}</view> <view>{{ appversion }}</view>
<info-item @click="checkUpdate" class="check" title="检测更新" content="" />
<info-item @click="openurl('http://baidu.com')" class="check" title="官方网站" content="" />
<info-item @click="goto('/pages/common/article?type=article&name=coom&title=商务合作')" class="check" title="商务合作" content="" />
<info-item @click="goto('/pages/common/article?type=article&name=contract&title=用户协议')" class="check" title="用户协议" content="" />
<info-item @click="goto('/pages/common/article?type=article&name=privacy&title=隐私政策')" class="check" title="隐私政策" content="" />
<info-item @click="goto('/pages/common/article?type=article&name=aboutus&title=关于我们')" class="check" title="关于我们" content="" />
<info-item @click="clearcache" class="check" title="清除缓存" content="" />
<info-item @click="show = true" class="check" title="上传调试日志" content="" />
<info-item <u-modal showCancelButton :show="show" title="上传日志" @confirm="uploadLog" @cancel="show = false">
@click="show = true" <view class="slot-content">
class="check" <u--input placeholder="日志数量" border="surround" v-model="line"></u--input>
title="上传调试日志" </view>
content="" </u-modal>
/> </view>
</view>
<u-modal showCancelButton :show="show" title="上传日志" @confirm="uploadLog" @cancel="show = false" >
<view class="slot-content">
<u--input
placeholder="日志数量"
border="surround"
v-model="line"
></u--input>
</view>
</u-modal>
</view>
</view>
</template> </template>
<script> <script>
import IMSDK from "openim-uniapp-polyfill"; import IMSDK from "openim-uniapp-polyfill";
import { version } from '@/common/config' import {version } from '@/common/config'
import CustomNavBar from "@/components/CustomNavBar/index.vue"; import CustomNavBar from "@/components/CustomNavBar/index.vue";
import { PageEvents } from "@/constant"; import {PageEvents } from "@/constant";
import InfoItem from "../selfInfo/InfoItem.vue"; import InfoItem from "../selfInfo/InfoItem.vue";
export default { import {checkUpgrade} from "@/api/login.js"
components: { export default {
CustomNavBar, components: {
InfoItem, CustomNavBar,
}, InfoItem,
data() { },
return { data() {
show: false, return {
line: 10000, show: false,
version: "", line: 10000,
loading: false, appversion: "",
}; loading: false,
}, };
computed: { },
v(){ onLoad() {
return version this.getAppVersion();
} },
}, mounted() {
onLoad() { IMSDK.subscribe('uploadLogsProgress', this.uploadHandler);
this.getAppVersion(); },
uni.$on(PageEvents.CheckForUpdateResp, this.checkRespHandler); beforeDestroy() {
}, IMSDK.unsubscribe('uploadLogsProgress', this.uploadHandler);
onUnload() { },
uni.$off(PageEvents.CheckForUpdateResp, this.checkRespHandler); methods: {
}, uploadLog() {
mounted() { this.show = false
IMSDK.subscribe('uploadLogsProgress', this.uploadHandler); IMSDK.asyncApi('uploadLogs',IMSDK.uuid(), {
}, line: this.line,
beforeDestroy() { ex: ""
IMSDK.unsubscribe('uploadLogsProgress', this.uploadHandler); })
}, uni.showLoading({
methods: { title: '上传中',
uploadLog() { mask: true,
this.show = false });
IMSDK.asyncApi( },
'uploadLogs', uploadHandler({data: {current,size},}) {
IMSDK.uuid(), console.log('uploadHandler', current, size)
{ if (current >= size) {
line: this.line, uni.hideLoading();
ex: "" uni.showToast({
} title: "上传成功",
) icon: "none",
uni.showLoading({ });
title: '上传中', return;
mask: true, }
}); },
}, getAppVersion() {
uploadHandler({ let system = uni.getSystemInfoSync();
data: { current, size }, const _this = this;
}) { plus.runtime.getProperty(plus.runtime.appid,(inf) => {
console.log('uploadHandler',current,size) console.log(inf);
if (current >= size) { _this.appversion = inf.version
uni.hideLoading(); });
uni.showToast({ },
title: "上传成功",
icon: "none", checkRespHandler() {
}); this.loading = false;
return; },
} goto(url){
}, uni.navigateTo({
getAppVersion() { url: url,
plus.runtime.getProperty( });
plus.runtime.appid, },
({ version }) => (this.appVersion = version), clearcache(){
);
}, },
updateCheck() { openurl(url){
this.loading = true; // #ifdef APP
uni.$emit(PageEvents.CheckForUpdate, true); plus.runtime.openWeb(url)
}, // #endif
checkRespHandler() { // #ifdef H5
this.loading = false; window.open(url);
}, // #endif
}, },
}; // 验证是否升级
checkUpdate() {
this.loading = true;
const _this = this;
let system = uni.getSystemInfoSync();
plus.runtime.getProperty(plus.runtime.appid, function(inf) {
checkUpgrade({version:system.appVersion,platform:system.platform,version_wgt:inf.versionCode}).then(res=>{
_this.loading = false;
if(!res.data){
uni.showToast({
title:"已经是最新版本"
})
return ;
}
let skip_version = uni.getStorageSync('skip_version')
if(res && res.version!=skip_version){
uni.$emit('closeWebview')
_this.setShow(_this.current, false)
uni.navigateTo({
url: '/pages/common/upgrade?model=' + JSON.stringify(res),
animationType:"fade-in"
});
}
})
})
},
},
};
</script> </script>
<style lang="scss"> <style lang="scss">
.page_container { .page_container {
background-color: #f8f8f8; background-color: #f8f8f8;
.logo_area { .logo_area {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
align-items: center; align-items: center;
margin: 24rpx 24rpx 0 24rpx; margin: 24rpx 24rpx 0 24rpx;
background: #fff; background: #fff;
border-radius: 6px; border-radius: 6px;
padding: 48rpx 0 16rpx 0; padding: 48rpx 0 16rpx 0;
color: $uni-text-color; color: $uni-text-color;
image { image {
width: 72px; width: 72px;
height: 72px; height: 72px;
margin-bottom: 24rpx; margin-bottom: 24rpx;
} }
} }
.check { .check {
margin-top: 26rpx; margin-top: 26rpx;
border-top: 1px #e8eaef solid; border-top: 1px #e8eaef solid;
padding: 20rpx; padding: 20rpx;
padding-bottom: 0; padding-bottom: 0;
width: 90%; width: 90%;
} }
.btn_row { .btn_row {
padding: 0 44rpx; padding: 0 44rpx;
} }
} }
</style> </style>
+15 -12
View File
@@ -86,19 +86,22 @@
}); });
}, },
logoutConfirm() { logoutConfirm() {
IMSDK.asyncApi(IMSDK.IMMethods.Logout, IMSDK.uuid()) console.log(1)
.then(() => { IMSDK.asyncApi(IMSDK.IMMethods.Logout, IMSDK.uuid()).then(() => {
uni.removeStorage({ console.log(2)
key: "IMToken", uni.removeStorage({
}); key: "IMToken",
uni.removeStorage({
key: "BusinessToken",
});
})
.catch((err) => console.log(err))
.finally(() => {
uni.$u.route("/pages/login/index");
}); });
uni.removeStorage({
key: "BusinessToken",
});
}).catch((err) => {
console.log(3)
console.log(err)
}).finally(() => {
console.log(4)
uni.$u.route("/pages/login/index");
});
}, },
profileMenuClick({idx}) { profileMenuClick({idx}) {
switch (idx) { switch (idx) {
+62 -65
View File
@@ -1,74 +1,71 @@
<template> <template>
<view @click="clickItem" class="info_item"> <view @click="clickItem" class="info_item">
<view class="left_label"> <view class="left_label">
<text>{{ title }}</text> <text>{{ title }}</text>
</view> </view>
<view class="right_value"> <view class="right_value">
<slot name="value"> <slot name="value">
<text class="content">{{ content }}</text> <text class="content">{{ content }}</text>
</slot> </slot>
<u-icon <u-icon v-if="showArrow" name="arrow-right" size="16" color="#999"></u-icon>
v-if="showArrow" </view>
name="arrow-right" <u-loading-icon v-show="loading" class="loading_icon"></u-loading-icon>
size="16" </view>
color="#999"
></u-icon>
</view>
<u-loading-icon v-show="loading" class="loading_icon"></u-loading-icon>
</view>
</template> </template>
<script> <script>
export default { export default {
name: "", name: "",
props: { props: {
title: String, title: String,
content: String, content: String,
showArrow: { showArrow: {
type: Boolean, type: Boolean,
default: true, default: true,
}, },
loading: { loading: {
type: Boolean, type: Boolean,
default: false, default: false,
}, },
}, },
data() { data() {
return {}; return {};
}, },
methods: { methods: {
clickItem() { clickItem() {
this.$emit("click"); this.$emit("click");
}, },
}, },
}; };
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.info_item { .info_item {
@include btwBox(); @include btwBox();
height: 82rpx; height: 82rpx;
padding: 0 44rpx; padding: 0 44rpx;
color: $uni-text-color; color: $uni-text-color;
// border-bottom: 1px solid rgba(153,153,153,0.3); // border-bottom: 1px solid rgba(153,153,153,0.3);
position: relative; position: relative;
.right_value { .right_value {
@include vCenterBox(); @include vCenterBox();
.content {
font-size: 28rpx;
color: #999;
}
.u-icon {
margin-left: 12rpx;
}
}
.loading_icon { .content {
position: absolute; font-size: 28rpx;
left: 50%; color: #999;
top: 50%; }
transform: translate(-50%, -50%);
} .u-icon {
} margin-left: 12rpx;
</style> }
}
.loading_icon {
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
}
}
</style>
+166 -202
View File
@@ -1,216 +1,180 @@
<template> <template>
<view class="page_container"> <view class="page_container">
<custom-nav-bar title="个人资料" /> <custom-nav-bar title="个人资料" />
<view class="info_wrap"> <view class="info_wrap">
<info-item <info-item :loading="loadingState.faceURL" @click="updateAvatar" title="头像">
:loading="loadingState.faceURL" <my-avatar :src="selfInfo.faceURL" :desc="selfInfo.nickname" size="30" slot="value" />
@click="updateAvatar" </info-item>
title="头像" <info-item @click="updateNickname" title="姓名" :content="selfInfo.nickname" />
> <info-item :loading="loadingState.gender" @click="updateGender" title="性别" :content="getGender" />
<my-avatar <info-item :loading="loadingState.birth" @click="() => (showDatePicker = true)" title="生日"
:src="selfInfo.faceURL" :content="getBirth" />
:desc="selfInfo.nickname" </view>
size="30"
slot="value"
/>
</info-item>
<info-item
@click="updateNickname"
title="姓名"
:content="selfInfo.nickname"
/>
<info-item
:loading="loadingState.gender"
@click="updateGender"
title="性别"
:content="getGender"
/>
<info-item
:loading="loadingState.birth"
@click="() => (showDatePicker = true)"
title="生日"
:content="getBirth"
/>
</view>
<view class="info_wrap"> <view class="info_wrap">
<info-item <info-item :showArrow="false" title="手机号码" :content="selfInfo.mobile || '-'" />
:showArrow="false" <info-item :showArrow="false" title="邮箱" :content="selfInfo.email || '-'" />
title="手机号码" </view>
:content="selfInfo.phoneNumber || '-'"
/>
<info-item
:showArrow="false"
title="邮箱"
:content="selfInfo.email || '-'"
/>
</view>
<u-datetime-picker <u-datetime-picker :minDate="0" :maxDate="nowDate" :show="showDatePicker" @confirm="confirmDate"
:minDate="0" @cancel="() => (showDatePicker = false)" v-model="selfInfo.birth" mode="date" />
:maxDate="nowDate" </view>
:show="showDatePicker"
@confirm="confirmDate"
@cancel="() => (showDatePicker = false)"
v-model="selfInfo.birth"
mode="date"
/>
</view>
</template> </template>
<script> <script>
import { businessInfoUpdate } from "@/api/login"; import {
import IMSDK from "openim-uniapp-polyfill"; businessInfoUpdate
import CustomNavBar from "@/components/CustomNavBar/index.vue"; } from "@/api/login";
import MyAvatar from "@/components/MyAvatar/index.vue"; import IMSDK from "openim-uniapp-polyfill";
import dayjs from "dayjs"; import CustomNavBar from "@/components/CustomNavBar/index.vue";
import InfoItem from "./InfoItem.vue"; import MyAvatar from "@/components/MyAvatar/index.vue";
import { getPurePath } from "@/util/common"; import dayjs from "dayjs";
export default { import InfoItem from "./InfoItem.vue";
components: { import {
CustomNavBar, getPurePath
MyAvatar, } from "@/util/common";
InfoItem, export default {
}, components: {
data() { CustomNavBar,
return { MyAvatar,
showDatePicker: false, InfoItem,
loadingState: { },
faceURL: false, data() {
gender: false, return {
birth: false, showDatePicker: false,
}, loadingState: {
nowDate: Date.now(), faceURL: false,
}; gender: false,
}, birth: false,
computed: { },
selfInfo() { nowDate: Date.now(),
return this.$store.getters.storeSelfInfo; };
}, },
getGender() { computed: {
if (this.selfInfo.gender === 0) { selfInfo() {
return "保密"; return this.$store.getters.storeSelfInfo;
} },
if (this.selfInfo.gender === 1) { getGender() {
return "男"; if (this.selfInfo.sex === 0) {
} return "保密";
return "女"; }
}, if (this.selfInfo.sex === 1) {
getBirth() { return "男";
const birth = this.selfInfo.birth ?? 0; }
return dayjs(birth).format("YYYY-MM-DD"); return "女";
}, },
}, getBirth() {
methods: { console.log(this.selfInfo);
updateNickname() { const birth = this.selfInfo.birthday ?? 0;
uni.navigateTo({ return dayjs(birth).format("YYYY-MM-DD");
url: `/pages/common/markOrIDPage/index?isSelfNickname=true&sourceInfo=${JSON.stringify( },
},
methods: {
updateNickname() {
uni.navigateTo({
url: `/pages/common/markOrIDPage/index?isSelfNickname=true&sourceInfo=${JSON.stringify(
this.selfInfo, this.selfInfo,
)}`, )}`,
}); });
}, },
updateGender() { updateGender() {
uni.showActionSheet({ uni.showActionSheet({
itemList: ["男", "女"], itemList: ['保密',"男", "女"],
success: async ({ tapIndex }) => { success: async ({
this.loadingState.gender = true; tapIndex
await this.updateSelfInfo( }) => {
{ this.loadingState.gender = true;
gender: tapIndex + 1, await this.updateSelfInfo({gender: tapIndex,},"gender",);
}, },
"gender", });
); },
}, updateAvatar() {
}); uni.chooseImage({
}, count: 1,
updateAvatar() { sizeType: ["compressed"],
uni.chooseImage({ success: async ({
count: 1, tempFilePaths
sizeType: ["compressed"], }) => {
success: async ({ tempFilePaths }) => { const path = tempFilePaths[0];
const path = tempFilePaths[0]; const nameIdx = path.lastIndexOf("/") + 1;
const nameIdx = path.lastIndexOf("/") + 1; const typeIdx = path.lastIndexOf(".") + 1;
const typeIdx = path.lastIndexOf(".") + 1; const fileName = path.slice(nameIdx);
const fileName = path.slice(nameIdx); const fileType = path.slice(typeIdx);
const fileType = path.slice(typeIdx); this.loadingState.faceURL = true;
this.loadingState.faceURL = true; const {
const { data: {
data: { url }, url
} = await IMSDK.asyncApi(IMSDK.IMMethods.UploadFile, IMSDK.uuid(), { },
filepath: getPurePath(tempFilePaths[0]), } = await IMSDK.asyncApi(IMSDK.IMMethods.UploadFile, IMSDK.uuid(), {
name: fileName, filepath: getPurePath(tempFilePaths[0]),
contentType: fileType, name: fileName,
uuid: IMSDK.uuid(), contentType: fileType,
}); uuid: IMSDK.uuid(),
console.log(url); });
this.updateSelfInfo( console.log(url);
{ this.updateSelfInfo({
faceURL: url, faceURL: url,
}, },
"faceURL", "faceURL",
); );
this.loadingState.faceURL = false; this.loadingState.faceURL = false;
}, },
}); });
}, },
toQrCode() { toQrCode() {
uni.navigateTo({ uni.navigateTo({
url: `/pages/common/userOrGroupQrCode/index`, url: `/pages/common/userOrGroupQrCode/index`,
}); });
}, },
copyID() { copyID() {
uni.setClipboardData({ uni.setClipboardData({
data: this.selfInfo.userID, data: this.selfInfo.userID,
success: () => { success: () => {
uni.hideToast(); uni.hideToast();
this.$nextTick(() => { this.$nextTick(() => {
uni.$u.toast("复制成功"); uni.$u.toast("复制成功");
}); });
}, },
}); });
}, },
async updateSelfInfo(data, key) { async updateSelfInfo(data, key) {
try { try {
await businessInfoUpdate({ console.log(data);
userID: this.selfInfo.userID, await businessInfoUpdate({
...data, userID: this.selfInfo.userID,
}); ...data,
await this.$store.dispatch("user/updateBusinessInfo"); });
uni.$u.toast("修改成功"); await this.$store.dispatch("user/updateBusinessInfo");
} catch (e) { uni.$u.toast("修改成功");
console.log(e); } catch (e) {
uni.$u.toast("修改失败"); console.log(e);
} uni.$u.toast("修改失败");
this.loadingState[key] = false; }
}, this.loadingState[key] = false;
confirmDate({ value }) { },
this.loadingState.birth = true; confirmDate({value}) {
this.updateSelfInfo( this.loadingState.birth = true;
{ this.updateSelfInfo({birth: value,},"birth",);
birth: value, this.showDatePicker = false;
}, },
"birth", },
); };
this.showDatePicker = false;
},
},
};
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.page_container { .page_container {
background-color: #f8f8f8; background-color: #f8f8f8;
.info_wrap { .info_wrap {
margin: 24rpx 24rpx 0 24rpx; margin: 24rpx 24rpx 0 24rpx;
background: #fff; background: #fff;
border-radius: 6px; border-radius: 6px;
.qr_icon { .qr_icon {
width: 22px; width: 22px;
height: 23px; height: 23px;
} }
} }
} }
</style> </style>
@@ -0,0 +1,22 @@
<template>
<view>
</view>
</template>
<script>
export default {
data() {
return {
}
},
methods: {
}
}
</script>
<style>
</style>
+264 -25
View File
@@ -1,31 +1,270 @@
<template> <template>
<web-view :src="linkUrl"></web-view> <view class="content">
<u-navbar :is-back="false" title="发现" :background="{ background: '#f4f4f5' }" title-color="#404133"
:title-bold="true" title-size="34" :border-bottom="false" z-index="1001">
</u-navbar>
<view style="background-color: #FFFFFF;">
<view>
<u-cell-item title="" :title-style="titleStyle" :border-bottom="showBorder(0)" :border-top="false"
@tap="linkTo(cellList[0])">
<u-icon class="u-m-r-10" slot="icon" name="/static/image/workbench/01.png" color="inherit" :size="44"></u-icon>
<view slot="title" class="u-flex u-row-left u-col-center" style="min-width: 200rpx;">
<view class="u-m-r-20">
<text>朋友圈</text>
</view>
<view class="u-flex u-row-center u-col-center" v-if="vuex_friendCircleUnreadCount>0"
style="width:36rpx;height:36rpx;background-color:#fa3534;border-radius:18rpx;font-size:28rpx;color: #ffffff;">
<text>{{vuex_friendCircleUnreadCount}}</text>
</view>
</view>
<view slot="right-icon" v-if="newCircleInfo&&newCircleInfo.userHeadImg.length>0">
<u-avatar :src="newCircleInfo.userHeadImg" mode="square" :size="70"></u-avatar>
<u-badge :is-dot="true" type="error" :offset="[20,60]"></u-badge>
</view>
</u-cell-item>
<u-gap :height="16" bg-color="#f4f4f5" v-if="showGap(0)"></u-gap>
</view>
<view v-for="(item,index) in cellList" :key="index">
<template v-if="item.hidden==false&&index!=0">
<u-cell-item :title="item.title" :title-style="titleStyle"
:border-bottom="showBorder(index)" :border-top="false"
@tap="linkTo(item)">
<u-icon :class="item.title=='购物'?'u-m-l-6 u-m-r-10':'u-m-r-10'"
slot="icon" :name="item.icon" :color="item.color" :size="item.size"></u-icon>
</u-cell-item>
<u-gap :height="16" bg-color="#f4f4f5" v-if="showGap(index)"></u-gap>
</template>
</view>
</view>
</view>
</template> </template>
<script> <script>
export default { export default {
data() { data() {
return { return {
linkUrl: "", cellList: [
}; {
}, id: 1,
onShow() { title: "朋友圈",
this.linkUrl = 'https://doc.rentsoft.cn/' icon: "/static/image/workbench/01.png",
}, color: "inherit",
onReady() { bind: "/pages/workbench/friend-circle/friend-circle",
// #ifdef APP-PLUS hidden:false,
setTimeout(() => { size:44,
this.$scope },
.$getAppWebview() {
.children()[0] id: 3,
.setStyle({ title: "扫一扫",
top: uni.getWindowInfo().statusBarHeight, //icon: "/static/image/wx/saoyisao.png",
height: uni.getWindowInfo().safeArea.height, icon: "/static/image/workbench/04.png",
}); color: "#409eff",
}); bind: "scan",
// #endif hidden:false,
}, size:44,
}; },
{
id: 4,
title: "摇一摇",
//icon: "/static/image/wx/yaoyiyao.png",
icon: "/static/image/workbench/05.png",
color: "#409eff",
bind: "/pages/tabbar/find/yaoyiyao/yyy-index",
hidden:false,
size:44,
},
{
id: 11,
title: "看一看",
icon: "/static/image/workbench/06.png",
color: "#f29100",
bind: "",
hidden:false,
size:44,
},
{
id: 13,
title: "附近",
icon: "/static/image/workbench/08.png",
color: "#fab6b6",
bind: "",
hidden:false,
size:44,
},
{
id: 14,
title: "购物",
icon: "/static/image/workbench/09.png",
color: "#fab6b6",
bind: "taobao",
hidden:false,
size:44,
},
{
id: 15,
title: "游戏",
icon: "/static/image/workbench/10.png",
color: "#fab6b6",
bind: "",
hidden:false,
size:44,
},
{
id: 6,
title: "小程序",
//icon: "/static/image/wx/xiaochengxu.png",
icon: "/static/image/workbench/11.png",
color: "#fab6b6",
bind: "",
hidden:false,
size:44,
},
{
id: 7,
title: "ChatGpt",
icon: "/static/image/find/chatgpt.png",
color: "#ff9900",
bind: "/pages/tabbar/group/chat/chat-gpt-conversion-wss",
hidden:true,
size:64,
},
{
id: 8,
title: "AI绘画",
icon: "http://open.yjai.art/assets/logo-9a019aa3.svg",
color: "#ff9900",
bind: "/pages/tabbar/find/AI/ai-text-to-create-img/ai-text-to-create-img",
hidden:true,
size:64,
},
{
id: 9,
title: "免费听歌",
icon: "/static/image/find/MP3.png",
color: "#19BE6B",
bind: "/pages/tabbar/find/music/free-music",
hidden:true,
size:64,
}
],
titleStyle: {
marginLeft: "20rpx",
fontSize: "34rpx",
color: "#000000"
},
newCircleInfo: {
userHeadImg:""
},
};
},
onShow: function() {
this.changeDefaultAvatar(1,10);
let unreadCount= 1;//this.vuex_friendCircleUnreadCount+"";
this.localGroupApi.setTabBarBadge(2,unreadCount);
},
methods: {
changeDefaultAvatar:function(min,max){
let that=this;
that.$u.api.friendCircle.checkFriendCircleUpdate().then(res => {
if(res.code==200){
console.log("查询朋友圈更新情况",res.data);
if(res.data&&res.data.length>0){
that.newCircleInfo=res.data[0];
}else{
that.newCircleInfo=null;
}
}
})
},
showBorder(index){
switch (index){
case 1:
return true;
case 3:
return true;
case 5:
return true;
case 8:
return true;
default:
return false;
}
},
showGap(index){
switch (index){
case 0:
return true;
case 2:
return true;
case 4:
return true;
case 6:
return true;
case 7:
return true;
case 9:
return true;
default:
return false;
}
},
linkTo(item) {
let that = this;
let url = item.bind;
console.log("跳转链接", url);
if (url != null && url.length > 0) {
if (url == 'taobao') {
if (plus.os.name == 'Android') {
plus.runtime.launchApplication({
pname: 'com.taobao.taobao'
},
function(e) {
console.log('Open system default browser failed: ' + e.message);
}
);
} else if (plus.os.name == 'iOS') {
//抖音 snssdk1128://
plus.runtime.launchApplication({
action: 'snssdk1128://'
}, function(e) {
console.log('Open system default browser failed: ' + e.message);
});
}
} else if (url == "scan") {
this.globalUtil.scanQRcode(that, {
complete: function(res) {
console.log("扫码结果", res);
if (res.resp_code == 1000) {
let respData = res.resp_result;
that.$u.route({
url: '/pages/chat/qr-info/qr-info',
params: {
qrInfo: respData
},
animationType: 'slide-in-bottom'
});
}
},
})
} else {
console.log("url", url);
this.$u.route(url);
return;
}
}
},
}
};
</script> </script>
<style lang="scss"></style> <style lang="scss" scoped>
.content {}
</style>
<style>
page {
background-color: #f4f4f5 !important;
}
</style>
Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

+8 -25
View File
@@ -1,6 +1,4 @@
import { import {v4 as uuidv4} from "uuid";
v4 as uuidv4
} from "uuid";
import IMSDK from "openim-uniapp-polyfill"; import IMSDK from "openim-uniapp-polyfill";
const state = { const state = {
@@ -46,14 +44,9 @@ const mutations = {
}; };
const actions = { const actions = {
async getConversationList({ async getConversationList({state,commit}, isFirstPage = true) {
state,
commit
}, isFirstPage = true) {
try { try {
const { const {data} = await IMSDK.asyncApi(
data
} = await IMSDK.asyncApi(
IMSDK.IMMethods.GetConversationListSplit, IMSDK.IMMethods.GetConversationListSplit,
uuidv4(), { uuidv4(), {
offset: isFirstPage ? 0 : state.conversationList.length, offset: isFirstPage ? 0 : state.conversationList.length,
@@ -71,9 +64,7 @@ const actions = {
return []; return [];
} }
}, },
getCurrentGroup({ getCurrentGroup({commit}, groupID) {
commit
}, groupID) {
IMSDK.asyncApi(IMSDK.IMMethods.GetSpecifiedGroupsInfo, uuidv4(), [ IMSDK.asyncApi(IMSDK.IMMethods.GetSpecifiedGroupsInfo, uuidv4(), [
groupID, groupID,
]).then(({ ]).then(({
@@ -82,10 +73,7 @@ const actions = {
commit("SET_CURRENT_GROUP", data[0] ?? {}); commit("SET_CURRENT_GROUP", data[0] ?? {});
}); });
}, },
getCurrentMemberInGroup({ getCurrentMemberInGroup({commit,rootState}, groupID) {
commit,
rootState
}, groupID) {
IMSDK.asyncApi(IMSDK.IMMethods.GetSpecifiedGroupMembersInfo, uuidv4(), { IMSDK.asyncApi(IMSDK.IMMethods.GetSpecifiedGroupMembersInfo, uuidv4(), {
groupID, groupID,
userIDList: [rootState.user.selfInfo.userID], userIDList: [rootState.user.selfInfo.userID],
@@ -95,20 +83,15 @@ const actions = {
commit("SET_CURRENT_MEMBER_IN_GROUP", data[0] ?? {}); commit("SET_CURRENT_MEMBER_IN_GROUP", data[0] ?? {});
}); });
}, },
getUnReadCount({ getUnReadCount({commit}) {
commit
}) {
IMSDK.asyncApi(IMSDK.IMMethods.GetTotalUnreadMsgCount, uuidv4()).then( IMSDK.asyncApi(IMSDK.IMMethods.GetTotalUnreadMsgCount, uuidv4()).then(
(res) => { (res) => {
console.log(res); //console.log(res);
commit("SET_UNREAD_COUNT", res.data); commit("SET_UNREAD_COUNT", res.data);
}, },
); );
}, },
updateCurrentMemberInGroup({ updateCurrentMemberInGroup({commit,state}, memberInfo) {
commit,
state
}, memberInfo) {
console.log(memberInfo); console.log(memberInfo);
if ( if (
memberInfo.groupID === state.currentMemberInGroup.groupID && memberInfo.groupID === state.currentMemberInGroup.groupID &&
+3 -9
View File
@@ -48,19 +48,13 @@ const actions = {
commit commit
}) { }) {
try { try {
const { const result = await IMSDK.asyncApi(IMSDK.IMMethods.GetSelfUserInfo,uuidv4(),);
data const res = await businessGetUserInfo(result.data.userID);
} = await IMSDK.asyncApi(
IMSDK.IMMethods.GetSelfUserInfo,
uuidv4(),
);
const res = await businessGetUserInfo(data.userID);
//console.log(res.data);
const businessData = res.data[0] ?? {}; const businessData = res.data[0] ?? {};
filterEmptyValue(businessData); filterEmptyValue(businessData);
commit("SET_SELF_INFO", { commit("SET_SELF_INFO", {
...data, ...result.data,
...businessData, ...businessData,
}); });
} catch (e) { } catch (e) {
+277 -278
View File
@@ -1,17 +1,19 @@
import store from "@/store"; import store from "@/store";
import { import {
CustomType, CustomType,
GroupSystemMessageTypes, GroupSystemMessageTypes,
AddFriendQrCodePrefix, AddFriendQrCodePrefix,
AddGroupQrCodePrefix, AddGroupQrCodePrefix,
} from "@/constant"; } from "@/constant";
import IMSDK, { import IMSDK, {
GroupAtType, GroupAtType,
MessageType, MessageType,
SessionType, SessionType,
} from "openim-uniapp-polyfill"; } from "openim-uniapp-polyfill";
import dayjs from "dayjs"; import dayjs from "dayjs";
import { isThisYear } from "date-fns"; import {
isThisYear
} from "date-fns";
import calendar from "dayjs/plugin/calendar"; import calendar from "dayjs/plugin/calendar";
import relativeTime from "dayjs/plugin/relativeTime"; import relativeTime from "dayjs/plugin/relativeTime";
@@ -24,338 +26,335 @@ dayjs.extend(updateLocale);
dayjs.locale("zh-cn"); dayjs.locale("zh-cn");
dayjs.updateLocale("en", { dayjs.updateLocale("en", {
calendar: { calendar: {
sameElse: "YYYY-MM-DD", sameElse: "YYYY-MM-DD",
}, },
}); });
dayjs.updateLocale("zh-cn", { dayjs.updateLocale("zh-cn", {
calendar: { calendar: {
sameDay: "HH:mm", sameDay: "HH:mm",
nextDay: "[明天]", nextDay: "[明天]",
nextWeek: "dddd", nextWeek: "dddd",
lastDay: "[昨天] HH:mm", lastDay: "[昨天] HH:mm",
lastWeek: "dddd HH:mm", lastWeek: "dddd HH:mm",
sameElse: "YYYY年M月D日 HH:mm", sameElse: "YYYY年M月D日 HH:mm",
}, },
}); });
export const formatMessageTime = (timestemp, keepSameYear = false) => { export const formatMessageTime = (timestemp, keepSameYear = false) => {
if (!timestemp) return ""; if (!timestemp) return "";
const isRecent = dayjs().diff(timestemp, "day") < 7; const isRecent = dayjs().diff(timestemp, "day") < 7;
const keepYear = keepSameYear || !isThisYear(timestemp); const keepYear = keepSameYear || !isThisYear(timestemp);
if (!isRecent && !keepYear) { if (!isRecent && !keepYear) {
return dayjs(timestemp).format("M月D日 HH:mm"); return dayjs(timestemp).format("M月D日 HH:mm");
} }
return dayjs(timestemp).calendar(); return dayjs(timestemp).calendar();
}; };
export const conversationSort = (conversationList) => { export const conversationSort = (conversationList) => {
const arr = []; const arr = [];
const filterArr = conversationList.filter( const filterArr = conversationList.filter(
(c) => !arr.includes(c.conversationID) && arr.push(c.conversationID), (c) => !arr.includes(c.conversationID) && arr.push(c.conversationID),
); );
filterArr.sort((a, b) => { filterArr.sort((a, b) => {
if (a.isPinned === b.isPinned) { if (a.isPinned === b.isPinned) {
const aCompare = const aCompare =
a.draftTextTime > a.latestMsgSendTime a.draftTextTime > a.latestMsgSendTime ?
? a.draftTextTime a.draftTextTime :
: a.latestMsgSendTime; a.latestMsgSendTime;
const bCompare = const bCompare =
b.draftTextTime > b.latestMsgSendTime b.draftTextTime > b.latestMsgSendTime ?
? b.draftTextTime b.draftTextTime :
: b.latestMsgSendTime; b.latestMsgSendTime;
if (aCompare > bCompare) { if (aCompare > bCompare) {
return -1; return -1;
} else if (aCompare < bCompare) { } else if (aCompare < bCompare) {
return 1; return 1;
} else { } else {
return 0; return 0;
} }
} else if (a.isPinned && !b.isPinned) { } else if (a.isPinned && !b.isPinned) {
return -1; return -1;
} else { } else {
return 1; return 1;
} }
}); });
return filterArr; return filterArr;
}; };
export const sec2Time = (seconds) => { export const sec2Time = (seconds) => {
var theTime1 = 0; // min var theTime1 = 0; // min
var theTime2 = 0; // hour var theTime2 = 0; // hour
var theTime3 = 0; // day var theTime3 = 0; // day
if (seconds > 60) { if (seconds > 60) {
theTime1 = parseInt(seconds / 60); theTime1 = parseInt(seconds / 60);
seconds = parseInt(seconds % 60); seconds = parseInt(seconds % 60);
if (theTime1 > 60) { if (theTime1 > 60) {
theTime2 = parseInt(theTime1 / 60); theTime2 = parseInt(theTime1 / 60);
theTime1 = parseInt(theTime1 % 60); theTime1 = parseInt(theTime1 % 60);
if (theTime2 > 24) { if (theTime2 > 24) {
theTime3 = parseInt(theTime2 / 24); theTime3 = parseInt(theTime2 / 24);
theTime2 = parseInt(theTime2 % 24); theTime2 = parseInt(theTime2 % 24);
} }
} }
} }
var result = ""; var result = "";
if (seconds > 0) { if (seconds > 0) {
result = "" + parseInt(seconds) + "秒"; result = "" + parseInt(seconds) + "秒";
} }
if (theTime1 > 0) { if (theTime1 > 0) {
result = "" + parseInt(theTime1) + "分钟" + result; result = "" + parseInt(theTime1) + "分钟" + result;
} }
if (theTime2 > 0) { if (theTime2 > 0) {
result = "" + parseInt(theTime2) + "小时" + result; result = "" + parseInt(theTime2) + "小时" + result;
} }
if (theTime3 > 0) { if (theTime3 > 0) {
result = "" + parseInt(theTime3) + "天" + result; result = "" + parseInt(theTime3) + "天" + result;
} }
return result; return result;
}; };
export const parseMessageByType = (pmsg) => { export const parseMessageByType = (pmsg) => {
const getName = (user) => { const getName = (user) => {
return user.userID === store.getters.storeCurrentUserID return user.userID === store.getters.storeCurrentUserID ?
? "你" "你" :
: user.nickname; user.nickname;
}; };
switch (pmsg.contentType) { switch (pmsg.contentType) {
case MessageType.TextMessage: case MessageType.TextMessage:
return pmsg.textElem.content; return pmsg.textElem.content;
case MessageType.PictureMessage: case MessageType.PictureMessage:
return `[图片]`; return `[图片]`;
case MessageType.FriendAdded: case MessageType.FriendAdded:
return "你们已经是好友了,开始聊天吧~"; return "你们已经是好友了,开始聊天吧~";
case MessageType.MemberEnter: case MessageType.MemberEnter:
const enterDetails = JSON.parse(pmsg.notificationElem.detail); const enterDetails = JSON.parse(pmsg.notificationElem.detail);
const enterUser = enterDetails.entrantUser; const enterUser = enterDetails.entrantUser;
return `${getName(enterUser)}进入了群聊`; return `${getName(enterUser)}进入了群聊`;
case MessageType.GroupCreated: case MessageType.GroupCreated:
const groupCreatedDetail = JSON.parse(pmsg.notificationElem.detail); const groupCreatedDetail = JSON.parse(pmsg.notificationElem.detail);
const groupCreatedUser = groupCreatedDetail.opUser; const groupCreatedUser = groupCreatedDetail.opUser;
return `${getName(groupCreatedUser)}创建了群聊`; return `${getName(groupCreatedUser)}创建了群聊`;
case MessageType.MemberInvited: case MessageType.MemberInvited:
const inviteDetails = JSON.parse(pmsg.notificationElem.detail); const inviteDetails = JSON.parse(pmsg.notificationElem.detail);
const inviteOpUser = inviteDetails.opUser; const inviteOpUser = inviteDetails.opUser;
const invitedUserList = inviteDetails.invitedUserList ?? []; const invitedUserList = inviteDetails.invitedUserList ?? [];
let inviteStr = ""; let inviteStr = "";
invitedUserList.find( invitedUserList.find(
(user, idx) => (inviteStr += getName(user) + "、") && idx > 3, (user, idx) => (inviteStr += getName(user) + "、") && idx > 3,
); );
inviteStr = inviteStr.slice(0, -1); inviteStr = inviteStr.slice(0, -1);
return `${getName(inviteOpUser)}邀请了${inviteStr}${ return `${getName(inviteOpUser)}邀请了${inviteStr}${
invitedUserList.length > 3 ? "..." : "" invitedUserList.length > 3 ? "..." : ""
}进入群聊`; }进入群聊`;
case MessageType.MemberKicked: case MessageType.MemberKicked:
const kickDetails = JSON.parse(pmsg.notificationElem.detail); const kickDetails = JSON.parse(pmsg.notificationElem.detail);
const kickOpUser = kickDetails.opUser; const kickOpUser = kickDetails.opUser;
const kickdUserList = kickDetails.kickedUserList ?? []; const kickdUserList = kickDetails.kickedUserList ?? [];
let kickStr = ""; let kickStr = "";
kickdUserList.find( kickdUserList.find(
(user, idx) => (kickStr += getName(user) + "、") && idx > 3, (user, idx) => (kickStr += getName(user) + "、") && idx > 3,
); );
kickStr = kickStr.slice(0, -1); kickStr = kickStr.slice(0, -1);
return `${getName(kickOpUser)}踢出了${kickStr}${ return `${getName(kickOpUser)}踢出了${kickStr}${
kickdUserList.length > 3 ? "..." : "" kickdUserList.length > 3 ? "..." : ""
}`; }`;
case MessageType.MemberQuit: case MessageType.MemberQuit:
const quitDetails = JSON.parse(pmsg.notificationElem.detail); const quitDetails = JSON.parse(pmsg.notificationElem.detail);
const quitUser = quitDetails.quitUser; const quitUser = quitDetails.quitUser;
return `${getName(quitUser)}退出了群聊`; return `${getName(quitUser)}退出了群聊`;
case MessageType.GroupInfoUpdated: case MessageType.GroupInfoUpdated:
const groupUpdateDetail = JSON.parse(pmsg.notificationElem.detail); const groupUpdateDetail = JSON.parse(pmsg.notificationElem.detail);
const groupUpdateUser = groupUpdateDetail.opUser; const groupUpdateUser = groupUpdateDetail.opUser;
return `${getName(groupUpdateUser)}修改了群信息`; return `${getName(groupUpdateUser)}修改了群信息`;
case MessageType.GroupOwnerTransferred: case MessageType.GroupOwnerTransferred:
const transferDetails = JSON.parse(pmsg.notificationElem.detail); const transferDetails = JSON.parse(pmsg.notificationElem.detail);
const transferOpUser = transferDetails.opUser; const transferOpUser = transferDetails.opUser;
const newOwner = transferDetails.newGroupOwner; const newOwner = transferDetails.newGroupOwner;
return `${getName(transferOpUser)}将群主转让给${getName(newOwner)}`; return `${getName(transferOpUser)}将群主转让给${getName(newOwner)}`;
case MessageType.GroupDismissed: case MessageType.GroupDismissed:
const dismissDetails = JSON.parse(pmsg.notificationElem.detail); const dismissDetails = JSON.parse(pmsg.notificationElem.detail);
const dismissUser = dismissDetails.opUser; const dismissUser = dismissDetails.opUser;
return `${getName(dismissUser)}解散了群聊`; return `${getName(dismissUser)}解散了群聊`;
case MessageType.GroupNameUpdated: case MessageType.GroupNameUpdated:
const groupNameUpdateDetail = JSON.parse(pmsg.notificationElem.detail); const groupNameUpdateDetail = JSON.parse(pmsg.notificationElem.detail);
const groupNameUpdateUser = groupNameUpdateDetail.opUser; const groupNameUpdateUser = groupNameUpdateDetail.opUser;
return `${getName(groupNameUpdateUser)}修改了群名称为${ return `${getName(groupNameUpdateUser)}修改了群名称为${
groupNameUpdateDetail.group.groupName groupNameUpdateDetail.group.groupName
}`; }`;
default: default:
return "[暂未支持的消息类型]"; return "[暂未支持的消息类型]";
} }
}; };
export const formatConversionTime = (timestemp) => { export const formatConversionTime = (timestemp) => {
const fromNowStr = dayjs(timestemp).fromNow(); const fromNowStr = dayjs(timestemp).fromNow();
if (fromNowStr.includes("秒")) { if (fromNowStr.includes("秒")) {
return "刚刚"; return "刚刚";
} }
if (!fromNowStr.includes("秒") && !fromNowStr.includes("分钟")) { if (!fromNowStr.includes("秒") && !fromNowStr.includes("分钟")) {
return dayjs(timestemp).calendar(); return dayjs(timestemp).calendar();
} }
return fromNowStr; return fromNowStr;
}; };
export const secFormat = (sec) => { export const secFormat = (sec) => {
let h; let h;
let s; let s;
h = Math.floor(sec / 60); h = Math.floor(sec / 60);
s = sec % 60; s = sec % 60;
h += ""; h += "";
s += ""; s += "";
h = h.length === 1 ? "0" + h : h; h = h.length === 1 ? "0" + h : h;
s = s.length === 1 ? "0" + s : s; s = s.length === 1 ? "0" + s : s;
return h + ":" + s; return h + ":" + s;
}; };
export const bytesToSize = (bytes) => { export const bytesToSize = (bytes) => {
if (bytes === 0) return "0 B"; if (bytes === 0) return "0 B";
var k = 1024, var k = 1024,
sizes = ["B", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"], sizes = ["B", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"],
i = Math.floor(Math.log(bytes) / Math.log(k)); i = Math.floor(Math.log(bytes) / Math.log(k));
return (bytes / Math.pow(k, i)).toPrecision(3) + " " + sizes[i]; return (bytes / Math.pow(k, i)).toPrecision(3) + " " + sizes[i];
}; };
export const tipMessaggeFormat = (msg, currentUserID) => { export const tipMessaggeFormat = (msg, currentUserID) => {
const getName = (user) => const getName = (user) =>
user.userID === currentUserID ? "你" : user.nickname; user.userID === currentUserID ? "你" : user.nickname;
switch (msg.contentType) { switch (msg.contentType) {
case MessageType.FriendAdded: case MessageType.FriendAdded:
return `你们已经是好友了~`; return `你们已经是好友了~`;
case MessageType.GroupCreated: case MessageType.GroupCreated:
const groupCreatedDetail = JSON.parse(msg.notificationElem.detail); const groupCreatedDetail = JSON.parse(msg.notificationElem.detail);
const groupCreatedUser = groupCreatedDetail.opUser; const groupCreatedUser = groupCreatedDetail.opUser;
return `${getName(groupCreatedUser)}创建了群聊`; return `${getName(groupCreatedUser)}创建了群聊`;
case MessageType.GroupInfoUpdated: case MessageType.GroupInfoUpdated:
const groupUpdateDetail = JSON.parse(msg.notificationElem.detail); const groupUpdateDetail = JSON.parse(msg.notificationElem.detail);
const groupUpdateUser = groupUpdateDetail.opUser; const groupUpdateUser = groupUpdateDetail.opUser;
return `${parseInfo(groupUpdateUser)}修改了群信息`; return `${parseInfo(groupUpdateUser)}修改了群信息`;
case MessageType.GroupOwnerTransferred: case MessageType.GroupOwnerTransferred:
const transferDetails = JSON.parse(msg.notificationElem.detail); const transferDetails = JSON.parse(msg.notificationElem.detail);
const transferOpUser = transferDetails.opUser; const transferOpUser = transferDetails.opUser;
const newOwner = transferDetails.newGroupOwner; const newOwner = transferDetails.newGroupOwner;
return `${parseInfo(transferOpUser)}转让群主给${parseInfo(newOwner)}`; return `${parseInfo(transferOpUser)}转让群主给${parseInfo(newOwner)}`;
case MessageType.MemberQuit: case MessageType.MemberQuit:
const quitDetails = JSON.parse(msg.notificationElem.detail); const quitDetails = JSON.parse(msg.notificationElem.detail);
const quitUser = quitDetails.quitUser; const quitUser = quitDetails.quitUser;
return `${parseInfo(quitUser)}退出了群组`; return `${parseInfo(quitUser)}退出了群组`;
case MessageType.MemberInvited: case MessageType.MemberInvited:
const inviteDetails = JSON.parse(msg.notificationElem.detail); const inviteDetails = JSON.parse(msg.notificationElem.detail);
const inviteOpUser = inviteDetails.opUser; const inviteOpUser = inviteDetails.opUser;
const invitedUserList = inviteDetails.invitedUserList ?? []; const invitedUserList = inviteDetails.invitedUserList ?? [];
let inviteStr = ""; let inviteStr = "";
invitedUserList.find( invitedUserList.find(
(user, idx) => (inviteStr += parseInfo(user) + "、") && idx > 3, (user, idx) => (inviteStr += parseInfo(user) + "、") && idx > 3,
); );
inviteStr = inviteStr.slice(0, -1); inviteStr = inviteStr.slice(0, -1);
return `${parseInfo(inviteOpUser)} 邀请了${inviteStr}${ return `${parseInfo(inviteOpUser)} 邀请了${inviteStr}${
invitedUserList.length > 3 ? "..." : "" invitedUserList.length > 3 ? "..." : ""
}加入群聊`; }加入群聊`;
case MessageType.MemberKicked: case MessageType.MemberKicked:
const kickDetails = JSON.parse(msg.notificationElem.detail); const kickDetails = JSON.parse(msg.notificationElem.detail);
const kickOpUser = kickDetails.opUser; const kickOpUser = kickDetails.opUser;
const kickdUserList = kickDetails.kickedUserList ?? []; const kickdUserList = kickDetails.kickedUserList ?? [];
let kickStr = ""; let kickStr = "";
kickdUserList.find( kickdUserList.find(
(user, idx) => (kickStr += parseInfo(user) + "、") && idx > 3, (user, idx) => (kickStr += parseInfo(user) + "、") && idx > 3,
); );
kickStr = kickStr.slice(0, -1); kickStr = kickStr.slice(0, -1);
return `${parseInfo(kickOpUser)} 踢出了${kickStr}${ return `${parseInfo(kickOpUser)} 踢出了${kickStr}${
kickdUserList.length > 3 ? "..." : "" kickdUserList.length > 3 ? "..." : ""
}`; }`;
case MessageType.MemberEnter: case MessageType.MemberEnter:
const enterDetails = JSON.parse(msg.notificationElem.detail); const enterDetails = JSON.parse(msg.notificationElem.detail);
const enterUser = enterDetails.entrantUser; const enterUser = enterDetails.entrantUser;
return `${parseInfo(enterUser)}加入了群聊`; return `${parseInfo(enterUser)}加入了群聊`;
case MessageType.GroupDismissed: case MessageType.GroupDismissed:
const dismissDetails = JSON.parse(msg.notificationElem.detail); const dismissDetails = JSON.parse(msg.notificationElem.detail);
const dismissUser = dismissDetails.opUser; const dismissUser = dismissDetails.opUser;
return `${parseInfo(dismissUser)}解散了群聊`; return `${parseInfo(dismissUser)}解散了群聊`;
default: default:
return ""; return "";
} }
}; };
export const markConversationAsRead = (conversation, fromChating = false) => { export const markConversationAsRead = (conversation, fromChating = false) => {
if (conversation.unreadCount !== 0) { if (conversation.unreadCount !== 0) {
IMSDK.asyncApi( IMSDK.asyncApi(
IMSDK.IMMethods.MarkConversationMessageAsRead, IMSDK.IMMethods.MarkConversationMessageAsRead,
IMSDK.uuid(), IMSDK.uuid(),
conversation.conversationID, conversation.conversationID,
); );
} }
}; };
export const prepareConversationState = (conversation, back2Tab = false) => { export const prepareConversationState = (conversation, back2Tab = false) => {
markConversationAsRead(conversation); markConversationAsRead(conversation);
if (conversation.conversationType === SessionType.WorkingGroup) { if (conversation.conversationType === SessionType.WorkingGroup) {
store.dispatch("conversation/getCurrentGroup", conversation.groupID); store.dispatch("conversation/getCurrentGroup", conversation.groupID);
store.dispatch( store.dispatch(
"conversation/getCurrentMemberInGroup", "conversation/getCurrentMemberInGroup",
conversation.groupID, conversation.groupID,
); );
} }
store.dispatch("message/resetMessageState"); store.dispatch("message/resetMessageState");
store.commit("conversation/SET_CURRENT_CONVERSATION", conversation); store.commit("conversation/SET_CURRENT_CONVERSATION", conversation);
let url = `/pages/conversation/chating/index?back2Tab=${back2Tab}`; let url = `/pages/conversation/chating/index?back2Tab=${back2Tab}`;
setTimeout(() => { setTimeout(() => {
uni.navigateTo({ uni.navigateTo({
url, url,
}); });
}, 300) }, 300)
}; };
export const navigateToDesignatedConversation = ( export const navigateToDesignatedConversation = (sourceID,sessionType,back2Tab = false,) => {
sourceID, return new Promise(async (resolve, reject) => {
sessionType, try {
back2Tab = false, const {
) => { data
return new Promise(async (resolve, reject) => { } = await IMSDK.asyncApi(
try { IMSDK.IMMethods.GetOneConversation,
const { data } = await IMSDK.asyncApi( IMSDK.uuid(), {
IMSDK.IMMethods.GetOneConversation, sessionType,
IMSDK.uuid(), sourceID,
{ },
sessionType, );
sourceID, prepareConversationState(data, back2Tab);
}, resolve();
); } catch (e) {
prepareConversationState(data, back2Tab); reject(e);
resolve(); }
} catch (e) { });
reject(e);
}
});
}; };
export const offlinePushInfo = { export const offlinePushInfo = {
title: "you have a new message", title: "you have a new message",
desc: "you have a new message", desc: "you have a new message",
ex: "", ex: "",
iOSPushSound: "", iOSPushSound: "",
iOSBadgeCount: true, iOSBadgeCount: true,
}; };
export const getConversationContent = (message) => { export const getConversationContent = (message) => {
if ( if (
!message.groupID || !message.groupID ||
message.sendID === store.getters.storeCurrentUserID message.sendID === store.getters.storeCurrentUserID
) { ) {
return parseMessageByType(message); return parseMessageByType(message);
} }
return `${message.senderNickname}${parseMessageByType(message)}`; return `${message.senderNickname}${parseMessageByType(message)}`;
}; };