cyl/master-apply
wangxia 3 months ago
parent 0ea2edd1b8
commit 3912e7a63f

@ -1,10 +1,10 @@
<script lang="ts">
import RootStore from "@xkit-yx/im-store-v2";
import V2NIM, { V2NIMConst } from "nim-web-sdk-ng/dist/v2/NIM_UNIAPP_SDK";
import { getMsgContentTipByType, setTabUnread } from "./pages/NEUIKit/utils/msg";
import { STORAGE_KEY } from "./pages/NEUIKit/utils/constants";
import { isWxApp } from "./pages/NEUIKit/utils";
import { V2NIMMessage, V2NIMMessagePushConfig, V2NIMConversation } from "nim-web-sdk-ng/dist/v2/NIM_UNIAPP_SDK/V2NIMMessageService";
// import RootStore from "@xkit-yx/im-store-v2";
// import V2NIM, { V2NIMConst } from "nim-web-sdk-ng/dist/v2/NIM_UNIAPP_SDK";
// import { getMsgContentTipByType, setTabUnread } from "./pages/NEUIKit/utils/msg";
// import { STORAGE_KEY } from "./pages/NEUIKit/utils/constants";
// import { isWxApp } from "./pages/NEUIKit/utils";
// import { V2NIMMessage, V2NIMMessagePushConfig, V2NIMConversation } from "nim-web-sdk-ng/dist/v2/NIM_UNIAPP_SDK/V2NIMMessageService";
import { unix } from "dayjs";
export default {
@ -45,7 +45,7 @@ export default {
uni.$on("isGlogin", function (data) {
// console.log("app.vue ", data);
if (uni.getStorageSync("apply-token")) {
that.initWyyx();
// that.initWyyx();
}
});
},
@ -176,7 +176,7 @@ export default {
}
} else if (uni.getStorageSync("apply-token") ) {
// console.log("IM SDK...");
that.initWyyx();
// that.initWyyx();
}
}, 1000);
},
@ -217,11 +217,11 @@ export default {
});
} else {
// console.log("IM");
that.initWyyx();
// that.initWyyx();
}
} else {
console.log("SDK未初始化重新初始化IM");
that.initWyyx();
// that.initWyyx();
}
};

@ -43,6 +43,10 @@ export function createApp () {
uni.setStorageSync("apply-agencyId", res.user.agencyId); // 单独存储 -- 代理id方便获取
uni.setStorageSync("apply-supplierAccount", res.supplierAccount); // 单独存储 -- 是否是发单号,方便获取 0.不是发单号 1.是发单号
if (res.agencyId) {
G.Get('/yishoudan/agency/role/checkDeptAdmin', {}, (val) => {
console.log('/yishoudan/agency/role/checkDeptAdmin', val);
uni.setStorageSync("is_teamleader", val === true ? 1 : 0); // 是否是部门管理员的判断
})
G.Get(apiInfo.login_agencyInfo, {}, (aRes) => {
uni.setStorageSync("agencyInfo", aRes.agency); // 1是创建者 2是普通成员
uni.setStorageSync("IS_CREATOR", aRes.agency.userId == res.user.id || res.admin == true ? 1 : 2); // 1是创建者 2是普通成员
@ -181,7 +185,7 @@ export function createApp () {
}, $sourceType);
},
/*
*/
*/
uploadImgByAlbum (callback = () => { }, type = 'default', $num = 1, $sourceType = ['album']) {
var that = this;
G.uploadImage($num, (imgRes) => {

1644
package-lock.json generated

File diff suppressed because it is too large Load Diff

@ -10,12 +10,9 @@
"author": "",
"license": "ISC",
"dependencies": {
"@xkit-yx/im-store-v2": "^0.4.0",
"@xkit-yx/utils": "^0.5.6",
"dayjs": "^1.11.7",
"fetch-event-source": "^1.0.0-alpha.2",
"mobx": "^6.6.1",
"nim-web-sdk-ng": "^10.4.0",
"pinyin": "^3.1.0",
"recorder-core": "^1.3.25011100"
},

@ -554,120 +554,6 @@
}
}
]
},
{ //
"root": "root/NEUIKit/pages",
"pages": [
{
"path": "Chat/index",
"style": {
"backgroundColor": "#ededed",
"backgroundColorTop": "#ededed",
"backgroundColorBottom": "#ededed",
"navigationBarTitleText": " "
}
},
{
"path": "Chat/showImg",
"style": {
"backgroundColor": "#ededed",
"backgroundColorTop": "#ededed",
"backgroundColorBottom": "#ededed",
"navigationBarTitleText": " "
}
},
// {
// "path": "Chat/message/p2p-set",
// "style": {
// "navigationBarTitleText": "聊天设置"
// }
// },
// {
// "path": "Chat/message/pin-list",
// "style": {
// "navigationBarTitleText": "标记列表"
// }
// },
{
"path": "Contact/index",
"style": {
"backgroundColor": "#ededed",
"backgroundColorTop": "#ededed",
"backgroundColorBottom": "#ededed",
"navigationBarTitleText": "通讯录"
}
},
{
"path": "Contact/BcFriend",
"style": {
"backgroundColor": "#ededed",
"backgroundColorTop": "#ededed",
"backgroundColorBottom": "#ededed",
"navigationBarTitleText": "内部好友"
}
},
{
"path": "Contact/contact-list/valid-list",
"style": {
"backgroundColor": "#ededed",
"backgroundColorTop": "#ededed",
"backgroundColorBottom": "#ededed",
"navigationBarTitleText": "验证消息"
}
},
{
"path": "Contact/contact-list/black-list",
"style": {
"backgroundColor": "#ededed",
"backgroundColorTop": "#ededed",
"backgroundColorBottom": "#ededed",
"navigationBarTitleText": "黑名单"
}
},
{
"path": "Friend/add-friend/index",
"style": {
"backgroundColor": "#ededed",
"backgroundColorTop": "#ededed",
"backgroundColorBottom": "#ededed",
"navigationBarTitleText": "添加好友"
}
},
{
"path": "Friend/friend-info-edit",
"style": {
"backgroundColor": "#ededed",
"backgroundColorTop": "#ededed",
"backgroundColorBottom": "#ededed",
"navigationBarTitleText": "编辑好友"
}
},
{
"path": "user-card/friend/index",
"style": {
"backgroundColor": "#ededed",
"backgroundColorTop": "#ededed",
"backgroundColorBottom": "#ededed",
"navigationBarTitleText": "好友名片"
}
},
{
"path": "user-card/my-detail/index",
"style": {
"backgroundColor": "#ededed",
"backgroundColorTop": "#ededed",
"backgroundColorBottom": "#ededed",
"navigationBarTitleText": "个人名片"
}
}
// {
// "path": "user-card/detail-item/index",
// "style": {
// "navigationBarTitleText": "个人名片信息编辑"
// }
// }
],
"independent": true
}
],
"globalStyle": {
@ -691,12 +577,12 @@
"selectedIconPath": "static/image/home.png",
"text": "首页"
},
{
"pagePath": "pages/message/index",
"iconPath": "static/image/message_gray.png",
"selectedIconPath": "static/image/message.png",
"text": "消息"
},
// {
// "pagePath": "pages/message/index",
// "iconPath": "static/image/message_gray.png",
// "selectedIconPath": "static/image/message.png",
// "text": "消息"
// },
{
"pagePath": "pages/home/order",
"iconPath": "static/image/plus-square_gray.png",

@ -1,313 +0,0 @@
<script lang="ts">
import RootStore from "@xkit-yx/im-store-v2";
import V2NIM, { V2NIMConst } from "nim-web-sdk-ng/dist/v2/NIM_UNIAPP_SDK";
import {
customRedirectTo,
customReLaunch,
customSwitchTab,
customNavigateTo
} from "./utils/customNavigate";
import { getMsgContentTipByType } from "./utils/msg";
import { STORAGE_KEY } from "./utils/constants";
import { isWxApp } from "./utils";
import {
V2NIMMessage,
V2NIMMessagePushConfig,
} from "nim-web-sdk-ng/dist/v2/NIM_UNIAPP_SDK/V2NIMMessageService";
// #ifdef APP-PLUS
//
const nimPushPlugin = uni.requireNativePlugin("NIMUniPlugin-PluginModule");
//
const nimCallKit = (uni.$UIKitCallKit =
uni.requireNativePlugin("netease-CallKit"));
// #endif
export default {
onLaunch() {
// #ifdef APP-PLUS
//
plus.navigator.closeSplashscreen();
plus.screen.lockOrientation("portrait-primary");
// #endif
if (
uni?.$UIKitStore?.connectStore?.connectStatus ===
V2NIMConst.V2NIMConnectStatus.V2NIM_CONNECT_STATUS_CONNECTED
) {
return;
}
const imOptions = uni.getStorageSync(STORAGE_KEY);
if (imOptions) {
this.initNim(imOptions);
} else {
// im
customRedirectTo({
url: isWxApp ? "/pages/index/index" : "/root/person/loginIndex",
});
}
},
onShow() {
// #ifdef APP-PLUS
uni?.$UIKitNIM?.V2NIMSettingService?.setAppBackground(false);
// #endif
},
onHide() {
// #ifdef APP-PLUS
uni?.$UIKitNIM?.V2NIMSettingService?.setAppBackground(true);
// #endif
},
methods: {
initNim(opts: { account: string; token: string }) {
//
uni.setStorage({
key: STORAGE_KEY,
data: opts,
success: function () {
console.log("保存登录信息success");
},
});
const nim = (uni.$UIKitNIM = V2NIM.getInstance(
{
appkey: "",
needReconnect: true,
// "reconnectionAttempts": 5,
debugLevel: "debug",
apiVersion: "v2",
},
{
V2NIMLoginServiceConfig: {
lbsUrls: isWxApp
? ["https://lbs.netease.im/lbs/wxwebconf.jsp"]
: ["https://lbs.netease.im/lbs/webconf.jsp"],
linkUrl: isWxApp ? "wlnimsc0.netease.im" : "weblink.netease.im",
/**
* 使用固定设备ID
*/
isFixedDeviceId: true,
},
}
));
const store = (uni.$UIKitStore = new RootStore(
nim,
{
//
addFriendNeedVerify: false,
// p2p p2p false
p2pMsgReceiptVisible: true,
// false
teamMsgReceiptVisible: true,
//
teamAgreeMode:
V2NIMConst.V2NIMTeamAgreeMode.V2NIM_TEAM_AGREE_MODE_NO_AUTH,
// ,
sendMsgBefore: async (options: {
msg: V2NIMMessage;
conversationId: string;
serverExtension?: Record<string, unknown>;
}) => {
const pushContent = getMsgContentTipByType({
text: options.msg.text,
messageType: options.msg.messageType,
});
const yxAitMsg = options.serverExtension
? options.serverExtension.yxAitMsg
: { forcePushIDsList: "[]", needForcePush: false };
// at 线
const { forcePushIDsList, needForcePush } = yxAitMsg
? // @ts-ignore
store.msgStore._formatExtAitToPushInfo(
yxAitMsg,
options.msg.text
)
: { forcePushIDsList: "[]", needForcePush: false };
console.log("forcePushIDsList: ", forcePushIDsList);
const { conversationId } = options;
const conversationType =
nim.V2NIMConversationIdUtil.parseConversationType(conversationId);
const targetId =
nim.V2NIMConversationIdUtil.parseConversationTargetId(
conversationId
);
const pushPayload = JSON.stringify({
// oppo
oppoField: {
click_action_type: 4, // oppo
click_action_activity: "", // TODO
action_parameters: {
sessionId: targetId,
sessionType: conversationType,
}, //
},
// vivo
vivoField: {
pushMode: 0, // 010
},
// huawei
hwField: {
click_action: {
type: 1,
action: "", // TODO
},
androidConfig: {
category: "IM",
data: JSON.stringify({
sessionId: targetId,
sessionType: conversationType,
}),
},
},
//
sessionId: targetId,
sessionType: conversationType,
});
const pushConfig: V2NIMMessagePushConfig = {
pushEnabled: true,
pushNickEnabled: true,
forcePush: needForcePush,
forcePushContent: pushContent,
forcePushAccountIds: forcePushIDsList,
pushPayload: "{}",
pushContent,
};
return { ...options, pushConfig };
},
},
"UniApp"
));
// #ifdef APP-PLUS
//
nim.V2NIMSettingService.setOfflinePushConfig(nimPushPlugin, {
miPush: {
appId: "",
appKey: "",
certificateName: "",
},
hwPush: {
appId: "",
certificateName: "",
},
oppoPush: {
appId: "",
appKey: "",
certificateName: "",
secret: "",
},
vivoPush: {
appId: "",
appKey: "",
certificateName: "",
},
fcmPush: {
certificateName: "",
},
mzPush: {
appId: "",
appKey: "",
certificateName: "",
},
apns: {
certificateName: "",
},
});
//
console.log("-------------callkit init 开始", opts.account, opts.token);
nimCallKit.initConfig(
{
appKey: "", // appkey
account: opts.account, // account
token: opts.token, // token
apnsCername: "",
pkCername: "",
},
(ret: any) => {
console.log("-------------callkit 回调", ret);
if (ret.code != 200) {
console.log("-------------callkit init失败\n错误码");
} else {
console.log("-------------callkit 开始登录------------");
nimCallKit.login(
{
account: opts.account,
token: opts.token,
},
function (ret: any) {
if (ret.code != 200) {
console.log("-------------callkit 登录失败------------", ret);
} else {
console.log(
"-------------callkit 登录成功------------ ",
ret
);
}
}
);
}
}
);
// #endif
nim.V2NIMLoginService.login(opts.account, opts.token).then(() => {
customNavigateTo({
url: "/pages/Conversation/index",
});
});
nim.V2NIMMessageService.on("onReceiveMessages", function (messages: V2NIMMessage[]) {
console.log('初始化监听会话:',messages)
})
},
logout() {
uni.removeStorageSync(STORAGE_KEY);
try {
nimCallKit.logout({}, (ret: any) => {
if (ret.code != 200) {
console.log("音视频通话插件退出失败");
} else {
console.log("音视频通话插件退出成功");
}
});
} catch (error) {
console.log("音视频通话插件退出失败", error);
}
uni.$UIKitNIM.V2NIMLoginService.logout().then(() => {
uni.$UIKitStore.destroy();
customReLaunch({
url: "/root/person/loginIndex",
});
});
},
},
};
</script>
<style>
uni-page-body {
height: 100%;
}
uni-page-body > uni-view {
height: 100%;
}
</style>

@ -1,88 +0,0 @@
<template>
<span
class="appellation"
:style="{ color: color, fontSize: fontSize + 'px' }"
>
{{ appellation }}
<span v-if="subtitle" style="color: orange;font-size:13px">{{ subtitle }}</span>
</span
>
</template>
<script lang="ts" setup>
import { autorun } from 'mobx'
import {
onUnmounted,
ref,
defineProps,
withDefaults,
} from '../utils/transformVue'
import { deepClone } from '../utils'
const appellation = ref('-')
const appType = ref(uni.getStorageSync("requestComeFrom"));
const { pid,account, teamId, ignoreAlias, nickFromMsg } = withDefaults(
defineProps<{
account: string
teamId?: string
ignoreAlias?: boolean
nickFromMsg?: string
color?: string
fontSize?: number
pid?: number
}>(),
{
teamId: undefined,
ignoreAlias: false,
nickFromMsg: '-',
color: '#333',
fontSize: 16,
pid:0
}
)
const subtitle = ref('');
const uninstallAppellationWatch = autorun(() => {
if(pid){
async function getUserInfo() {
try {
const res = await uni.$UIKitStore.userStore.getUserActive(pid.split('|')[2])
return res
} catch (error) {
console.error('getUserInfo error:', error)
}
}
getUserInfo().then(res => {
if(res.serverExtension && appType.value == 'isToB'){
subtitle.value = '@' + JSON.parse(res.serverExtension).fullName;
}else{
subtitle.value = '';
}
appellation.value = res.name;
})
}else{
appellation.value = deepClone(
uni.$UIKitStore.uiStore.getAppellation({
account,
teamId,
ignoreAlias,
nickFromMsg,
})
)
}
})
onUnmounted(() => {
uninstallAppellationWatch()
})
</script>
<style scoped lang="scss">
.appellation {
color: #333;
font-size: 16px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
</style>

@ -1,163 +0,0 @@
<template>
<div class="avatar" :style="{ width: avatarSize + 'px', height: avatarSize + 'px' }" @click="handleAvatarClick" @longpress="longpress" @touchend="touchend">
<!-- 使用遮罩层避免android长按头像会出现保存图片的弹窗 -->
<div class="img-mask"></div>
<image :lazy-load="true" class="avatar-img" v-if="avatarUrl" :src="avatarUrl" mode="aspectFill" />
<div class="avatar-name-wrapper" :style="{ backgroundColor: color }">
<div class="avatar-name-text" :style="{ fontSize: fontSize + 'px' }">
{{ appellation }}
</div>
</div>
</div>
</template>
<script lang="ts" setup>
import { customNavigateTo, customRedirectTo } from "../utils/customNavigate";
import { autorun } from "mobx";
import { ref, computed, onUnmounted, defineProps, withDefaults } from "../utils/transformVue";
import { deepClone } from "../utils";
import { V2NIMUser } from "nim-web-sdk-ng/dist/v2/NIM_UNIAPP_SDK/V2NIMUserService";
const props = withDefaults(
defineProps<{
account: string;
teamId?: string;
avatar?: string;
size?: string;
gotoUserCard?: boolean;
fontSize?: string;
isRedirect?: boolean;
}>(),
{
teamId: "",
avatar: "",
size: "",
gotoUserCard: false,
fontSize: "",
isRedirect: false,
}
);
const $emit = defineEmits(["onLongpress"]);
const avatarSize = props.size || 42;
const user = ref<V2NIMUser>();
let isLongPress = false; // uniapp
const appellation = computed(() => {
return uni.$UIKitStore.uiStore
.getAppellation({
account: props.account,
teamId: props.teamId,
ignoreAlias: false,
nickFromMsg: "",
})
.slice(0, 2);
});
const uninstallUserInfoWatch = autorun(async () => {
uni.$UIKitStore?.userStore?.getUserActive(props.account).then((data) => {
user.value = data;
});
});
const avatarUrl = computed(() => {
user.value = uni.$UIKitStore?.userStore?.users?.get(props.account);
// return props.avatar || user.value?.avatar
return user.value?.avatar || 'https://bocai-cms.oss-cn-beijing.aliyuncs.com/web-resource/1shoudan/defaultAva.svg';
});
const key = `__yx_avatar_color_${props.account}__`;
let color = uni.getStorageSync(key);
if (!color) {
const colorMap: { [key: number]: string } = {
0: "#60CFA7",
1: "#53C3F3",
2: "#537FF4",
3: "#854FE2",
4: "#BE65D9",
5: "#E9749D",
6: "#F9B751",
};
const _color = colorMap[Math.floor(Math.random() * 7)];
uni.setStorageSync(key, _color);
color = _color;
}
const handleAvatarClick = () => {
if (props.gotoUserCard && !isLongPress) {
if (props.isRedirect) {
if (props.account === uni.$UIKitStore?.userStore?.myUserInfo.accountId) {
customRedirectTo({
url: `/pages/user-card/my-detail/index`,
});
} else {
customRedirectTo({
url: `/pages/user-card/friend/index?account=${props.account}`,
});
}
} else {
if (props.account === uni.$UIKitStore?.userStore?.myUserInfo.accountId) {
customNavigateTo({
url: `/pages/user-card/my-detail/index`,
});
} else {
customNavigateTo({
url: `/pages/user-card/friend/index?account=${props.account}`,
});
}
}
}
};
const longpress = () => {
isLongPress = true;
$emit("onLongpress");
};
const touchend = () => {
setTimeout(() => {
isLongPress = false;
}, 200);
};
onUnmounted(() => {
uninstallUserInfoWatch();
});
</script>
<style scoped lang="scss">
.avatar {
overflow: hidden;
border-radius: 50%;
flex-shrink: 0;
position: relative;
}
.img-mask {
position: absolute;
z-index: 10;
left: 0;
right: 0;
top: 0;
bottom: 0;
opacity: 0;
}
.avatar-img {
width: 100%;
height: 100%;
border-radius: 50%;
}
.avatar-name-wrapper {
width: 100%;
height: 100%;
display: flex;
align-items: center;
justify-content: center;
}
.avatar-name-text {
color: #fff;
size: 14px;
}
</style>

@ -1,63 +0,0 @@
<template>
<div>
<div class="dot" v-if="dot" :style="customStyle"></div>
<div class="badge" v-else-if="text" :style="customStyle">{{ text }}</div>
<div class="hidden">{{ props.num }}</div>
</div>
</template>
<script lang="ts" setup>
import {
StyleValue,
computed,
defineProps,
withDefaults,
} from '../utils/transformVue'
const props = withDefaults(
defineProps<{
num: number
max?: number
dot?: boolean
customStyle?: StyleValue
}>(),
{
max: 99,
dot: false,
}
)
const max = props.max || 99
const text = computed(() => {
return props.num > 0 ? (props.num > max ? `${max}+` : props.num + '') : ''
})
</script>
<style scoped lang="scss">
.dot {
background-color: #ff4d4f;
color: #fff;
width: 10px;
height: 10px;
border-radius: 5px;
box-sizing: border-box;
z-index: 99;
}
.badge {
background-color: #ff4d4f;
color: #fff;
font-size: 12px;
min-width: 20px;
height: 20px;
line-height: 19px;
border-radius: 10px;
padding: 0 5px;
box-sizing: border-box;
text-align: center;
z-index: 99;
position: relative;
}
.hidden {
display: none;
}
</style>

@ -1,42 +0,0 @@
<template>
<div class="empty-wrapper">
<image
class="empty-img"
src="https://bocai-cms.oss-cn-beijing.aliyuncs.com/web-resource/dailibaoming/noData.svg"
/>
<div class="empty-text">{{ text }}</div>
</div>
</template>
<script lang="ts" setup>
import { defineProps, withDefaults } from '../utils/transformVue'
withDefaults(
defineProps<{
text?: string
}>(),
{
text: '',
}
)
</script>
<style lang="scss" scoped>
.empty-wrapper {
margin: 75px 10px;
display: flex;
justify-content: center;
flex-direction: column;
align-items: center;
.empty-img {
display: block;
width: 66px;
height: 66px;
}
.empty-text {
display: block;
color: #a6adb6;
margin: 10px;
}
}
</style>

@ -1,78 +0,0 @@
<template>
<view :class="className" :style="iconStyle">
<!-- #ifdef APP-PLUS -->
<image
:src="_url"
:style="{
width: (width || size) + 'px',
height: (height || size) + 'px',
}"
class="icon"
/>
<!-- #endif -->
<!-- #ifndef APP-PLUS -->
<img
:src="_url"
:style="{
width: (width || size) + 'px',
height: (height || size) + 'px',
}"
class="icon"
/>
<!-- #endif -->
</view>
</template>
<script lang="ts" setup>
// svg https://github.com/iconfont-cli/mini-program-iconfont-cli/tree/master
import { computed, defineProps, withDefaults } from '../utils/transformVue'
const props = withDefaults(
defineProps<{
type: string
size?: number
width?: number
height?: number
iconClassName?: string
iconStyle?: any
}>(),
{
size: 16,
}
)
const urlMap = {
'icon-yanzheng':
'https://yx-web-nosdn.netease.im/common/5a0c2769626284ff646298a7ef1f66c2/icon-yanzheng.png',
'icon-lahei2':
'https://yx-web-nosdn.netease.im/common/1ee2a3bffb33b81727583189a2562658/icon-lahei2.png',
'icon-xiaoximiandarao':
'https://yx-web-nosdn.netease.im/common/1c92731bb3fa91fa3fc5ff45bf9e4dbe/icon-xiaoximiandarao.png',
'icon-read':
'https://bocai-cms.oss-cn-beijing.aliyuncs.com/web-resource/bocaigongyinglian/wyyx_check_0514.svg',
}
//访
const _url = computed(() => {
// @ts-ignore
return urlMap[props.type]
})
// const prefix = 'https://yiyong-qa.netease.im/yiyong-static/statics/uniapp-vue2-h5'
// const url = computed(() => {
// return `${prefix}/static/icons/${props.type}.png`
// })
const className = `${props.iconClassName || ''} icon-wrapper`
</script>
<style scoped lang="scss">
.icon-wrapper {
display: inline-block;
line-height: 0;
}
.icon {
display: inline-block;
vertical-align: middle;
}
</style>

@ -1,5 +0,0 @@
{
"messageText": "Message",
"cantactsText": "Cantact",
"mineText": "Me"
}

@ -1,5 +0,0 @@
{
"messageText": "消息",
"cantactsText": "通讯录",
"mineText": "我的"
}

@ -1,19 +0,0 @@
// zn.js
export default {
appText: '云信IM',
deleteStickTopText: '取消置顶',
contactText: '通讯录',
addFriendText: '添加好友',
addStickTopText: '置顶消息',
deleteSessionText: '不显示',
createTeamText: '创建群聊',
validMsgText: '验证消息',
blacklistText: '黑名单',
teamMenuText: '我的群组',
someoneText: '有人',
meText: '我',
recall: '撤回了一条消息',
conversationSendFailText: '[发送失败]',
conversationNotificationText: '[通知消息]',
noFriendText: '暂无好友',
}

@ -1,208 +0,0 @@
<template>
<!-- :style="{ height: `calc(100vh - ${43 + tabbarHeight}px)` }" -->
<view class="g_bg_f_5">
<div style="height: 10px"></div>
<div class="g_bg_f_5" style="width: calc(100% - 40rpx); margin: 0px auto 10px">
<div class="">
<view style="background-color: #ededed; padding: 0 12px">
<u-search placeholder="请输入手机号" :show-action="false" bg-color="#fff" placeholder-class="g_c_c" :input-style="{ fontSize: '16px' }" height="80" search-icon-color="#999999" v-model="wxyx_tel" @search="handleSearch" @custom="handleCustom"></u-search>
</view>
</div>
<div class="g_flex_row_between g_pl_10 g_pr_10" v-if="receiverUserData && receiverUserData.userId" style="background-color: #fff; border-radius: 8px; padding: 12px 10px; margin-top: 10px">
<div class="g_flex_1">
<div style="font-size: 16px; font-weight: 600">
{{ receiverUserData.tel || "-" }}
</div>
<div style="color: #a1a1a1; font-size: 14px; margin-top: 8px">
{{ receiverUserData.userName || "-" }}
</div>
</div>
<div class="g_flex_none g_ml_12 g_flex_column_center">
<div>
<u-button :loading="isStart" type="primary" size="mini" @click="startChat"></u-button>
</div>
</div>
</div>
<div class="nei-box g_mt_10" style="background-color: #fff; border-radius: 8px" v-if="allUser && allUser.length > 0">
<!-- <div class="label-title" style="font-size: 16px; font-weight: 600; padding: 12px 16px; border-bottom: 1px solid #eee">内部通讯录</div> -->
<div v-for="(item, index) in allUser" :key="index" @click="startCopyChat(item)" class="g_flex_row_between g_pt_12 g_pb_12 g_pl_16 g_pr_16 border_bottom">
<div class="g_flex_1 g_flex_row_start g_fs_16">
<div class="g_flex_none g_mr_12">
<image :src="item.imgSrc || 'https://bocai-cms.oss-cn-beijing.aliyuncs.com/web-resource/1shoudan/defaultAva.svg'" style="width: 48px; height: 48px; border-radius: 50px"></image>
</div>
<div class="g_flex_1 g_flex_column_between">
<div class="g_c_3 g_fs_17" style="line-height: 24px">
{{ item.userName }}
</div>
<div
class="g_c_3 g_fs_14 g_ell_1"
style="line-height: 20px"
:style="{
color: '#999',
}"
>
{{ item.tel }}
</div>
</div>
</div>
<!-- <div class="g_flex_1">
<div style="font-size: 16px; font-weight: 600">
{{ item.userName || "-" }}
</div>
<div style="color: #a1a1a1; font-size: 14px; margin-top: 8px">
{{ item.tel || "-" }}
</div>
</div> -->
<!-- <div class="g_flex_none g_ml_12 g_flex_column_center">
<div>
<u-button :loading="item.isStart" type="primary" size="mini" @click="startCopyChat(item)"></u-button>
</div>
</div> -->
</div>
</div>
</div>
<div style="height: 100rpx"></div>
</view>
</template>
<script>
import { customRedirectTo, customReLaunch, customSwitchTab, customNavigateTo } from "../../utils/customNavigate";
export default {
data() {
return {
allUser: [],
isStart: false,
isSend: false,
wxyx_tel: "",
receiverUserData: {},
tabbarHeight: uni.getStorageSync("TABBAR_HEIGHT"),
};
},
created() {
let that = this;
that.getCopyUserList();
},
methods: {
getCopyUserList() {
let that = this;
that.F.wyyxGet(that.api.wyyx_getCorpUserList, {}, (res) => {
console.log("获取通讯录:", res);
if (res && res.length > 0) {
res.forEach((item) => {
item.isStart = false;
});
}
that.allUser = res;
});
},
handleSearch(e) {
this.getUserList(e);
},
handleCustom(e) {
this.getUserList(e);
},
getUserList(e) {
let that = this;
that.F.wyyxGet(
this.api.wyyx_getCorpUserList,
{
key: e,
},
(res) => {
console.log("搜索手机号", res);
that.receiverUserData = res[0];
}
);
},
sendPointMessage() {
let that = this;
that.isSend = true;
that.F.wyyxPost(
that.api.wyyx_sendMessage,
{
conversationType: 1,
senderUserId: uni.getStorageSync("apply-uid"), // id id
receiverUserId: that.receiverUserData.userId, // id
text: "我是招呼语" + that.G.getPointTime(),
},
(res) => {
that.isSend = false;
that.receiverUserData = {};
that.goYunxin();
},
() => {
that.isSend = false;
}
);
},
async startCopyChat($item) {
let that = this;
$item.isStart = true;
that.F.wyyxPost(
that.api.wyyx_create,
{
senderUserId: uni.getStorageSync("apply-uid"),
receiverUserId: $item.userId,
},
(res) => {
$item.isStart = false;
uni.$UIKitStore.uiStore.selectConversation(res.conversationId);
customNavigateTo({
url: "/pages/Chat/index",
});
},
() => {
$item.isStart = false;
}
);
},
async startChat() {
let that = this;
that.isStart = true;
that.F.wyyxPost(
that.api.wyyx_create,
{
senderUserId: uni.getStorageSync("apply-uid"),
receiverUserId: that.receiverUserData.userId,
},
(res) => {
that.isStart = false;
uni.$UIKitStore.uiStore.selectConversation(res.conversationId);
that.receiverUserData = {};
customNavigateTo({
url: "/pages/Chat/index",
});
},
() => {
that.isStart = false;
}
);
},
goYunxin() {
customNavigateTo({
url: "/pages/Conversation/index",
});
},
},
};
</script>
<style lang="less">
page {
background-color: #ededed;
}
.border_bottom {
position: relative;
&:not(:last-child):after {
content: "";
display: block;
height: 1rpx;
width: calc(100% - 80px);
background: #eee;
position: absolute;
bottom: 0;
right: 0;
}
}
</style>

@ -1,111 +0,0 @@
<template>
<div class="friend-list-container g_bg_f_5">
<div class="friend-group-list">
<Empty v-if="friendGroupList.length === 0" :text="t('noFriendText')" />
<div
class="friend-group-item"
v-for="friendGroup in friendGroupList"
:key="friendGroup.key"
>
<div class="friend-group-title">
{{ friendGroup.key }}
</div>
<div
class="friend-item"
v-for="friend in friendGroup.data"
:key="friend.accountId"
@click="handleFriendItemClick(friend)"
>
<Avatar :account="friend.accountId" />
<div class="friend-name">{{ friend.appellation }}</div>
</div>
</div>
</div>
</div>
</template>
<script lang="ts" setup>
import Avatar from '../../../components/Avatar.vue'
import { autorun } from 'mobx'
import { onUnmounted, ref } from '../../../utils/transformVue'
import { friendGroupByPy } from '../../../utils/friend'
import { customNavigateTo } from '../../../utils/customNavigate'
import Empty from '../../../components/Empty.vue'
import { deepClone } from '../../../utils'
import { t } from '../../../utils/i18n'
import { V2NIMFriend } from 'nim-web-sdk-ng/dist/v2/NIM_UNIAPP_SDK/V2NIMFriendService'
type FriendItem = V2NIMFriend & { appellation: string }
const friendGroupList = ref<
{ key: string; data: { accountId: string; appellation: string }[] }[]
>([])
function handleFriendItemClick(friend: FriendItem) {
customNavigateTo({
url: `/pages/user-card/friend/index?account=${friend.accountId}`,
})
}
const uninstallFriendListWatch = autorun(() => {
const data = uni.$UIKitStore.uiStore.friends
.filter(
(item) =>
!uni.$UIKitStore.relationStore.blacklist.includes(item.accountId)
)
.map((item) => ({
accountId: item.accountId,
appellation: uni.$UIKitStore.uiStore.getAppellation({
account: item.accountId,
}),
}))
friendGroupList.value = deepClone(
friendGroupByPy(
data,
{
firstKey: 'appellation',
},
false
)
)
})
onUnmounted(() => {
uninstallFriendListWatch()
})
</script>
<style lang="scss" scoped>
.friend-group-item {
padding-left: 20px;
background-color: #fff;
}
.friend-group-title {
height: 40px;
line-height: 40px;
font-size: 14px;
color: #b3b7bc;
border-bottom: 1rpx solid #dbe0e8;
}
.friend-item {
// margin-top: 16px;
display: flex;
align-items: center;
padding: 12px 0;
.friend-name {
margin-left: 12px;
padding-right: 20px;
color: #333333;
flex: 1;
overflow: hidden; //
text-overflow: ellipsis; //
white-space: nowrap; //
}
}
</style>

@ -1,276 +0,0 @@
<template>
<div class="contact-list-container g_bg_f_5">
<!-- <div
class="dropdown-mark"
v-if="addDropdownVisible"
@touchstart="hideAddDropdown"
/> -->
<div class="navigation-bar">
<div class="logo-box" v-if="false">
<div>{{ t("contactText") }}</div>
</div>
<div :class="buttonClass" v-if="false">
<image src="https://yx-web-nosdn.netease.im/common/9ae07d276ba2833b678a4077960e2d1e/Group 1899.png" class="button-icon" @tap="showAddDropdown" style="width: 40px !important; height: 40px !important; border-radius: 50%" />
<div v-if="addDropdownVisible" class="dropdown-container">
<div class="add-menu-list">
<div class="add-menu-item" @tap="onDropdownClick('addFriend')">
<div :style="{ marginRight: '5px' }">
<Icon type="icon-tianjiahaoyou" />
</div>
{{ t("addFriendText") }}
</div>
<div class="add-menu-item" @tap="onDropdownClick('createGroup')" v-if="false">
<div :style="{ marginRight: '5px' }">
<Icon type="icon-chuangjianqunzu" />
</div>
{{ t("createTeamText") }}
</div>
</div>
</div>
</div>
</div>
<div class="contact-list">
<div class="contact-item-content g_bg_f_5">
<div class="contact-item" @click="onDropdownClick('addFriend')">
<img src="https://bocai-cms.oss-cn-beijing.aliyuncs.com/web-resource/bocaigongyinglian/add_friend.svg" alt="" style="width: 48px; height: 48px; vertical-align: middle" />
<!-- <Badge :num="unreadSysMsgCount" :style="{ position: 'absolute', top: '5px', left: '51px' }" /> -->
<span class="contact-item-title">添加好友</span>
<Icon iconClassName="more-icon" color="#999" type="icon-jiantou" />
</div>
<div class="contact-item" @click="handleValidMsgClick">
<Icon iconClassName="contact-item-icon contact-valid-icon" :size="48" type="icon-yanzheng" color="#fff" />
<Badge :num="unreadSysMsgCount" :style="{ position: 'absolute', top: '5px', left: '51px' }" />
<span class="contact-item-title"> {{ t("validMsgText") }}</span>
<Icon iconClassName="more-icon" color="#999" type="icon-jiantou" />
</div>
<div class="contact-item" @click="handleBlacklistClick">
<Icon iconClassName="contact-item-icon contact-blacklist-icon" :size="48" type="icon-lahei2" color="#fff" />
<span class="contact-item-title"> {{ t("blacklistText") }}</span>
<Icon iconClassName="more-icon" color="#999" type="icon-jiantou" />
</div>
<div class="contact-item" @click="onDropdownClick('innerAddress')" v-if="corpUserFlag && false">
<img src="https://bocai-cms.oss-cn-beijing.aliyuncs.com/web-resource/bocaigongyinglian/inner.svg" alt="" style="width: 48px; height: 48px; border-radius: 50%" />
<!-- <Badge :num="unreadSysMsgCount" :style="{ position: 'absolute', top: '5px', left: '51px' }" /> -->
<span class="contact-item-title">公司内部成员</span>
<Icon iconClassName="more-icon" color="#999" type="icon-jiantou" />
</div>
<!-- <div class="contact-item" @click="handleGroupContactClick">
<Icon
iconClassName="contact-item-icon contact-group-icon"
:size="48"
type="icon-team2"
color="#fff"
/>
<span class="contact-item-title"> {{ t('teamMenuText') }}</span>
<Icon iconClassName="more-icon" color="#999" type="icon-jiantou" />
</div> -->
</div>
<FriendList />
</div>
</div>
</template>
<script lang="ts" setup>
import Icon from "../../../components/Icon.vue";
import Badge from "../../../components/Badge.vue";
import FriendList from "./friend-list.vue";
import { onUnmounted, ref } from "../../../utils/transformVue";
import { onHide } from "@dcloudio/uni-app";
import { customNavigateTo } from "../../../utils/customNavigate";
import { autorun } from "mobx";
import { t } from "../../../utils/i18n";
const addDropdownVisible = ref(false);
const unreadSysMsgCount = ref(0);
const uninstallUnreadWatch = autorun(() => {
unreadSysMsgCount.value = uni.$UIKitStore.sysMsgStore.getTotalUnreadMsgsCount();
});
const corpUserFlag = ref(uni.getStorageSync("apply-userinfo").corpUserFlag);
const onDropdownClick = (urlType: "addFriend" | "createGroup") => {
const urlMap = {
//
addFriend: "/pages/Friend/add-friend/index",
//
createGroup: "/pages/Group/group-create/index",
//
innerAddress: "/pages/Contact/BcFriend",
};
addDropdownVisible.value = false;
customNavigateTo({
url: urlMap[urlType],
});
};
const handleValidMsgClick = () => {
uni.$UIKitStore.sysMsgStore.setAllApplyMsgRead();
customNavigateTo({
url: `/pages/Contact/contact-list/valid-list`,
});
};
const handleBlacklistClick = () => {
customNavigateTo({
url: `/pages/Contact/contact-list/black-list`,
});
};
const handleGroupContactClick = () => {
customNavigateTo({
url: `/pages/Contact/contact-list/group-list`,
});
};
const showAddDropdown = () => {
addDropdownVisible.value = true;
};
const hideAddDropdown = () => {
addDropdownVisible.value = false;
};
let buttonClass = "button-box";
// #ifdef MP
buttonClass = "button-box-mp";
// #endif
onUnmounted(() => {
uninstallUnreadWatch();
});
onHide(() => {
addDropdownVisible.value = false;
});
</script>
<style lang="scss" scoped>
page {
height: 100vh;
overflow: hidden;
}
.contact-list-container {
height: 100vh;
box-sizing: border-box;
}
.navigation-bar {
// height: 60px;
// border-bottom: 1rpx solid #e9eff5;
padding: 0 20px;
display: flex;
align-items: center;
justify-content: space-between;
// padding-top: var(--status-bar-height);
.logo-box {
display: flex;
align-items: center;
font-size: 20px;
font-weight: 500;
}
}
.contact-list {
height: calc(100% - 60px - var(--status-bar-height));
box-sizing: border-box;
width: 100%;
overflow-y: auto;
overflow-x: hidden;
.contact-item-content {
padding-bottom: 5px;
}
.contact-item {
height: 72px;
display: flex;
align-items: center;
padding: 0 16px;
background: #fff;
position: relative;
&:not(:last-child) {
border-bottom: 1px solid #f5f8fc;
}
.contact-item-icon {
height: 42px;
width: 42px;
border-radius: 50%;
text-align: center;
line-height: 39px;
font-size: 20px;
color: #fff;
}
.contact-valid-icon {
background-color: #60cfa7;
}
.contact-blacklist-icon {
background-color: #53c3f4;
}
.contact-group-icon {
background-color: #be65d9;
}
.contact-item-title {
margin-left: 12px;
font-size: 17px;
color: #333333;
flex: 1;
}
.more-icon {
margin: 0 16px;
color: #999999;
}
}
}
.dropdown-mark {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
z-index: 1;
}
.dropdown-container {
position: absolute;
top: -70px;
right: 30px;
min-width: 122px;
min-height: 40px;
background-color: #fff;
border: 1px solid #e6e6e6;
box-shadow: 0px 4px 7px rgba(133, 136, 140, 0.25);
border-radius: 8px;
z-index: 99;
}
.add-menu-list {
padding: 15px 10px;
.add-menu-item {
white-space: nowrap;
font-size: 16px;
padding-left: 5px;
margin-bottom: 10px;
height: 30px;
line-height: 30px;
display: flex;
align-items: center;
&:last-child {
margin-bottom: 0;
}
}
}
</style>

@ -1,25 +0,0 @@
<template>
<ContactList />
</template>
<script lang="ts" setup>
import ContactList from './contact-list/index.vue'
import { onShow } from '@dcloudio/uni-app'
import { setContactTabUnread, setTabUnread } from '../utils/msg';
import { trackInit } from '../utils/reporter'
trackInit('ContactUIKit')
onShow(() => {
setTabUnread()
setContactTabUnread()
})
</script>
<style>
page {
height: 100vh;
overflow: hidden;
}
</style>

@ -1,100 +0,0 @@
<template>
<div
class="p2p-msg-receipt-wrapper"
v-if="
conversationType ===
V2NIMConst.V2NIMConversationType.V2NIM_CONVERSATION_TYPE_P2P &&
p2pMsgReceiptVisible
"
>
<div v-if="p2pMsgRotateDeg == 360" class="icon-read-wrapper">
<Icon type="icon-read" :size="16"></Icon>
</div>
<div v-else class="sector">
<span
class="cover-1"
:style="`transform: rotate(${p2pMsgRotateDeg}deg)`"
></span>
<span
:class="p2pMsgRotateDeg >= 180 ? 'cover-2 cover-3' : 'cover-2'"
></span>
</div>
</div>
</template>
<script lang="ts" setup>
import { defineProps, withDefaults, ref, onMounted, computed } from 'vue'
import Icon from '../../../components/Icon.vue'
import { V2NIMConst } from 'nim-web-sdk-ng/dist/v2/NIM_UNIAPP_SDK'
import { autorun } from 'mobx'
import { V2NIMConversationForUI } from '@xkit-yx/im-store-v2/dist/types/types'
const props = withDefaults(
defineProps<{
conversation: V2NIMConversationForUI
}>(),
{}
)
// p2p p2p false
const p2pMsgReceiptVisible = uni.$UIKitStore.localOptions.p2pMsgReceiptVisible
const conversationType =
uni.$UIKitNIM.V2NIMConversationIdUtil.parseConversationType(
props.conversation.conversationId
)
const p2pMsgRotateDeg = computed(() => {
return (props?.conversation?.msgReceiptTime || 0) >=
(props?.conversation?.lastMessage?.messageRefer?.createTime || 0)
? 360
: 0
})
</script>
<style scoped lang="scss">
.p2p-msg-receipt-wrapper {
width: 18px;
height: 18px;
margin-right: 3px;
overflow: hidden;
line-height: 18px;
}
.icon-read-wrapper {
margin: 0px 3px 0px 0;
width: 18px;
height: 18px;
overflow: hidden;
display: flex;
align-items: center;
}
.sector {
display: inline-block;
position: relative;
overflow: hidden;
border: 2px solid #4c84ff;
width: 12px;
height: 12px;
background-color: #ffffff;
border-radius: 50%;
margin: 0px 3px 0 0;
.cover-1,
.cover-2 {
position: absolute;
top: 0;
width: 50%;
height: 100%;
background-color: #ffffff;
}
.cover-1 {
background-color: #4c84ff;
transform-origin: right;
}
.cover-3 {
right: 0;
background-color: #4c84ff;
}
}
</style>

@ -1,458 +0,0 @@
<template>
<div
:class="[
'conversation-item-container',
{
'show-action-list': showMoreActions,
'stick-on-top': conversation.stickTop,
},
props.heihei,
]"
class="u-skeleton"
@touchstart="handleTouchStart"
@touchmove="handleTouchMove"
@click="handleConversationItemClick()"
>
<div class="conversation-item-content">
<div class="conversation-item-left u-skeleton-fillet">
<div class="unread" v-if="unread">
<div class="dot" v-if="isMute"></div>
<div class="badge" v-else>{{ unread }}</div>
</div>
<Avatar class="" :account="to" size="48" :avatar="teamAvatar" />
</div>
<div class="conversation-item-right">
<div class="conversation-item-top u-skeleton-fillet">
<Appellation :pid="props.conversation.conversationId" class="conversation-item-title" fontSize="17" v-if="conversation.type === V2NIMConst.V2NIMConversationType.V2NIM_CONVERSATION_TYPE_P2P && !loading" :account="to" />
<span v-else class="conversation-item-title">
{{ sessionName }}
</span>
<span class="conversation-item-time" :data-time="date">{{ date }}</span>
</div>
<div class="conversation-item-desc u-skeleton-fillet">
<span v-if="beMentioned && !loading" class="beMentioned">
{{ "[" + t("someoneText") + "@" + t("meText") + "]" }}
</span>
<!-- <ConversationItemIsRead v-if="showSessionUnread" :conversation="props.conversation"></ConversationItemIsRead> -->
<span class="conversation-item-desc-content">{{ lastMsgContent }}</span>
<Icon v-if="isMute" iconClassName="conversation-item-desc-state" type="icon-xiaoximiandarao" color="#ccc" />
</div>
</div>
</div>
<div class="right-action-list">
<div v-for="action in moreActions" :key="action.type" :class="['right-action-item', action.class]" @click="() => handleClick(action.type)">
{{ action.name }}
</div>
</div>
<!-- <u-skeleton :loading="loading" :animation="true" bgColor="#ededed"></u-skeleton> -->
</div>
<u-skeleton :loading="loading" :animation="true" el-color="#ededed" bg-color="#fff"></u-skeleton>
</template>
<script lang="ts" setup>
import Avatar from "../../../components/Avatar.vue";
import Appellation from "../../../components/Appellation.vue";
import Icon from "../../../components/Icon.vue";
import { getMsgContentTipByType } from "../../../utils/msg";
import { computed, onUpdated, withDefaults, onMounted, ref } from "../../../utils/transformVue";
import dayjs from "dayjs";
import { t } from "../../../utils/i18n";
import { V2NIMConst } from "nim-web-sdk-ng/dist/v2/NIM_UNIAPP_SDK";
import { V2NIMConversationForUI } from "@xkit-yx/im-store-v2/dist/types/types";
import ConversationItemIsRead from "./conversation-item-isRead.vue";
const props = withDefaults(
defineProps<{
conversation: V2NIMConversationForUI;
showMoreActions?: boolean;
loading: boolean;
heihei: "";
}>(),
{ showMoreActions: false }
);
let pageScroll = ref(false);
onMounted(() => {
uni.$on("pageScroll", (e: any) => {
console.log("pageScroll", e);
if (Math.abs(e.detail.deltaY) > 0) {
pageScroll.value = true;
}
});
});
const emit = defineEmits(["click", "delete", "stickyToTop", "leftSlide"]);
const moreActions = computed(() => {
return [
{
name: props.conversation.stickTop ? t("deleteStickTopText") : t("addStickTopText"),
class: "action-top",
type: "action-top",
},
{
name: t("deleteSessionText"),
class: "action-delete",
type: "action-delete",
},
];
});
const handleClick = (type: string) => {
if (type === "action-top") {
emit("stickyToTop", props.conversation);
} else {
emit("delete", props.conversation);
}
};
//
const teamAvatar = computed(() => {
if (props.conversation.type === V2NIMConst.V2NIMConversationType.V2NIM_CONVERSATION_TYPE_TEAM) {
const { avatar } = props.conversation;
return avatar;
}
});
//
const sessionName = computed(() => {
if (props.conversation.name) {
return props.conversation.name;
}
return props.conversation.conversationId;
});
//
const lastMsgContent = computed(() => {
const lastMsg = props.conversation.lastMessage;
if (lastMsg) {
const { sendingState, messageType, lastMessageState } = lastMsg;
if (lastMessageState === V2NIMConst.V2NIMLastMessageState.V2NIM_MESSAGE_STATUS_REVOKE) {
return t("recall");
}
if (messageType === void 0) {
return "";
}
if (messageType === V2NIMConst.V2NIMMessageType.V2NIM_MESSAGE_TYPE_NOTIFICATION) {
return t("conversationNotificationText");
}
if (sendingState === V2NIMConst.V2NIMMessageSendingState.V2NIM_MESSAGE_SENDING_STATE_SENDING) {
return "";
}
if (sendingState === V2NIMConst.V2NIMMessageSendingState.V2NIM_MESSAGE_SENDING_STATE_FAILED) {
return t("conversationSendFailText");
}
let _str = "[多媒体]";
if (!lastMsg.text && lastMsg.attachment && lastMsg.attachment.raw) {
if (!lastMsg.text && lastMsg.attachment && lastMsg.attachment.raw && lastMsg.attachment.ext == ".mp4" && lastMsg.attachment.url) {
_str = "[视频]";
} else if (JSON.parse(lastMsg.attachment.raw).type == 100002) {
_str = "[工单] " + JSON.parse(lastMsg.attachment.raw).userName;
} else if (JSON.parse(lastMsg.attachment.raw).type == 100000) {
_str = "[职位] " + JSON.parse(lastMsg.attachment.raw).title;
} else {
_str = "[新消息] ";
}
}
if (!lastMsg.text && lastMsg.attachment && lastMsg.attachment.ext == ".mp3") {
_str = "[语音]";
}
if (!lastMsg.text && lastMsg.attachment && (lastMsg.attachment.ext == ".jpg" || lastMsg.attachment.ext == ".png" || lastMsg.attachment.ext == ".jpeg" || lastMsg.attachment.ext == ".gif")) {
_str = "[图片]";
}
return getMsgContentTipByType({
messageType: lastMsg.messageType,
text: lastMsg.text ? lastMsg.text : _str,
});
}
return "";
});
const to = computed(() => {
const res = uni.$UIKitNIM.V2NIMConversationIdUtil.parseConversationTargetId(props.conversation.conversationId);
return res;
});
const date = computed(() => {
const now = dayjs();
// console.log(dayjs(props.conversation.lastMessage?.messageRefer.createTime).format('YYYY-MM-DD HH:mm') +" ");
// console.log(dayjs(props.conversation.updateTime).format('YYYY-MM-DD HH:mm') +" ");
const time = props.conversation.lastMessage?.messageRefer.createTime || props.conversation.updateTime;
// const time = props.conversation.updateTime;
if (!time) {
return "";
}
const messageTime = dayjs(time);
// 1. 1
if (now.diff(messageTime, "minute") < 1) {
return "刚刚";
}
// 2. 17:45
if (messageTime.isSame(now, "day")) {
return messageTime.format("HH:mm");
}
// 3. 17:34
if (messageTime.isSame(now.subtract(1, "day"), "day")) {
return `昨天 ${messageTime.format("HH:mm")}`;
}
// 4. 52
if (messageTime.isSame(now, "year")) {
const month = messageTime.month() + 1;
const day = messageTime.date();
return `${month}${day}`;
}
// 5. 202478
const year = messageTime.year();
const month = messageTime.month() + 1;
const day = messageTime.date();
return `${year}${month}${day}`;
});
const max = 99;
const unread = computed(() => {
return props.conversation.unreadCount > 0 ? (props.conversation.unreadCount > max ? `${max}+` : props.conversation.unreadCount + "") : "";
});
const isMute = computed(() => {
return !!props.conversation.mute;
});
const beMentioned = computed(() => {
return !!props.conversation.beMentioned;
});
const showSessionUnread = computed(() => {
const myUserAccountId = uni.$UIKitNIM.V2NIMLoginService.getLoginUser();
if (props.conversation.type === V2NIMConst.V2NIMConversationType.V2NIM_CONVERSATION_TYPE_P2P) {
return props?.conversation?.lastMessage?.messageRefer.senderId === myUserAccountId && props?.conversation?.lastMessage?.messageType !== V2NIMConst.V2NIMMessageType.V2NIM_MESSAGE_TYPE_CALL && props?.conversation?.lastMessage?.messageType !== V2NIMConst.V2NIMMessageType.V2NIM_MESSAGE_TYPE_NOTIFICATION && props?.conversation?.lastMessage?.sendingState === V2NIMConst.V2NIMMessageSendingState.V2NIM_MESSAGE_SENDING_STATE_SUCCEEDED && props?.conversation?.lastMessage?.lastMessageState !== V2NIMConst.V2NIMLastMessageState.V2NIM_MESSAGE_STATUS_REVOKE;
} else {
return false;
}
});
// action
let startX = 0,
startY = 0;
//
function handleTouchStart(event: TouchEvent) {
startX = event.changedTouches[0].pageX;
startY = event.changedTouches[0].pageY;
pageScroll.value = false;
}
function handleTouchMove(event: TouchEvent) {
const moveEndX = event.changedTouches[0].pageX;
const moveEndY = event.changedTouches[0].pageY;
const X = moveEndX - startX;
const Y = moveEndY - startY;
// console.log("X", X, "Y", Y);
console.log("pageScroll.value", pageScroll.value);
if (Math.abs(Y) > Math.abs(X) || pageScroll.value == true) {
return;
}
const horizontalThreshold = 50;
const verticalThreshold = 50;
if (Math.abs(X) > Math.abs(Y) && Math.abs(X) > verticalThreshold) {
if (X < -horizontalThreshold) {
emit("leftSlide", props.conversation);
// emit("leftSlide", null);
} else if (X > horizontalThreshold) {
// emit("leftSlide", props.conversation);
emit("leftSlide", null);
}
}
}
function handleConversationItemClick() {
uni.setStorageSync("selectopenimid", props.conversation.conversationId);
if (props.showMoreActions) {
emit("leftSlide", null);
return;
}
emit("click", props.conversation);
}
onUpdated(() => {
console.log("onUpdated", props.conversation.unreadCount);
});
</script>
<style lang="scss" scoped>
$cellHeight: 72px;
.conversation-item-container {
position: relative;
transition: transform 0.3s;
background-color: #fff;
&.show-action-list {
transform: translateX(-200px);
}
&.stick-on-top {
background: #efefef;
}
.beMentioned {
color: #ff4d4f;
}
.content {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
}
.right-action-list {
position: absolute;
top: 0;
right: -200px;
bottom: 0;
width: 200px;
.right-action-item {
width: 100px;
display: inline-block;
color: #fff;
text-align: center;
height: $cellHeight;
line-height: $cellHeight;
}
.action-top {
background: #337eff;
}
.action-delete {
background: #fa9d3b;
}
}
.conversation-item-content {
display: flex;
align-items: center;
padding: 10px 10px;
height: $cellHeight;
box-sizing: border-box;
// background-color: #fff;
}
.conversation-item-left {
position: relative;
.conversation-item-badge {
position: absolute;
top: 0px;
right: 0px;
z-index: 10;
}
}
.conversation-item-right {
flex: 1;
width: 0;
margin-left: 10px;
&:after {
content: "";
display: block;
height: 1rpx;
width: calc(100% - 80px);
background: #eee;
position: absolute;
top: 0;
right: 0;
}
}
.mmp0 .conversation-item-right::after {
height: 0;
}
.conversation-item-top {
margin-bottom: 5px;
display: flex;
justify-content: space-between;
align-items: center;
.conversation-item-title {
overflow: hidden; //
text-overflow: ellipsis; //
white-space: nowrap; //
}
.conversation-item-time {
font-size: 12px;
color: #cccccc;
text-align: right;
width: 100px;
flex-shrink: 0;
}
}
.conversation-item-desc {
font-size: 14px;
color: #999;
display: flex;
flex-direction: row;
align-items: center;
justify-content: space-between;
.conversation-item-desc-content {
overflow: hidden; //
text-overflow: ellipsis; //
white-space: nowrap; //
flex: 1;
}
.conversation-item-desc-state {
margin-left: 10px;
}
}
.dot {
background-color: #ff4d4f;
color: #fff;
width: 10px;
height: 10px;
border-radius: 5px;
box-sizing: border-box;
z-index: 99;
}
.badge {
background-color: #ff4d4f;
color: #fff;
font-size: 12px;
min-width: 20px;
height: 20px;
line-height: 19px;
border-radius: 10px;
padding: 0 5px;
box-sizing: border-box;
text-align: center;
z-index: 99;
position: relative;
}
.unread {
position: absolute;
right: -4px;
top: -2px;
z-index: 99;
}
</style>

@ -1,365 +0,0 @@
<template>
<div class="conversation-wrapper">
<!-- {{ conversationList }} -->
<!-- 页面初始化的过程中sessionList编译到小程序和h5出现sessionList为undefined的情况即使给了默认值为空数组故在此处进行判断 -->
<div class="conversation-list-wrapper " v-if="conversationList && conversationList.length > 0">
<!-- 此处的key如果用session.id会在ios上渲染存在问题会出现会话列表显示undefined -->
<div v-for="(conversation, index) in conversationList" class="ConversationItem" style="min-height:72px" :key="conversation.renderKey">
<ConversationItem :key="conversation.renderKey" :loading="loading"
:showMoreActions="currentMoveSessionId === conversation.conversationId"
:conversation="conversation"
@delete="handleSessionItemDeleteClick"
:heihei="'mmp' + index"
@stickyToTop="handleSessionItemStickTopChange"
@click="handleSessionItemClick"
@leftSlide="handleSessionItemLeftSlide"
/>
</div>
</div>
<!-- <div style="height: 48px; background-color: #ededed" v-if="conversationList && conversationList.length > 0"></div> -->
<div v-if="conversationList.length == 0 && !loading" style="padding-top: 130px; background-color: #ededed">
<rh-empty text="暂无会话" style="margin-top: 0px" />
</div>
<!-- <u-skeleton :loading="loading" :animation="true" el-color="#fff" bg-color="#000"></u-skeleton> -->
</div>
</template>
<script lang="ts" setup>
import { computed,getCurrentInstance } from "vue";
import { onUnmounted, ref, defineExpose, watch } from "../../../utils/transformVue";
import { autorun } from "mobx";
import { onHide } from "@dcloudio/uni-app";
import Icon from "../../../components/Icon.vue";
import NetworkAlert from "../../../components/NetworkAlert.vue";
import Empty from "../../../components/Empty.vue";
import ConversationItem from "./conversation-item.vue";
import { setContactTabUnread, setTabUnread } from "../../../utils/msg";
import { t } from "../../../utils/i18n";
import { customNavigateTo } from "../../../utils/customNavigate";
import { deepClone } from "../../../utils";
import { V2NIMConversation } from "nim-web-sdk-ng/dist/v2/NIM_UNIAPP_SDK/V2NIMConversationService";
const corpUserFlag = ref(uni.getStorageSync("apply-userinfo").corpUserFlag);
const G = getCurrentInstance().appContext.app.config.globalProperties.G;
const appType = ref(uni.getStorageSync("requestComeFrom"));
const conversationList = ref<V2NIMConversation[]>([]);
defineExpose({
conversationList,
});
const addDropdownVisible = ref(false);
const loading = ref(true);
const currentMoveSessionId = ref("");
let buttonClass = "button-box";
// #ifdef MP
buttonClass = "button-box-mp";
// #endif
const handleSessionItemLeftSlide = (conversation: V2NIMConversation | null) => {
// conversation null
if (conversation) {
currentMoveSessionId.value = conversation.conversationId;
} else {
currentMoveSessionId.value = "";
}
};
let flag = false;
//
const handleSessionItemClick = async (conversation: V2NIMConversation) => {
if (flag) return;
currentMoveSessionId.value = "";
try {
flag = true;
await uni.$UIKitStore.uiStore.selectConversation(conversation.conversationId);
const itemUserInfo = await uni.$UIKitStore.userStore.getUserActive(conversation.conversationId.split('|')[2])
let _title = '';
console.log('appType.valueappType.valueappType.value',appType.value);
if(itemUserInfo.serverExtension && appType.value == 'isToB'){
_title = itemUserInfo.name + '@' + JSON.parse(itemUserInfo.serverExtension).fullName;
}else{
_title = itemUserInfo.name;
}
customNavigateTo({
url: "/pages/Chat/index?ctitle=" + _title,
});
} catch {
uni.showToast({
title: t("selectSessionFailText"),
icon: "error",
});
} finally {
flag = false;
}
};
//
const handleSessionItemDeleteClick = async (conversation: V2NIMConversation) => {
try {
await uni.$UIKitStore.conversationStore.deleteConversationActive(conversation.conversationId);
} catch {
uni.showToast({
title: t("deleteSessionFailText"),
icon: "error",
});
}
};
//
const handleSessionItemStickTopChange = async (conversation: V2NIMConversation) => {
if (conversation.stickTop) {
try {
await uni.$UIKitStore.conversationStore.stickTopConversationActive(conversation.conversationId, false);
} catch {
uni.showToast({
title: t("deleteStickTopFailText"),
icon: "error",
});
}
} else {
try {
await uni.$UIKitStore.conversationStore.stickTopConversationActive(conversation.conversationId, true);
} catch {
uni.showToast({
title: t("addStickTopFailText"),
icon: "error",
});
}
}
};
const showAddDropdown = () => {
addDropdownVisible.value = true;
};
const hideAddDropdown = () => {
addDropdownVisible.value = false;
};
const onDropdownClick = (urlType: "addFriend" | "createGroup") => {
const urlMap = {
//
addFriend: "/pages/Friend/add-friend/index",
//
createGroup: "/pages/Group/group-create/index",
};
addDropdownVisible.value = false;
customNavigateTo({
url: urlMap[urlType],
});
};
const jumpToSearch = () => {
customNavigateTo({
url: "/pages/Conversation/conversation-search/index",
});
};
onHide(() => {
addDropdownVisible.value = false;
});
const conversationListWatch = autorun(() => {
const conversations = deepClone(uni.$UIKitStore?.uiStore?.conversations) || [];
// renderKey
const conversationsWithKey = conversations.map((conversation: V2NIMConversation) => ({
...conversation,
renderKey: conversation.conversationId,
}));
//
const stickyList = conversationsWithKey.filter((conv: V2NIMConversation) => conv.stickTop);
const normalList = conversationsWithKey.filter((conv: V2NIMConversation) => !conv.stickTop);
// console.log("stickyList", stickyList);
// console.log("normalList", normalList);
//
const sortStickyList = (list: V2NIMConversation[]) => list.sort((a, b) => new Date(b.updateTime).getTime() - new Date(a.updateTime).getTime());
const sortNormalList = (list: V2NIMConversation[]) => list.sort((a, b) => new Date(b.lastMessage?.messageRefer.createTime || b.updateTime).getTime() - new Date(a.lastMessage?.messageRefer.createTime || a.updateTime).getTime());
//
conversationList.value = [...sortStickyList(stickyList), ...sortNormalList(normalList)];
setTimeout(() => {
loading.value = false;
}, 2000);
setTabUnread();
});
// const conversationListWatch = autorun(() => {
// const conversations = deepClone(uni.$UIKitStore?.uiStore?.conversations) || [];
// // renderKey
// const conversationsWithKey = conversations.map((conversation: V2NIMConversation) => ({
// ...conversation,
// renderKey: conversation.conversationId,
// }));
// //
// const stickyList = conversationsWithKey.filter((conv: V2NIMConversation) => conv.stickTop);
// const normalList = conversationsWithKey.filter((conv: V2NIMConversation) => !conv.stickTop);
// // updateTime
// const sortList = (list: V2NIMConversation[]) => list.sort((a: V2NIMConversation, b: V2NIMConversation) => new Date(b.updateTime).getTime() - new Date(a.updateTime).getTime()); //list
// //
// conversationList.value = [...sortList(stickyList), ...sortList(normalList)];
// setTimeout(() => {
// loading.value = false;
// }, 2000);
// console.log("conversationListWatch", conversationList.value);
// setTabUnread();
// });
const getTotalUnreadMsgsCountWatch = autorun(() => {
// console
console.log(
"unreadSysMsgCount:",
uni.$UIKitStore?.sysMsgStore?.getTotalUnreadMsgsCount()
);
setContactTabUnread();
});
onUnmounted(() => {
conversationListWatch();
getTotalUnreadMsgsCountWatch();
});
</script>
<style lang="scss" scoped>
.conversation-wrapper {
overflow: hidden;
}
.navigation-bar {
position: fixed;
// height: 60px;
// border-bottom: 1rpx solid #e9eff5;
// padding: 0 20px;
display: flex;
align-items: center;
justify-content: space-between;
// padding-top: var(--status-bar-height);
background-color: #fff;
width: 100%;
opacity: 1;
z-index: 999;
}
.conversation-search {
display: flex;
align-items: center;
height: 54px;
box-sizing: border-box;
overflow: hidden;
padding: 10px;
}
.search-input-wrapper {
flex: 1;
display: flex;
align-items: center;
height: 34px;
overflow: hidden;
box-sizing: border-box;
padding: 8px 10px;
background: #f3f5f7;
border-radius: 5px;
}
.search-input {
margin-left: 5px;
color: #999999;
}
.search-icon-wrapper {
height: 22px;
display: flex;
align-items: center;
}
.block {
height: 60px;
width: 100%;
display: block;
padding-top: var(--status-bar-height);
}
.conversation-list-wrapper {
// height: calc(100% - 60px - var(--status-bar-height));
min-height: 85vh;
background-color: #ededed;
box-sizing: border-box;
width: 100%;
overflow-y: auto;
overflow-x: hidden;
}
.logo-box {
display: flex;
align-items: center;
font-size: 20px;
font-weight: 500;
.logo-img {
width: 32px;
height: 32px;
margin-right: 10px;
}
}
.button-icon-add {
position: relative;
right: 20px;
}
.dropdown-mark {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
z-index: 1;
}
.dropdown-container {
position: absolute;
top: -70px;
right: 30px;
min-width: 122px;
min-height: 40px;
background-color: #fff;
border: 1rpx solid #eee;
box-shadow: 0px 4px 7px rgba(133, 136, 140, 0.25);
border-radius: 8px;
z-index: 99;
}
.add-menu-list {
padding: 15px 10px;
.add-menu-item {
white-space: nowrap;
font-size: 16px;
padding-left: 5px;
margin-bottom: 10px;
height: 30px;
line-height: 30px;
display: flex;
align-items: center;
&:last-child {
margin-bottom: 0;
}
}
}
.conversation-block {
width: 100%;
height: 72px;
}
.ConversationItem:first-child{
border-radius: 6px 6px 0 0 ;
overflow: hidden;
}
.ConversationItem:last-child{
border-radius: 0 0 6px 6px;
overflow: hidden;
}
</style>

@ -1,35 +0,0 @@
{
"compilerOptions": {
"target": "esnext",
"module": "esnext",
"strict": true,
"jsx": "preserve",
"moduleResolution": "node",
"experimentalDecorators": true,
"skipLibCheck": true,
"esModuleInterop": true,
"allowSyntheticDefaultImports": true,
"forceConsistentCasingInFileNames": true,
"useDefineForClassFields": true,
"sourceMap": true,
"strictFunctionTypes": false,
"preserveValueImports": false,
"isolatedModules": false,
"baseUrl": ".",
"types": ["node", "webpack-env", "vue/types", "vue-router/types"],
"paths": {
"@/*": ["src/*"]
},
"lib": ["esnext", "dom", "dom.iterable", "scripthost"]
},
"files": ["*.d.ts", "**/*.ts", "**/*.tsx", "**/*.vue", "**/*.ts", "**/*.tsx"],
"include": [
"*.d.ts",
"**/*.ts",
"**/*.tsx",
"**/*.vue",
"**/*.ts",
"**/*.tsx"
],
"exclude": ["node_modules"]
}

@ -1,90 +0,0 @@
import { t } from './i18n'
import { V2NIMConst } from 'nim-web-sdk-ng/dist/v2/NIM_UNIAPP_SDK'
// 自定义的一些事件常量
export const events = {
// 自己发出一条消息
SEND_MSG: 'sendMsg',
// 发送消息失败
SEND_MSG_FAILED: 'sendMsgFailed',
// 收到一条消息
ON_MSG: 'onMsg',
// 加载更多
ON_LOAD_MORE: 'onLoadMore',
// 首次进入聊天页并获取历史记录
ON_CHAT_MOUNTED: 'onChatMounted',
// 重新编辑撤回消息
ON_REEDIT_MSG: 'onReEditMsg',
// 页面触底
ON_REACH_BOTTOM: 'onReachBottom',
// 页面触顶
ON_REACH_TOP: 'onReactTop',
// 回复消息
REPLY_MSG: 'replyMsg',
// input框聚焦
ON_INPUT_FOCUS_CHANGE: 'onInputFocusChange',
// input框失焦
ON_INPUT_BLUR: 'onInputBlur',
// 滚动到底部
ON_SCROLL_BOTTOM: 'onScrollBottom',
// @群成员
AIT_TEAM_MEMBER: 'aitTeamMember',
// 表情框弹起与收起变化
EMOJI_AREA_CHANGE: 'emojiAreaChange',
// 获取历史消息
GET_HISTORY_MSG: 'getHistoryMsg',
// 取消转发消息
CANCEL_FORWARD_MSG: 'cancelForwardMsg',
// 确认转发消息
CONFIRM_FORWARD_MSG: 'confirmForwardMsg',
// @消息 @群成员
HANDLE_AIT_MEMBER: 'handleAitMember',
// 关闭@弹窗
CLOSE_AIT_POPUP: 'closeAitPopup',
// 表情点击
EMOJI_CLICK: 'emojiClick',
// 表情删除
EMOJI_DELETE: 'emojiDelete',
// 表情发送
EMOJI_SEND: 'emojiSend',
// 好友选择
FRIEND_SELECT: 'friendSelect',
// 处理滚动穿透
HANDLE_MOVE_THROUGH: 'handleMoveThrough',
// 关闭表情、语音面板
CLOSE_PANEL: 'closePanel',
// 语音消息url改变
AUDIO_URL_CHANGE: 'audioUrlChange',
}
export const HISTORY_LIMIT = 15
export const MSG_ID_FLAG = 'message-item-'
export const AT_ALL_ACCOUNT = 'ait_all'
export const ALLOW_AT = 'yxAllowAt'
export const REPLY_MSG_TYPE_MAP: { [key: number]: string } = {
[V2NIMConst.V2NIMMessageType.V2NIM_MESSAGE_TYPE_IMAGE]: t('imgMsgText'),
[V2NIMConst.V2NIMMessageType.V2NIM_MESSAGE_TYPE_AUDIO]: t('audioMsgText'),
[V2NIMConst.V2NIMMessageType.V2NIM_MESSAGE_TYPE_VIDEO]: t('videoMsgText'),
[V2NIMConst.V2NIMMessageType.V2NIM_MESSAGE_TYPE_FILE]: t('fileMsgText'),
}
export const STORAGE_KEY = '__yx_im_options__'
export const callTypeMap = {
audio: '1',
video: '2',
}
export const g2StatusMap: any = {
1: t('callDurationText'),
2: t('callCancelText'),
3: t('callRejectedText'),
4: t('callTimeoutText'),
5: t('callBusyText'),
}
export const msgRecallTime = 2 * 60 * 1000

@ -1,17 +0,0 @@
const preUrl = '/root/NEUIKit'
export function customNavigateTo(options: { url: string }) {
uni.navigateTo({ ...options, url: preUrl + options.url })
}
export function customRedirectTo(options: { url: string }) {
uni.redirectTo({ ...options, url: preUrl + options.url })
}
export function customSwitchTab(options: { url: string }) {
uni.switchTab({ ...options, url: preUrl + options.url })
}
export function customReLaunch(options: { url: string }) {
uni.reLaunch({ ...options, url: preUrl + options.url })
}

@ -1,58 +0,0 @@
import { t } from './i18n'
export function caculateTimeago(dateTimeStamp: number): string {
const minute = 1000 * 60 // 把分,时,天,周,半个月,一个月用毫秒表示
const hour = minute * 60
const day = hour * 24
const week = day * 7
const now = new Date().getTime() // 获取当前时间毫秒
const diffValue = now - dateTimeStamp // 时间差
let result = ''
if (diffValue < 0) {
return t('nowText')
}
const minC = Math.floor(diffValue / minute) // 计算时间差的分,时,天,周,月
const hourC = Math.floor(diffValue / hour)
const dayC = Math.floor(diffValue / day)
const weekC = Math.floor(diffValue / week)
if (weekC >= 1 && weekC <= 4) {
result = ` ${weekC}${t('weekText')}`
} else if (dayC >= 1 && dayC <= 6) {
result = ` ${dayC}${t('dayText')}`
} else if (hourC >= 1 && hourC <= 23) {
result = ` ${hourC}${t('hourText')}`
} else if (minC >= 1 && minC <= 59) {
result = ` ${minC}${t('minuteText')}`
} else if (diffValue >= 0 && diffValue <= minute) {
result = t('nowText')
} else {
const datetime = new Date()
datetime.setTime(dateTimeStamp)
const Nyear = datetime.getFullYear()
const Nmonth =
datetime.getMonth() + 1 < 10
? `0${datetime.getMonth() + 1}`
: datetime.getMonth() + 1
const Ndate =
datetime.getDate() < 10 ? `0${datetime.getDate()}` : datetime.getDate()
result = `${Nyear}-${Nmonth}-${Ndate}`
}
return result
}
export const formatDateRange = (type) => {
const date = new Date()
let year = date.getFullYear()
let month: string | number = date.getMonth() + 1
let day: string | number = date.getDate()
if (type === 'start') {
year = year - 100
} else if (type === 'end') {
year = year
}
month = month > 9 ? month : '0' + month
day = day > 9 ? day : '0' + day
return `${year}-${month}-${day}`
}

@ -1,79 +0,0 @@
// #ifdef APP-PLUS
import pinyin from 'pinyin'
// #endif
export const friendGroupByPy = <
T extends {
[key: string]: any
}
>(
arr: T[],
keys: {
firstKey: string
secondKey?: string
thirdKey?: string
},
isLowerCase = true
): { key: string; data: T[] }[] => {
const res: { [key: string]: T[] } = {}
const OTHER_TAG = '#'
const add = (k: string, v: T) => {
const _k = isLowerCase ? k.toLowerCase() : k.toUpperCase()
if (!res[_k]) {
res[_k] = [v]
} else {
res[_k].push(v)
}
}
arr.forEach((item) => {
const v =
item[keys.firstKey] ||
item[keys.secondKey || ''] ||
item[keys.thirdKey || '']
if (!!v && typeof v === 'string') {
const str = v[0]
if (/^[a-zA-Z]$/.test(str)) {
add(str.toLowerCase(), item)
} else if (/^[\u4e00-\u9fa5]$/.test(str)) {
const en = '*abcdefghjklmnopqrstwxyz'.split('')
// #ifdef APP-PLUS
// @ts-ignore
const k = en.find((k) => {
const py = pinyin(str, {
style: 'FIRST_LETTER',
})
return py[0][0] === k
})
// #endif
// #ifndef APP-PLUS
const zh = '阿八嚓哒妸发旮哈讥咔垃痳拏噢妑七呥扨它穵夕丫帀'.split('')
// @ts-ignore
const k = en.find(
(k, ki) =>
(!zh[ki - 1] || zh[ki - 1].localeCompare(str, 'zh') <= 0) &&
str.localeCompare(zh[ki], 'zh') == -1
)
// #endif
if (k && k !== '*') {
add(k, item)
} else {
add(OTHER_TAG, item)
}
} else {
add(OTHER_TAG, item)
}
} else {
add(OTHER_TAG, item)
}
})
const data = Object.keys(res).map((k) => ({ key: k, data: res[k] }))
const sortData = data
.filter((item) => item.key !== OTHER_TAG)
.sort((a, b) => a.key.localeCompare(b.key, 'en'))
const otherData = data.filter((item) => item.key === OTHER_TAG)
return sortData.concat(otherData)
}

@ -1,12 +0,0 @@
import zh from '../locale/zh-Hans'
const messages = {
zh,
}
const localeMap = {
'zh-Hans': 'zh',
'zh-Hant': 'zh',
}
export const t = (key: string) => {
return zh[key]
}

@ -1,151 +0,0 @@
import { events } from './constants'
export const getUniPlatform = () => {
// @ts-ignore
return uni.getSystemInfoSync().uniPlatform
}
export const getPlatform = () => {
// @ts-ignore
return uni.getSystemInfoSync().platform
}
// 是否是android app
export const isAndroidApp =
uni.getSystemInfoSync().platform == 'android' &&
uni.getSystemInfoSync().uniPlatform == 'app'
// 是否是Ios app
export const isIosApp =
uni.getSystemInfoSync().platform == 'ios' &&
uni.getSystemInfoSync().uniPlatform == 'app'
// 是否是Ios web
export const isIosWeb =
uni.getSystemInfoSync().uniPlatform === 'web' &&
uni.getSystemInfoSync().platform === 'ios'
// 是否是App
export const isApp = uni.getSystemInfoSync().uniPlatform == 'app'
// 是否是微信小程序
export const isWxApp = uni.getSystemInfoSync().uniPlatform == 'mp-weixin'
// 是否是web
export const isWeb = uni.getSystemInfoSync().uniPlatform === 'web'
// @ts-ignore
export function deepClone(source: any, visited = new WeakMap()) {
if (source === null || typeof source !== 'object') {
return source
}
if (visited.has(source)) {
return visited.get(source)
}
// @ts-ignore
let clone
if (source instanceof Date) {
clone = new Date(source.getTime())
} else if (source instanceof RegExp) {
clone = new RegExp(source)
} else if (source instanceof Map) {
clone = new Map()
visited.set(source, clone)
source.forEach((value, key) => {
// @ts-ignore
clone.set(key, deepClone(value, visited))
})
} else if (source instanceof Set) {
clone = new Set()
visited.set(source, clone)
source.forEach((value) => {
// @ts-ignore
clone.add(deepClone(value, visited))
})
} else if (Array.isArray(source)) {
clone = []
// @ts-ignore
visited.set(source, clone)
for (let i = 0; i < source.length; i++) {
clone[i] = deepClone(source[i], visited)
}
} else {
clone = Object.create(Object.getPrototypeOf(source))
visited.set(source, clone)
for (const prop in source) {
if (source.hasOwnProperty(prop)) {
clone[prop] = deepClone(source[prop], visited)
}
}
}
return clone
}
export function stopAllAudio() {
uni.$emit(events.AUDIO_URL_CHANGE, '')
}
/**
*
*/
export const convertSecondsToTime = (seconds: number): string | null => {
if (!seconds) {
return null
}
const hours: number = Math.floor(seconds / 3600)
const minutes: number = Math.floor((seconds - hours * 3600) / 60)
const remainingSeconds: number = seconds - hours * 3600 - minutes * 60
let timeString = ''
const includeHours = seconds >= 3600
if (includeHours) {
if (hours < 10) {
timeString += '0'
}
timeString += hours.toString() + ':'
}
if (minutes < 10) {
timeString += '0'
}
timeString += minutes.toString() + ':'
if (remainingSeconds < 10) {
timeString += '0'
}
timeString += remainingSeconds.toString()
return timeString
}
export const startCall = (options: {
remoteUserAccid: string
currentUserAccid: string
type: number
remoteShowName: string
}) => {
try {
// @ts-ignore
uni.$UIKitCallKit.toCallPage(
{
calledAccount: options.remoteUserAccid,
// currentUserAccid: options.currentUserAccid,
type: options.type,
calledShowName: options.remoteShowName,
},
() => {
console.log('toCallPage: ', {
remoteUserAccid: options.remoteUserAccid,
currentUserAccid: options.currentUserAccid,
type: options.type,
remoteShowName: options.remoteShowName,
})
}
)
} catch (error) {
console.log('handleVideoCall error', error)
}
}

@ -1,117 +0,0 @@
import { V2NIMConst } from 'nim-web-sdk-ng/dist/v2/NIM_UNIAPP_SDK'
import { t } from './i18n'
import { V2NIMMessageType } from 'nim-web-sdk-ng/dist/v2/NIM_UNIAPP_SDK/V2NIMMessageService'
const translate = (key: string): string => {
const text =
{
textMsgText: t('textMsgText'),
customMsgText: t('customMsgText'),
audioMsgText: t('audioMsgText'),
videoMsgText: t('videoMsgText'),
fileMsgText: t('fileMsgText'),
callMsgText: t('callMsgText'),
geoMsgText: t('geoMsgText'),
imgMsgText: t('imgMsgText'),
notiMsgText: t('notiMsgText'),
robotMsgText: t('robotMsgText'),
tipMsgText: t('tipMsgText'),
unknowMsgText: t('unknowMsgText'),
}[key] || ''
return `[${text}]`
}
export const getMsgContentTipByType = (msg: {
messageType?: V2NIMMessageType
text?: string
}): string => {
const { messageType, text } = msg
// switch (messageType) {
// case V2NIMConst.V2NIMMessageType.V2NIM_MESSAGE_TYPE_TEXT:
// return text || translate('textMsgText')
// case V2NIMConst.V2NIMMessageType.V2NIM_MESSAGE_TYPE_FILE:
// return translate('fileMsgText')
// case V2NIMConst.V2NIMMessageType.V2NIM_MESSAGE_TYPE_IMAGE:
// return translate('imgMsgText')
// case V2NIMConst.V2NIMMessageType.V2NIM_MESSAGE_TYPE_CUSTOM:
// return text || translate('customMsgText')
// case V2NIMConst.V2NIMMessageType.V2NIM_MESSAGE_TYPE_AUDIO:
// return translate('audioMsgText')
// case V2NIMConst.V2NIMMessageType.V2NIM_MESSAGE_TYPE_CALL:
// return translate('callMsgText')
// case V2NIMConst.V2NIMMessageType.V2NIM_MESSAGE_TYPE_LOCATION:
// return translate('geoMsgText')
// case V2NIMConst.V2NIMMessageType.V2NIM_MESSAGE_TYPE_NOTIFICATION:
// return translate('notiMsgText')
// case V2NIMConst.V2NIMMessageType.V2NIM_MESSAGE_TYPE_ROBOT:
// return translate('robotMsgText')
// case V2NIMConst.V2NIMMessageType.V2NIM_MESSAGE_TYPE_TIPS:
// return translate('tipMsgText')
// case V2NIMConst.V2NIMMessageType.V2NIM_MESSAGE_TYPE_VIDEO:
// return translate('videoMsgText')
// default:
// return translate('unknowMsgText')
// }
return text;
}
export const setTabUnread = (val): void => {
const routes = getCurrentPages()
const curRoute = routes[routes.length - 1].route
const tabPaths = [
'pages/home/index',
'pages/home/order',
'pages/workBench/index',
'pages/message/index',
'pages/person/index',
'root/person/changeTeam'
]
if (curRoute && !tabPaths.includes(curRoute)) {
// 不是首页和聊天页不需要设置tabbar的badge
return
}
const store = uni.$UIKitStore
const unread = store?.conversationStore.totalUnreadCount || 0
// console.log('store?.conversationStore.totalUnreadCount', store?.conversationStore.totalUnreadCount);
uni.$emit('newMessage', { count: store?.conversationStore.totalUnreadCount, type: 'message' })
uni.setStorageSync("chat_info", { count: store?.conversationStore.totalUnreadCount, type: 'message' });
if (unread === 0) {
uni.hideTabBarRedDot({
//隐藏数字
index: 1, //tabbar下标
})
} else {
uni.showTabBarRedDot({
index: 1, //tabbar下标
})
}
}
export const setContactTabUnread = (): void => {
const routes = getCurrentPages()
const curRoute = routes[routes.length - 1].route
const tabPaths = [
'pages/home/index',
'pages/home/order',
'pages/workBench/index',
'pages/message/index',
'pages/person/index',
'root/person/changeTeam'
]
if (curRoute && !tabPaths.includes(curRoute)) {
// 不是首页和聊天页不需要设置tabbar的badge
return
}
// const unread = uni.$UIKitStore?.sysMsgStore?.getTotalUnreadMsgsCount()
// if (unread === 0) {
// uni.hideTabBarRedDot({
// //隐藏数字
// index: 3, //tabbar下标
// })
// } else {
// uni.showTabBarRedDot({
// index: 3, //tabbar下标
// })
// }
}

@ -1,27 +0,0 @@
import { t } from './i18n'
export const handleNoPermission = (res: any): void => {
if (
uni.getSystemInfoSync().platform == 'android' ||
uni.getSystemInfoSync().platform == 'ios'
) {
const appAuthorizeSetting = uni.getAppAuthorizeSetting()
//点击取消时不出现弹窗
const isCameraDenied = appAuthorizeSetting.cameraAuthorized === 'denied'
const isUserCancelled =
res.errMsg === 'chooseImage:fail User cancelled' ||
res.errMsg === 'chooseImage:fail cancel' ||
res.errMsg === 'chooseVideo:fail cancel' ||
res.errMsg === 'chooseVideo:fail User cancelled'
if (
(res.code === 11 && isCameraDenied && !isUserCancelled) ||
(res.code === 12 && isCameraDenied && !isUserCancelled) ||
(res.code === 2 && !isUserCancelled)
) {
uni.showToast({
icon: 'none',
title: t('addPermissionText'),
})
}
}
}

@ -1,20 +0,0 @@
import { EventTracking } from '@xkit-yx/utils/dist/uniapp'
import imPkg from 'nim-web-sdk-ng/package.json'
export const trackInit = (
component: 'ChatUIKit' | 'ContactUIKit' | 'ConversationUIKit' | 'SearchUIKit'
): void => {
console.log('js init');
if (uni.$UIKitNIM && uni.$UIKitNIM.options.appkey) {
const eventTracking = new EventTracking({
appKey: uni.$UIKitNIM.options.appkey,
version: '10.2.0',
component,
imVersion: imPkg.version,
platform: 'UniApp',
})
eventTracking.track('init', '')
}else{
console.log('js 异常')
}
}

@ -1,12 +0,0 @@
let vueVersion: number
// #ifndef VUE3
export * from '@vue/composition-api'
vueVersion = 2
// #endif
// #ifdef VUE3
export * from 'vue'
vueVersion = 3
// #endif
console.log(`vue version is ${vueVersion}`)
export { vueVersion }

@ -10,11 +10,12 @@
<view class="g_h_10"></view>
<!-- background-color: #ededed; -->
<view class="g_radius_6" style="margin: 0 10px; overflow: hidden">
<ConversationList ref="contactList" />
<rh-loading paddingBottom="g_pb_120" />
<!-- <ConversationList ref="contactList" /> -->
</view>
</view>
<view class="" v-if="current == 1">
<telPanel />
<!-- <telPanel /> -->
</view>
<div style="height: 48px; background-color: #ededed"></div>
</scroll-view>
@ -43,11 +44,11 @@
<script lang="ts" setup>
import { ref, onMounted, computed, getCurrentInstance } from "vue";
import ConversationList from "../NEUIKit/pages/Conversation/conversation-list/index.vue";
import { trackInit } from "../NEUIKit/utils/reporter.ts";
// import ConversationList from "../NEUIKit/pages/Conversation/conversation-list/index.vue";
// import { trackInit } from "../NEUIKit/utils/reporter.ts";
import { onShow, onLoad } from "@dcloudio/uni-app";
import telPanel from "../NEUIKit/pages/Contact/contact-list/index.vue";
import chatPanel from "../NEUIKit/pages/Contact/BcFriend.vue";
// import telPanel from "../NEUIKit/pages/Contact/contact-list/index.vue";
// import chatPanel from "../NEUIKit/pages/Contact/BcFriend.vue";
const G = getCurrentInstance().appContext.app.config.globalProperties.G;
import gEmpty from "@/components/empty.vue";
// import gMessageCell from "@/components/panel/messageCell.vue";
@ -121,7 +122,7 @@ onShow(() => {
}, 200);
if (isLogin.value && uni && uni.$UIKitStore) {
trackInit("ConversationUIKit");
// trackInit("ConversationUIKit");
//
uni.$UIKitStore?.uiStore.selectConversation("");
const conversationId = uni.$UIKitStore.uiStore.selectedConversation;

@ -84,7 +84,7 @@
@clickItem="handleClickNus"
/> -->
</view>
<view class="g_mt_10 g_position_rela" v-if="userInfo.admin">
<view class="g_mt_10 g_position_rela" v-if="userInfo.admin || isTeamleader">
<view class="g_radius_50 g_text_c" style="position: absolute; right: 16px; top: 5px; color: #fff; background-color: #ff4400; font-size: 12px; min-width: 16px" v-if="applyNum > 0">
{{ applyNum }}
</view>
@ -92,7 +92,7 @@
:list="[
{
icon: 'icon-tuandui1',
label: '团队管理',
label: '团队管理',
result: agencyInfo.fullName || agencyInfo.agencyName || '设置企业信息',
path: '/root/person/teamManage',
pRow: 12,
@ -355,6 +355,7 @@ export default {
path: "/root/person/applyIndex?status=5",
},
],
isTeamleader: uni.getStorageSync("is_teamleader"), //
};
},
onShow() {

@ -136,7 +136,7 @@ export default {
onLoad(options) {
let that = this;
if (options.status) {
that.menuActive = Number(options.status);
that.menuActive = Number(options.status);
// setTimeout(() => {
// that.menuActive = Number(options.status);
// }, 200);
@ -176,6 +176,7 @@ export default {
// this.menuList = this.tabInfo[this.tabActive].childList;
// this.getList();
// }
this.isLogin = uni.getStorageSync("apply-token") ? true : false;
},
onShow() {
let that = this;
@ -286,7 +287,7 @@ export default {
} else {
that.query.list = that.query.list.concat(res.recordList);
}
}
},
);
},
goTel($item) {

@ -22,7 +22,7 @@
<span v-else-if="i.status == 1" class="g_fs_14 g_c_9">已通过</span>
<span v-else-if="i.status == 2" class="g_fs_14 g_c_9">已拒绝</span>
<!-- v-else -->
<div class="g_flex_row_end">
<div class="g_flex_row_end" v-else>
<div class="g_mr_8">
<rh-button primaryColor="#00b666" btnText="拒绝" fontSize="14" color="#000" customBgColor="#d8d8d8" size="height" type="disabled" height="24" width="50" @clickBtn="approve(i, 'reject')"></rh-button>
</div>
@ -128,6 +128,7 @@ export default {
configList: {},
pickerType: "",
markCheck: false,
currentUser: {},
};
},
onShow() {
@ -160,6 +161,23 @@ export default {
setTeamManagerStatus() {
this.G.Get(this.api.order_updateApplyNumHasViewed, {}, (res) => {});
},
resetList() {
let that = this;
this.teamList = [];
this.roleList = [];
that.configList.teams.forEach((item) => {
item.checked = false;
item.showChild = false;
if (item.childs.length > 0) {
item.childs.forEach((child) => {
child.checked = false;
});
}
});
that.configList.roles.forEach((item) => {
item.checked = false;
});
},
getUserApplyList() {
let that = this;
this.G.Post(this.api.order_getUserApplyList, { pageNum: that.query.page, pageSize: that.query.size }, (res) => {
@ -188,8 +206,10 @@ export default {
const that = this;
console.log(_item);
console.log(type);
this.resetList();
if (type == "resolve") {
this.showUserSelect = true;
this.currentUser = _item;
} else {
this.G.Post(this.api.order_userApplyApprove, { id: _item.id, status: 2 }, (res) => {
console.log(res);
@ -203,9 +223,19 @@ export default {
},
uploadUserInfo() {
const that = this;
this.G.Post(this.api.order_userApplyApprove, { id: _item.id, status: 1 }, (res) => {
let params = {
id: this.currentUser.id,
status: 1,
agencyRoleIds: this.roleList.map((obj) => obj.id.toString()).join(","),
agencyTeamIds: this.teamList.map((obj) => obj.id.toString()).join(","),
};
this.G.Post(this.api.order_userApplyApprove, params, (res) => {
console.log(res);
_item.status = 1;
that.applyList.forEach(() => {
if (that.currentUser.id == item.id) {
item.status = 1;
}
});
uni.showToast({
title: "操作成功",
icon: "none",

@ -120,7 +120,7 @@
<script>
import gPanelFormItem from "@/components/panel/formItem.vue";
import unloginInfo from "@/components/unloginInfo.vue";
import { getMsgContentTipByType, setTabUnread } from "../../pages/NEUIKit/utils/msg";
// import { getMsgContentTipByType, setTabUnread } from "../../pages/NEUIKit/utils/msg";
export default {
components: {
gPanelFormItem,
@ -409,7 +409,7 @@ export default {
});
that.getAgencyInfo();
that.getTeamList();
setTabUnread()
// setTabUnread()
that.isAdmin = uni.getStorageSync("apply-userinfo").admin;
});
});

@ -14,6 +14,7 @@ let data = {
loginText: '请登录',
coziID: '7537572244600471579',
baseUrl: "https://daotian.matripe.com.cn",// 网络请求的基础路径
// baseUrl: "http://192.168.1.3:8001",// 网络请求的基础路径
// baseUrl: "http://192.168.3.83:8001", // 网络请求的基础路径
// #ifdef MP-WEIXIN
version: uni.getAccountInfoSync().miniProgram.version || "1.0.16",

Loading…
Cancel
Save