diff --git a/java-mall-app-shop-admin/App.vue b/java-mall-app-shop-admin/App.vue
index 426fbf3..d5ba577 100644
--- a/java-mall-app-shop-admin/App.vue
+++ b/java-mall-app-shop-admin/App.vue
@@ -3,6 +3,7 @@
import APPUpdate, { getCurrentNo } from "@/config/appUpdate";
// #endif
import { mapState, mapActions } from "vuex";
+import { webSocketManager } from "@/utils/socket.js";
export default {
data() {
return {
@@ -27,7 +28,7 @@ export default {
// #endif
},
computed: {
- ...mapState("user", ["uid", "userInfo", "socket"]),
+ ...mapState("user", ["uid", "userInfo"]),
},
onShow: function () {
this.globalData.isAppActive = true;
@@ -40,6 +41,7 @@ export default {
},
onHide: function () {
this.globalData.isAppActive = false;
+ webSocketManager.closeAllGlobalConnections();
},
globalData: {
isAppActive: false,
diff --git a/java-mall-app-shop-admin/api/warehouse/commodity.js b/java-mall-app-shop-admin/api/warehouse/commodity.js
new file mode 100644
index 0000000..7616cf0
--- /dev/null
+++ b/java-mall-app-shop-admin/api/warehouse/commodity.js
@@ -0,0 +1,174 @@
+import http from "../../utils/http";
+import config from "../../config/config";
+
+/** 添加商品和编辑商品
+ *
+ * @author Seven
+ * @data 2025-7-22
+ * @params {
+ * productObj{},
+ * productItems:{}
+ * }
+ * @see https://mall.gpxscs.cn/api/admin/shop/shop-product-base/saveProduct
+ */
+
+export function UpdateCommodityInfo(params) {
+ return http({
+ url: "/shop/shop-product-base/saveProduct",
+ method: "post",
+ baseURL: config.adminApi,
+ headers: {
+ "content-type": "application/x-www-form-urlencoded;charset=UTF-8",
+ },
+ params,
+ });
+}
+
+/** 添加商品和编辑商品
+ *
+ * @author Seven
+ * @data 2025-7-22
+ * @params {
+ * product_id : 33002
+ item_id : 66419
+ item_unit_price :10
+ item_quantity :20
+ * }
+ * @see https://mall.gpxscs.cn/api/admin/shop/shop-product-item/editQuantity
+ */
+
+export function UpdateCommodityPriceAndQuantity(params) {
+ return http({
+ url: "/shop/shop-product-item/editQuantity",
+ method: "post",
+ baseURL: config.adminApi,
+ headers: {
+ "content-type": "application/x-www-form-urlencoded;charset=UTF-8",
+ },
+ params,
+ });
+}
+
+/** 获取分类详情
+ *
+ * @author Seven
+ * @data 2025-7-22
+ * @params { category_id }
+ * @see https://mall.gpxscs.cn/api/admin/shop/shop-base-product-category/get
+ */
+
+export function GetClassifyInfo(params) {
+ return http({
+ url: "/shop/shop-base-product-category/get",
+ method: "get",
+ baseURL: config.adminApi,
+ params,
+ });
+}
+
+/** 获取商品base详情
+ *
+ * @author Seven
+ * @data 2025-7-22
+ * @params { product_id : number }
+ * @see https://mall.gpxscs.cn/api/admin/shop/shop-product-info/productInfoByPid
+ */
+
+export function GetCommodityBaseInfo(params) {
+ return http({
+ url: "/shop/shop-product-info/productInfoByPid",
+ method: "get",
+ baseURL: config.adminApi,
+ params,
+ });
+}
+
+/** 获取商品规格 库存 和 价格
+ *
+ * @author Seven
+ * @data 2025-7-6
+ * @param { product_id }
+ * @returns { }
+ * @see https://mall.gpxscs.cn/api/admin/shop/shop-product-item/items?product_id=23591&source_lang=zh_CN
+ */
+
+export function GetCommoditSpecification(params) {
+ return http({
+ url: "/shop/shop-product-item/items",
+ method: "get",
+ params,
+ baseURL: config.adminApi,
+ });
+}
+
+/** 获取商品规格 品牌 信息
+ *
+ * @author Seven
+ * @data 2025-7-22
+ * @param { spec_id }
+ * @returns { }
+ * @see https://mall.gpxscs.cn/api/admin/shop/shop-base-product-type/get
+ */
+
+export function GetCommoditSpecificationBaseInfo(params) {
+ return http({
+ url: "/shop/shop-base-product-type/get",
+ method: "get",
+ params,
+ baseURL: config.adminApi,
+ });
+}
+
+/** 添加商品规格
+ *
+ * @author Seven
+ * @data 2025-7-22
+ * @param { spec_id : number , spec_item_name : 10 }
+ * @returns { }
+ * @see https://mall.gpxscs.cn/api/admin/shop/shop-product-spec-item/edit
+ */
+
+export function UpdateCommoditSpecification(params) {
+ return http({
+ url: "/shop/shop-product-spec-item/edit",
+ method: "post",
+ params,
+ baseURL: config.adminApi,
+ });
+}
+
+/** 删除商品规格
+ *
+ * @author Seven
+ * @data 2025-7-22
+ * @param { spec_item_id : number }
+ * @returns { }
+ * @see https://mall.gpxscs.cn/api/admin/shop/shop-product-spec-item/delete
+ */
+
+export function DelectCommoditSpecification(params) {
+ return http({
+ url: "/shop/shop-product-spec-item/delete",
+ method: "post",
+ params,
+ baseURL: config.adminApi,
+ });
+}
+
+/** 获取当前分类规格列表
+ *
+ * @author Seven
+ * @data 2025-7-22
+ * @param { spec_item_id : number }
+ * @returns { }
+ * @see https://mall.gpxscs.cn/api/admin/shop/shop-product-spec-item/specItems
+ */
+
+export function GetClassifySpecificationList(params) {
+ return http({
+ url: "/shop/shop-product-spec-item/specItems",
+ method: "get",
+ params,
+ baseURL: config.adminApi,
+ });
+}
diff --git a/java-mall-app-shop-admin/api/warehouse/productList.js b/java-mall-app-shop-admin/api/warehouse/productList.js
index 0f90f8d..6aafee6 100644
--- a/java-mall-app-shop-admin/api/warehouse/productList.js
+++ b/java-mall-app-shop-admin/api/warehouse/productList.js
@@ -70,21 +70,3 @@ export function DelectCommodity(params) {
baseURL: config.adminApi,
});
}
-
-/** 获取商品规格 库存 和 价格
- *
- * @author Seven
- * @data 2025-7-6
- * @param { product_id }
- * @returns { }
- * @see https://mall.gpxscs.cn/api/admin/shop/shop-product-item/items?product_id=23591&source_lang=zh_CN
- */
-
-export function GetCommoditSpecification(params) {
- return http({
- url: "/shop/shop-product-item/items",
- method: "get",
- params,
- baseURL: config.adminApi,
- });
-}
diff --git a/java-mall-app-shop-admin/components/poiuy-uImgUpload/README.md b/java-mall-app-shop-admin/components/poiuy-uImgUpload/README.md
new file mode 100644
index 0000000..46241f3
--- /dev/null
+++ b/java-mall-app-shop-admin/components/poiuy-uImgUpload/README.md
@@ -0,0 +1,165 @@
+
+
+插件安装
+
+图片上传组件 将组件放在自己的组件库里导入即可
+
+### 注意
+
+1.最好在回调结果后使用debugger看一下结果!
+
+2.请先看一下示范代码。
+
+3.如果有问题和建议可以联系我,也可以自己修改成符合自己项目的。
+
+4.注意,一定要去看看接口的返回值和插件写的返回值是否一样,如果不一样,可以在下面写注释的地方修改。
+
+#### 导入:
+> import imgUpload from '@/components/my-components/uImgUpload.vue';
+
+-------------------------------------
+
+#### 属性 attribute
+
+| 属性名 | 类型 | 介绍 | 默认值 |
+|----------------|--------|-------------|------------------|
+| imgArr | Array | 图片展示列表 | \[\] |
+| uploadImgCount | Number | 一次可选多少张图片 | 3 |
+| imgCount | Number | 一共可以上传多少张图片 | 3 |
+| imgSize | Number | 上传图片的大小 | 2 \(M\) |
+| imgType | Array | 能上传图片的类型(注:小程序下不兼容) | \["jepg","png"\] |
+| closeTip | Boolean | 是否关闭提示 | false |
+| formData | Object | 提交时携带数据 | {} |
+| loading | Boolean | 是否存在加载动画 | true |
+| url | String | 上传图片的url (1.1.0版本新增) | "" |
+| async | Boolean | 是否选择图片后直接上传 (1.1.0版本新增) | false |
+| header | Array | 请求头添加新的属性值 (1.1.1版本新增) | [] |
+| previewMany | Boolean | 是否开启多图预览 (1.1.2版本新增) | false |
+| config | Object | 配置对象 **已经设置默认值** (1.1.2版本新增) | {} |
+| pressImg | Number | 是否开启图片压缩,0-100为压缩值 (1.1.3版本新增) | -1(不开启) |
+| single | Boolean | 单图模式,上传一张后不会再出现上传按钮 (1.1.7版本新增) | false |
+| disabled | Boolean | 禁用,用于回显展示 (1.1.7版本新增) | false |
+-------------------------------------
+
+>>config对象参数
+
+| 属性名 | 类型 | 介绍 | 默认值 |
+|----------------|--------|-------------|------------------|
+| delIcon | String | 删除图片的icon[使用图片链接] | "" |
+| resultTip | Boolean | 是否显示结果提示 | true |
+| resultType | String | 结果展示类型 [正在开发2风格] | 1 |
+| loadIcon | String | 加载时的图标[使用图片链接] | "" |
+| loadText | String | 加载时的文字 | "" |
+| borderStyle | String | 上传框的样式[完全自定义] | 'border:2px dotted #dadada' |
+| addStyle | String | 上传图片的中间icon[1(图片标识)/2(加号标识)] | "1" |
+
+-------------------------------------
+
+#### 方法 method
+
+>当**async**为**true**的时候
+>存在两个方法
+
+| 方法名 | 介绍 |
+|--------|------------------------|
+| result | 上传后的返回结果\(成功对象\),存在all和new两种类型(详细解释见下) |
+| delImg | 删除图片返回下标\(传入的图片数组的下标\)*与async值无关* |
+-------------------------------------
+**all: 将会把之前传的和新传入的图片数组一起返回出来。**
+
+**new: 将新传输的图片以数组的方式直接返回,格式为["图片1","图片2"],可以直接用数组合并在提交数据上。**
+
+-------------------------------------
+
+>当**async**为**false**的时候
+>开始上传图片 在父页面中调用该方法(当async为false,也就是默认值的时候使用)
+> *注意* 一定要给组件 **ref="imgUpload"**
+
+-------------------------------------
+
+####示范代码
+
+```
+
+
+
+
+
+
+
+
+
+
+
+
+```
+
+
+-------------------------------------
+
+###[彩蛋提示]
+可以在组件里修改组件小提示的颜色哦!只需要修改成功失败警告的颜色即可。
+
+```
+tipObj: {
+ prompt: '',
+ typeColor: '#009100',
+ success: '#009100', //成功-#009100; 可自定义修改
+ warning: '#d3d300', // 警告 -#d3d300; 可自定义修改
+ error: '#FF0000' // 失败--#FF0000; 可自定义修改
+ },
+
+```
+
+
+
+
+
+
\ No newline at end of file
diff --git a/java-mall-app-shop-admin/components/poiuy-uImgUpload/font/font_2170343_nij8dm8i18.eot b/java-mall-app-shop-admin/components/poiuy-uImgUpload/font/font_2170343_nij8dm8i18.eot
new file mode 100644
index 0000000..d134a2f
Binary files /dev/null and b/java-mall-app-shop-admin/components/poiuy-uImgUpload/font/font_2170343_nij8dm8i18.eot differ
diff --git a/java-mall-app-shop-admin/components/poiuy-uImgUpload/font/font_2170343_nij8dm8i18.svg b/java-mall-app-shop-admin/components/poiuy-uImgUpload/font/font_2170343_nij8dm8i18.svg
new file mode 100644
index 0000000..e1eef05
--- /dev/null
+++ b/java-mall-app-shop-admin/components/poiuy-uImgUpload/font/font_2170343_nij8dm8i18.svg
@@ -0,0 +1,56 @@
+
+
+
+
diff --git a/java-mall-app-shop-admin/components/poiuy-uImgUpload/font/font_2170343_nij8dm8i18.ttf b/java-mall-app-shop-admin/components/poiuy-uImgUpload/font/font_2170343_nij8dm8i18.ttf
new file mode 100644
index 0000000..a3f9005
Binary files /dev/null and b/java-mall-app-shop-admin/components/poiuy-uImgUpload/font/font_2170343_nij8dm8i18.ttf differ
diff --git a/java-mall-app-shop-admin/components/poiuy-uImgUpload/font/font_2170343_nij8dm8i18.woff b/java-mall-app-shop-admin/components/poiuy-uImgUpload/font/font_2170343_nij8dm8i18.woff
new file mode 100644
index 0000000..9e7fb70
Binary files /dev/null and b/java-mall-app-shop-admin/components/poiuy-uImgUpload/font/font_2170343_nij8dm8i18.woff differ
diff --git a/java-mall-app-shop-admin/components/poiuy-uImgUpload/font/font_2170343_nij8dm8i18.woff2 b/java-mall-app-shop-admin/components/poiuy-uImgUpload/font/font_2170343_nij8dm8i18.woff2
new file mode 100644
index 0000000..88b0d01
Binary files /dev/null and b/java-mall-app-shop-admin/components/poiuy-uImgUpload/font/font_2170343_nij8dm8i18.woff2 differ
diff --git a/java-mall-app-shop-admin/components/poiuy-uImgUpload/imgUpload.vue b/java-mall-app-shop-admin/components/poiuy-uImgUpload/imgUpload.vue
new file mode 100644
index 0000000..2dd9cbb
--- /dev/null
+++ b/java-mall-app-shop-admin/components/poiuy-uImgUpload/imgUpload.vue
@@ -0,0 +1,950 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ conf.loadText || "上传中..." }}
+
+
+
+
+
+
+
+
+
+
+
+ 上传成功
+
+
+
+ 上传失败
+
+
+
+
+
+
+
+
+
+
+
+ * 最多上传{{ imgCount }}张图片(
+
+ /{{ imgCount }})
+
+
+ {{ tipObj.prompt }}
+
+
+
+
+
+
+
diff --git a/java-mall-app-shop-admin/components/uni-nav-bar/uni-nav-bar.vue b/java-mall-app-shop-admin/components/uni-nav-bar/uni-nav-bar.vue
index 6f2e56a..778e8c7 100644
--- a/java-mall-app-shop-admin/components/uni-nav-bar/uni-nav-bar.vue
+++ b/java-mall-app-shop-admin/components/uni-nav-bar/uni-nav-bar.vue
@@ -32,9 +32,9 @@
class="uni-navbar-btn-text"
v-if="leftText.length"
>
- {{
- leftText
- }}
+
+ {{ leftText }}
+
@@ -47,8 +47,9 @@
{{ title }}
+ {{ title }}
+
@@ -68,8 +69,9 @@
{{ rightText }}
+ {{ rightText }}
+
@@ -247,6 +249,7 @@ $nav-height: 44px;
/* #ifndef APP-PLUS */
font-size: 14px;
/* #endif */
+ font-weight: bold;
}
.uni-nav-bar-right-text {
diff --git a/java-mall-app-shop-admin/config/componentConfig.js b/java-mall-app-shop-admin/config/componentConfig.js
index 4380af0..c6fe2b3 100644
--- a/java-mall-app-shop-admin/config/componentConfig.js
+++ b/java-mall-app-shop-admin/config/componentConfig.js
@@ -70,8 +70,6 @@ export default {
break;
}
- console.log("marketId", marketId);
- console.log("phoneInfo.brand", phoneInfo.brand);
let params = {
marketId: 100,
diff --git a/java-mall-app-shop-admin/main.js b/java-mall-app-shop-admin/main.js
index aa2c81c..11c0451 100644
--- a/java-mall-app-shop-admin/main.js
+++ b/java-mall-app-shop-admin/main.js
@@ -4,14 +4,11 @@ import store from "./store";
import uView from "@/uni_modules/uview-ui";
import "./uni.promisify.adaptor";
import tui from "./utils/httpRequest";
-import Socket from "./utils/socket.js";
Vue.use(uView);
Vue.config.productionTip = false;
-// Vue.prototype.$utils = Utils
Vue.prototype.tui = tui;
-Vue.prototype.$Socket = Socket;
App.mpType = "app";
const app = new Vue({
diff --git a/java-mall-app-shop-admin/manifest.json b/java-mall-app-shop-admin/manifest.json
index 74e0f54..04364a9 100644
--- a/java-mall-app-shop-admin/manifest.json
+++ b/java-mall-app-shop-admin/manifest.json
@@ -4,7 +4,7 @@
"package" : "com.xiaofa.shopAdmin",
"description" : "",
"versionName" : "1.0.0",
- "versionCode" : 102,
+ "versionCode" : 100,
"transformPx" : false,
/* 5+App特有相关 */
"app-plus" : {
@@ -17,19 +17,13 @@
"autoclose" : true,
"delay" : 0
},
- "ios" : {
- "capabilities" : {
- "com.apple.SafariKeychain" : true
- }
- },
/* 模块配置 */
"modules" : {
"Maps" : {},
"Camera" : {},
"Record" : {},
"VideoPlayer" : {},
- "UIWebview" : {},
- "Push" : {}
+ "UIWebview" : {}
},
/* 应用发布信息 */
"distribute" : {
@@ -68,25 +62,7 @@
},
/* SDK配置 */
"sdkConfigs" : {
- "maps" : {},
- "push" : {
- "igexin" : {
- "appid" : "rQxaGAKl7t83KlTubAaKC3",
- "appkey" : "QSElTn6ttq5nmrIZtFhCT",
- "appsecret" : "zbC1MMuzaf7kW91fdhm9v8"
- },
- "unipush" : {
- "version" : "2",
- "offline" : false,
- "hms" : {},
- "oppo" : {},
- "vivo" : {},
- "mi" : {},
- "meizu" : {},
- "honor" : {},
- "fcm" : {}
- }
- }
+ "maps" : {}
},
"icons" : {
"android" : {
@@ -121,7 +97,7 @@
}
},
"splashscreen" : {
- "androidStyle" : "common"
+ "androidStyle" : "default"
}
}
},
diff --git a/java-mall-app-shop-admin/pages/IM/IM.vue b/java-mall-app-shop-admin/pages/IM/IM.vue
index 85a8673..259913f 100644
--- a/java-mall-app-shop-admin/pages/IM/IM.vue
+++ b/java-mall-app-shop-admin/pages/IM/IM.vue
@@ -6,7 +6,8 @@
{{ msgInfo.mine.user_nickname }}
@@ -149,7 +150,7 @@ export default {
},
onLoad() {},
computed: {
- ...mapState("user", ["uid", "userInfo", "socket", "imWeidu", "getMsg"]),
+ ...mapState("user", ["uid", "userInfo", "imWeidu", "getMsg"]),
},
watch: {
imWeidu: {
@@ -198,9 +199,9 @@ export default {
this.loading = true;
let res = await GetImConfig({ type: "json", uid: this.uid });
+ console.log(res);
if (res && res.status == 200) {
this.msgInfo = res.data;
-
if (res.data.friend.length > 0) {
let _imWeiDu = uni.getStorageSync("imWeiDu");
if (_imWeiDu) {
@@ -217,6 +218,7 @@ export default {
this.msgList = res.data.friend[0].list;
}
}
+ // this.connectSocket(this.userInfo);
}
this.loading = false;
},
@@ -279,11 +281,12 @@ export default {
.IM-status {
display: flex;
align-items: center;
- gap: 10rpx;
+ gap: 20rpx;
.img {
width: 88rpx;
height: 88rpx;
- border-radius: 10rpx;
+ border-radius: 100%;
+ margin-right: 20rpx;
}
}
@@ -384,7 +387,7 @@ export default {
}
.icon-kefu {
- // margin-right: 40rpx;
+ margin-right: 40rpx;
}
.IM-loading {
diff --git a/java-mall-app-shop-admin/pages/IM/IMmsgContent.vue b/java-mall-app-shop-admin/pages/IM/IMmsgContent.vue
index 6f64fc8..dad1a7e 100644
--- a/java-mall-app-shop-admin/pages/IM/IMmsgContent.vue
+++ b/java-mall-app-shop-admin/pages/IM/IMmsgContent.vue
@@ -144,6 +144,7 @@ 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";
import { mapState } from "vuex";
+import { webSocketManager } from "@/utils/socket.js";
export default {
components: {
tChatBar,
@@ -178,7 +179,6 @@ export default {
RECORDER: uni.getRecorderManager(),
playMsgid: "",
isPlayVoice: false,
- // socket: {},
chattype: "user",
isHideKeyBoard: false,
emojiPath: "https://res.wx.qq.com/mpres/htmledition/images/icon/emotion/",
@@ -326,7 +326,7 @@ export default {
},
},
computed: {
- ...mapState("user", ["uid", "userInfo", "socket", "getMsg"]),
+ ...mapState("user", ["uid", "userInfo", "getMsg"]),
},
methods: {
async setMsgRead(lastid) {
@@ -515,26 +515,7 @@ export default {
// }
}
},
- // socketServer() {
- // console.log(this.userInfo.im.node_site_url);
- // 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.socket.connectserver(this.userInfo.im);
- // },
processTimeString(timeStr) {
const parts = timeStr.split(":");
@@ -800,7 +781,9 @@ export default {
if (res && res.status == 200) {
chat_data.mine.message_id = res.data.message_other_id;
- this.socket.nsend(chat_data);
+ let connection = webSocketManager.getConnection("ws1");
+
+ connection.send(chat_data);
let lastid = res.data.message_other_id;
let tempmy = this.userInfo.im;
///TOID现在是模拟的
diff --git a/java-mall-app-shop-admin/pages/audit/checkAudit.vue b/java-mall-app-shop-admin/pages/audit/checkAudit.vue
index c8839dc..35397b9 100644
--- a/java-mall-app-shop-admin/pages/audit/checkAudit.vue
+++ b/java-mall-app-shop-admin/pages/audit/checkAudit.vue
@@ -276,6 +276,7 @@
:placeholder="item.placeholder"
:readonly="item.isReadonly"
:maxlength="item.maxLength"
+ clearable
/>
diff --git a/java-mall-app-shop-admin/pages/audit/mapAddress.vue b/java-mall-app-shop-admin/pages/audit/mapAddress.vue
index cb94598..ba16578 100644
--- a/java-mall-app-shop-admin/pages/audit/mapAddress.vue
+++ b/java-mall-app-shop-admin/pages/audit/mapAddress.vue
@@ -29,6 +29,7 @@
v-model="form.searchAddress"
placeholder="搜索地址,更快填写"
@input="handerSearchAddress"
+ clearable
/>
diff --git a/java-mall-app-shop-admin/pages/audit/shop1.vue b/java-mall-app-shop-admin/pages/audit/shop1.vue
index 806bbb8..efaa946 100644
--- a/java-mall-app-shop-admin/pages/audit/shop1.vue
+++ b/java-mall-app-shop-admin/pages/audit/shop1.vue
@@ -35,6 +35,7 @@
class="form-input"
v-model="form.contact_name"
placeholder="请输入联系人"
+ clearable
/>
diff --git a/java-mall-app-shop-admin/pages/audit/shop2.vue b/java-mall-app-shop-admin/pages/audit/shop2.vue
index 109472c..fc559cd 100644
--- a/java-mall-app-shop-admin/pages/audit/shop2.vue
+++ b/java-mall-app-shop-admin/pages/audit/shop2.vue
@@ -66,6 +66,7 @@
class="form-input"
v-model="form.biz_license_company"
placeholder="请输入公司名称"
+ clearable
/>
@@ -73,6 +74,7 @@
class="form-input"
v-model="form.legal_person_name"
placeholder="请输入法人姓名"
+ clearable
/>
@@ -80,6 +82,7 @@
class="form-input"
v-model="form.biz_license_number"
placeholder="请输入注册号"
+ clearable
/>
@@ -88,6 +91,7 @@
class="form-input"
v-model="form.legal_person_mobile"
placeholder="请输入法人手机号"
+ clearable
/>
@@ -96,6 +100,7 @@
class="form-input"
v-model="form.biz_license_content"
placeholder="请输入经营范围"
+ clearable
/>
-
+
@@ -496,7 +496,7 @@ export default {
}
.input_icon {
- ::v-deep .u-icon__icon {
+ ::v-deep .u-icon__icon {
font-size: 36rpx !important;
}
}
diff --git a/java-mall-app-shop-admin/pages/order/order.vue b/java-mall-app-shop-admin/pages/order/order.vue
index f874b12..68139b2 100644
--- a/java-mall-app-shop-admin/pages/order/order.vue
+++ b/java-mall-app-shop-admin/pages/order/order.vue
@@ -1265,7 +1265,6 @@ export default {
this.showOrderLoading = true;
}
- console.log(this.dashboardInfo.store_info.store_id);
this.params = {
storeId: this.dashboardInfo.store_info.store_id,
diff --git a/java-mall-app-shop-admin/pages/register/register.vue b/java-mall-app-shop-admin/pages/register/register.vue
index 8de9ade..0daba9f 100644
--- a/java-mall-app-shop-admin/pages/register/register.vue
+++ b/java-mall-app-shop-admin/pages/register/register.vue
@@ -57,9 +57,10 @@
- 已有账号? 立即登录
+
+ 已有账号?
+ 立即登录
+
-
+
+ 注册代表你已经同意
+ 《用户协议》
+
@@ -270,7 +270,7 @@ export default {
}
.input_icon {
- ::v-deep.u-icon__icon {
+ ::v-deep.u-icon__icon {
font-size: 36rpx !important;
}
}
@@ -372,7 +372,7 @@ export default {
.agreement-content {
position: fixed;
bottom: 10%;
- width: 90%;
+ width: 83%;
text-align: center;
font-size: 28rpx;
color: #ccc;
diff --git a/java-mall-app-shop-admin/pages/warehouse/manage/addAndEditProduct.vue b/java-mall-app-shop-admin/pages/warehouse/manage/addAndEditProduct.vue
index 1ac0981..7caf3d3 100644
--- a/java-mall-app-shop-admin/pages/warehouse/manage/addAndEditProduct.vue
+++ b/java-mall-app-shop-admin/pages/warehouse/manage/addAndEditProduct.vue
@@ -6,9 +6,9 @@
:border="false"
:fixed="true"
:height="'44px'"
- rightWidth="0"
+ :rightWidth="40"
:leftWidth="30"
- title="编辑分类"
+ :title="isAdd ? '添加商品' : '编辑商品'"
backgroundColor="#fff"
>
@@ -19,6 +19,7 @@
@click="pageBack()"
>
+ 删除
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ form.product_sale_time || "预计上架时间" }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 共{{ specificationInfoList.length }}个规格
+
+
+
+
+
+ {{ item.spec_item_name }}
+
+
+
+ 属性编号:{{ item.item_number }}
+
+
+ 库存:{{ item.item_quantity || item.item_quantity_2 }}
+
+
+
+
+ 市场价:{{
+ item.item_market_price || item.item_market_price_2
+ }}
+
+
+ 零售价:{{ item.item_unit_price || item.item_unit_price_2 }}
+
+
+
+
+
+
+
+
+ 还可以设置购买上限、店内码/货号、商品描述、 开售时间、 库存锁定
+
+
+
+
+ {{ isUnfold ? "收起部分" : " 展示全部" }}
+
+
+
+
+
+
+
+
+
+ {{ isAdd ? "添加" : "保存" }}
+
+
+
+
+
+
+
+
@@ -117,5 +1053,255 @@ export default {
@import "@/styles/variables.scss";
.addAndEditProduct-container {
+ width: 100vw;
+ height: calc(100vh - 120rpx);
+ overflow: auto;
+
+ .nav-bar {
+ ::v-deep.uni-navbar__content {
+ z-index: 1100;
+ }
+ }
+
+ .addAndEditProduct-content {
+ .u-form {
+ background: #f5f6fa;
+
+ .form-item {
+ background: #fff;
+ padding: 0 40rpx;
+ }
+
+ .form-item-margin-top-20 {
+ margin-top: 40rpx;
+ }
+
+ .form-item-margin-20 {
+ margin: 40rpx 0;
+ }
+
+ .form-sale-time-item {
+ ::v-deep.u-form-item__body__right__content__slot {
+ display: flex;
+ flex-flow: column;
+ align-items: normal;
+ }
+
+ .sale-time {
+ margin: 40rpx 0;
+ background: #eeeeee;
+ padding: 20rpx;
+ color: #6666;
+ }
+ }
+
+ .form-item-specification {
+ ::v-deep.u-form-item__body__right__content__slot {
+ display: flex;
+ flex-flow: column;
+ align-items: normal;
+ }
+
+ .total-content {
+ display: flex;
+ justify-content: space-between;
+ margin: 8px 0 8px 8px;
+ font-weight: bold;
+ }
+
+ .specification-content {
+ background: #f5f6fa;
+ border-radius: 16rpx;
+
+ .specification-item {
+ display: flex;
+ flex-flow: column;
+ justify-content: space-between;
+ padding: 8px;
+
+ .specification-name {
+ margin: 3px 0;
+ font-size: 16px;
+ font-weight: bold;
+ }
+
+ .specification-info {
+ display: flex;
+ justify-content: space-between;
+ height: 96rpx;
+ font-size: 24rpx;
+ color: #626262;
+ }
+
+ .info-item {
+ display: flex;
+ flex-flow: column;
+ justify-content: space-around;
+ }
+ }
+ }
+ }
+ }
+
+ .tips-content {
+ padding: 40rpx 20rpx;
+ background: #f5f6fa;
+
+ .tips {
+ font-size: 28rpx;
+ color: #666666;
+ }
+
+ .btn-unfold {
+ margin: 52rpx auto 20rpx;
+ width: 200rpx;
+ font-size: 24rpx;
+ height: 60rpx;
+
+ &::after {
+ border: none;
+ }
+ }
+ }
+ }
+
+ .affirm-popup {
+ ::v-deep.u-popup__content {
+ border-radius: 16rpx;
+ }
+
+ ::v-deep.u-fade-enter-to {
+ z-index: 10076 !important;
+ }
+
+ .affirm-popup-content {
+ width: 600rpx;
+
+ .affirm-popup-title {
+ padding: 40rpx;
+ text-align: center;
+ font-weight: bold;
+ }
+
+ .affirm-popup-tips {
+ padding: 0 60rpx;
+ font-size: 28rpx;
+ text-align: center;
+ }
+
+ .popup-btn-list {
+ display: flex;
+ margin: 50rpx;
+
+ .btn-item {
+ width: 46%;
+ height: 80rpx;
+ border-color: #909193;
+
+ &::after {
+ border: none;
+ }
+ }
+
+ .btn-item-2 {
+ background: $base-color;
+ color: #fff;
+ border: none;
+ }
+ }
+ }
+ }
+
+ .add-popup {
+ ::v-deep.u-popup__content {
+ border-radius: 16rpx;
+ }
+
+ ::v-deep.u-fade-enter-to {
+ z-index: 10076 !important;
+ }
+
+ .add-popup-content {
+ width: 700rpx;
+
+ .add-popup-title {
+ padding: 40rpx;
+ text-align: center;
+ font-weight: bold;
+ font-size: 36rpx;
+ }
+
+ .add-tips {
+ padding: 0 24rpx;
+ text-align: center;
+ color: red;
+ }
+
+ .u-form {
+ margin: 0 40rpx;
+
+ .form-item {
+ margin: 28rpx 0;
+ }
+ }
+
+ .popup-btn-list {
+ display: flex;
+ margin: 50rpx;
+
+ .btn-item {
+ width: 46%;
+ height: 80rpx;
+ border-color: #909193;
+
+ &::after {
+ border: none;
+ }
+ }
+
+ .btn-item-2 {
+ background: $base-color;
+ color: #fff;
+ border: none;
+ }
+ }
+ }
+ }
+
+ .bottom-btn {
+ position: fixed;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ padding: 20rpx;
+ background: #fff;
+ border-top: 2rpx solid $uni-border-color;
+ z-index: 2;
+
+ .bottom-list {
+ display: flex;
+ align-items: center;
+ justify-content: flex-end;
+
+ .bottom-btn-item {
+ font-size: 28rpx;
+ border-color: $base-color;
+ color: #fff;
+ background: $base-color;
+
+ .bottom-icon {
+ margin-right: 8rpx;
+ }
+
+ &::after {
+ border: none;
+ }
+ }
+ }
+ }
+
+ .loading-page {
+ z-index: 1099;
+ }
}
diff --git a/java-mall-app-shop-admin/pages/warehouse/manage/batchSearch.vue b/java-mall-app-shop-admin/pages/warehouse/manage/batchSearch.vue
index fdcd0c7..aadc1a8 100644
--- a/java-mall-app-shop-admin/pages/warehouse/manage/batchSearch.vue
+++ b/java-mall-app-shop-admin/pages/warehouse/manage/batchSearch.vue
@@ -179,7 +179,7 @@
shape="circle"
@click="handerPageBack"
>
- 确认
+ 退出
@@ -759,7 +759,7 @@ export default {
.affirm-popup-title {
padding: 40rpx;
text-align: center;
- font-weight: bold;
+ font-weight: bold;
}
.affirm-popup-tips {
diff --git a/java-mall-app-shop-admin/pages/warehouse/manage/classifyList.vue b/java-mall-app-shop-admin/pages/warehouse/manage/classifyList.vue
index 1168658..cd5597b 100644
--- a/java-mall-app-shop-admin/pages/warehouse/manage/classifyList.vue
+++ b/java-mall-app-shop-admin/pages/warehouse/manage/classifyList.vue
@@ -381,6 +381,7 @@
type="number"
placeholder="请输入商品排序"
border="none"
+ clearable
>
@@ -229,6 +232,7 @@
diff --git a/java-mall-app-shop-admin/pages/warehouse/manage/productList.vue b/java-mall-app-shop-admin/pages/warehouse/manage/productList.vue
index 0556fe9..5bcdbce 100644
--- a/java-mall-app-shop-admin/pages/warehouse/manage/productList.vue
+++ b/java-mall-app-shop-admin/pages/warehouse/manage/productList.vue
@@ -6,9 +6,9 @@
:border="false"
:fixed="true"
:height="'44px'"
- rightWidth="0"
+ :rightWidth="0"
:leftWidth="30"
- backgroundColor="#f5f6fa"
+ backgroundColor="#f5f6fa"
>
下架
-
-
- 编辑
+
+
+ 编辑
+
@@ -189,32 +194,25 @@
+ <<<<<<< Updated upstream =======
+ 分类管理
+ >>>>>>> Stashed changes
-
- 分类管理
+
+ 分类管理
-
+
批量操作
-
- 商品新建
+
+
+ 商品新建
+
@@ -268,8 +266,8 @@
:placeholder="String(item.item_quantity)"
border="surround"
type="number"
+ clearable
v-model="item.item_quantity_2"
- @change="haderPopupRepertoryInputChange($event, index)"
>
@@ -282,13 +280,27 @@
:hairline="true"
:plain="true"
shape="circle"
- @click="handerSave"
+ @click="updateCommodityPriceAndQuantity"
>
保存
+
+
@@ -297,18 +309,22 @@ import {
GetProductCategoryTree,
GetProductList,
UpdateProductPutaway,
- GetCommoditSpecification,
} from "@/api/warehouse/productList";
+import {
+ GetCommoditSpecification,
+ UpdateCommodityPriceAndQuantity,
+} from "@/api/warehouse/commodity";
import navBar from "@/components/uni-nav-bar/uni-nav-bar";
import tuiCollapse from "../manage/components/tui-collapse/tui-collapse.vue";
import favoriteLoading from "@/components/favorite-loading/favorite-loading.vue";
-
+import addAndEditProduct from "./addAndEditProduct.vue";
export default {
name: "productList",
components: {
navBar,
tuiCollapse,
favoriteLoading,
+ addAndEditProduct,
},
data() {
return {
@@ -372,6 +388,10 @@ export default {
time2: null,
showBottomPopup: false,
currSpecificationList: [],
+ showRightPopup: false,
+ productItem: {},
+ isAdd: true,
+ selectCommodisItems: [],
};
},
computed: {},
@@ -431,9 +451,61 @@ export default {
};
let res = await GetCommoditSpecification(params);
-
if (res && res.status == 200) {
- this.currSpecificationList = res.data;
+ this.selectCommodisItems = res.data;
+
+ // 1. 解析产品规格模板
+ let productSpec = JSON.parse(JSON.stringify(item.product_spec));
+
+ productSpec = JSON.parse(productSpec);
+ if (!Array.isArray(productSpec)) {
+ productSpec = [productSpec]; // 确保是数组格式
+ }
+
+ const specItemMap = [];
+
+ productSpec.forEach((specGroup) => {
+ if (specGroup.item && Array.isArray(specGroup.item)) {
+ specGroup.item.forEach((item) => {
+ specItemMap.push(item.id);
+ });
+ }
+ });
+
+ this.currSpecificationList = this.selectCommodisItems
+ .map((item) => {
+ try {
+ // 解析规格数据(兼容字符串和对象)
+ const itemSpec =
+ typeof item.item_spec === "string"
+ ? JSON.parse(item.item_spec)
+ : item.item_spec;
+
+ if (Array.isArray(itemSpec) && itemSpec.length > 0) {
+ const firstSpec = itemSpec[0];
+
+ // 匹配规格逻辑
+ if (firstSpec.item && firstSpec.item.id) {
+ const matchedSpec = specItemMap.find(
+ (id) => id == firstSpec.item.id
+ );
+
+ if (matchedSpec) {
+ return {
+ ...item,
+ spec_item_id: matchedSpec,
+ item_is_default: Boolean(item.item_is_default),
+ // 保留原始数据(调试用)
+ };
+ }
+ }
+ }
+ } catch (e) {
+ console.error(`处理商品 ${item.item_id} 时出错:`, e);
+ }
+ })
+ .filter((item) => item != undefined);
+ console.log(this.currSpecificationList);
this.showBottomPopup = true;
}
},
@@ -642,18 +714,49 @@ export default {
url: "../../news/search/search",
});
},
- haderPopupPriceInputChange(e, index) {
- this.currSpecificationList[index].item_unit_price_2 = e;
+ async updateCommodityPriceAndQuantity(item) {
+ let params = {};
+
+ let res = await UpdateCommodityPriceAndQuantity(params);
+ if (res && res.status) {
+ this.$refs.uToast.show({
+ message: "修改成功",
+ type: "succeed",
+ duration: 1000,
+ });
+
+ // 静默更新数组
+ let listParams = {
+ kind_id: "1201,1202,1203",
+ pageNum: 9999,
+ pageSize: this.pageSize,
+ product_state_id: this.currProductStateId,
+ category_id: this.currCategoryId,
+ openCount: true,
+ };
+
+ let result = await GetProductList(listParams);
+ if (result && result.status == 200) {
+ this.commodityList = res.data.items;
+ }
+ }
+ this.showBottomPopup = false;
},
- haderPopupRepertoryInputChange(e, index) {
- this.currSpecificationList[index].item_quantity_2 = e;
- },
- handerSave() {},
skipuBatch() {
uni.navigateTo({
url: "/pages/warehouse/manage/batch",
});
},
+ skipuClassify() {
+ uni.navigateTo({
+ url: "/pages/warehouse/manage/classifyList",
+ });
+ },
+ handerProductEdit(item) {
+ this.productItem = item;
+ this.showRightPopup = true;
+ this.isAdd = false;
+ },
},
};
@@ -661,14 +764,14 @@ export default {
diff --git a/java-mall-app-shop-admin/pages/warehouse/manage/specificationOfGood.vue b/java-mall-app-shop-admin/pages/warehouse/manage/specificationOfGood.vue
new file mode 100644
index 0000000..da1e9d9
--- /dev/null
+++ b/java-mall-app-shop-admin/pages/warehouse/manage/specificationOfGood.vue
@@ -0,0 +1,1165 @@
+
+
+
+
+
+
+
+
+ 注意!,这个是每个分类下对应的规格,不是当前商品的规格。
+
+
+
+
+ {{ commoditSpecificationBaseInfo2.specs[0].spec_name }}
+
+
+
+ 新增
+
+ 编辑
+
+
+
+ 规格列表
+
+
+
+
+
+
+
+
+ 设置售卖信息
+
+
+
+
+
+
+ 规格{{ index + 1 }} {{ item.spec_item_name }}
+
+
+ 是否默认
+
+
+
+
+ 属性编号
+
+
+
+ 市场价
+
+
+
+ 零售价
+
+
+
+ 库存
+
+
+
+
+
+
+
+
+
+ 保存
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/java-mall-app-shop-admin/pages/warehouse/manage/typeManagement.vue b/java-mall-app-shop-admin/pages/warehouse/manage/typeManagement.vue
index a014b9c..62aa5ce 100644
--- a/java-mall-app-shop-admin/pages/warehouse/manage/typeManagement.vue
+++ b/java-mall-app-shop-admin/pages/warehouse/manage/typeManagement.vue
@@ -15,44 +15,46 @@
:refresher-triggered="isRefreshing"
@refresherrefresh="handleRefresh"
>
-
-
-
- {{ item.type_name }}
-
- {{ item.type_category_name }}
+
+
+
+ {{ item.type_name }}
+
+ {{ item.type_category_name }}
+
-
-
-
- 删除
+
+
+
+ 删除
+
+
+
+
+ 编辑
+
-
-
- 编辑
-
-
-
-
+
-
+
新建商品类型
@@ -209,7 +216,10 @@
v-for="(item, index) in allSpecificationList"
:key="index"
>
- 分类名称:{{ item.name }}
+
+
+ 分类名称:{{ item.name }}
+
diff --git a/java-mall-app-shop-admin/store/modules/user.js b/java-mall-app-shop-admin/store/modules/user.js
index ed04423..649f3c9 100644
--- a/java-mall-app-shop-admin/store/modules/user.js
+++ b/java-mall-app-shop-admin/store/modules/user.js
@@ -1,7 +1,7 @@
import { GetAuditInfo, GetAuditStatus } from "../../api/audit";
import { GetAccountLogin, GetLogin } from "../../api/login";
import { OutLogin } from "../../api/user";
-import $Socket from "../../utils/socket";
+import { webSocketManager } from "@/utils/socket.js";
import Vue from "vue";
// import $cookies from '../../utils/vue-cookies'
@@ -72,10 +72,12 @@ const mutations = {
state.imWeidu = {};
state.dashboardInfo = {};
},
- CONNECT_SOCKET(state, { socket }) {
- state.socket = socket;
+ CONNECT_SOCKET(state, { webSocketManager }) {
+ state.socket = webSocketManager;
},
GET_IM_MSG(state, { msg }) {
+ console.log("GET_IM_MSG", msg);
+ if (!msg.id) return;
state.getMsg = msg;
var im = {};
let _imWeiDu = uni.getStorageSync("imWeiDu");
@@ -121,8 +123,7 @@ const actions = {
// #endif
- params.cid = "ae9c4517a4ae17ea33570839a0f5fdba";
- params.osType = 1;
+ console.log("push_clientid");
const res = await GetAccountLogin(params);
@@ -195,6 +196,8 @@ const actions = {
}
},
async LoginOut({ commit }, isTokenExpires) {
+ webSocketManager.closeAllGlobalConnections();
+
if (isTokenExpires) {
await OutLogin();
@@ -379,27 +382,22 @@ const actions = {
},
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 });
+ webSocketManager.createGlobalConnection(
+ "ws1",
+ userInfo.im.node_site_url,
+ 2000
+ );
+
+ webSocketManager.getConnection("ws1").onMessage((res) => {
+ // 处理消息逻辑
+ if (res) {
+ let msg = res;
+
+ console.log("ws1收到的消息:", msg);
+ commit("GET_IM_MSG", { msg });
+ }
+ });
},
};
diff --git a/java-mall-app-shop-admin/styles/variables.scss b/java-mall-app-shop-admin/styles/variables.scss
index e582cee..e32cfd0 100644
--- a/java-mall-app-shop-admin/styles/variables.scss
+++ b/java-mall-app-shop-admin/styles/variables.scss
@@ -1,4 +1,3 @@
/*主颜色*/
-$base-color: #FE411B; // 蓝色 #4b71ff
-
-$base-btn-bg-color: #FE411B;
+$base-color: #fe411b; // 蓝色 #4b71ff
+$base-btn-bg-color: #fe411b;
diff --git a/java-mall-app-shop-admin/uni_modules/uview-ui/components/u-toast/u-toast.vue b/java-mall-app-shop-admin/uni_modules/uview-ui/components/u-toast/u-toast.vue
index f194830..f2a7fce 100644
--- a/java-mall-app-shop-admin/uni_modules/uview-ui/components/u-toast/u-toast.vue
+++ b/java-mall-app-shop-admin/uni_modules/uview-ui/components/u-toast/u-toast.vue
@@ -1,291 +1,306 @@
-
-
-
-
-
-
- {{ tmpConfig.message }}
-
-
-
+
+
+
+
+
+
+
+ {{ tmpConfig.message }}
+
+
+
+
diff --git a/java-mall-app-shop-admin/utils/socket.js b/java-mall-app-shop-admin/utils/socket.js
index 5c931ff..0ab2c3b 100644
--- a/java-mall-app-shop-admin/utils/socket.js
+++ b/java-mall-app-shop-admin/utils/socket.js
@@ -1,261 +1,189 @@
-const noop = function() {};
-class Socket {
- static stopTime = 0;
- static concatCount = 0;
- constructor({
- url = '',
- onOpen = noop,
- onMsg = noop,
- onClose = noop,
- onError = noop,
- onReload = noop,
- onRdFinsh = noop,
- maxInterValCount = 10,
- interValTime = 2000,
- SocketState = {},
- ...args
- } = {}) {
- this.isRconnectIng = false; //是否处于重连状态
- this.waiting = Promise.resolve(false); //心跳检查必须等待重连完成后
- this.waitDep = []; //等待时收集依赖的容器
- this.SocketTask = {
- nsend: noop,
- nclose: noop,
- nrconnect: noop,
- isconnect: false,
- uniColse: false,
- maxInterValCount,
- interValTime,
- InterValCount: 0,
- eventPatch: null,
- url,
- onOpen,
- onMsg,
- onClose,
- onError,
- onReload,
- onRdFinsh,
- extra: args
- };
- this._EventDispath(this.SocketTask);
- //this.initChat(this.SocketTask, this.SocketTask.extra);
- return this.SocketTask;
+class WebsocketUtil {
+ constructor(url, time) {
+ this.is_open_socket = false; // 避免重复连接
+ this.url = url; // 地址
+ this.data = null;
+ // 心跳检测
+ this.timeout = time; // 多少秒执行检测
+ this.heartbeatInterval = null; // 检测服务器端是否还活着
+ this.reconnectInterval = null; // 重连之后多久再次重连
+ this.messageCallbacks = []; // 存储消息回调函数
+ this.store = null; // 存储Vuex store引用
- }
- set CONCATCOUNT(value) {
- Socket.concatCount = value;
- if (value > 0) this._notify();
- }
- get CONCATCOUNT() {
- return Socket.concatCount
- }
- /**
- * 仅供内部使用,通知所有收集到的依赖
- */
- _notify() {
- for (let i = 0; i < this.waitDep.length; i++) {
- this.waitDep[i].call(this.SocketTask);
- }
- this.waitDep = [];
- }
- /**
- * 仅供内部使用,确认当前是否连接成功,收集依赖
- */
- _chunkConnect(fn) {
- if (Socket.concatCount > 0) {
- fn();
- } else {
- this.waitDep.push(fn);
- }
- }
- /**
- * 仅供内部使用,事件注册
- */
- _EventDispath({
- onReload
- } = {}) {
- let SocketTask = this.SocketTask;
- let events = {
- onOpen: [],
- onMsg: [],
- onClose: [],
- onError: [],
- onReload: [],
- onRdFinsh: [],
- }
- SocketTask.connectserver = config => {
- //重连,判断是否
- if (!SocketTask.isconnect && !this.isRconnectIng)
- {
- this.SocketTask.url = config.node_site_url
- this.initChat(this.SocketTask, this.SocketTask.extra);
- }
- }
- SocketTask.nsend = msg => {
- let text = JSON.stringify(msg)
- this._chunkConnect(() => {
- uni.sendSocketMessage({
- data: text
- })
- })
- }
- SocketTask.nclose = t => {
- this._chunkConnect(() => {
- SocketTask.uniColse = true;
- uni.closeSocket();
- })
- }
- SocketTask.nrconnect = t => {
- this._chunkConnect(() => {
- this.waiting = new Promise(async (resolve) => {
- uni.closeSocket();
- let reloadStatus = false;
- try {
- const res = await this.initChat(SocketTask, SocketTask.extra);
- reloadStatus = res;
- } catch (e) {}
- onReload.call(SocketTask, reloadStatus, SocketTask);
- SocketTask.eventPatch.dispatchEvent('onReload', reloadStatus);
- resolve(reloadStatus);
- })
- })
- }
+ try {
+ return this.connectSocketInit();
+ } catch (e) {
+ this.is_open_socket = false;
+ }
+ }
- function EventDispatcher() {
- this.events = events;
- }
- for (let key in events) {
- EventDispatcher.prototype[key] = function(handler) {
- if (typeof handler != 'function') return;
- this.events[key].push(handler)
- }
- }
- EventDispatcher.prototype.dispatchEvent = function(type, msg) {
- let evenArr = this.events[type];
- if (evenArr.length > 0) {
- for (let i = 0; i < evenArr.length; i++) {
- evenArr[i].call(SocketTask, msg, SocketTask);
- }
- }
- }
- SocketTask.eventPatch = new EventDispatcher();
- }
- /**
- * 心跳检测
- */
- async hbDetection() {
- const SocketTask = this.SocketTask;
- if (SocketTask.uniColse) {
- return false;
- }
- clearTimeout(Socket.stopTime);
- if (!SocketTask.isconnect) { //未连接则启动连接
- if (SocketTask.maxInterValCount > SocketTask.InterValCount) {
- Socket.stopTime = setTimeout(async () => {
- try {
- const R_result = await this.waiting;
- if (R_result) return;
- this.isRconnectIng = true;
- const openResult = await this.initChat(SocketTask, SocketTask.extra);
- if (openResult) return;
- SocketTask.InterValCount++;
- return this.hbDetection();
- } catch (e) {
- return this.hbDetection();
- }
- }, SocketTask.interValTime)
- } else {
- SocketTask.onRdFinsh.call(SocketTask, SocketTask.maxInterValCount, SocketTask);
- SocketTask.eventPatch.dispatchEvent('onRdFinsh', SocketTask.maxInterValCount);
- }
- }
- }
- /**
- * websocket监听事件
- */
- SocketEvents({
- onOpen,
- onMsg,
- onClose,
- onError,
- onReload,
- } = {}) {
- return new Promise((resolve, reject) => {
- const SocketTask = this.SocketTask;
- uni.onSocketOpen(res => {
- this.CONCATCOUNT += 1;
- this.isRconnectIng = false;
- SocketTask.isconnect = true;
- SocketTask.InterValCount = 0;
- SocketTask.uniColse = false;
- resolve(true);
- onOpen.call(SocketTask, res, SocketTask);
- SocketTask.eventPatch.dispatchEvent('onOpen', res)
- })
- uni.onSocketMessage(msg => {
- onMsg.call(SocketTask, msg, SocketTask);
- SocketTask.eventPatch.dispatchEvent('onMsg', msg)
- })
- uni.onSocketClose(async err => {
- SocketTask.isconnect = false;
- resolve(false);
- if (!this.isRconnectIng) {
- this.hbDetection();
- onClose.call(SocketTask, err, SocketTask);
- SocketTask.eventPatch.dispatchEvent('onClose', err);
- }
- })
- uni.onSocketError(err => {
- uni.closeSocket();
- onError.call(SocketTask, err, SocketTask);
- SocketTask.eventPatch.dispatchEvent('onError', err)
- })
- })
- }
- /**
- * 开始初始化chat
- */
- initChat({
- url,
- onOpen,
- onMsg,
- onClose,
- onError,
- onReload
- } = {}, args) {
- return new Promise(async (resolve, reject) => {
- try {
- await this.connectSocket(url, args);
- let res = await this.SocketEvents({
- onOpen,
- onMsg,
- onClose,
- onError,
- onReload,
- })
- resolve(res);
- } catch (e) {
- console.log(e)
- reject();
- }
- })
- }
- /**
- * 连接webSocket
- */
- connectSocket(url, args) {
- return new Promise((resolve, reject) => {
- uni.connectSocket({
- url,
- success: () => {
- resolve();
- },
- fail: err => {
- reject();
- },
- ...args
- })
- })
- }
+ // 设置store
+ setStore(store) {
+ this.store = store;
+ }
+
+ // 创建WebSocket连接
+ connectSocketInit() {
+ if (this.is_open_socket) return;
+
+ this.socketTask = uni.connectSocket({
+ url: this.url,
+ success: () => {
+ this.is_open_socket = true;
+ return this.socketTask;
+ },
+ });
+
+ this.socketTask.onOpen((res) => {
+ clearInterval(this.reconnectInterval);
+ clearInterval(this.heartbeatInterval);
+ this.is_open_socket = true;
+ this.start();
+
+ this.socketTask.onMessage((res) => {
+ try {
+ const data = JSON.parse(res.data);
+ // 如果有store,将数据存入store
+ if (this.store) {
+ this.store.commit("setWebSocketData", data);
+ }
+ // 执行所有注册的回调函数
+ this.messageCallbacks.forEach((callback) => callback(data));
+ } catch (e) {
+ console.error("WebSocket消息解析错误:", e);
+ }
+ });
+ });
+
+ this.socketTask.onError((res) => {
+ this.is_open_socket = false;
+ if (this.socketTask) {
+ this.socketTask.close();
+ }
+ });
+
+ this.socketTask.onClose(() => {
+ this.is_open_socket = false;
+ });
+ }
+
+ // 发送消息
+ send(value) {
+ if (!this.is_open_socket) return;
+
+ this.socketTask.send({
+ data: JSON.stringify(value),
+ success() {
+ console.log("消息发送成功", value);
+ },
+ fail(err) {
+ console.error("消息发送失败", err);
+ },
+ });
+ }
+
+ // 关闭连接
+ close() {
+ clearInterval(this.heartbeatInterval);
+ clearInterval(this.reconnectInterval);
+ this.is_open_socket = false;
+ if (this.socketTask) {
+ this.socketTask.close();
+ }
+ }
+
+ // 开启心跳检测
+ start() {
+ // this.heartbeatInterval = setInterval(() => {
+ // const heartbeatMsg = {
+ // type: 'heartbeat',
+ // userId: uni.getStorageSync('userinfo')?.user_id
+ // }
+ // this.send(heartbeatMsg)
+ // }, this.timeout)
+ }
+
+ // 重新连接
+ reconnect() {
+ clearInterval(this.heartbeatInterval);
+ if (!this.is_open_socket) {
+ this.reconnectInterval = setInterval(() => {
+ this.connectSocketInit();
+ }, 3000);
+ }
+ }
+
+ // 注册消息回调
+ onMessage(callback) {
+ this.messageCallbacks.push(callback);
+ }
+
+ // 移除消息回调
+ offMessage(callback) {
+ this.messageCallbacks = this.messageCallbacks.filter(
+ (cb) => cb !== callback
+ );
+ }
}
-export default Socket
+
+class WebSocketManager {
+ constructor() {
+ this.connections = {}; // 存储所有WebSocket连接
+ this.globalConnections = []; // 存储需要全局管理的连接名称
+ }
+
+ // 创建全局连接
+ createGlobalConnection(name, url, time, store) {
+ if (!this.connections[name]) {
+ this.connections[name] = new WebsocketUtil(url, time);
+ if (store) this.connections[name].setStore(store);
+ this.globalConnections.push(name);
+ }
+ return this.connections[name];
+ }
+
+ // 创建页面级连接
+ createPageConnection(name, url, time) {
+ if (!this.connections[name]) {
+ this.connections[name] = new WebsocketUtil(url, time);
+ }
+ return this.connections[name];
+ }
+
+ // 获取连接
+ getConnection(name) {
+ return this.connections[name];
+ }
+
+ // 关闭指定连接
+ closeConnection(name) {
+ console.log("关闭指定连接", name);
+ if (this.connections[name]) {
+ this.connections[name].close();
+ delete this.connections[name];
+
+ // 从全局连接列表中移除
+ this.globalConnections = this.globalConnections.filter((n) => n !== name);
+ }
+ }
+
+ // 关闭所有全局连接
+ closeAllGlobalConnections() {
+ this.globalConnections.forEach((name) => {
+ this.closeConnection(name);
+ });
+ }
+
+ // 关闭所有连接
+ closeAllConnections() {
+ Object.keys(this.connections).forEach((name) => {
+ this.connections[name].close();
+ });
+ this.connections = {};
+ this.globalConnections = [];
+ }
+}
+
+// 导出单例实例
+export const webSocketManager = new WebSocketManager();
+export default WebsocketUtil;