diff --git a/common/api/market/chat.js b/common/api/market/chat.js new file mode 100644 index 0000000..0758172 --- /dev/null +++ b/common/api/market/chat.js @@ -0,0 +1,11 @@ +// 引入 request 文件 +import request from "@/common/api/request.js"; +import { prveUrl } from "./config.js"; + +export const couponGrant = (data) => { + return request({ + url: prveUrl + "/user/chat/coupon/grant", + method: "post", + data: data, + }); +}; diff --git a/common/api/upload.js b/common/api/upload.js new file mode 100644 index 0000000..7505b7c --- /dev/null +++ b/common/api/upload.js @@ -0,0 +1,64 @@ +function getHeader() { + let token = uni.cache.get("token") || ""; + const shopId = uni.cache.get("shopId") * 1; + const userInfo = uni.cache.get("userInfo") || {}; + + return { + version: uni.conf.version, + type: uni.getSystemInfoSync().platform, + // #ifdef APP-PLUS + platformType: "APP", + // #endif + // #ifdef H5 + platformType: "H5", + // #endif + // #ifdef MP-WEIXIN + platformType: "WX", + // #endif + // #ifdef MP-ALIPAY + platformType: "ALI", + // #endif + token, + id: userInfo.id || "", + shopId: shopId || "", + userId: userInfo.id || "", + }; +} + +// 上传 +export function upload(uri, file, data, showLoading = true, extParams = {}) { + return new Promise((resolve, reject) => { + uni.showLoading(); + + uni + .uploadFile( + Object.assign( + { + url: uni.conf.baseUrl + uri, + formData: data, + name: "file", + filePath: file.path || file.url || file, + header: getHeader(), + }, + extParams + ) + ) + .then((httpData) => { + // uni.upload 返回bodyData 的是 string类型。 需要解析。 + httpData.data = JSON.parse(httpData.data); + if( httpData.data.code==200){ + resolve( httpData.data.data); + } + reject() + }) + .catch((err) => { + reject(); + uni.hideLoading(); + infoBox.showErrorToast(`上传失败`); + }); + }); +} + +export const uploadFile = (file, data) => { + return upload("/account/user/common/upload", file, data); +}; diff --git a/common/config.js b/common/config.js index 7c72342..a12d3f1 100644 --- a/common/config.js +++ b/common/config.js @@ -37,6 +37,8 @@ export const changeEnv = (env) => { uni.conf = { debug: true, baseUrl: "http://192.168.1.42", + phpUrl:'http://192.168.1.42:8787/api/', + phpChatWx:'ws://192.168.1.42:2348', version: 100, autoRemoveCache, baseUrlwws: "ws://192.168.1.42:2348", diff --git a/common/css/common.scss b/common/css/common.scss index eee4645..425b73c 100644 --- a/common/css/common.scss +++ b/common/css/common.scss @@ -105,6 +105,7 @@ page, justify-content: center; } .u-flex-col{ + display: flex; flex-direction: column!important; } .min-h-100vh{ @@ -115,4 +116,59 @@ page, } .align-center{ align-items: center; - } \ No newline at end of file + } + .u-row-between{ + justify-content: space-between; + } + .u-row-right { + justify-content: flex-end; + } + + // 定义字体(rpx)单位,大于或等于20的都为rpx单位字体 +@for $i from 20 through 40 { + .u-font-#{$i} { + font-size: $i + rpx; + } +} + +.min-page{ + /* #ifdef H5 */ + min-height: calc(100vh - 44px); + /* #endif */ + /* #ifndef H5 */ + min-height: 100vh; + /* #endif */ +} +.bg-f7{ + background-color: #F7F7F7; +} + +.default-box-padding{ + padding: 32rpx 28rpx; +} +.default-box-radius{ + border-radius: 16rpx; +} +.default-box-x-padding{ + padding-left: 28rpx; + padding-right: 28rpx; +} +.default-box-y-padding{ + padding-top: 32rpx; + padding-bottom: 32rpx; +} +$height: 70rpx; + + + .u-col-baseline{ + align-items: baseline; + } + .text-right{ + text-align: right; + } + .u-row-center{ + justify-content: center; + } + .u-col-center{ + align-items: center; + } \ No newline at end of file diff --git a/http/php/chat.js b/http/php/chat.js new file mode 100644 index 0000000..25e1758 --- /dev/null +++ b/http/php/chat.js @@ -0,0 +1,91 @@ +import { request } from "./request"; +const prveUrl = "chat/"; + +/** + * 群消息 + * @param {Object} data + * @returns + */ +export const groupInfo = (data) => { + return request(prveUrl + "group/info", "POST", data, true); +}; + +export const commonPhrase = (data) => { + return request(prveUrl + "common-phrase/index", "POST", data, true); +}; +export const commonPhraseAdd = (data) => { + return request(prveUrl + "common-phrase/add", "POST", data, true); +}; + +export const commonPhraseDel = (data) => { + return request(prveUrl + "common-phrase/del", "POST", data, true); +}; + +export const groupCreate = (data) => { + return request(prveUrl + "group/create", "POST", data, true); +}; + +export const groupJoin = (data) => { + return request(prveUrl + "group/join", "POST", data, true); +}; +export const groupGetGroupUrl = (data) => { + return request(prveUrl + "group/getgrepurl", "POST", data, true); +}; + +export const groupQuit = (data) => { + return request(prveUrl + "group/quit", "POST", data, true); +}; + +export const groupTarsGroup = (data) => { + return request(prveUrl + "group/tarsgroup", "POST", data, true); +}; + +export const groupAnnouncement = (data) => { + return request(prveUrl + "group/announcement", "POST", data, true); +}; +export const groupMute = (data) => { + return request(prveUrl + "group/mute", "POST", data, true); +}; + +export const groupMunute = (data) => { + return request(prveUrl + "group/unmute", "POST", data, true); +}; + +export const groupKick = (data) => { + return request(prveUrl + "group/kick", "POST", data, true); +}; + +export const groupMembers = (data) => { + return request(prveUrl + "group/members", "POST", data, true); +}; + +export const messageHistory = (data) => { + return request(prveUrl + "message/history", "POST", data, true); +}; + +export const messageMarkRead = (data) => { + return request(prveUrl + "message/mark-read", "POST", data, true); +}; + +export const messageMarkReadAll = (data) => { + return request(prveUrl + "message/mark-read-all", "POST", data, true); +}; + +export const messageUnreadCount = (data) => { + return request(prveUrl + "message/unread-count", "POST", data, true); +}; + +export const messageSessionList = (data) => { + return request(prveUrl + "message/sessionlist", "POST", data, true); +}; + +export const groupDoNotDisturb = (data) => { + return request(prveUrl + "group/do-not-disturb", "POST", data, true); +}; + +export const groupShopinfo = (data) => { + return request(prveUrl + "group/shopinfo", "POST", data, true); +}; +export const sessionlistdel = (data) => { + return request(prveUrl + "message/sessionlistdel", "POST", data, true); +}; diff --git a/http/php/request.ts b/http/php/request.ts new file mode 100644 index 0000000..1b2c630 --- /dev/null +++ b/http/php/request.ts @@ -0,0 +1,100 @@ +//服务器接口地址 +// const baseURL : string = 'https://newblockwlx.sxczgkj.cn/index.php/api/' +let baseURL: string = "http://192.168.1.42:8787/api/"; +// #ifdef H5 +baseURL = "/phpapi/api/"; +// #endif + + +// 封装公共请求方法 +function request( + url: string, + method: "GET" | "POST" | undefined, + data: object | any, + toast: boolean +) { + let networkType = ""; + uni.getNetworkType({ + success: (res) => { + networkType = res.networkType; + }, + }); + if (networkType == "none") { + uni.showToast({ + title: "网络异常,请检查网络", + icon: "none", + }); + return false; + } + if (toast) { + uni.showLoading({ + title: "加载中", + mask: true, + }); + } + return new Promise(async (resolve, reject) => { + let header: any; + header = { + "content-type": "application/json", + token: uni.cache.get('token'), + }; + uni.request({ + url: baseURL + url, + method: method, + data: data, + header: header, + success(res: any) { + if (res.data.code != 1) { + if (res.data.code === 3000) { + uni.showToast({ + title: '请登录后操作', + icon: "none", + }); + uni.hideLoading(); + reject(); + return; + } + //是否提示错误 + if (toast) { + uni.showToast({ + title: res.data.msg || res.data.message, + icon: "none", + }); + setTimeout(() => { + uni.hideLoading(); + }, 1000); + } + if (res.data.code == 401) { + uni.showToast({ + title: res.message || res.msg, + icon: "none", + success: () => { + // uni.removeStorageSync('logintoken'); + // uni.removeStorageSync('token'); + uni.reLaunch({ + url: "/pages/index/index", + }); + }, + }); + } + uni.hideLoading(); + reject(res.message | res.msg); + } else { + uni.hideLoading(); + console.log(res); + resolve(res.data.data); + } + }, + fail(err) { + uni.hideLoading(); + //请求失败 + uni.showToast({ + title: "无法连接到服务器", + icon: "none", + }); + reject(err); + }, + }); + }); +} +export { request, baseURL }; diff --git a/pageChat/chat.vue b/pageChat/chat.vue new file mode 100644 index 0000000..b7016d4 --- /dev/null +++ b/pageChat/chat.vue @@ -0,0 +1,726 @@ + + + diff --git a/pageChat/components/chat-item.vue b/pageChat/components/chat-item.vue new file mode 100644 index 0000000..dfd5019 --- /dev/null +++ b/pageChat/components/chat-item.vue @@ -0,0 +1,152 @@ + + + + + diff --git a/pageChat/components/date-time-picker.vue b/pageChat/components/date-time-picker.vue new file mode 100644 index 0000000..9234ac3 --- /dev/null +++ b/pageChat/components/date-time-picker.vue @@ -0,0 +1,108 @@ + + + + diff --git a/pageChat/components/modal.vue b/pageChat/components/modal.vue new file mode 100644 index 0000000..7308c90 --- /dev/null +++ b/pageChat/components/modal.vue @@ -0,0 +1,85 @@ + + + + diff --git a/pageChat/components/shop-sel-action-sheet.vue b/pageChat/components/shop-sel-action-sheet.vue new file mode 100644 index 0000000..db51b63 --- /dev/null +++ b/pageChat/components/shop-sel-action-sheet.vue @@ -0,0 +1,49 @@ + + + \ No newline at end of file diff --git a/pageChat/coupon-activity/detail.vue b/pageChat/coupon-activity/detail.vue new file mode 100644 index 0000000..ad11d1a --- /dev/null +++ b/pageChat/coupon-activity/detail.vue @@ -0,0 +1,184 @@ + + + + + diff --git a/pageChat/coupon-activity/index.vue b/pageChat/coupon-activity/index.vue new file mode 100644 index 0000000..6ff8026 --- /dev/null +++ b/pageChat/coupon-activity/index.vue @@ -0,0 +1,310 @@ + + + + + diff --git a/pageChat/group-info/index.vue b/pageChat/group-info/index.vue new file mode 100644 index 0000000..ae4f9c4 --- /dev/null +++ b/pageChat/group-info/index.vue @@ -0,0 +1,182 @@ + + + diff --git a/pageChat/index.vue b/pageChat/index.vue new file mode 100644 index 0000000..df346dc --- /dev/null +++ b/pageChat/index.vue @@ -0,0 +1,223 @@ + + + + + diff --git a/pageChat/static/clear.png b/pageChat/static/clear.png new file mode 100644 index 0000000..e07b381 Binary files /dev/null and b/pageChat/static/clear.png differ diff --git a/pageChat/static/coupon.png b/pageChat/static/coupon.png new file mode 100644 index 0000000..e02df91 Binary files /dev/null and b/pageChat/static/coupon.png differ diff --git a/pageChat/static/exit.png b/pageChat/static/exit.png new file mode 100644 index 0000000..8ee6d43 Binary files /dev/null and b/pageChat/static/exit.png differ diff --git a/pageChat/static/pic.png b/pageChat/static/pic.png new file mode 100644 index 0000000..4069281 Binary files /dev/null and b/pageChat/static/pic.png differ diff --git a/pageChat/static/video.png b/pageChat/static/video.png new file mode 100644 index 0000000..a82291f Binary files /dev/null and b/pageChat/static/video.png differ diff --git a/pages.json b/pages.json index eaaa5e2..23ca9bf 100644 --- a/pages.json +++ b/pages.json @@ -295,6 +295,22 @@ } } ] + }, + { + "root": "pageChat", + "pages": [{ + "path": "index", + "style": { + "navigationBarTitleText": "消息" + } + }, + { + "path": "chat", + "style": { + "navigationBarTitleText": "群聊" + } + } + ] } ], "uniIdRouter": {}, diff --git a/pages/order/confirm-order.vue b/pages/order/confirm-order.vue index f0c6ece..1d9329d 100644 --- a/pages/order/confirm-order.vue +++ b/pages/order/confirm-order.vue @@ -157,6 +157,7 @@ import { APIusershopInfodetail, APIshopUserInfo } from '@/common/api/member.js'; import { APImemberPointsmyPoints, APImemberPointscalcUsablePoints } from '@/common/api/shop/index.js'; import { useCartsStore } from '@/stores/carts.js'; import { useWebSocket } from '@/stores/carts-websocket.js'; +import * as chatApi from "@/http/php/chat"; function pwdClose() { ispws.value = false; @@ -977,10 +978,18 @@ const navTitle = computed(() => { }); //支付成功后的处理 -function paySucessCallback() { +async function paySucessCallback() { console.log('paySucessCallback'); cartsSocket.closeSocket(); showDrainage.value = true; + const groupinfo=await chatApi.groupShopinfo({shop_id:cartStore.shopInfo.id}) + if(groupinfo&&groupinfo[0]){ + console.log('groupinfo',groupinfo[0].id); + chatApi.groupJoin({ + group_id:groupinfo[0].id + }) + } + } //私域引流配置 diff --git a/pages/user/user.vue b/pages/user/user.vue index 75c6bf8..f81aaef 100644 --- a/pages/user/user.vue +++ b/pages/user/user.vue @@ -281,6 +281,11 @@ const myFunList = ref([ type: "fenxiao", icon: "/static/icon/fenxiao.svg", }, + { + name: "商家推送", + type: "msg", + icon: "/static/icon/msg.png", + }, // { // name: "我的订单", // type: "my_order", @@ -383,6 +388,9 @@ const clickTo = (item, index) => { } let shopId = null; switch (item.type) { + case "msg": + uni.navigateTo({ url: "/pageChat/index" }); + break; case "my_order": uni.pro.switchTab("order/index"); break; diff --git a/static/icon/msg.png b/static/icon/msg.png new file mode 100644 index 0000000..d8997d8 Binary files /dev/null and b/static/icon/msg.png differ diff --git a/stores/chat.js b/stores/chat.js new file mode 100644 index 0000000..868b72b --- /dev/null +++ b/stores/chat.js @@ -0,0 +1,126 @@ +import { + defineStore +} from "pinia"; +// import * as shopApi from "@/http/api/shop.js"; + +// #ifdef H5 +const socketUrl = "http://192.168.1.42:2348"; +// #endif +// #ifndef H5 +const socketUrl = "ws://192.168.1.42:2348"; +// #endif + +// 聊天 +export const useChatStore = defineStore("chat", { + state: () => { + return { + socketUrl, + isConnect: false, + socketTask: null, + onReceiveMsg: () => {}, + chatList: [], + }; + }, + actions: { + init() { + if (!this.isConnect) { + return uni.showToast({ + title: "请先连接socket", + icon: "none", + }); + } + this.sendMessage({ + type: "OnbocChat", + operate_type: "init", + shop_id: uni.cache.get('shopInfo').id || '', + token: uni.cache.get('token'), + }, + false + ); + }, + sendMessage(msg, isAutoAppend = true) { + if (!this.isConnect) { + return uni.showToast({ + title: "请先连接socket", + icon: "none", + }); + } + console.log(this.socketTask); + const message = isAutoAppend ? { + type: "OnbocChat", + operate_type: "sendMsg", + shop_id: uni.cache.get('shopInfo').id || '', + token: uni.cache.get('token'), + ...msg, + } : + msg; + this.socketTask.send({ + data: JSON.stringify(message), + success: (res) => { + console.log("发送成功", message); + }, + fail: (error) => { + console.log("发送失败", error); + }, + }); + }, + connectSocket() { + this.socketTask = uni.connectSocket({ + url: socketUrl, + success: (res) => {}, + fail: (res) => { + console.log(res); + }, + }); + + this.socketTask.onOpen((res) => { + this.isConnect = true; + this.init(); + }); + + this.socketTask.onMessage((res) => { + const data = JSON.parse(res.data); + console.log("收到服务器消息", data); + if (data.msg) { + uni.showToast({ + title: data.msg, + icon: "none", + }); + } + + if (data && data.operate_type == "sendMsg") { + this.chatList.unshift(data.data); + this.onReceiveMsg(data.data); + console.log(this.chatList); + } + if (data && data.operate_type == "receive_msg") { + const msg={ + ...data.data, + coupon:data.data.coupon?JSON.parse(data.data.coupon):{}, + operate_type:"receive_msg", + } + this.chatList.unshift(msg); + this.onReceiveMsg(msg); + console.log(this.chatList); + } + }); + + this.socketTask.onError((res) => { + this.isConnect = false; + console.log("连接错误", res); + }); + + this.socketTask.onClose(() => { + this.isConnect = false; + console.log("连接已关闭"); + this.connectSocket(); + }); + }, + + closeSocket() { + this.socketTask.close(); + this.isConnect = false; + }, + }, + unistorage: false, // 开启后对 state 的数据读写都将持久化 +}); \ No newline at end of file