Compare commits

...

2 Commits

Author SHA1 Message Date
qijq
34ea079dc6 合并冲突 并更新IM通知,修复BUG 2025-05-22 16:54:43 +08:00
qijq
ce532df5d3 更新im通知 修复已知BUG 2025-05-22 16:51:36 +08:00
31 changed files with 2715 additions and 632 deletions

1
.gitignore vendored Normal file
View File

@ -0,0 +1 @@
/.vscode/settings.json

View File

@ -1,2 +1,2 @@
VUE_APP_BASE_API = '/mobile'
VUE_APP_BACK_ADMIN_API = '/api/admin'
VUE_APP_BACK_ADMIN_API = '/api/admin'

View File

@ -14,6 +14,7 @@ yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
# Editor directories and files
.idea
*.suo
@ -46,4 +47,5 @@ public/video
src/vab/styles/themes/red.scss
/src/vab/styles/themes/red-black.scss
/src/vab/styles/themes/red-white.scss
unpackage/
unpackage/
/.vscode/settings.json

View File

@ -2,7 +2,7 @@
// #ifdef APP-PLUS
import APPUpdate, { getCurrentNo } from "@/config/appUpdate";
// #endif
import { mapState, mapActions } from "vuex";
export default {
data() {
return {
@ -10,17 +10,34 @@ export default {
};
},
onLaunch: function () {
uni.setStorageSync("isImSound", true);
// #ifdef APP-PLUS
getCurrentNo((res) => {
this.version = res.version;
});
this.onAPPUpdate();
// #endif
setTimeout(() => {
uni.hideTabBar();
}, 500);
},
computed: {
...mapState("user", ["uid", "userInfo", "socket"]),
},
onShow: function () {
setTimeout(() => {
uni.hideTabBar();
}, 500);
setTimeout(() => {
if (this.userInfo && Object.keys(this.userInfo).length > 0) {
this.connectSocket(this.userInfo);
}
});
},
onShow: function () {},
onHide: function () {},
onBackPress: function () {},
methods: {
...mapActions("user", ["connectSocket"]),
onAPPUpdate() {
APPUpdate(this.version);
},

View File

@ -0,0 +1,25 @@
import http from '../utils/http';
import config from '../config/config';
/**
* 获取商店基础信息
* @author Seven
* @data 2025-3-27
* @returns { }
* @see https://mall.gpxscs.cn/mobile/admin/app-market-update/check/version
*/
export function GetAPPversions(params) {
return new Promise((resolve, reject) => {
http({
url: '/admin/app-market-update/check/version',
method: 'post',
data: params,
baseURL: config.baseApi,
})
.then((res) => {
resolve(res);
})
.catch((e) => reject(console.warn(e)));
});
}

View File

@ -121,7 +121,7 @@ export function GetAuditInfo(params) {
data: params,
})
.then((res) => {
if (res && res.status == 200) {
if (res && res.data && res.status == 200) {
uni.setStorageSync('approvalStatus', res.data.approval_status);
}
resolve(res);
@ -240,7 +240,6 @@ export function GetBizCategoryList(params) {
});
}
/**
* 搜索银行支行分页列表
* @author Seven

View File

@ -1,5 +1,5 @@
import http from '../utils/http';
import config from '../config/config';
import http from "../utils/http";
import config from "../config/config";
/**
* 获取聊天配置
@ -12,8 +12,8 @@ import config from '../config/config';
export function GetImConfig(params) {
return http({
url: '/sns/im/getImConfig',
method: 'get',
url: "/sns/im/getImConfig",
method: "get",
params,
baseURL: config.baseApi,
});
@ -30,8 +30,8 @@ export function GetImConfig(params) {
export function GetImMsgList(params) {
return http({
url: 'https://mall.gpxscs.cn/api/mobile/sns/userMessage/listChatMsg',
method: 'get',
url: "https://mall.gpxscs.cn/api/mobile/sns/userMessage/listChatMsg",
method: "get",
params,
baseURL: config.apiMobile,
});
@ -48,9 +48,27 @@ export function GetImMsgList(params) {
export function GetSendMsgAdd(params) {
return http({
url: 'https://mall.gpxscs.cn/api/mobile/sns/userMessage/add',
method: 'get',
url: "https://mall.gpxscs.cn/api/mobile/sns/userMessage/add",
method: "get",
params,
baseURL: config.apiMobile,
});
}
/**
* 设置消息已读
* @author Seven
* @data 2025-1-27
* @param {message_id}
* @returns { }
* @see https://mall.gpxscs.cn/mobile/sns/userMessage/setRead
*/
export function SetMsgRead(params) {
return http({
url: "https://mall.gpxscs.cn/mobile/sns/userMessage/setRead",
method: "post",
data: params,
baseURL: config.baseApi,
});
}

View File

@ -27,7 +27,8 @@ export function GetAccountDashboard() {
export function OutLogin() {
return http({
url: 'https://mall.gpxscs.cn/api/mobile/account/login/doLogout',
url: '/account/login/doLogout',
method: 'get',
baseURL: config.apiMobile,
});
}

View File

@ -1,15 +1,17 @@
<template>
<view @touchmove.stop.prevent>
<view
class="tui-reply-tabbar"
:class="{ 'tui-reply-tabbar': !showVoiceMask }"
:style="{ paddingBottom: `${keyboardHeight}px` }"
>
<view :class="['tui-chat-tabbar', { isIos: 'tui-chat-ios-tabbar' }]">
<view
v-show="!showVoiceMask"
class="tui-icon tui-icon-im_more tui-icon-mr"
@tap="showKeyBoard(3)"
></view>
<view
v-show="!showVoiceMask"
class="tui-icon tui-icon-im_face tui-icon-mr"
@tap="showKeyBoard(2)"
></view>
@ -40,16 +42,34 @@
placeholder-class="tui-phcolor"
@tap.stop="showKeyBoard(1)"
ref="textarea"
v-show="!isVoice"
v-show="!isVoice && !showVoiceMask"
></textarea>
<view
class="tui-chat-voice_btn"
:class="[
showVoiceMask ? 'mask-bottom' : 'tui-chat-voice_btn',
{ 'no-area': needCancel },
]"
hover-class="tui-opcity"
:hover-stay-time="150"
v-if="isVoice"
>{{ isVoice ? "按住 说话" : "松开 发送" }}
@touchstart="handleTouchStart"
@touchmove="handleTouchMove"
@touchend="handleTouchEnd"
>
<text v-if="!showVoiceMask">
{{ isVoice ? "按住 说话" : "松开 发送" }}
</text>
<image
v-if="showVoiceMask"
:src="
needCancel
? '../../static/images/chat/voice2.png'
: '../../static/images/chat/voice.png'
"
></image>
</view>
<view class="tui-send-box">
<view class="tui-send-box" v-show="!showVoiceMask">
<view
class="tui-icon tui-icon-im_voice"
v-if="!isVoice && !content"
@ -67,8 +87,9 @@
hover-class="tui-opcity"
:hover-stay-time="150"
@tap="hideKeyboard"
>{{ sendText }}</view
>
{{ sendText }}
</view>
</view>
</view>
<view class="tui-reply-more">
@ -92,9 +113,12 @@
</view>
</scroll-view>
<view class="tui-delete-face_box">
<view class="tui-delete-keybord" :class="{ 'tui-opcity': !content }"
><text class="tui-icon tui-icon-delete_keybord"></text
></view>
<view
class="tui-delete-keybord"
:class="{ 'tui-opcity': !content }"
>
<text class="tui-icon tui-icon-delete_keybord"></text>
</view>
</view>
</view>
<view
@ -141,7 +165,7 @@
</view>
<view
class="tui-reply-mask"
v-if="mask"
v-if="mask && showVoiceMask"
:class="{
'tui-box-show': showIndex,
'tui-mask-show': showIndex && !maskOpacity,
@ -149,6 +173,42 @@
@touchmove.stop.prevent
@tap="hideKeyboard"
></view>
<view class="voice-mask" v-show="showVoiceMask">
<!--语音条 -->
<view
class="voice-bar voice-del"
:class="{ voiceDel: needCancel }"
:style="{ width: getVoiceBarWidth }"
>
<image
src="../../static/images/chat/yinping.png"
class="voice-volume"
></image>
<view class="trangle-bottom" :class="{ trangleDel: needCancel }"></view>
</view>
<view class="voice-send">
<!-- 取消和转文字图标 -->
<view class="voice-middle-wrapper">
<!-- 取消 -->
<view class="voice-left-wrapper">
<view class="cancel-del" :class="{ delTip: needCancel }">
松开 取消
</view>
<view
class="voice-middle-inner close"
:class="{ bigger: needCancel }"
>
<u-icon name="close" color="#fff" size="24"></u-icon>
</view>
</view>
<!-- 转文字 -->
<view class="send-tip" :class="{ sendTipNone: needCancel }">
松开 发送
</view>
</view>
<!-- 底部语音按钮 -->
</view>
</view>
</view>
</template>
@ -157,6 +217,7 @@
// import emoji from "@/utils/emoji.js";
import emoji from "../../static/im/emojiData.js";
import uParse from "../../uni_modules/uview-ui/components/u-parse/u-parse.vue";
const recorderManager = uni.getRecorderManager();
export default {
components: { uParse },
name: "tChatBar",
@ -226,8 +287,26 @@ export default {
isEmoji: false,
editorContent: "",
isIos: false,
showVoiceMask: false,
voicePopupTouches: {},
voicelength: 0,
needCancel: false,
startX: 0,
startY: 0,
timer: 0,
maskBottomRect: null,
isRecording: false,
isOutside: false,
tempFilePath: null,
startTime: 0,
};
},
computed: {
//
getVoiceBarWidth() {
return 230 + this.voicelength * 4 + "rpx";
},
},
watch: {
isHideKeyBoard: {
handler(newVal, oldVal) {
@ -332,6 +411,122 @@ export default {
uploadVideo() {
this.$emit("uploadVideo");
},
async getMaskBottomRect() {
return new Promise((resolve) => {
const query = uni.createSelectorQuery().in(this);
query
.select(".mask-bottom")
.boundingClientRect((data) => {
this.maskBottomRect = data;
console.log("元素位置信息:", data); //
resolve(data);
})
.exec();
});
},
async handleTouchStart(e) {
console.log("handleTouchStart", e);
this.$emit("showVoicePopup");
this.showVoiceMask = true;
// DOM
await this.$nextTick();
if (!this.maskBottomRect) {
await this.getMaskBottomRect();
}
recorderManager.start({
format: "mp3",
});
this.voicelength = 1;
this.startX = e.touches[0].pageX;
this.startY = e.touches[0].pageY;
this.timer = setInterval(() => {
this.voicelength += 1;
if (this.voicelength >= 60) {
clearInterval(this.timer);
this.handleTouchEnd();
}
}, 1000);
this.isRecording = true;
this.isOutside = false;
},
handleTouchMove(e) {
// mask-bottom
if (!this.maskBottomRect) return;
const touchX = e.touches[0].pageX;
const touchY = e.touches[0].pageY;
// mask-bottom
//
const SAFE_MARGIN = 5; //
const isNowOutside =
touchX < this.maskBottomRect.left - SAFE_MARGIN ||
touchX >
this.maskBottomRect.left + this.maskBottomRect.width + SAFE_MARGIN ||
touchY < this.maskBottomRect.top - SAFE_MARGIN ||
touchY >
this.maskBottomRect.top + this.maskBottomRect.height + SAFE_MARGIN;
//
console.log(
`触摸点: (${touchX}, ${touchY})`,
`元素区域: [${this.maskBottomRect.left}, ${this.maskBottomRect.top}, ${this.maskBottomRect.width}, ${this.maskBottomRect.height}]`,
`是否在外: ${isNowOutside}`
);
//
if (isNowOutside !== this.isOutside) {
this.isOutside = isNowOutside;
if (this.isOutside) {
//
recorderManager.pause();
console.log("已离开区域,暂停录制");
this.needCancel = true;
} else {
//
recorderManager.resume();
console.log("已回到区域,继续录制");
this.needCancel = false;
}
}
},
async handleTouchEnd(e) {
clearInterval(this.timer);
recorderManager.stop();
console.log("松开");
if (!this.needCancel) {
recorderManager.onStop((res) => {
const message = {
voice: res.tempFilePath,
length: this.voicelength,
};
console.log("recorderManager", res);
this.inputSubmit(message, 2);
});
} else {
this.inputSubmit();
}
this.showVoiceMask = false;
this.needCancel = false;
},
inputSubmit(msg = {}, types = "") {
if (msg && types) {
this.$emit("voiceEnd", msg);
} else {
this.$emit("voiceEnd");
}
},
},
};
</script>
@ -416,7 +611,7 @@ export default {
display: flex;
flex-direction: column;
box-sizing: border-box;
z-index: 999;
z-index: 1;
.tui-chat-tabbar {
width: 100%;
@ -619,7 +814,6 @@ export default {
position: fixed;
left: 0;
top: 0;
z-index: 990;
background-color: $uni-bg-color-mask;
visibility: hidden;
transition: all 0.3s ease;
@ -649,4 +843,158 @@ export default {
}
}
}
.voice-mask {
position: fixed;
top: 0;
right: 0;
bottom: 0;
left: 0;
background-color: rgba(0, 0, 0, 0.8);
z-index: 200; /* 确保足够高 */
display: flex;
justify-content: center;
align-items: center;
}
.voice-bar {
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -30%);
height: 150rpx;
background-color: #51ff50;
border-radius: 26rpx;
margin-bottom: 220rpx;
z-index: 200;
}
.voiceDel {
left: 80rpx;
top: 50%;
width: 170rpx !important;
transform: translateX(0%);
transform: translateY(-30%);
background-color: red;
}
.voice-volume {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 160rpx;
height: 36rpx;
}
.volumeDel {
width: 80rpx;
}
.trangle-bottom {
position: absolute;
bottom: -38rpx;
left: 50%;
transform: translateX(-50%);
border-width: 20rpx;
border-style: solid;
border-color: #51ff50 transparent transparent transparent;
z-index: 9999;
}
.trangleDel {
border-color: red transparent transparent transparent;
}
.voice-send {
position: relative;
bottom: 0;
width: 100%;
height: 100%;
z-index: 9999;
}
.voice-middle-wrapper {
width: 100%;
display: flex;
position: absolute;
justify-content: space-between;
align-items: flex-end;
margin-bottom: 40rpx;
bottom: 15%;
}
.voice-left-wrapper {
display: flex;
flex-direction: column;
justify-content: center;
align-items: flex-end;
}
.cancel-del {
display: none;
}
.delTip {
display: block;
color: #bfbfbf;
margin: 0 22rpx 18rpx 0;
}
.voice-middle-inner {
display: flex;
justify-content: center;
align-items: center;
background-color: #595959;
width: 140rpx;
height: 140rpx;
border-radius: 50%;
}
.close {
transform: rotate(350deg);
margin-left: 80rpx;
}
.bigger {
width: 170rpx;
height: 170rpx;
background: #ececec;
}
.to-text {
transform: rotate(10deg);
margin-right: 80rpx;
}
.close-icon {
width: 80rpx;
height: 80rpx;
color: #fff;
}
.wen {
font-size: 40rpx;
color: #bfbfbf;
}
.send-tip {
position: absolute;
left: 50%;
bottom: 0rpx;
transform: translate(-50%, 36%);
color: #bfbfbf;
}
.sendTipNone {
display: none;
}
.mask-bottom {
position: absolute;
left: 0;
right: 0;
bottom: 0;
width: 100%;
height: 180rpx;
border-top: #bababb 8rpx solid;
border-radius: 50% 50% 0 0;
background-image: linear-gradient(#949794, #e1e3e1);
z-index: 9999;
}
.mask-bottom image {
position: absolute;
width: 60rpx;
height: 60rpx;
top: 0;
right: 0;
bottom: 0;
left: 0;
margin: auto;
}
.no-area {
border-color: #595959;
background-image: linear-gradient(#595959, #595959);
}
</style>

View File

@ -0,0 +1,192 @@
<template>
<view class="tabbar-container">
<u-tabbar
:value="tabbarName"
@change="changeTabbar"
:fixed="true"
:placeholder="false"
activeColor="#4b71ff"
:safeAreaInsetBottom="true"
>
<u-tabbar-item text="工作台" name="order">
<u-icon
class="u-icon"
custom-prefix="custom-icon-gongzuotai custom-icon"
size="22"
slot="active-icon"
color="#4b71ff"
></u-icon>
<u-icon
class="u-icon"
custom-prefix="custom-icon-gongzuotai custom-icon"
size="22"
slot="inactive-icon"
color="#000"
></u-icon>
</u-tabbar-item>
<u-tabbar-item text="消息" name="IM" :badge="weiduNum">
<u-icon
class="u-icon"
custom-prefix="custom-icon-xiaoxi1 custom-icon"
size="22"
slot="active-icon"
color="#4b71ff"
></u-icon>
<u-icon
class="u-icon"
custom-prefix="custom-icon-xiaoxi1 custom-icon"
size="22"
slot="inactive-icon"
color="#000"
></u-icon>
</u-tabbar-item>
<u-tabbar-item text="视图中心" name="shituzhongxin">
<u-icon
class="u-icon"
custom-prefix="custom-icon-shituzhongxin custom-icon"
size="20"
slot="active-icon"
color="#4b71ff"
></u-icon>
<u-icon
class="u-icon"
custom-prefix="custom-icon-shituzhongxin custom-icon"
size="20"
slot="inactive-icon"
color="#000"
></u-icon>
</u-tabbar-item>
<u-tabbar-item text="我的" name="my">
<u-icon
class="u-icon"
custom-prefix="custom-icon-wode custom-icon"
size="24"
slot="active-icon"
color="#4b71ff"
></u-icon>
<u-icon
class="u-icon"
custom-prefix="custom-icon-wode custom-icon"
size="24"
slot="inactive-icon"
color="#000"
></u-icon>
</u-tabbar-item>
</u-tabbar>
</view>
</template>
<script>
import { mapState } from "vuex";
import permission from "../../utils/permission.js";
export default {
props: {
tabbarName: {
type: String,
default: "order",
},
},
data() {
return {
weiduNum: 0,
};
},
computed: {
...mapState("user", ["imWeidu"]),
},
watch: {
imWeidu: {
handler(newValue, oldValue) {
if (newValue) {
this.weiduNum = Object.values(this.imWeidu).reduce((sum, item) => {
// item weidu
return typeof item === "object" && item.weidu !== undefined
? sum + item.weidu
: sum;
}, 0);
}
if (newValue) {
var keys = Object.keys(newValue);
if (keys.length === 1 && keys[0] === "userId") {
this.weiduNum = 0;
}
}
},
deep: true,
},
},
mounted() {
let imWeiDu = uni.getStorageSync("imWeiDu");
if (imWeiDu) {
this.weiduNum = Object.values(imWeiDu).reduce((sum, item) => {
// item weidu
return typeof item === "object" && item.weidu !== undefined
? sum + item.weidu
: sum;
}, 0);
}
},
onShow() {
console.log("asdasdasd");
},
methods: {
async changeTabbar(e) {
switch (e) {
case "order":
uni.switchTab({
url: "/pages/order/order",
});
break;
case "IM":
// #ifdef APP-PLUS
let result = await permission.premissionCheck(
"CAMERA_EXTERNAL_STORAGE_RECORD_AUDIO"
); //使
if (result == 1) {
uni.switchTab({
url: "/pages/IM/IM",
});
}
// #endif
// #ifdef H5
uni.switchTab({
url: "/pages/IM/IM",
});
// #endif
break;
case "shituzhongxin":
uni.switchTab({
url: "/pages/viewCenter/viewCenter",
});
break;
case "my":
uni.switchTab({
url: "/pages/my/my",
});
break;
default:
break;
}
},
},
};
</script>
<style lang="scss">
.tabbar-container {
.u-icon {
font-weight: bold;
}
/deep/.u-tabbar__content__item-wrapper {
height: 116rpx;
.u-tabbar-item__icon {
margin-bottom: 4rpx;
}
}
}
</style>

View File

@ -1,21 +1,21 @@
/**** 此文件说明请看注释 *****/
// 可以用自己项目的请求方法
// 请求配置说明https://ext.dcloud.net.cn/plugin?id=822
import { GetAPPversion } from '../api/checkAPPupdate';
import { GetAPPversion } from "../api/checkAPPupdate";
/**** 结束 *****/
const platform = uni.getSystemInfoSync().platform;
const phoneInfo = uni.getSystemInfoSync();
export default {
// 发起ajax请求获取服务端版本号
getServerNo: async (version, isPrompt = false, callback) => {
if (platform != 'android') {
if (platform != "android") {
let appleId = 1549638327; //app的appleId
plus.runtime.launchApplication(
{
action: `itms-apps://itunes.apple.com/cn/app/id${appleId}?mt=8`,
},
function (e) {
console.log('Open system default browser failed: ' + e.message);
console.log("Open system default browser failed: " + e.message);
}
);
@ -47,22 +47,22 @@ export default {
phoneInfo.brand = phoneInfo.brand.toLowerCase();
switch (phoneInfo.brand) {
case 'xiaomi':
case "xiaomi":
marketId = 1;
break;
case 'huawei':
case "huawei":
marketId = 2;
break;
case 'tengxun':
case "tengxun":
marketId = 3;
break;
case 'oppo':
case "oppo":
marketId = 4;
break;
case 'vivo':
case "vivo":
marketId = 5;
break;
case 'samsung':
case "samsung":
marketId = 6;
break;
default:
@ -70,12 +70,12 @@ export default {
break;
}
console.log('marketId', marketId);
console.log('phoneInfo.brand', phoneInfo.brand);
console.log("marketId", marketId);
console.log("phoneInfo.brand", phoneInfo.brand);
let params = {
marketId: marketId,
packageName: 'com.xiaofa.shopAdmin',
marketId: 100,
packageName: "com.xiaofa.shopAdmin",
currVersionKey: version,
};
@ -83,9 +83,9 @@ export default {
if (res && res.status == 200) {
if (res.data) {
res.data.updateType = 'solicit';
res.data.updateType = "solicit";
if (res.data.is_force_update == 1) {
res.data.updateType = 'forcibly';
res.data.updateType = "forcibly";
callback && callback(res.data);
} else {
callback && callback(res.data);
@ -128,7 +128,7 @@ export default {
/****************以上是示例*******************/
},
// 弹窗主颜色(不填默认粉色)
appUpdateColor: 'f00',
appUpdateColor: "f00",
// 弹窗图标(不填显示默认图标,链接配置示例如: '/static/demo/ic_attention.png'
appUpdateIcon: '/static/ic_ar.png',
appUpdateIcon: "/static/ic_ar.png",
};

View File

@ -1,151 +1,150 @@
{
"name" : "小发同城商家版",
"appid" : "__UNI__95F809F",
"package" : "com.xiaofa.shopAdmin",
"description" : "",
"versionName" : "1.0.0",
"versionCode" : 100,
"transformPx" : false,
/* 5+App */
"app-plus" : {
"usingComponents" : true,
"nvueStyleCompiler" : "uni-app",
"compilerVersion" : 3,
"splashscreen" : {
"alwaysShowBeforeRender" : true,
"waiting" : true,
"autoclose" : true,
"delay" : 0
"name": "小发同城商家版",
"appid": "__UNI__95F809F",
"package": "com.xiaofa.shopAdmin",
"description": "",
"versionName": "1.0.0",
"versionCode": 100,
"transformPx": false,
/* 5+App */
"app-plus": {
"usingComponents": true,
"nvueStyleCompiler": "uni-app",
"compilerVersion": 3,
"splashscreen": {
"alwaysShowBeforeRender": true,
"waiting": true,
"autoclose": true,
"delay": 0
},
/* */
"modules": {
"Maps": {},
"Camera": {},
"Record": {},
"VideoPlayer": {},
"UIWebview": {}
},
/* */
"distribute": {
/* android */
"android": {
"permissions": [
"<uses-permission android:name=\"android.permission.CHANGE_NETWORK_STATE\"/>",
"<uses-permission android:name=\"android.permission.MOUNT_UNMOUNT_FILESYSTEMS\"/>",
"<uses-permission android:name=\"android.permission.VIBRATE\"/>",
"<uses-permission android:name=\"android.permission.READ_LOGS\"/>",
"<uses-permission android:name=\"android.permission.ACCESS_WIFI_STATE\"/>",
"<uses-feature android:name=\"android.hardware.camera.autofocus\"/>",
"<uses-permission android:name=\"android.permission.ACCESS_NETWORK_STATE\"/>",
"<uses-permission android:name=\"android.permission.CAMERA\"/>",
"<uses-permission android:name=\"android.permission.GET_ACCOUNTS\"/>",
"<uses-permission android:name=\"android.permission.READ_PHONE_STATE\"/>",
"<uses-permission android:name=\"android.permission.CHANGE_WIFI_STATE\"/>",
"<uses-permission android:name=\"android.permission.WAKE_LOCK\"/>",
"<uses-permission android:name=\"android.permission.FLASHLIGHT\"/>",
"<uses-feature android:name=\"android.hardware.camera\"/>",
"<uses-permission android:name=\"android.permission.WRITE_SETTINGS\"/>"
]
},
/* ios */
"ios": {
"privacyDescription": {
"NSPhotoLibraryAddUsageDescription": "此App会在上传头像图片服务中访问您的相机权限",
"NSPhotoLibraryUsageDescription": "此App会在上传头像图片服务中访问您的相机权限",
"NSCameraUsageDescription": "此App会在上传头像图片服务中访问您的相机权限",
"NSMicrophoneUsageDescription": "此APP会在使用声音识别服务中使用您的麦克风权限",
"NSLocationWhenInUseUsageDescription": "此App会在使用导航服务中使用您的定位权限",
"NSLocationAlwaysUsageDescription": "此App会在使用导航服务中使用您的定位权限",
"NSLocationAlwaysAndWhenInUseUsageDescription": "此App会在使用导航服务中使用您的定位权限"
},
/* */
"modules" : {
"Maps" : {},
"Camera" : {},
"Record" : {},
"VideoPlayer" : {},
"UIWebview" : {}
"dSYMs": false
},
/* SDK */
"sdkConfigs": {
"maps": {}
},
"icons": {
"android": {
"hdpi": "unpackage/res/icons/72x72.png",
"xhdpi": "unpackage/res/icons/96x96.png",
"xxhdpi": "unpackage/res/icons/144x144.png",
"xxxhdpi": "unpackage/res/icons/192x192.png"
},
/* */
"distribute" : {
/* android */
"android" : {
"permissions" : [
"<uses-permission android:name=\"android.permission.CHANGE_NETWORK_STATE\"/>",
"<uses-permission android:name=\"android.permission.MOUNT_UNMOUNT_FILESYSTEMS\"/>",
"<uses-permission android:name=\"android.permission.VIBRATE\"/>",
"<uses-permission android:name=\"android.permission.READ_LOGS\"/>",
"<uses-permission android:name=\"android.permission.ACCESS_WIFI_STATE\"/>",
"<uses-feature android:name=\"android.hardware.camera.autofocus\"/>",
"<uses-permission android:name=\"android.permission.ACCESS_NETWORK_STATE\"/>",
"<uses-permission android:name=\"android.permission.CAMERA\"/>",
"<uses-permission android:name=\"android.permission.GET_ACCOUNTS\"/>",
"<uses-permission android:name=\"android.permission.READ_PHONE_STATE\"/>",
"<uses-permission android:name=\"android.permission.CHANGE_WIFI_STATE\"/>",
"<uses-permission android:name=\"android.permission.WAKE_LOCK\"/>",
"<uses-permission android:name=\"android.permission.FLASHLIGHT\"/>",
"<uses-feature android:name=\"android.hardware.camera\"/>",
"<uses-permission android:name=\"android.permission.WRITE_SETTINGS\"/>"
]
},
/* ios */
"ios" : {
"privacyDescription" : {
"NSPhotoLibraryAddUsageDescription" : "此App会在上传头像图片服务中访问您的相机权限",
"NSPhotoLibraryUsageDescription" : "此App会在上传头像图片服务中访问您的相机权限",
"NSCameraUsageDescription" : "此App会在上传头像图片服务中访问您的相机权限",
"NSMicrophoneUsageDescription" : "此APP会在使用声音识别服务中使用您的麦克风权限",
"NSLocationWhenInUseUsageDescription" : "此App会在使用导航服务中使用您的定位权限",
"NSLocationAlwaysUsageDescription" : "此App会在使用导航服务中使用您的定位权限",
"NSLocationAlwaysAndWhenInUseUsageDescription" : "此App会在使用导航服务中使用您的定位权限"
},
"dSYMs" : false
},
/* SDK */
"sdkConfigs" : {
"maps" : {}
},
"icons" : {
"android" : {
"hdpi" : "unpackage/res/icons/72x72.png",
"xhdpi" : "unpackage/res/icons/96x96.png",
"xxhdpi" : "unpackage/res/icons/144x144.png",
"xxxhdpi" : "unpackage/res/icons/192x192.png"
},
"ios" : {
"appstore" : "unpackage/res/icons/1024x1024.png",
"ipad" : {
"app" : "unpackage/res/icons/76x76.png",
"app@2x" : "unpackage/res/icons/152x152.png",
"notification" : "unpackage/res/icons/20x20.png",
"notification@2x" : "unpackage/res/icons/40x40.png",
"proapp@2x" : "unpackage/res/icons/167x167.png",
"settings" : "unpackage/res/icons/29x29.png",
"settings@2x" : "unpackage/res/icons/58x58.png",
"spotlight" : "unpackage/res/icons/40x40.png",
"spotlight@2x" : "unpackage/res/icons/80x80.png"
},
"iphone" : {
"app@2x" : "unpackage/res/icons/120x120.png",
"app@3x" : "unpackage/res/icons/180x180.png",
"notification@2x" : "unpackage/res/icons/40x40.png",
"notification@3x" : "unpackage/res/icons/60x60.png",
"settings@2x" : "unpackage/res/icons/58x58.png",
"settings@3x" : "unpackage/res/icons/87x87.png",
"spotlight@2x" : "unpackage/res/icons/80x80.png",
"spotlight@3x" : "unpackage/res/icons/120x120.png"
}
}
}
"ios": {
"appstore": "unpackage/res/icons/1024x1024.png",
"ipad": {
"app": "unpackage/res/icons/76x76.png",
"app@2x": "unpackage/res/icons/152x152.png",
"notification": "unpackage/res/icons/20x20.png",
"notification@2x": "unpackage/res/icons/40x40.png",
"proapp@2x": "unpackage/res/icons/167x167.png",
"settings": "unpackage/res/icons/29x29.png",
"settings@2x": "unpackage/res/icons/58x58.png",
"spotlight": "unpackage/res/icons/40x40.png",
"spotlight@2x": "unpackage/res/icons/80x80.png"
},
"iphone": {
"app@2x": "unpackage/res/icons/120x120.png",
"app@3x": "unpackage/res/icons/180x180.png",
"notification@2x": "unpackage/res/icons/40x40.png",
"notification@3x": "unpackage/res/icons/60x60.png",
"settings@2x": "unpackage/res/icons/58x58.png",
"settings@3x": "unpackage/res/icons/87x87.png",
"spotlight@2x": "unpackage/res/icons/80x80.png",
"spotlight@3x": "unpackage/res/icons/120x120.png"
}
}
}
}
},
/* */
"quickapp": {},
/* */
"mp-weixin": {
"appid": "",
"setting": {
"urlCheck": false
},
/* */
"quickapp" : {},
/* */
"mp-weixin" : {
"appid" : "",
"setting" : {
"urlCheck" : false
},
"usingComponents" : true
},
"h5" : {
// "devServer" : {
// "https" : true,
// "host" : "127.0.0.1",
// "port" : 8080,
// "disableHostCheck" : true,
// "proxy" : {
// "/place/v2/suggestion" : {
// "target" : "https://api.map.baidu.com",
// "changeOrigin" : true,
// "secure" : false
// },
// "/admin/shop/shop-base-product-category/list" : {
// "target" : "https://mall.gpxscs.cn",
// "changeOrigin" : true
// }
// }
// },
"title" : "小发商城商家中心",
"template" : "index.html",
"router" : {
"mode" : "history",
"base" : "/mchapp/"
}
},
"mp-alipay" : {
"usingComponents" : true
},
"mp-baidu" : {
"usingComponents" : true
},
"mp-toutiao" : {
"usingComponents" : true
},
"uniStatistics" : {
"enable" : false
},
"vueVersion" : "2"
"usingComponents": true
},
"h5": {
// "devServer" : {
// "https" : true,
// "host" : "127.0.0.1",
// "port" : 8080,
// "disableHostCheck" : true,
// "proxy" : {
// "/place/v2/suggestion" : {
// "target" : "https://api.map.baidu.com",
// "changeOrigin" : true,
// "secure" : false
// },
// "/admin/shop/shop-base-product-category/list" : {
// "target" : "https://mall.gpxscs.cn",
// "changeOrigin" : true
// }
// }
// },
"title": "小发商城商家中心",
"template": "index.html",
"router": {
"mode": "history",
"base": "/mchapp/"
}
},
"mp-alipay": {
"usingComponents": true
},
"mp-baidu": {
"usingComponents": true
},
"mp-toutiao": {
"usingComponents": true
},
"uniStatistics": {
"enable": false
},
"vueVersion": "2"
}
/* 5+App */

View File

@ -1,13 +1,14 @@
{
"pages": [ //pageshttps://uniapp.dcloud.io/collocation/pages
{
"path": "pages/login/launch",
"style": {
"navigationBarTitleText": "启动页",
"navigationStyle": "custom"
}
},
{
"pages": [
//pageshttps://uniapp.dcloud.io/collocation/pages
{
"path": "pages/login/launch",
"style": {
"navigationBarTitleText": "启动页",
"navigationStyle": "custom"
}
},
{
"path": "pages/index/index",
"style": {
"navigationStyle": "custom"
@ -26,25 +27,25 @@
}
},
{
"path":"pages/audit/businessType",
"style":{
"navigationBarTitleText":"选择经营品类"
"path": "pages/audit/businessType",
"style": {
"navigationBarTitleText": "选择经营品类"
}
},
{
"path":"pages/audit/shop2",
"style":{
"path": "pages/audit/shop2",
"style": {
"navigationStyle": "custom"
}
},
{
"path":"pages/audit/shop3",
"style":{
"path": "pages/audit/shop3",
"style": {
"navigationStyle": "custom"
}
},
{
"path":"pages/audit/checkAudit",
"path": "pages/audit/checkAudit",
"style": {
"navigationStyle": "custom"
}
@ -62,7 +63,6 @@
"style": {
"navigationBarTitleText": "注册",
"navigationBarTextStyle": "white"
}
}
},
@ -76,65 +76,70 @@
"path": "pages/forgetPassword/forgetPassword",
"style": {
"navigationBarTitleText": "忘记密码"
}
},
{
"path": "pages/order/order",
"style": {
"path": "pages/order/order",
"style": {
"navigationStyle": "custom"
// "onReachBottomDistance": 105,
// "enablePullDownRefresh": true
}
},
},
{
"path": "pages/IM/IM",
"style": {
"path": "pages/IM/IM",
"style": {
"navigationStyle": "custom"
}
},
},
{
"path": "pages/IM/IMmsgContent",
"style": {
"path": "pages/IM/IMmsgContent",
"style": {
"navigationStyle": "custom"
}
},
},
{
"path": "pages/viewCenter/viewCenter",
"style": {
"path": "pages/IM/IMsetting",
"style": {
"navigationBarTitleText": "聊天设置"
}
},
{
"path": "pages/viewCenter/viewCenter",
"style": {
"navigationStyle": "custom"
}
},
},
{
"path": "pages/manage/manage",
"style": {
"path": "pages/manage/manage",
"style": {
"navigationStyle": "custom"
}
},
},
{
"path": "pages/my/my",
"style": {
"path": "pages/my/my",
"style": {
"navigationStyle": "custom"
}
},
},
{
"path": "pages/my/shopInfo",
"style": {
"navigationBarTitleText": "店铺信息"
"path": "pages/my/shopInfo",
"style": {
"navigationBarTitleText": "店铺信息"
}
},
},
{
"path": "pages/my/setting",
"style": {
"navigationBarTitleText": "设置"
"path": "pages/my/setting",
"style": {
"navigationBarTitleText": "设置"
}
},
},
{
"path": "pages/my/contract",
"style": {
"navigationBarTitleText": "合同"
"path": "pages/my/contract",
"style": {
"navigationBarTitleText": "合同"
}
},
},
{
"path": "pages/my/printer/printerList",
"style": {
@ -168,53 +173,52 @@
{
"path": "pages/my/aboutUs/records",
"style": {
"navigationBarTitleText": "网址"
"navigationBarTitleText": "网址"
}
},
{
"path": "pages/my/versions",
"style": {
"navigationBarTitleText": "版本号"
"navigationBarTitleText": "版本号"
}
}
],
"globalStyle": {
"navigationBarTextStyle": "black",
"navigationBarTitleText": "uni-app",
"navigationBarBackgroundColor": "#FFFFFF",
"backgroundColor": "#FFFFFF",
],
"globalStyle": {
"navigationBarTextStyle": "black",
"navigationBarTitleText": "uni-app",
"navigationBarBackgroundColor": "#FFFFFF",
"backgroundColor": "#FFFFFF",
"pageOrientation": "portrait",
"adjustPosition": true
},
"tabBar": {
"color": "#000",
"selectedColor": "#4b71ff",
"borderStyle": "black",
"backgroundColor": "#ffffff",
},
"tabBar": {
"custom": true,
"color": "#000",
"selectedColor": "#4b71ff",
"borderStyle": "black",
"backgroundColor": "#ffffff",
"iconfontSrc": "/static/font/iconfont.ttf",
"fontSize":"14px",
"height": "58px",
"spacing":"5px",
"list": [
"fontSize": "14px",
"list": [
{
"pagePath": "pages/order/order",
"iconfont": {
"text": "\ue607",
"selectedText": "\ue607",
"selectedColor": "#4b71ff",
"color":"#000",
"fontSize":"20px"
"color": "#000",
"fontSize": "20px"
},
"text": "工作台"
},
},
{
"pagePath": "pages/IM/IM",
"iconfont": {
"text": "\ue66c",
"selectedText": "\ue66c",
"selectedColor": "#4b71ff",
"color":"#000",
"fontSize":"22px"
"color": "#000",
"fontSize": "22px"
},
"text": "消息"
},
@ -224,8 +228,8 @@
"text": "\ue6bc",
"selectedText": "\ue6bc",
"selectedColor": "#4b71ff",
"color":"#000",
"fontSize":"20px"
"color": "#000",
"fontSize": "20px"
},
"text": "视图中心"
},
@ -235,12 +239,11 @@
"text": "\ue64c",
"selectedText": "\ue64c",
"selectedColor": "#4b71ff",
"color":"#000",
"fontSize":"24px"
"color": "#000",
"fontSize": "24px"
},
"text": "我的"
}
]
}
}
}

View File

@ -4,12 +4,24 @@
<view class="IM-setting">
<view class="IM-status">
<text>{{ msgInfo.mine.user_nickname }}</text>
<text class="status-color"></text>
<u-icon name="arrow-down">arrow-down</u-icon>
<!-- <text class="status-color"></text> -->
<!-- <u-icon name="arrow-down">arrow-down</u-icon> -->
</view>
<view class="setting-icon-block">
<u-icon name="photo">arrow-down</u-icon>
<u-icon name="photo">arrow-down</u-icon>
<u-icon
class="u-icon icon-kefu"
custom-prefix="custom-icon-kefu custom-icon"
size="26"
color="#000"
@click="senMsgAdmin"
></u-icon>
<u-icon
class="u-icon icon-shezhi"
custom-prefix="custom-icon-shezhi custom-icon"
size="22"
color="#000"
@click="skipuIMsetting"
></u-icon>
</view>
</view>
<view class="tabs-block">
@ -45,8 +57,18 @@
>
<view class="user-img-content">
<view class="user-img-block">
<image class="img" :src="item.avatar" />
<image
class="img"
:src="item.avatar || '../../static/images/user-avatar.jpg'"
/>
</view>
<u-badge
class="im-weidu-badge"
:show="true"
shape="horn"
:value="item.weidu || 0"
max="99"
></u-badge>
</view>
<view class="msg-info-block" @click="skiupMsg(item)">
<view class="msg-title">{{ item.username }}</view>
@ -60,6 +82,7 @@
</view>
</view>
</view>
<tabbar tabbarName="IM"></tabbar>
</view>
</template>
@ -69,10 +92,12 @@ import tuiTabs from "../../components/tui-tabs.vue";
import { GetImConfig } from "../../api/im";
import statusBar from "../../components/status-bar.vue";
import { mapState } from "vuex";
import tabbar from "@/components/tabbar/tabbar.vue";
export default {
components: {
tuiTabs,
statusBar,
tabbar,
},
data() {
return {
@ -102,7 +127,49 @@ export default {
},
onLoad() {},
computed: {
...mapState("user", ["uid"]),
...mapState("user", ["uid", "userInfo", "socket", "imWeidu", "getMsg"]),
},
watch: {
imWeidu: {
handler(newValue, oldValue) {
if (newValue) {
this.msgList = this.msgList.map((item) => {
if (this.imWeidu.hasOwnProperty(item.id) && item.id !== "userId") {
// obj
return {
...item, //
...this.imWeidu[item.id], // objid
};
}
return item;
});
}
},
deep: true,
},
getMsg: {
handler(newValue, oldValue) {
if (newValue) {
const exists = this.msgList.some((item) => item.id == newValue.id);
if (!exists) {
const newItem = {
user_id: newValue.user_id,
friend_id: newValue.friend_id,
username: newValue.username,
avatar: newValue.avatar,
user_nickname: newValue.username,
user_avatar: newValue.avatar,
rid: 2,
id: newValue.id,
weidu: 1,
};
this.msgList = [...this.msgList, newItem];
}
}
},
},
},
methods: {
async getImConfig() {
@ -112,7 +179,20 @@ export default {
this.msgInfo = res.data;
if (res.data.friend.length > 0) {
this.msgList = res.data.friend[0].list;
let _imWeiDu = uni.getStorageSync("imWeiDu");
if (_imWeiDu) {
this.msgList = res.data.friend[0].list.map((item) => {
if (_imWeiDu.hasOwnProperty(item.id) && item.id !== "userId") {
return {
...item,
..._imWeiDu[item.id],
};
}
return item;
});
} else {
this.msgList = res.data.friend[0].list;
}
}
}
},
@ -120,10 +200,43 @@ export default {
this.currentTab = e.index;
},
skiupMsg(item) {
this.$store.commit("user/REMOVE_IM_KEY", item.id.toString());
uni.navigateTo({
url: `/pages/IM/IMmsgContent?item=${JSON.stringify(item)}`,
});
},
senMsgAdmin() {
let item = {
user_friend_id: 36,
user_id: 10001,
friend_id: 10001,
friend_note: "",
user_friend_addtime: "2025-05-09 10:03:33",
friend_state: 2,
friend_invite: 2,
username: "系统客服",
avatar:
"https://media-mall-prod-1259811287.cos.ap-guangzhou.myqcloud.com/media/media/plantform/20250307/c4cab676e06a49b282c2cbbe481f0fa1.png",
sign: "",
level_name: "v1",
user_nickname: "系统客服",
user_avatar:
"https://media-mall-prod-1259811287.cos.ap-guangzhou.myqcloud.com/media/media/plantform/20250307/c4cab676e06a49b282c2cbbe481f0fa1.png",
user_sign: "",
user_level_name: "v1",
rid: 2,
id: 776395489,
};
uni.navigateTo({
url: `/pages/IM/IMmsgContent?item=${JSON.stringify(item)}`,
});
},
skipuIMsetting() {
uni.navigateTo({
url: "/pages/IM/IMsetting",
});
},
},
};
</script>
@ -133,6 +246,7 @@ export default {
.IM-setting {
display: flex;
justify-content: space-between;
align-items: center;
padding: 32rpx 40rpx;
.IM-status {
@ -161,6 +275,7 @@ export default {
margin-bottom: 40rpx;
.user-img-content {
position: relative;
.user-img-block {
width: 80rpx;
height: 80rpx;
@ -172,6 +287,11 @@ export default {
height: 100%;
}
}
.im-weidu-badge {
position: absolute;
right: -50%;
top: 0;
}
}
.msg-info-block {
@ -197,5 +317,12 @@ export default {
}
}
}
.u-icon {
flex-direction: column-reverse;
}
.icon-kefu {
margin-right: 40rpx;
}
}
</style>
</style>

View File

@ -1,8 +1,12 @@
<template>
<view
:class="['IMmsgContent-container', { isIos: 'IMmsgContent-ios-container' }]"
:class="[
'IMmsgContent-container',
{ isIos: 'IMmsgContent-ios-container' },
{ 'disable-scroll': showVoiceMask },
]"
>
<u-navbar :title="ImItemInfo.username" :autoBack="true"> </u-navbar>
<u-navbar :title="ImItemInfo.username" :autoBack="true"></u-navbar>
<view class="tui-chat-content" id="tui-chat-content">
<!-- <tui-loadmore
v-if="loadding"
@ -13,9 +17,9 @@
<view>
<!-- <view class="tui-label">对方已通过您的好友请求</view> -->
<view v-for="(item, index) of msgList" :key="index">
<view class="tui-chat-center">{{
formatTime(item.message_time)
}}</view>
<view class="tui-chat-center">
{{ formatTime(item.message_time) }}
</view>
<view class="tui-chat-right" v-if="item.message_kind == 1">
<view
v-if="item.msg.type == 'text' || item.msg.type == 'user'"
@ -56,9 +60,9 @@
"
class="tui-chat-voice tui-rotate tui-ml"
></image>
<view :style="{ width: calculateVoiceWidth(item.mp3Time) }"
>{{ item.mp3Time }}"</view
>
<view :style="{ width: calculateVoiceWidth(item.mp3Time) }">
{{ item.mp3Time }}"
</view>
</view>
</view>
<image
@ -84,9 +88,9 @@
"
class="tui-chat-voice tui-mr"
></image>
<view :style="{ width: calculateVoiceWidth(item.mp3Time) }"
>{{ item.mp3Time }}"</view
>
<view :style="{ width: calculateVoiceWidth(item.mp3Time) }">
{{ item.mp3Time }}"
</view>
</view>
<!-- <tui-badge :dot="true" type="danger"></tui-badge> -->
</view>
@ -116,15 +120,22 @@
@uploadPictures="uploadPictures"
@photograph="photograph"
@uploadVideo="selectVideo"
@showVoicePopup="showVoicePopup"
@voiceEnd="voiceEnd"
:isHideKeyBoard="isHideKeyBoard"
></t-chat-bar>
</view>
</template>
<script>
import { GetImConfig, GetImMsgList, GetSendMsgAdd } from "../../api/im";
import {
GetImConfig,
GetImMsgList,
GetSendMsgAdd,
SetMsgRead,
} from "../../api/im";
import { UploadFilePromise } from "../../api/upload";
import { renderTime } from "../../utils/date";
import { toDayTime } from "../../utils/date";
import tChatBar from "@/components/t-chat-bar/t-chat-bar";
import tuiBadge from "@/components/tui-badge/tui-badge.vue";
import emoji from "../../static/im/emojiData.js";
@ -163,11 +174,12 @@ export default {
RECORDER: uni.getRecorderManager(),
playMsgid: "",
isPlayVoice: false,
sockrt: {},
// socket: {},
chattype: "user",
isHideKeyBoard: false,
emojiPath: "https://res.wx.qq.com/mpres/htmledition/images/icon/emotion/",
isIos: false,
showVoiceMask: false,
};
},
onLoad: function (options) {
@ -178,7 +190,7 @@ export default {
this.faceList = emoji.imgArr[1].emojiList;
},
onShow() {
this.socketServer();
// this.socketServer();
this.getPcEmoji();
// this.getImConfig();
this.getImMsgList();
@ -190,10 +202,174 @@ export default {
}
// #endif
},
watch: {
getMsg: function (val) {
let that = this;
let cacheid = 0;
console.log("获取到数据");
console.log(val);
var nowDate = new Date();
let lastid = val.message_id;
let tempmy = this.userInfo.im;
let msg_type = val.msg_type;
var nowDate = new Date();
let msg = {
type: "user",
sendmethod: this.chattype,
avatar: val.avatar,
needload: false,
fromid: this.ImItemInfo.id,
toid: tempmy.puid,
message_kind: 2,
msg: {
id: lastid,
type: msg_type,
userinfo: {
uid: this.ImItemInfo.id,
username: this.ImItemInfo.username,
face: val.avatar,
},
content: {
text: val.content,
},
},
mp3Time: msg_type == "voice" ? val.length : 0,
message_time: nowDate,
};
//
switch (msg_type) {
case "text":
msg.msg.content.text = val.content;
break;
case "voice":
msg.msg.content.url = val.content;
break;
case "img":
msg.msg.content.url = val.content;
break;
case "video":
msg.msg.content.url = val.content;
break;
case "redEnvelope":
msg.msg.content.blessing = val.content;
break;
case "rtc":
msg.msg.content.text = val.content;
break;
}
if (that.chattype == "user" && val.type == "friend") {
if (that.ImItemInfo.id == val.id) {
console.log("screened");
console.log(msg);
that.screened(msg);
// //
// if (msg_type == "rtc") {
// // #ifdef MP-WEIXIN
// this.$.gotopage("/rtc/room/1v1wx?to_user_id=" + that.options.uid);
// // #endif
// // #ifdef APP-PLUS
// this.$.gotopage("/rtc/room/1v1?to_user_id=" + that.options.uid);
// // #endif
// }
}
cacheid = msg.fromid;
} else if (that.chattype == "group" && val.type == "group") {
if (that.ImItemInfo.id == val.toid) {
that.screened(msg);
}
cacheid = msg.toid;
///
} else {
///
}
if (that.ImItemInfo.id == val.id) {
this.setMsgRead(lastid);
//
}
this.$nextTick(() => {
const query = uni.createSelectorQuery().in(this);
query.select(".IMmsgContent-container").boundingClientRect();
query.selectAll(".IMmsgContent-container view").boundingClientRect();
query.exec((res) => {
const scrollViewHeight = res[0].height;
const scrollContentHeight = res[1].reduce(
(total, item) => total + item.height,
0
);
// const scrollTop = scrollContentHeight - scrollViewHeight;
uni.pageScrollTo({
scrollTop: scrollViewHeight,
duration: 0,
});
});
});
// this.$apiconfig.cacheMessage(val, val.sendmethod, cacheid, tempmy);
// //
// this.$store.commit("resetWeidu", {
// type: this.chattype,
// val: this.chat_to_puid,
// });
},
},
computed: {
...mapState("user", ["uid", "userInfo"]),
...mapState("user", ["uid", "userInfo", "socket", "getMsg"]),
},
methods: {
async setMsgRead(lastid) {
await SetMsgRead({ message_id: lastid });
},
voiceEnd(voiceMP3Info) {
console.log('"voiceEnd"', voiceMP3Info);
if (voiceMP3Info) {
uni.uploadFile({
url: "https://mall.gpxscs.cn/mobile/shop/oss/upload", //
filePath: voiceMP3Info.voice,
header: {
merchcode: "cb0ac353f02a73a7c45885a862fe4de1",
},
name: "upfile",
formData: {
user: "test",
},
success: (uploadFileRes) => {
console.log(voiceMP3Info);
let tmpres = JSON.parse(uploadFileRes.data);
let msg = {
length: voiceMP3Info.length,
url: tmpres.data.url,
mp3Time: voiceMP3Info.length,
};
// let min = parseInt(this.recordLength / 60);
// let sec = this.recordLength % 60;
// min = min < 10 ? "0" + min : min;
// sec = sec < 10 ? "0" + sec : sec;
// msg.length = min + ":" + sec;
///
this.sendMsg(msg, "voice");
},
});
}
this.showVoiceMask = false;
console.log("结束录音");
},
showVoicePopup() {
this.AUDIO.stop();
this.showVoiceMask = true;
},
uploadPictures() {
this.isHideKeyBoard = true;
this.selectPhotoOrTakeShot("album");
@ -274,8 +450,6 @@ export default {
},
//
addTextMsg(msg) {
console.info("addTextMsg");
console.info(msg);
this.msgList.push(msg);
},
//
@ -337,26 +511,26 @@ export default {
// }
}
},
socketServer() {
console.log(this.userInfo.im.node_site_url);
// socketServer() {
// console.log(this.userInfo.im.node_site_url);
this.sockrt = new this.$Socket({
url: this.userInfo.im.node_site_url,
maxInterValCount: 5,
interValTime: 2000,
onClose: (res) => {
console.log("sockrt关闭");
},
onOpen: (res) => {
console.log("sockrt连接成功");
},
onMsg: (res) => {
console.log("onMsg", res);
},
});
// this.socket = new this.$Socket({
// url: this.userInfo.im.node_site_url,
// maxInterValCount: 5,
// interValTime: 2000,
// onClose: (res) => {
// console.log("socket");
// },
// onOpen: (res) => {
// console.log("socket");
// },
// onMsg: (res) => {
// console.log("onMsg", res);
// },
// });
this.sockrt.connectserver(this.userInfo.im);
},
// this.socket.connectserver(this.userInfo.im);
// },
processTimeString(timeStr) {
const parts = timeStr.split(":");
@ -608,8 +782,6 @@ export default {
to: to,
};
console.log(this.ImItemInfo);
let params = {
user_other_id: this.ImItemInfo.friend_id,
message_content: mine.content,
@ -624,7 +796,7 @@ export default {
if (res && res.status == 200) {
chat_data.mine.message_id = res.data.message_other_id;
this.sockrt.nsend(chat_data);
this.socket.nsend(chat_data);
let lastid = res.data.message_other_id;
let tempmy = this.userInfo.im;
///TOID
@ -646,6 +818,7 @@ export default {
},
content: content,
},
mp3Time: type == "voice" ? content.length : 0,
message_time: nowDate,
};
this.screened(msg);
@ -782,10 +955,6 @@ export default {
let res = await GetImMsgList(params);
if (res && res.status == 200) {
this.msgList = res.data.items.reverse();
this.msgList.forEach((item) => {
let time = this.formatTime(item.message_time);
console.log("时间:", time);
});
this.msgList.forEach((item) => {
item.msg.content.text = this.im_decode(item.msg.content.text);
@ -831,7 +1000,7 @@ export default {
});
},
formatTime(time) {
return renderTime(time);
return toDayTime(time);
},
//
setPicSize(content) {
@ -874,15 +1043,31 @@ export default {
background-color: #fafafa;
font-size: 1rem;
font-family: -apple-system-font, Helvetica Neue, Helvetica, sans-serif;
min-height: 100vh;
&.disable-scroll {
height: 100vh;
overflow: hidden;
}
.u-navbar {
height: 88rpx;
margin-bottom: 20rpx;
}
/*chatbox*/
.tui-chat-content {
width: 100%;
/* 阻止默认触摸行为 */
pointer-events: auto;
/* 阻止滚动传递 */
overscroll-behavior: contain;
/* 当显示语音面板时添加的类 */
}
.penetrate-touch {
pointer-events: none;
}
.tui-chatbox {

View File

@ -0,0 +1,48 @@
<template>
<view class="IMsetting-container">
<view class="sound-setting-content">
<view class="sound-label">声音设置</view>
<view class="sound-switch">
<u-switch
v-model="soundSwitchValue"
activeColor="#5ac725"
inactiveColor="#f56c6c"
@change="changSound"
></u-switch>
</view>
</view>
</view>
</template>
<script>
export default {
data() {
return {
soundSwitchValue: true,
};
},
onShow() {
this.soundSwitchValue = uni.getStorageSync("isImSound");
},
methods: {
changSound(e) {
uni.setStorageSync("isImSound", e);
},
},
};
</script>
<style lang="scss">
.IMsetting-container {
padding: 20rpx;
min-height: calc(100vh - 88rpx);
overflow: hidden;
background-color: #fafafa;
.sound-setting-content {
display: flex;
background: #fff;
justify-content: space-between;
padding: 40rpx;
border-radius: 12rpx;
}
}
</style>

View File

@ -0,0 +1,380 @@
<template>
<view class="voice-mask" v-show="showVoiceMask">
<!--语音条 -->
<view
class="voice-bar voice-del"
:class="{ voiceDel: needCancel }"
:style="{ width: getVoiceBarWidth }"
>
<image
src="../../static/images/chat/yinping.png"
class="voice-volume"
></image>
<view class="trangle-bottom" :class="{ trangleDel: needCancel }"></view>
</view>
<view class="voice-send">
<!-- 取消和转文字图标 -->
<view class="voice-middle-wrapper">
<!-- 取消 -->
<view class="voice-left-wrapper">
<view class="cancel-del" :class="{ delTip: needCancel }">
松开 取消
</view>
<view
class="voice-middle-inner close"
:class="{ bigger: needCancel }"
>
<u-icon name="close" color="#fff" size="24"></u-icon>
</view>
</view>
<!-- 转文字 -->
<view class="send-tip" :class="{ sendTipNone: needCancel }">
松开 发送
</view>
</view>
<!-- 底部语音按钮 -->
<view
ref="maskBottom"
class="mask-bottom"
@touchstart="handleTouchStart"
@touchmove="handleTouchMove"
@touchend="handleTouchEnd"
>
<image src="../../static/images/chat/voice.png"></image>
</view>
</view>
</view>
</template>
<script>
const recorderManager = uni.getRecorderManager();
export default {
props: {
showVoiceMask: {
type: Boolean,
default: false,
},
voicePopupTouches: {
type: Object,
default: {},
},
},
data() {
return {
voicelength: 0,
needCancel: false,
startX: 0,
startY: 0,
timer: 0,
maskBottomRect: null,
isRecording: false,
isOutside: false,
tempFilePath: null,
startTime: 0,
isOutside: false,
};
},
computed: {
//
getVoiceBarWidth() {
return 230 + this.voicelength * 4 + "rpx";
},
},
watch: {
showVoiceMask: {
handler: function (val, oldVal) {
if (val) {
console.log("showVoicePopupTouches", this.voicePopupTouches);
console.log(this.$refs["maskBottom"].$el.dispatchEvent);
const mockEvent = new TouchEvent("touchstart", {
touches: [{ pageX: 100, pageY: 100 }], //
});
this.$refs["maskBottom"].$el.dispatchEvent(mockEvent);
this.handleTouchStart(this.voicePopupTouches);
}
},
},
},
created() {
//
recorderManager.onStart(() => {
console.log("录音开始");
this.isRecording = true;
this.startTime = Date.now();
});
recorderManager.onPause(() => {
console.log("录音暂停");
this.isRecording = false;
});
recorderManager.onResume(() => {
console.log("录音继续");
this.isRecording = true;
});
},
methods: {
async getMaskBottomRect() {
return new Promise((resolve) => {
const query = uni.createSelectorQuery().in(this);
query
.select(".mask-bottom")
.boundingClientRect((data) => {
this.maskBottomRect = data;
console.log("元素位置信息:", data); //
resolve(data);
})
.exec();
});
},
async handleTouchStart(e) {
console.log("handleTouchStart", e);
if (!this.maskBottomRect) {
await this.getMaskBottomRect();
}
recorderManager.start();
this.length = 1;
this.startX = e.touches[0].pageX;
this.startY = e.touches[0].pageY;
this.timer = setInterval(() => {
this.length += 1;
if (this.length >= 60) {
clearInterval(this.timer);
this.handleTouchEnd();
}
}, 1000);
this.isRecording = true;
this.isOutside = false;
},
handleTouchMove(e) {
// mask-bottom
if (!this.maskBottomRect) return;
const touchX = e.touches[0].pageX;
const touchY = e.touches[0].pageY;
// mask-bottom
//
const SAFE_MARGIN = 5; //
const isNowOutside =
touchX < this.maskBottomRect.left - SAFE_MARGIN ||
touchX >
this.maskBottomRect.left + this.maskBottomRect.width + SAFE_MARGIN ||
touchY < this.maskBottomRect.top - SAFE_MARGIN ||
touchY >
this.maskBottomRect.top + this.maskBottomRect.height + SAFE_MARGIN;
//
console.log(
`触摸点: (${touchX}, ${touchY})`,
`元素区域: [${this.maskBottomRect.left}, ${this.maskBottomRect.top}, ${this.maskBottomRect.width}, ${this.maskBottomRect.height}]`,
`是否在外: ${isNowOutside}`
);
//
if (isNowOutside !== this.isOutside) {
this.isOutside = isNowOutside;
if (this.isOutside) {
//
recorderManager.pause();
console.log("已离开区域,暂停录制");
} else {
//
recorderManager.resume();
console.log("已回到区域,继续录制");
}
}
//
if (this.startX - touchX > 14 && this.startY - touchY > 50) {
this.needCancel = true;
} else {
this.needCancel = false;
}
},
handleTouchEnd(e) {
clearInterval(this.timer);
recorderManager.stop();
recorderManager.onStop((res) => {
const message = {
voice: res.tempFilePath,
length: this.length,
};
if (!this.needCancel) {
this.inputSubmit(message, 2);
} else {
this.inputSubmit();
}
this.needCancel = false;
});
},
inputSubmit(msg, types) {
if (msg && types) {
this.$emit("voiceEnd", msg, types);
} else {
this.$emit("voiceEnd");
}
},
},
};
</script>
<style lang="scss">
.voice-mask {
position: fixed;
top: 0;
right: 0;
bottom: 0;
left: 0;
background-color: rgba(0, 0, 0, 0.8);
z-index: 9999; /* 确保足够高 */
display: flex;
justify-content: center;
align-items: center;
}
.voice-bar {
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -30%);
height: 150rpx;
background-color: #51ff50;
border-radius: 26rpx;
margin-bottom: 220rpx;
z-index: 9999;
}
.voiceDel {
left: 80rpx;
top: 50%;
width: 170rpx !important;
transform: translateX(0%);
transform: translateY(-30%);
background-color: red;
}
.voice-volume {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 160rpx;
height: 36rpx;
}
.volumeDel {
width: 80rpx;
}
.trangle-bottom {
position: absolute;
bottom: -38rpx;
left: 50%;
transform: translateX(-50%);
border-width: 20rpx;
border-style: solid;
border-color: #51ff50 transparent transparent transparent;
z-index: 9999;
}
.trangleDel {
border-color: red transparent transparent transparent;
}
.voice-send {
position: relative;
bottom: 0;
width: 100%;
height: 100%;
z-index: 9999;
}
.voice-middle-wrapper {
width: 100%;
display: flex;
position: absolute;
justify-content: space-between;
align-items: flex-end;
margin-bottom: 40rpx;
bottom: 15%;
}
.voice-left-wrapper {
display: flex;
flex-direction: column;
justify-content: center;
align-items: flex-end;
}
.cancel-del {
display: none;
}
.delTip {
display: block;
color: #bfbfbf;
margin: 0 22rpx 18rpx 0;
}
.voice-middle-inner {
display: flex;
justify-content: center;
align-items: center;
background-color: #595959;
width: 140rpx;
height: 140rpx;
border-radius: 50%;
}
.close {
transform: rotate(350deg);
margin-left: 80rpx;
}
.bigger {
width: 170rpx;
height: 170rpx;
background: #ececec;
}
.to-text {
transform: rotate(10deg);
margin-right: 80rpx;
}
.close-icon {
width: 80rpx;
height: 80rpx;
color: #fff;
}
.wen {
font-size: 40rpx;
color: #bfbfbf;
}
.send-tip {
position: absolute;
left: 50%;
bottom: 0rpx;
transform: translate(-50%, 36%);
color: #bfbfbf;
}
.sendTipNone {
display: none;
}
.mask-bottom {
position: absolute;
left: 0;
right: 0;
bottom: 0;
width: 100%;
height: 180rpx;
border-top: #bababb 8rpx solid;
border-radius: 50% 50% 0 0;
background-image: linear-gradient(#949794, #e1e3e1);
z-index: 9999;
}
.mask-bottom image {
position: absolute;
width: 60rpx;
height: 60rpx;
top: 0;
right: 0;
bottom: 0;
left: 0;
margin: auto;
}
</style>

View File

@ -31,7 +31,13 @@
<view class="img-await"></view>
<view class="tips">审核中1-7个工作日内答复请耐心等待</view>
</view>
<view class="time">申请时间:{{ auditInfo.created_at }}</view>
<view class="" v-if="auditInfo.approval_status == 4">
<view class="img-no-audit"></view>
<view class="tips">暂无申请记录</view>
</view>
<view class="time" v-if="auditInfo.approval_status != 4"
>申请时间:{{ auditInfo.created_at }}</view
>
<u-form :model="form" class="form" ref="uForm" label-width="70">
<u-form-item
:label="item.label"
@ -175,12 +181,17 @@ export default {
let res = await GetAuditInfo(params);
if (res && res.status == 200) {
this.auditInfo = res.data || {
approval_status: 3,
approval_status: 4,
created_at: "2099-02-17 09:25:53",
approval_remark: "",
approval_invalid_col: [],
};
if (!res.data) {
this.showLoading = false;
return;
}
if (this.auditInfo.contract_download_url) {
uni.setStorageSync(
"contractDownloadUrl",
@ -413,6 +424,16 @@ export default {
background-size: 100% 100%;
}
.img-no-audit {
margin: 0 auto;
margin-top: 17%;
margin-bottom: 20%;
width: 600rpx;
height: 600rpx;
background-image: url("../../static/no-data.png");
background-size: 100% 100%;
}
.tips {
margin-bottom: 24rpx;
text-align: center;

View File

@ -20,18 +20,18 @@
<view class="user-info">
<view class="user-name-block" @click="skipu()">
<view class="user-name">
{{ accountInfo.store_info.store_name }}</view
>
{{ accountInfo.store_info.store_name }}
</view>
<u-icon
style="display: inline-block; margin-left: 8rpx"
name="arrow-right"
size="12"
color="#aaaaaa"
></u-icon
></view>
<view class="user-store-name">{{
accountInfo.store_info.store_grade_name
}}</view>
></u-icon>
</view>
<view class="user-store-name">
{{ accountInfo.store_info.store_grade_name }}
</view>
</view>
</view>
<view class="hander-right">
@ -88,7 +88,7 @@
<view class="business-box">
<view class="business-status">
<view class="status-name">店铺正常营业中</view>
<view class="business-time"> 营业时间0700 - 2230 </view>
<view class="business-time">营业时间0700 - 2230</view>
</view>
<u-switch
v-model="isBusiness"
@ -118,7 +118,7 @@
></u-icon>
店铺二维码
</view>
<view class="fm-item">
<!-- <view class="fm-item">
<u-icon
class="fm-icon"
custom-prefix="custom-icon-yunfei custom-icon"
@ -126,18 +126,21 @@
color="#000"
></u-icon>
运费设置
</view>
</view> -->
</view>
</view>
<tabbar tabbarName="my"></tabbar>
</view>
</template>
<script>
import { GetAccountDashboard } from "../../api/user";
import statusBar from "../../components/status-bar.vue";
import tabbar from "@/components/tabbar/tabbar.vue";
export default {
components: {
statusBar,
tabbar,
},
data() {
return {
@ -205,7 +208,7 @@ export default {
};
</script>
<style lang='scss'>
<style lang="scss">
.my-container {
background: #f8f8f8;
height: calc(100vh - 100rpx);
@ -270,8 +273,9 @@ export default {
display: flex;
flex-flow: column;
align-items: center;
justify-content: end;
justify-content: flex-end;
margin-left: 48rpx;
height: 90rpx;
}
.icon-shezhi {
@ -367,4 +371,4 @@ export default {
}
}
}
</style>
</style>

View File

@ -22,7 +22,7 @@
></u-icon>
</view>
<view class="form-item" style="margin-top: 40rpx">
<view class="item-label"> 铃声设置 </view>
<view class="item-label">铃声设置</view>
<u-icon
style="display: inline-block; margin-left: 8rpx"
name="arrow-right"
@ -31,7 +31,7 @@
></u-icon>
</view>
<view class="form-item" style="margin-top: 40rpx" @click="skipuProtocol">
<view class="item-label"> 隐私政策 </view>
<view class="item-label">隐私政策</view>
<u-icon
style="display: inline-block; margin-left: 8rpx"
name="arrow-right"
@ -40,7 +40,7 @@
></u-icon>
</view>
<view class="form-item" @click="skipuAboutUs">
<view class="item-label"> 关于我们 </view>
<view class="item-label">关于我们</view>
<u-icon
style="display: inline-block; margin-left: 8rpx"
name="arrow-right"
@ -49,7 +49,7 @@
></u-icon>
</view>
<view class="form-item" style="margin-top: 40rpx" @click="skipuVersions">
<view class="item-label"> 版本信息 </view>
<view class="item-label">版本信息</view>
<u-icon
style="display: inline-block; margin-left: 8rpx"
name="arrow-right"
@ -58,7 +58,7 @@
></u-icon>
</view>
<view class="form-item btn-outLogin" @click="outLogin">
<view class="item-label"> 退出登录 </view>
<view class="item-label">退出登录</view>
</view>
</view>
</template>
@ -148,4 +148,4 @@ export default {
}
}
}
</style>
</style>

View File

@ -107,16 +107,18 @@
>
<view class="order-info-hander">
<view class="order-num-block">
<view class="order-serial-num"
>#<text
<view class="order-serial-num">
#
<text
style="
font-size: 46rpx;
padding-left: 4rpx;
font-weight: bold;
"
>{{ item.orderNum }}</text
></view
>
>
{{ item.orderNum }}
</text>
</view>
<view class="delivery-status">
{{ sfFormatStatus(item.order_state_id) }}
</view>
@ -135,14 +137,14 @@
item.buyer_info.da_mobile.slice(-4)
}}
</view>
<view class="user-address"
>收货地址{{
<view class="user-address">
收货地址{{
item.buyer_info.da_province +
item.buyer_info.da_city +
item.buyer_info.da_county +
item.buyer_info.da_address
}}</view
>
}}
</view>
<view class="distance">距离{{ item.distance / 1000 }}km</view>
</view>
<view class="picking-info">
@ -153,9 +155,9 @@
<u-button class="picking-btn">拣货完成</u-button>
</view>
<view class="delivery-status-info">
<view class="delivery-status">{{
sfFormatStatus(item.order_state_id)
}}</view>
<view class="delivery-status">
{{ sfFormatStatus(item.order_state_id) }}
</view>
<view class="delivery-num">{{ item.order_pickup_num_str }}</view>
</view>
<view class="order-remark">
@ -164,9 +166,9 @@
</view>
<view class="commodity-info-block">
<view class="commodity-num">
<text style="font-size: 36rpx">{{
item.order_items.length || 0
}}</text>
<text style="font-size: 36rpx">
{{ item.order_items.length || 0 }}
</text>
<text>件商品</text>
</view>
<view
@ -179,31 +181,29 @@
:src="group.order_item_image"
></image>
<view class="commodity-content">
<view class="commodity-name"
>{{ group.item_name || 0 }}
<view class="commodity-name">{{ group.item_name || 0 }}</view>
<view class="commodity-barcode">
条码
<text style="padding-left: 8rpx">
{{ group.item_barcode || 0 }}
</text>
</view>
<view class="commodity-barcode"
>条码
<text style="padding-left: 8rpx"
>{{ group.item_barcode || 0 }}
</text></view
>
<view class="commodity-specification"
>规格
<text style="padding-left: 8rpx"
>{{ item.specification || 0 }}
<view class="commodity-specification">
规格
<text style="padding-left: 8rpx">
{{ item.specification || 0 }}
</text>
</view>
</view>
<view class="commodity-num"
>X
<text style="padding-left: 8rpx">{{
item.order_item_quantity || 0
}}</text></view
>
<view class="commodity-price"
>{{ item.item_cost_price || 0 }}</view
>
<view class="commodity-num">
X
<text style="padding-left: 8rpx">
{{ item.order_item_quantity || 0 }}
</text>
</view>
<view class="commodity-price">
{{ item.item_cost_price || 0 }}
</view>
</view>
</view>
<!-- <view class="baling-charges-block">
@ -213,63 +213,74 @@
<view class="cost-info-block">
<view class="cost-info-item cost-info-subtotal">
<view class="cost-info-title">小计</view>
<view class="cost-info-num"
>{{ item.order_product_amount }}</view
>
<view class="cost-info-num">
{{ item.order_product_amount }}
</view>
</view>
<view class="cost-info-item cost-info-subtotal">
<view
class="cost-info-title"
style="color: #333333; font-weight: 700"
>商家活动支付<text
><u-icon
>
商家活动支付
<text>
<u-icon
style="display: inline-block; margin-left: 8rpx"
name="question-circle"
size="12"
color="aaaaaa"
></u-icon></text
></view>
<view class="cost-info-num"
>{{ item.order_discount_amount }}</view
>
></u-icon>
</text>
</view>
<view class="cost-info-num">
{{ item.order_discount_amount }}
</view>
</view>
<view class="cost-info-item cost-info-subtotal">
<view
class="cost-info-title"
style="color: #333333; font-weight: 700"
>平台服务费<text
><u-icon
>
平台服务费
<text>
<u-icon
style="display: inline-block; margin-left: 8rpx"
name="question-circle"
size="12"
color="#aaaaaa"
></u-icon></text
></view>
></u-icon>
</text>
</view>
<view class="cost-info-num">{{ item.platform_fee }}</view>
</view>
<view class="cost-info-item cost-info-subtotal">
<view
class="cost-info-title"
style="color: #333333; font-weight: 700"
>配送费用<text
><u-icon
>
配送费用
<text>
<u-icon
style="display: inline-block; margin-left: 8rpx"
name="question-circle"
size="12"
color="#aaaaaa"
></u-icon></text
></view>
<view class="cost-info-num"
>{{ item.order_shipping_fee }}</view
>
></u-icon>
</text>
</view>
<view class="cost-info-num">
{{ item.order_shipping_fee }}
</view>
</view>
<view class="cost-info-income">
<view class="predict-income"
>预计收入<text
<view class="predict-income">
预计收入
<text
style="font-size: 40rpx; color: #333333; font-weight: 700"
>24.95</text
></view
>
>
24.95
</text>
</view>
<view class="customer-actual-payment">
顾客实际支付 30.50
</view>
@ -346,16 +357,18 @@
>
<view class="order-info-hander">
<view class="order-num-block">
<view class="order-serial-num"
>#<text
<view class="order-serial-num">
#
<text
style="
font-size: 46rpx;
padding-left: 4rpx;
font-weight: bold;
"
>{{ item.orderNum }}</text
></view
>
>
{{ item.orderNum }}
</text>
</view>
<view class="delivery-status" style="color: red">
{{ sfFormatStatus(item.order_state_id) }}
</view>
@ -375,16 +388,16 @@
item.buyer_info.da_mobile.slice(-4)
}}
</view>
<view class="user-info-icon-block"> </view>
<view class="user-info-icon-block"></view>
</view>
<view class="user-address"
>收货地址{{
<view class="user-address">
收货地址{{
item.buyer_info.da_province +
item.buyer_info.da_city +
item.buyer_info.da_county +
item.buyer_info.da_address
}}</view
>
}}
</view>
<view class="distance">距离{{ item.distance / 1000 }}km</view>
</view>
<!-- <view class="picking-info">
@ -406,9 +419,9 @@
</view>
<view class="commodity-info-block">
<view class="commodity-num">
<text style="font-size: 36rpx">{{
item.order_items.length || 0
}}</text>
<text style="font-size: 36rpx">
{{ item.order_items.length || 0 }}
</text>
<text>件商品</text>
</view>
<view
@ -421,31 +434,29 @@
:src="group.order_item_image"
></image>
<view class="commodity-content">
<view class="commodity-name"
>{{ group.item_name || 0 }}
<view class="commodity-name">{{ group.item_name || 0 }}</view>
<view class="commodity-barcode">
条码
<text style="padding-left: 8rpx">
{{ group.item_barcode || 0 }}
</text>
</view>
<view class="commodity-barcode"
>条码
<text style="padding-left: 8rpx"
>{{ group.item_barcode || 0 }}
</text></view
>
<view class="commodity-specification"
>规格
<text style="padding-left: 8rpx"
>{{ item.specification || 0 }}
<view class="commodity-specification">
规格
<text style="padding-left: 8rpx">
{{ item.specification || 0 }}
</text>
</view>
</view>
<view class="commodity-num"
>X
<text style="padding-left: 8rpx">{{
item.order_item_quantity || 0
}}</text></view
>
<view class="commodity-price"
>{{ item.item_cost_price || 0 }}</view
>
<view class="commodity-num">
X
<text style="padding-left: 8rpx">
{{ item.order_item_quantity || 0 }}
</text>
</view>
<view class="commodity-price">
{{ item.item_cost_price || 0 }}
</view>
</view>
</view>
<!-- <view class="baling-charges-block">
@ -455,63 +466,74 @@
<view class="cost-info-block">
<view class="cost-info-item cost-info-subtotal">
<view class="cost-info-title">小计</view>
<view class="cost-info-num"
>{{ item.order_product_amount }}</view
>
<view class="cost-info-num">
{{ item.order_product_amount }}
</view>
</view>
<view class="cost-info-item cost-info-subtotal">
<view
class="cost-info-title"
style="color: #333333; font-weight: 700"
>商家活动支付<text
><u-icon
>
商家活动支付
<text>
<u-icon
style="display: inline-block; margin-left: 8rpx"
name="question-circle"
size="12"
color="aaaaaa"
></u-icon></text
></view>
<view class="cost-info-num"
>{{ item.order_discount_amount }}</view
>
></u-icon>
</text>
</view>
<view class="cost-info-num">
{{ item.order_discount_amount }}
</view>
</view>
<view class="cost-info-item cost-info-subtotal">
<view
class="cost-info-title"
style="color: #333333; font-weight: 700"
>平台服务费<text
><u-icon
>
平台服务费
<text>
<u-icon
style="display: inline-block; margin-left: 8rpx"
name="question-circle"
size="12"
color="#aaaaaa"
></u-icon></text
></view>
></u-icon>
</text>
</view>
<view class="cost-info-num">{{ item.platform_fee }}</view>
</view>
<view class="cost-info-item cost-info-subtotal">
<view
class="cost-info-title"
style="color: #333333; font-weight: 700"
>配送费用<text
><u-icon
>
配送费用
<text>
<u-icon
style="display: inline-block; margin-left: 8rpx"
name="question-circle"
size="12"
color="#aaaaaa"
></u-icon></text
></view>
<view class="cost-info-num"
>{{ item.order_shipping_fee }}</view
>
></u-icon>
</text>
</view>
<view class="cost-info-num">
{{ item.order_shipping_fee }}
</view>
</view>
<view class="cost-info-income">
<view class="predict-income"
>预计收入<text
<view class="predict-income">
预计收入
<text
style="font-size: 40rpx; color: #333333; font-weight: 700"
>24.95</text
></view
>
>
24.95
</text>
</view>
<view class="customer-actual-payment">
顾客实际支付 30.50
</view>
@ -587,47 +609,47 @@
>
<view class="order-info-hander">
<view class="order-num-block">
<view class="order-serial-num"
>#<text
<view class="order-serial-num">
#
<text
style="
font-size: 46rpx;
padding-left: 4rpx;
font-weight: bold;
"
>3</text
></view
>
>
3
</text>
</view>
<view class="order-num">订单号{{ item.order_id }}</view>
</view>
<view class="rider-info">
<view class="delivery-time"> </view>
<view class="delivery-time"></view>
<view class="delivery-status">
{{ sfFormatStatus(item.order_state_id) }}
</view>
</view>
<view class="order-msg-tips"
>取消原因订单符合未发货秒退规则平台已优先退款</view
>
<view class="order-msg-tips">
取消原因订单符合未发货秒退规则平台已优先退款
</view>
</view>
<view class="steps-content" v-show="item.showRefundOrderInfo">
<view class="steps-title"
>退款
<view class="steps-title">
退款
<u-icon
style="display: inline-block; margin: 0 8rpx"
@click="handlePopup"
name="question-circle"
size="12"
color="aaaaaa"
>
</u-icon
></view>
></u-icon>
</view>
<u-steps :current="0" direction="column" :dot="true">
<u-steps-item
class="steps-item-1"
title="系统自动退款"
desc="订单符合未发货秒退规则,平台已优先退款"
>
</u-steps-item>
></u-steps-item>
<u-steps-item
title="顾客申请全部退款"
desc="理由:商家联系我说没货了"
@ -636,10 +658,10 @@
</view>
<view class="" v-show="item.showRefundOrderInfo">
<view class="user-info-block">
<view class="user-info"> 张先生 手机尾号3158 </view>
<view class="user-address"
>收货地址金凤凰商业街18号4楼桂平发发网络有限公司</view
>
<view class="user-info">张先生 手机尾号3158</view>
<view class="user-address">
收货地址金凤凰商业街18号4楼桂平发发网络有限公司
</view>
</view>
<view class="order-remark">
<text style="color: red; font-weight: bold">备注</text>
@ -658,23 +680,21 @@
<image class="commodity-info-img" :src="item.imrUrl"></image>
<view class="commodity-content">
<view class="commodity-name">{{ item.name }}</view>
<view class="commodity-barcode"
>条码
<text style="padding-left: 8rpx">{{
item.barcode
}}</text></view
>
<view class="commodity-specification"
>规格
<text style="padding-left: 8rpx">{{
item.specification
}}</text>
<view class="commodity-barcode">
条码
<text style="padding-left: 8rpx">{{ item.barcode }}</text>
</view>
<view class="commodity-specification">
规格
<text style="padding-left: 8rpx">
{{ item.specification }}
</text>
</view>
</view>
<view class="commodity-num"
>X
<text style="padding-left: 8rpx">{{ item.num }}</text></view
>
<view class="commodity-num">
X
<text style="padding-left: 8rpx">{{ item.num }}</text>
</view>
<view class="commodity-price">{{ item.price }}</view>
</view>
</view>
@ -691,37 +711,45 @@
<view
class="cost-info-title"
style="color: #333333; font-weight: 700"
>商家活动支付<text
><u-icon
>
商家活动支付
<text>
<u-icon
style="display: inline-block; margin-left: 8rpx"
name="question-circle"
size="12"
color="aaaaaa"
></u-icon></text
></view>
></u-icon>
</text>
</view>
<view class="cost-info-num">30.50</view>
</view>
<view class="cost-info-item cost-info-subtotal">
<view
class="cost-info-title"
style="color: #333333; font-weight: 700"
>平台服务费<text
><u-icon
>
平台服务费
<text>
<u-icon
style="display: inline-block; margin-left: 8rpx"
name="question-circle"
size="12"
color="#aaaaaa"
></u-icon></text
></view>
></u-icon>
</text>
</view>
<view class="cost-info-num">30.50</view>
</view>
<view class="cost-info-income">
<view class="predict-income"
>预计收入<text
<view class="predict-income">
预计收入
<text
style="font-size: 40rpx; color: #333333; font-weight: 700"
>24.95</text
></view
>
>
24.95
</text>
</view>
<view class="customer-actual-payment">
顾客实际支付 30.50
</view>
@ -766,6 +794,7 @@
<view class="no-data-tips">暂无交易记录!</view>
</view>
</view>
<tabbar tabbarName="order"></tabbar>
</view>
</template>
@ -778,12 +807,14 @@ import { GetAuditInfo } from "../../api/audit";
import { GetAccountDashboard } from "../../api/user";
import favoriteLoading from "@/components/favorite-loading/favorite-loading.vue";
import tuiDropdownList from "@/components/tui-dropdown-list/tui-dropdown-list.vue";
import tabbar from "@/components/tabbar/tabbar.vue";
export default {
components: {
tuiTabs,
statusBar,
favoriteLoading,
tuiDropdownList,
tabbar,
},
computed: {
...mapState("account", ["accountInfo"]),
@ -1117,8 +1148,6 @@ export default {
};
</script>
<style lang="scss">
.index-container {
// overflow: hidden;

View File

@ -2,7 +2,7 @@
<view class="view-container">
<status-bar :backgroundColor="'#fff'" v-if="true"></status-bar>
<view class="item-content">
<view class="title"> 待办事处 </view>
<view class="title">待办事处</view>
<view class="item-list">
<view class="item">
<view class="item-value">{{ dashboardInfo.return.review_num }}</view>
@ -13,21 +13,21 @@
<view class="item-title">违规商品</view>
</view>
<view class="item">
<view class="item-value">{{
dashboardInfo.product.product_warning_num || 0
}}</view>
<view class="item-value">
{{ dashboardInfo.product.product_warning_num || 0 }}
</view>
<view class="item-title">待补货</view>
</view>
</view>
</view>
<view class="order-content">
<view class="title"> 销量统计 </view>
<view class="title">销量统计</view>
<view class="order-list">
<view class="order-item">
<view class="order-title">今日销售额</view>
<view class="order-item-num">{{ orderSalesAmoutInfo.today }}</view>
<view class="order-bottom"
>昨日
<view class="order-bottom">
昨日
{{
orderSalesAmoutInfo.daym2m && orderSalesAmoutInfo.daym2m > 0
? "+"
@ -37,28 +37,26 @@
orderSalesAmoutInfo.daym2m == null
? "-"
: Number(orderSalesAmoutInfo.daym2m * 100).toFixed(0) + "%"
}}</view
>
}}
</view>
</view>
<view class="order-item order-item-1">
<view class="order-title">订单量</view>
<view class="order-item-num">{{ orderNumInfo.today }}</view>
<view class="order-bottom"
>昨日{{
orderNumInfo.daym2m && orderNumInfo.daym2m > 0 ? "+" : "-"
}}
<view class="order-bottom">
昨日{{ orderNumInfo.daym2m && orderNumInfo.daym2m > 0 ? "+" : "-" }}
{{
orderNumInfo.daym2m == null
? "-"
: Number(orderNumInfo.daym2m * 100).toFixed(0) + "%"
}}</view
>
}}
</view>
</view>
<view class="order-item order-item-2">
<view class="order-title">退货单数</view>
<view class="order-item-num">{{ orderReturnNumInfo.today }}</view>
<view class="order-bottom"
>昨日{{
<view class="order-bottom">
昨日{{
orderReturnNumInfo.daym2m && orderReturnNumInfo.daym2m > 0
? "+"
: "-"
@ -67,11 +65,12 @@
orderReturnNumInfo.daym2m == null
? "-"
: Number(orderReturnNumInfo.daym2m * 100).toFixed(0) + "%"
}}</view
>
}}
</view>
</view>
</view>
</view>
<tabbar tabbarName="shituzhongxin"></tabbar>
</view>
</template>
@ -83,10 +82,12 @@ import {
GetOrderReturnNum,
} from "../../api/shop";
import statusBar from "@/components/status-bar.vue";
import tabbar from "@/components/tabbar/tabbar.vue";
export default {
name: "viewCenter",
components: {
statusBar,
tabbar,
},
data() {
return {
@ -253,4 +254,4 @@ export default {
}
}
}
</style>
</style>

Binary file not shown.

After

Width:  |  Height:  |  Size: 619 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 54 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 72 KiB

View File

@ -1,20 +1,25 @@
import { GetLogin, GetAccountLogin } from '../../api/login';
import { OutLogin, GetAccountDashboard } from '../../api/user';
import { GetAuditStatus, GetAuditInfo } from '../../api/audit';
import { GetAuditInfo, GetAuditStatus } from "../../api/audit";
import { GetAccountLogin, GetLogin } from "../../api/login";
import { OutLogin } from "../../api/user";
import $Socket from "../../utils/socket";
import Vue from "vue";
// import $cookies from '../../utils/vue-cookies'
const defaultState = () => {
return {
userInfo: uni.getStorageSync('userInfo') || {},
uid: uni.getStorageSync('uid') || '',
ukey: uni.getStorageSync('ukey') || '',
auditStatusInfo: uni.getStorageSync('auditStatusInfo') || {
userInfo: uni.getStorageSync("userInfo") || {},
uid: uni.getStorageSync("uid") || "",
ukey: uni.getStorageSync("ukey") || "",
auditStatusInfo: uni.getStorageSync("auditStatusInfo") || {
approval_invalid_col: [],
approval_status: -4,
approval_remark: '',
approval_remark: "",
id: 0,
},
approvalStatus: uni.getStorageSync('approvalStatus'),
approvalStatus: uni.getStorageSync("approvalStatus"),
socket: {},
getMsg: {},
imWeidu: {},
};
};
@ -28,16 +33,45 @@ const mutations = {
state.auditStatusInfo = auditStatusInfo;
},
LOGIN_OUT(state) {
state.userInfo = '';
state.uid = '';
state.ukey = '';
state.userInfo = "";
state.uid = "";
state.ukey = "";
state.auditStatusInfo = {
approval_invalid_col: [],
approval_status: -4,
approval_remark: '',
approval_remark: "",
id: 0,
};
state.approvalStatus = '';
state.approvalStatus = "";
state.socket = {};
state.getMsg = {};
state.imWeidu = {};
},
CONNECT_SOCKET(state, { socket }) {
state.socket = socket;
},
GET_IM_MSG(state, { msg }) {
state.getMsg = msg;
var im = {};
let _imWeiDu = uni.getStorageSync("imWeiDu");
if (_imWeiDu) {
im = _imWeiDu;
}
if (!im[msg.id]) {
im[msg.id] = { weidu: 0 };
}
im[msg.id].weidu += 1;
im.userId = state.userInfo.user_id;
state.imWeidu = im;
uni.setStorageSync("imWeiDu", im);
},
REMOVE_IM_KEY(state, imId) {
Vue.delete(state.imWeidu, imId);
let imWeiDu = uni.getStorageSync("imWeiDu");
if (!imWeiDu && !imWeiDu[imId]) return;
delete imWeiDu[imId];
uni.setStorageSync("imWeiDu", imWeiDu);
},
};
@ -46,9 +80,9 @@ const actions = {
const res = await GetAccountLogin(params);
if (res && res.status == 200) {
let mobile = '';
let mobile = "";
let isContain = res.data.user_mobile.indexOf('86');
let isContain = res.data.user_mobile.indexOf("86");
if (isContain != -1 && res.data.user_mobile.length > 11) {
mobile = res.data.user_mobile.slice(2);
@ -58,23 +92,23 @@ const actions = {
const userInfo = res.data;
await dispatch('checkAccountIsPass', {
await dispatch("checkAccountIsPass", {
mobile: mobile,
userInfo: userInfo,
});
uni.setStorageSync('uid', res.data.user_id);
uni.setStorageSync('ukey', res.data.key);
uni.setStorageSync('userInfo', res.data);
uni.setStorageSync("uid", res.data.user_id);
uni.setStorageSync("ukey", res.data.key);
uni.setStorageSync("userInfo", res.data);
}
},
async GetLogin({ dispatch }, params) {
const res = await GetLogin(params);
if (res && res.status == 200) {
let mobile = '';
let mobile = "";
let isContain = res.data.user_mobile.indexOf('86');
let isContain = res.data.user_mobile.indexOf("86");
if (isContain != -1 && res.data.user_mobile.length > 11) {
mobile = res.data.user_mobile.slice(2);
@ -84,39 +118,66 @@ const actions = {
const userInfo = res.data;
uni.setStorageSync('uid', res.data.user_id);
uni.setStorageSync('ukey', res.data.key);
uni.setStorageSync('userInfo', res.data);
uni.setStorageSync("uid", res.data.user_id);
uni.setStorageSync("ukey", res.data.key);
uni.setStorageSync("userInfo", res.data);
await dispatch('checkAccountIsPass', {
await dispatch("checkAccountIsPass", {
mobile: mobile,
userInfo: userInfo,
});
await dispatch("connectSocket", res.data);
}
},
LoginOut({ commit }) {
async LoginOut({ commit }, isTokenExpires) {
if (isTokenExpires) {
let result = await OutLogin();
if (result && result.status == 200) {
uni.removeStorageSync("ukey");
uni.removeStorageSync("uid");
uni.removeStorageSync("accountDashboard");
uni.removeStorageSync("approvalStatus");
uni.removeStorageSync("auditInfo");
uni.removeStorageSync("auditId");
uni.removeStorageSync("contractDownloadUrl");
uni.removeStorageSync("pdfjs.history");
uni.removeStorageSync("userInfo");
commit("LOGIN_OUT");
setTimeout(() => {
uni.redirectTo({
url: "/pages/login/login",
});
}, 100);
}
return;
}
uni.showModal({
title: '退出登录',
title: "退出登录",
content: `您是否要退出登录?`,
success: async (res) => {
if (res.confirm) {
let res = await OutLogin();
if (res && res.status == 200) {
uni.removeStorageSync('ukey');
uni.removeStorageSync('uid');
uni.removeStorageSync('accountDashboard');
uni.removeStorageSync('approvalStatus');
uni.removeStorageSync('auditInfo');
uni.removeStorageSync('auditId');
uni.removeStorageSync('contractDownloadUrl');
uni.removeStorageSync('pdfjs.history');
uni.removeStorageSync('userInfo');
uni.removeStorageSync("ukey");
uni.removeStorageSync("uid");
uni.removeStorageSync("accountDashboard");
uni.removeStorageSync("approvalStatus");
uni.removeStorageSync("auditInfo");
uni.removeStorageSync("auditId");
uni.removeStorageSync("contractDownloadUrl");
uni.removeStorageSync("pdfjs.history");
uni.removeStorageSync("userInfo");
commit('LOGIN_OUT');
commit("LOGIN_OUT");
setTimeout(() => {
uni.redirectTo({
url: '/pages/index/index',
url: "/pages/login/login",
});
}, 100);
}
@ -129,14 +190,20 @@ const actions = {
let res = await GetAuditStatus({ mobile: mobile });
if (res && res.status == 200) {
const auditStatusInfo = res.data;
commit('GET_LOGIN', { userInfo, auditStatusInfo });
commit("GET_LOGIN", { userInfo, auditStatusInfo });
const lastIM = uni.getStorageSync("imWeiDu");
if (lastIM) {
if (lastIM.userId != userInfo.user_id) {
uni.removeStorageSync("imWeiDu");
}
}
let { approval_status, signed_status, store_status } = res.data;
//2-未通过3-待审核4-未申请过5-已提交审核;'
if ([2, 3, 4, 5].includes(approval_status)) {
uni.navigateTo({
url: '/pages/audit/checkAudit',
url: "/pages/audit/checkAudit",
});
return;
}
@ -147,7 +214,7 @@ const actions = {
// 5 - 已过期签署截止日到期后触发7 - 已拒签(签署方拒绝签署)',
if (signed_status != 2) {
uni.navigateTo({
url: '/pages/audit/checkAudit',
url: "/pages/audit/checkAudit",
});
return;
}
@ -157,19 +224,43 @@ const actions = {
let result = await GetAuditInfo({ mobile: mobile });
uni.setStorageSync(
'contractDownloadUrl',
"contractDownloadUrl",
result.data.contract_download_url
);
uni.setStorageSync('auditId', result.data.id);
uni.setStorageSync('auditInfo', result.data);
uni.setStorageSync("auditId", result.data.id);
uni.setStorageSync("auditInfo", result.data);
uni.switchTab({
url: '/pages/order/order',
url: "/pages/order/order",
});
return;
}
}
},
connectSocket({ commit }, userInfo) {
if (!userInfo) return;
var socket = new $Socket({
url: userInfo.im.node_site_url,
maxInterValCount: 5,
interValTime: 20000,
onClose: (res) => {
console.log("sockrt关闭");
},
onOpen: (res) => {
console.log("sockrt连接成功");
},
onMsg: (res) => {
console.log("onMsg", res);
if (res) {
let msg = JSON.parse(res.data);
commit("GET_IM_MSG", { msg });
}
},
});
socket.connectserver(userInfo.im);
commit("CONNECT_SOCKET", { socket });
},
};
export default {

View File

@ -2,18 +2,58 @@
* @description 日期转换工具类
*/
/**
* 2020-07-12T11:39:35.000+00:00 = 2020-07-12 12:24:18
* 如果是当天的话 只显示时分秒
* @returns {string}
* @param date
*/
export function toDayTime(date) {
if (!date) return "";
// Convert input date to Date object
const inputDate = new Date(date);
// Get current date
const now = new Date();
// Check if the input date is today
const isToday =
inputDate.getDate() === now.getDate() &&
inputDate.getMonth() === now.getMonth() &&
inputDate.getFullYear() === now.getFullYear();
// Adjust for timezone offset (+8 hours)
const adjustedDate = new Date(+inputDate + 8 * 3600 * 1000);
if (isToday) {
// Return only time (HH:MM:SS)
return adjustedDate
.toISOString()
.split("T")[1]
.replace(/\.[\d]{3}Z/, "");
} else {
// Return full date and time (YYYY-MM-DD HH:MM:SS)
return adjustedDate
.toISOString()
.replace(/T/g, " ")
.replace(/\.[\d]{3}Z/, "");
}
}
/**
* 2020-07-12T11:39:35.000+00:00 = 2020-07-12 12:24:18
* @returns {string}
* @param date
*/
export function renderTime(date) {
if (!date) return ''
const dateee = new Date(date).toJSON()
if (!date) return "";
const dateee = new Date(date).toJSON();
return new Date(+new Date(dateee) + 8 * 3600 * 1000)
.toISOString()
.replace(/T/g, ' ')
.replace(/\.[\d]{3}Z/, '')
.replace(/T/g, " ")
.replace(/\.[\d]{3}Z/, "");
}
/**
@ -23,54 +63,61 @@ export function renderTime(date) {
*/
export function timestampToTime(timestamp) {
if (timestamp) {
let date = new Date(parseInt(timestamp))
let Y = date.getFullYear() + '-'
let date = new Date(parseInt(timestamp));
let Y = date.getFullYear() + "-";
let M =
(date.getMonth() + 1 < 10
? '0' + (date.getMonth() + 1)
: date.getMonth() + 1) + '-'
let D = date.getDate() < 10 ? '0' + date.getDate() : date.getDate()
? "0" + (date.getMonth() + 1)
: date.getMonth() + 1) + "-";
let D = date.getDate() < 10 ? "0" + date.getDate() : date.getDate();
let h =
(date.getHours() < 10 ? '0' + date.getHours() : date.getHours()) + ':'
(date.getHours() < 10 ? "0" + date.getHours() : date.getHours()) + ":";
let m =
(date.getMinutes() < 10 ? '0' + date.getMinutes() : date.getMinutes()) +
':'
let s = date.getSeconds() < 10 ? '0' + date.getSeconds() : date.getSeconds()
return Y + M + D + ' ' + h + m + s
(date.getMinutes() < 10 ? "0" + date.getMinutes() : date.getMinutes()) +
":";
let s =
date.getSeconds() < 10 ? "0" + date.getSeconds() : date.getSeconds();
return Y + M + D + " " + h + m + s;
} else {
return ''
return "";
}
}
export function renderDate(date) {
if (!date) return ''
if (!date) return "";
const fmt = "yyyy-MM-dd";
return renderDefault(date, fmt)
return renderDefault(date, fmt);
}
export function renderDefault(data, fmt) {
if (data == null) {
return null
return null;
}
const date = new Date(data);
const o = {
"M+": date.getMonth() + 1, //月份
"d+": date.getDate(), //日
"h+": date.getHours(), //小时
"m+": date.getMinutes(), //分
"s+": date.getSeconds(), //秒
"M+": date.getMonth() + 1, //月份
"d+": date.getDate(), //日
"h+": date.getHours(), //小时
"m+": date.getMinutes(), //分
"s+": date.getSeconds(), //秒
"q+": Math.floor((date.getMonth() + 3) / 3), //季度
"S": date.getMilliseconds() //毫秒
S: date.getMilliseconds(), //毫秒
};
if (/(y+)/.test(fmt)) {
fmt = fmt.replace(RegExp.$1, (date.getFullYear() + "").substr(4 - RegExp.$1.length));
fmt = fmt.replace(
RegExp.$1,
(date.getFullYear() + "").substr(4 - RegExp.$1.length)
);
}
for (const k in o) {
if (new RegExp("(" + k + ")").test(fmt)) {
fmt = fmt.replace(RegExp.$1, (RegExp.$1.length == 1) ? (o[k]) : (("00" + o[k]).substr(("" + o[k]).length)));
fmt = fmt.replace(
RegExp.$1,
RegExp.$1.length == 1 ? o[k] : ("00" + o[k]).substr(("" + o[k]).length)
);
}
}
return fmt;
@ -83,16 +130,16 @@ export function renderDefault(data, fmt) {
*/
export function timeToYMD(time) {
if (time) {
let date = new Date(time)
let Y = date.getFullYear() + '-'
let date = new Date(time);
let Y = date.getFullYear() + "-";
let M =
(date.getMonth() + 1 < 10
? '0' + (date.getMonth() + 1)
: date.getMonth() + 1) + '-'
let D = date.getDate() < 10 ? '0' + date.getDate() : date.getDate()
return Y + M + D
? "0" + (date.getMonth() + 1)
: date.getMonth() + 1) + "-";
let D = date.getDate() < 10 ? "0" + date.getDate() : date.getDate();
return Y + M + D;
} else {
return ''
return "";
}
}

View File

@ -1,6 +1,8 @@
import axios from 'axios';
import config from '../config/config';
import axiosAdapterUniapp from 'axios-adapter-uniapp';
import $store from '../store/index';
const service = axios.create({
baseURL: config.baseApi, // url = base url + request url
headers: {
@ -39,6 +41,7 @@ service.interceptors.response.use(
duration: 1000,
});
}
if (res.code == 30) {
uni.showToast({
title: `token已经过期需要重新登录`,
@ -46,11 +49,7 @@ service.interceptors.response.use(
duration: 1000,
});
uni.removeStorageSync('ukey');
uni.redirectTo({
url: '/pages/login/login',
});
$store.dispatch('user/LoginOut', true);
return;
}

View File

@ -0,0 +1,542 @@
//permission.js
/**
* 本模块封装了AndroidiOS的应用权限判断打开应用权限设置界面以及位置系统服务是否开启
*/
var isIos;
var unPermission = []; //当前未获取到的权限
// #ifdef APP-PLUS
isIos = plus.os.name == "iOS";
// #endif
var viewShow = true;
// 判断推送权限是否开启
function judgeIosPermissionPush() {
var result = false;
var UIApplication = plus.ios.import("UIApplication");
var app = UIApplication.sharedApplication();
var enabledTypes = 0;
if (app.currentUserNotificationSettings) {
var settings = app.currentUserNotificationSettings();
enabledTypes = settings.plusGetAttribute("types");
console.log("enabledTypes1:" + enabledTypes);
if (enabledTypes == 0) {
console.log("推送权限没有开启");
unPermission.push("推送权限");
} else {
result = true;
console.log("已经开启推送功能!");
}
plus.ios.deleteObject(settings);
} else {
enabledTypes = app.enabledRemoteNotificationTypes();
if (enabledTypes == 0) {
console.log("推送权限没有开启!");
} else {
result = true;
console.log("已经开启推送功能!");
}
console.log("enabledTypes2:" + enabledTypes);
}
plus.ios.deleteObject(app);
plus.ios.deleteObject(UIApplication);
return result;
}
// 判断定位权限是否开启
function judgeIosPermissionLocation() {
var result = false;
var cllocationManger = plus.ios.import("CLLocationManager");
var status = cllocationManger.authorizationStatus();
result = status != 2;
console.log("定位权限开启:" + result);
// 以下代码判断了手机设备的定位是否关闭,推荐另行使用方法 checkSystemEnableLocation
/* var enable = cllocationManger.locationServicesEnabled();
var status = cllocationManger.authorizationStatus();
console.log("enable:" + enable);
console.log("status:" + status);
if (enable && status != 2) {
result = true;
console.log("手机定位服务已开启且已授予定位权限");
} else {
console.log("手机系统的定位没有打开或未给予定位权限");
} */
plus.ios.deleteObject(cllocationManger);
return result;
}
// 判断麦克风权限是否开启
function judgeIosPermissionRecord() {
var result = false;
var avaudiosession = plus.ios.import("AVAudioSession");
var avaudio = avaudiosession.sharedInstance();
var permissionStatus = avaudio.recordPermission();
console.log("permissionStatus:" + permissionStatus);
if (permissionStatus == 1684369017 || permissionStatus == 1970168948) {
console.log("麦克风权限没有开启");
unPermission.push("麦克风权限");
} else {
result = true;
console.log("麦克风权限已经开启");
}
plus.ios.deleteObject(avaudiosession);
return result;
}
// 判断相机权限是否开启
function judgeIosPermissionCamera() {
var result = false;
var AVCaptureDevice = plus.ios.import("AVCaptureDevice");
var authStatus = AVCaptureDevice.authorizationStatusForMediaType("vide");
console.log("authStatus:" + authStatus);
if (authStatus == 3) {
result = true;
console.log("相机权限已经开启");
} else {
console.log("相机权限没有开启");
unPermission.push("相机权限");
}
plus.ios.deleteObject(AVCaptureDevice);
return result;
}
// 判断相册权限是否开启
function judgeIosPermissionPhotoLibrary() {
var result = false;
var PHPhotoLibrary = plus.ios.import("PHPhotoLibrary");
var authStatus = PHPhotoLibrary.authorizationStatus();
console.log("authStatus:" + authStatus);
if (authStatus == 3) {
result = true;
console.log("相册权限已经开启");
} else {
console.log("相册权限没有开启");
unPermission.push("相册权限");
}
plus.ios.deleteObject(PHPhotoLibrary);
return result;
}
// 判断通讯录权限是否开启
function judgeIosPermissionContact() {
var result = false;
var CNContactStore = plus.ios.import("CNContactStore");
var cnAuthStatus = CNContactStore.authorizationStatusForEntityType(0);
if (cnAuthStatus == 3) {
result = true;
console.log("通讯录权限已经开启");
} else {
console.log("通讯录权限没有开启");
unPermission.push("通讯录权限");
}
plus.ios.deleteObject(CNContactStore);
return result;
}
// 判断日历权限是否开启
function judgeIosPermissionCalendar() {
var result = false;
var EKEventStore = plus.ios.import("EKEventStore");
var ekAuthStatus = EKEventStore.authorizationStatusForEntityType(0);
if (ekAuthStatus == 3) {
result = true;
console.log("日历权限已经开启");
} else {
console.log("日历权限没有开启");
unPermission.push("日历权限");
}
plus.ios.deleteObject(EKEventStore);
return result;
}
// 判断备忘录权限是否开启
function judgeIosPermissionMemo() {
var result = false;
var EKEventStore = plus.ios.import("EKEventStore");
var ekAuthStatus = EKEventStore.authorizationStatusForEntityType(1);
if (ekAuthStatus == 3) {
result = true;
console.log("备忘录权限已经开启");
} else {
console.log("备忘录权限没有开启");
nPermission.push("备忘录权限");
}
plus.ios.deleteObject(EKEventStore);
return result;
}
//获取当前权限中文描述
function getCurrentPermissionType(permissionId) {
console.log(permissionId);
switch (permissionId) {
case "android.permission.READ_EXTERNAL_STORAGE":
return "文件读取权限";
case "android.permission.WRITE_EXTERNAL_STORAGE":
return "文件写入权限";
case "android.permission.CAMERA":
return "相机权限";
case "android.permission.RECORD_AUDIO":
return "麦克风权限";
default:
return "其他权限";
}
}
// Android权限查询 -export
function requestAndroidPermission(permissionID) {
console.log(permissionID.split(","));
return new Promise((resolve, reject) => {
plus.android.requestPermissions(
permissionID.split(","),
// [permissionID], // 理论上支持多个权限同时查询,但实际上本函数封装只处理了一个权限的情况。有需要的可自行扩展封装
function (resultObj) {
var result = 0;
for (var i = 0; i < resultObj.granted.length; i++) {
var grantedPermission = resultObj.granted[i];
console.log("已获取的权限:" + grantedPermission);
result = 1;
}
for (var i = 0; i < resultObj.deniedPresent.length; i++) {
var deniedPresentPermission = resultObj.deniedPresent[i];
console.log("拒绝本次申请的权限:" + deniedPresentPermission);
console.log("deniedPresentPermission", deniedPresentPermission);
let permissionName = getCurrentPermissionType(
deniedPresentPermission
);
console.log(permissionName);
unPermission.push(permissionName);
result = 0;
}
for (var i = 0; i < resultObj.deniedAlways.length; i++) {
var deniedAlwaysPermission = resultObj.deniedAlways[i];
console.log("永久拒绝申请的权限:" + deniedAlwaysPermission);
console.log("deniedPresentPermission", deniedAlwaysPermission);
let permissionName = getCurrentPermissionType(deniedAlwaysPermission);
unPermission.push(permissionName);
result = -1;
}
resolve(result);
// 若所需权限被拒绝,则打开APP设置界面,可以在APP设置界面打开相应权限
// if (result != 1) {
// gotoAppPermissionSetting()
// }
},
function (error) {
console.log("申请权限错误:" + error.code + " = " + error.message);
resolve({
code: error.code,
message: error.message,
});
}
);
});
}
// 使用一个方法,根据参数判断权限 -export
function judgeIosPermission(permissionID) {
return new Promise((resolve, reject) => {
console.log(permissionID);
let result;
if (permissionID == "location") {
result = judgeIosPermissionLocation();
resolve(result);
} else if (permissionID == "camera") {
result = judgeIosPermissionCamera();
resolve(result);
} else if (permissionID == "photoLibrary") {
result = judgeIosPermissionPhotoLibrary();
resolve(result);
} else if (permissionID == "record") {
result = judgeIosPermissionRecord();
resolve(result);
} else if (permissionID == "push") {
result = judgeIosPermissionPush();
resolve(result);
} else if (permissionID == "contact") {
result = judgeIosPermissionContact();
resolve(result);
} else if (permissionID == "calendar") {
result = judgeIosPermissionCalendar();
resolve(result);
} else if (permissionID == "memo") {
result = judgeIosPermissionMemo();
resolve(result);
}
resolve(false);
});
}
// 跳转到**应用**的权限页面 -export
export function gotoAppPermissionSetting() {
if (isIos) {
var UIApplication = plus.ios.import("UIApplication");
var application2 = UIApplication.sharedApplication();
var NSURL2 = plus.ios.import("NSURL");
// var setting2 = NSURL2.URLWithString("prefs:root=LOCATION_SERVICES");
var setting2 = NSURL2.URLWithString("app-settings:");
application2.openURL(setting2);
plus.ios.deleteObject(setting2);
plus.ios.deleteObject(NSURL2);
plus.ios.deleteObject(application2);
} else {
// console.log(plus.device.vendor);
var Intent = plus.android.importClass("android.content.Intent");
var Settings = plus.android.importClass("android.provider.Settings");
var Uri = plus.android.importClass("android.net.Uri");
var mainActivity = plus.android.runtimeMainActivity();
var intent = new Intent();
intent.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
var uri = Uri.fromParts("package", mainActivity.getPackageName(), null);
intent.setData(uri);
mainActivity.startActivity(intent);
}
}
// 检查系统的设备服务是否开启 -export
// var checkSystemEnableLocation = async function () {
export function checkSystemEnableLocation() {
if (isIos) {
var result = false;
var cllocationManger = plus.ios.import("CLLocationManager");
var result = cllocationManger.locationServicesEnabled();
console.log("系统定位开启:" + result);
plus.ios.deleteObject(cllocationManger);
return result;
} else {
var context = plus.android.importClass("android.content.Context");
var locationManager = plus.android.importClass(
"android.location.LocationManager"
);
var main = plus.android.runtimeMainActivity();
var mainSvr = main.getSystemService(context.LOCATION_SERVICE);
var result = mainSvr.isProviderEnabled(locationManager.GPS_PROVIDER);
console.log("系统定位开启:" + result);
return result;
}
}
let permissionMap = {
android: {
CAMERA_EXTERNAL_STORAGE: {
// 相机权限/相册读写权限
name: "android.permission.READ_EXTERNAL_STORAGE,android.permission.WRITE_EXTERNAL_STORAGE,android.permission.CAMERA",
title: "相机/相册权限说明",
content:
"便于您使用该功能上传您的照片/图片/视频及用于更换头像、发布产品/需求、下载、与客服沟通等场景中读取和写入相册和文件内容",
},
CAMERA: {
// 相机权限
name: "android.permission.CAMERA",
title: "相机权限说明",
content: "便于您使用该功能上传图片,用于与客服沟通等场景中发送拍摄图片",
},
EXTERNAL_STORAGE: {
//相册读写权限
name: "android.permission.READ_EXTERNAL_STORAGE,android.permission.WRITE_EXTERNAL_STORAGE",
title: "相册读写权限说明",
content:
"便于您使用该功能上传您的照片/图片/视频及用于更换头像、发布产品/需求、下载、与客服沟通等场景中读取和写入相册和文件内容",
},
CAMERA_EXTERNAL_STORAGE_RECORD_AUDIO: {
//视频录制和获取权限
name: "android.permission.READ_EXTERNAL_STORAGE,android.permission.WRITE_EXTERNAL_STORAGE,android.permission.CAMERA,android.permission.RECORD_AUDIO",
title: "相机/相册和麦克风权限说明",
content:
"便于您使用该功能获取并上传视频用于发布产品/需求过程中读取和写入视频文件内容",
},
},
ios: {},
};
let view = null;
//华为要求每一个获取权限都要有对应的说明提示,否则无法上架
function showViewDesc(permission) {
let plat = isIos ? "ios" : "android";
view = new plus.nativeObj.View("per-modal", {
top: "0px",
left: "0px",
width: "100%",
backgroundColor: "rgba(0,0,0,0.2)",
//opacity: '.9'
});
view.drawRect(
{
color: "#fff",
radius: "5px",
},
{
top: "30px",
left: "5%",
width: "90%",
height: "100px",
}
);
view.drawText(
permissionMap[plat][permission]["title"],
{
top: "40px",
left: "8%",
height: "30px",
},
{
align: "left",
color: "#000",
},
{
onClick: function (e) {
console.log(e);
},
}
);
view.drawText(
permissionMap[plat][permission]["content"],
{
top: "65px",
height: "60px",
left: "8%",
width: "84%",
},
{
whiteSpace: "normal",
size: "14px",
align: "left",
color: "#656563",
}
);
setTimeout(() => {
if (viewShow) view.show();
}, 200);
}
async function permissionIosCheck(permission) {
console.log("permissionIosCheck", permission);
let results = [];
if (permission == "CAMERA_EXTERNAL_STORAGE") {
results.push(await judgeIosPermission("camera"));
results.push(await judgeIosPermission("photoLibrary"));
} else if (permission == "CAMERA_EXTERNAL_STORAGE_RECORD_AUDIO") {
results.push(await judgeIosPermission("camera"));
results.push(await judgeIosPermission("photoLibrary"));
results.push(await judgeIosPermission("record"));
} else if (permission == "CAMERA") {
results.push(await judgeIosPermission("camera"));
} else if (permission == "RECORD") {
results.push(await judgeIosPermission("record"));
} else if (permission == "PHOTO_LIBRARY") {
results.push(await judgeIosPermission("photoLibrary"));
}
// 检查所有权限是否都已开启
let allPermissionsGranted = results.every((result) => result);
return allPermissionsGranted;
}
// 权限检查
/**
*
* @param {*} permission // 要获取的权限 type:String
* @returns
*/
function premissionCheck(permission) {
console.log(permission);
console.log(isIos);
return new Promise(async (resolve, reject) => {
let plat = isIos ? "ios" : "android";
unPermission = [];
if (isIos) {
// ios
// const camera = judgeIosPermissionCamera();//判断ios是否给予摄像头权限
// //ios相册没权限系统会自动弹出授权框
// //let photoLibrary = permission.judgeIosPermission("photoLibrary");//判断ios是否给予相册权限
// if(camera){
// resolve();
// }else{
// reject('需要开启相机使用权限');
// }
console.log("permission", permission);
if (permission) {
let result = await permissionIosCheck(permission);
if (result) {
resolve(1);
} else {
// reject('需要开启相机使用权限');
let str = unPermission.join(",");
uni.showModal({
title: "温馨提示",
content: `请注意:该功能需要获取${str}!`,
showCancel: true,
confirmText: "去设置",
success: function (res) {
if (res.confirm) {
gotoAppPermissionSetting();
} else if (res.cancel) {
return;
}
},
});
}
}
} else {
// android
console.log("android");
let permission_arr = permissionMap[plat][permission]["name"].split(",");
console.log(permission_arr);
let flag = true;
for (let i = 0; i < permission_arr.length; i++) {
let status = plus.navigator.checkPermission(permission_arr[i]);
if (status == "undetermined") {
flag = false;
}
}
console.log("flag", flag);
if (flag == false) {
// 未完全授权
console.log("未授权");
showViewDesc(permission);
requestAndroidPermission(permissionMap[plat][permission]["name"]).then(
(res) => {
viewShow = false;
setTimeout(() => {
viewShow = true;
}, 120);
console.log("值", res);
if (res == -1) {
let str = unPermission.join(",");
console.log(str);
uni.showModal({
title: "提示",
content: `操作权限已被拒绝,请手动前往设置${str}`,
confirmText: "立即设置",
success: (res) => {
if (res.confirm) {
gotoAppPermissionSetting();
}
view.close();
resolve(res);
},
fail() {
view.close();
resolve(res);
},
});
} else if (res == 1) {
view.close();
resolve(res);
} else {
view.close();
}
}
);
} else {
resolve(1);
}
}
});
}
module.exports = {
judgeIosPermission: judgeIosPermission,
requestAndroidPermission: requestAndroidPermission,
checkSystemEnableLocation: checkSystemEnableLocation,
gotoAppPermissionSetting: gotoAppPermissionSetting,
premissionCheck: premissionCheck,
};

View File

@ -1,27 +1,31 @@
module.exports = {
devServer: {
port:8080,
port: 8080,
proxy: {
'/mobile': { // 匹配所有以 /mobile 开头的请求路径
target: 'https://mall.gpxscs.cn/mobile', // 目标服务器
'/mobile': {
// 匹配所有以 /mobile 开头的请求路径
target: 'https://mall.gpxscs.cn', // 目标服务器
changeOrigin: true, // 是否改变请求源
pathRewrite: {
"^/mobile": ""
}
'^/mobile': '/mobile',
},
},
'/api/admin': { // 匹配所有以 /api 开头的请求路径
target: 'https://mall.gpxscs.cn/api/admin', // 目标服务器
'/api/admin': {
// 匹配所有以 /api 开头的请求路径
target: 'https://mall.gpxscs.cn', // 目标服务器
changeOrigin: true, // 是否改变请求源
pathRewrite: {
"^/api/admin": ""
}
'^/api/admin': '/api/admin',
},
},
'/api/mobile': { // 匹配所有以 /api/mobile 开头的请求路径
target: 'https://mall.gpxscs.cn/api/mobile', // 目标服务器
'/api/mobile': {
// 匹配所有以 /api/mobile 开头的请求路径
target: 'https://mall.gpxscs.cn', // 目标服务器
changeOrigin: true, // 是否改变请求源
logLevel: 'debug',
pathRewrite: {
"^/api/mobile": ""
}
'^/api/mobile': '/api/mobile',
},
},
// '/signed':{
// target:"https://mall.gpxscs.cn",
@ -29,6 +33,6 @@ module.exports = {
// pathRewrite:{
// }
// },
}
}
}
},
},
};