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 @@
+
+
+
+
+ {{ groupInfo.name }}
+
+ ({{ membersRes?.user_list?.length || 0 }}人)
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ item.nick_name }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 商家
+ {{ shopInfo.shopName }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 商家已禁言
+
+
+
+
+
+ {{ item.title }}
+
+
+
+
+
+
+
+
+
+
+
+
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 @@
+
+ {{ item.content }}
+
+
+
+ {{ item.coupon.title }}
+
+
+
+
+ ¥
+ {{
+ item.coupon.discountAmount
+ }}
+
+ 满{{ item.coupon.fullAmount }}可用
+
+
+
+
+
+ 商品兑换券
+
+ 满{{ item.coupon.fullAmount }}可用
+
+
+
+
+
+
+ {{ item.coupon.discountRate / 100 }}折
+
+ 满{{ item.coupon.fullAmount }}可用
+
+
+
+
+
+ 第二件半价券
+
+
+
+
+
+
+
+ 买一送一券
+
+
+
+
+
+
+ {{ item.coupon.couponName }}
+ 有效期:{{ returnTime(item.coupon) }}
+
+
+
+
+ 领取
+
+
+
+
+
+
+
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 @@
+
+
+
+
+
+ 请选择日期范围
+ {{ startTime }} - {{ endTime }}
+
+
+
+
+
+
+
+
+
+
+
+
+
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 @@
+
+
+
+
+ 优惠券名称
+ {{ couponActivity.couponJson.couponName }}
+
+
+ 发放数量
+ {{ couponActivity.giveNum }}
+
+
+ 已领取数量
+ {{ couponActivity.giveNum - couponActivity.leftNum }}
+
+
+ 剩余数量
+ {{ couponActivity.leftNum }}
+
+
+ 已使用数量
+ {{ couponActivity.useNum }}
+
+
+
+
+
+
+
+ {{ selStatus.label }}
+ 请选择状态
+
+
+
+
+
+
+
+
+
+
+
+ 用户昵称(40239)
+ 2025/06/27 20:07:18)
+ 2025/01/15 08:02:38
+ 已使用
+ 失效
+
+
+
+
+
+
+
+
+
+
+
+
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 @@
+
+
+
+
+
+
+
+
+
+
+
+ {{ item.couponJson.couponName }}
+
+
+ {{
+ returnStateText(item)
+ }}
+ ID:{{ item.id }}
+
+
+
+
+ 使用门槛
+ 满{{ item.couponJson.fullAmount }}元可用
+
+
+ 有效期
+ 领券后{{ item.couponJson.validDays }}天过期
+
+
+
+
+ {{ item.giveNum }}
+ 发放数量
+
+
+ {{
+ item.giveNum - item.leftNum
+ }}
+ 已领取
+
+
+
+ {{ item.leftNum }}
+ 剩余
+
+
+
+ {{ item.useNum }}
+ 已使用
+
+
+
+
+ 分享
+ 失效
+ 查看
+
+
+
+
+
+
+
+
+
+
+
+
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 @@
+
+
+
+
+ 群成员(22人)
+ 移除
+
+
+
+
+ {{ item.nick_name }}
+
+
+
+
+
+
+ 查看更多
+
+
+
+
+
+
+ 群聊名称
+
+ {{ groupInfo.name }}
+
+
+
+
+
+ 禁言
+
+ 开启后,顾客将不能在群内发消息
+
+
+
+
+ 优惠券领取记录
+
+ 去查看
+
+
+
+
+
+
+
+
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 @@
+
+
+
+
+
+
+
+
+ 清空未读
+
+
+
+
+
+
+
+
+
+
+ {{
+ item.unread_count >= 99 ? "99" : item.unread_count
+ }}
+
+
+
+ {{ item.name }}
+ {{ item.msg }}
+
+ {{ item.send_time }}
+
+
+
+
+
+
+
+
+
+
+
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