更新商品编辑

This commit is contained in:
qijq 2025-07-28 01:55:47 +08:00
parent 079ee7a9e7
commit 868a749cc7
35 changed files with 4514 additions and 795 deletions

View File

@ -3,6 +3,7 @@
import APPUpdate, { getCurrentNo } from "@/config/appUpdate"; import APPUpdate, { getCurrentNo } from "@/config/appUpdate";
// #endif // #endif
import { mapState, mapActions } from "vuex"; import { mapState, mapActions } from "vuex";
import { webSocketManager } from "@/utils/socket.js";
export default { export default {
data() { data() {
return { return {
@ -27,7 +28,7 @@ export default {
// #endif // #endif
}, },
computed: { computed: {
...mapState("user", ["uid", "userInfo", "socket"]), ...mapState("user", ["uid", "userInfo"]),
}, },
onShow: function () { onShow: function () {
this.globalData.isAppActive = true; this.globalData.isAppActive = true;
@ -40,6 +41,7 @@ export default {
}, },
onHide: function () { onHide: function () {
this.globalData.isAppActive = false; this.globalData.isAppActive = false;
webSocketManager.closeAllGlobalConnections();
}, },
globalData: { globalData: {
isAppActive: false, isAppActive: false,

View File

@ -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,
});
}

View File

@ -70,21 +70,3 @@ export function DelectCommodity(params) {
baseURL: config.adminApi, 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,
});
}

View File

@ -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"**
-------------------------------------
####示范代码
```
<template>
<!--里面一些属性是示范作用才写上去的,具体需要使用哪些属性可自由调整-->
<!--直接上传图片-->
<imgUpload config:"config" previewMany :imgArr="imgArray" loading async url="xxx(上传图片的url)" @result="resultUrl" @delImg="delImg"></imgUpload>
<!--点击按钮一次提交-->
<imgUpload :imgArr="imgArray" imgCount="9" ref="imgUpload" url="xxx(上传图片的url)"></imgUpload>
<button type="default" @click="submit">提交</button>
</template>
<script>
import imgUpload from '@/components/my-components/imgUpload.vue';
export default {
components: {
imgUpload
},
data() {
return {
imgArray:[],
head:[{token:"zx6c54asdq89w7eqw6e46ad4"},{sign:'s6d5a4dqwe7q9w87a6'}], //示范格式 JSON 使用方式header="head"
config:{
delIcon: '', //删除图片icon
resultTip: true, //结果提示
resultType:'1', //结果展示类型
loadIcon: '', //加载时的图标
loadText: '' //加载时的文字
}
}
},
# methods: {
submit(){
//开始上传图片
this.$refs.imgUpload.upload(res=>{
if(res.code==0){
//0为正常返回将回调的线上图片数组 赋值给需要提交的表单里
//res.urlArray 线上路径图片数组对象
//TODO
}else{
//用户没有上传图片的返回 code码为400
}
//可以在下面继续写提交代码
});
},
//直接上传的方法
resultUrl(e){
console.log(e);
//成功默认为0
if(e.code==0){
//e在单图(single=true)情况下 e.url 可得到。多图情况下e是一个数组
this.imgArr.push(...e.new);
}
},
delImg(e){
this.imgArr.splice(e,1) //为删除图片数组的下标
}
}
</script>
```
-------------------------------------
###[彩蛋提示]
可以在组件里修改组件小提示的颜色哦!只需要修改成功失败警告的颜色即可。
```
tipObj: {
prompt: '',
typeColor: '#009100',
success: '#009100', //成功-#009100; 可自定义修改
warning: '#d3d300', // 警告 -#d3d300; 可自定义修改
error: '#FF0000' // 失败--#FF0000; 可自定义修改
},
```

View File

@ -0,0 +1,56 @@
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" >
<!--
2013-9-30: Created.
-->
<svg>
<metadata>
Created by iconfont
</metadata>
<defs>
<font id="iconfont" horiz-adv-x="1024" >
<font-face
font-family="iconfont"
font-weight="500"
font-stretch="normal"
units-per-em="1024"
ascent="896"
descent="-128"
/>
<missing-glyph />
<glyph glyph-name="shanchu2" unicode="&#59269;" d="M571.733333 384l226.133334 226.133333c17.066667 17.066667 17.066667 42.666667 0 59.733334s-42.666667 17.066667-59.733334 0L512 443.733333 285.866667 669.866667c-17.066667 17.066667-42.666667 17.066667-59.733334 0s-17.066667-42.666667 0-59.733334l226.133334-226.133333-226.133334-226.133333c-17.066667-17.066667-17.066667-42.666667 0-59.733334 8.533333-8.533333 17.066667-12.8 29.866667-12.8s21.333333 4.266667 29.866667 12.8l226.133333 226.133334 226.133333-226.133334c8.533333-8.533333 21.333333-12.8 29.866667-12.8s21.333333 4.266667 29.866667 12.8c17.066667 17.066667 17.066667 42.666667 0 59.733334L571.733333 384z" horiz-adv-x="1024" />
<glyph glyph-name="jiazai2" unicode="&#59169;" d="M227.9 411.1c11.6-11.6 17.3-25.5 17.3-41.9s-5.8-30.2-17.3-41.9S202.4 310 186 310s-30.2 5.8-41.9 17.3-17.3 25.5-17.3 41.9 5.8 30.2 17.3 41.9c11.6 11.6 25.5 17.3 41.9 17.3s30.3-5.8 41.9-17.3zM333.7 652c14.5-14.5 21.8-32 21.8-52.3s-7.3-37.7-21.8-52.3c-14.5-14.6-32-21.9-52.3-21.9-20.3 0-37.7 7.2-52.3 21.8s-21.8 32-21.8 52.3c0 20.3 7.2 37.7 21.8 52.3s32 21.8 52.3 21.8c20.3 0 37.7-7.2 52.3-21.7z m-10.4-471.6c11.6-11.6 17.3-25.5 17.3-41.9s-5.8-30.2-17.3-41.9c-11.6-11.6-25.5-17.3-41.9-17.3-16.1 0-29.9 5.9-41.7 17.6-11.7 11.7-17.6 25.6-17.6 41.7 0 16.4 5.8 30.2 17.3 41.9 11.6 11.6 25.5 17.3 41.9 17.3s30.4-5.8 42-17.4zM575 758.1c17.2-17.3 25.9-38.2 25.9-63s-8.7-45.6-25.9-63c-17.3-17.3-38.2-25.9-63-25.9s-45.6 8.7-63 25.9c-17.3 17.2-25.9 38.2-25.9 63s8.7 45.6 25.9 63c17.2 17.2 38.2 25.9 63 25.9 24.7 0 45.6-8.7 63-25.9z m-21.2-673c11.6-11.6 17.3-25.5 17.3-41.9s-5.8-30.2-17.3-41.9c-11.6-11.6-25.5-17.3-41.9-17.3s-30.2 5.8-41.9 17.3c-11.7 11.6-17.3 25.5-17.3 41.9s5.8 30.2 17.3 41.9c11.6 11.6 25.5 17.3 41.9 17.3s30.3-5.8 41.9-17.3z m292.4 514.5c0-28.7-10.2-53.2-30.6-73.4-20.3-20.2-44.8-30.2-73.1-30.2-28.7 0-53.2 10.1-73.4 30.2-20.2 20.2-30.2 44.7-30.2 73.4 0 28.4 10.1 52.8 30.2 73.1 20.2 20.3 44.7 30.6 73.4 30.6 28.4 0 52.8-10.2 73.1-30.6 20.4-20.2 30.6-44.6 30.6-73.1z m-44.5-461.1c0-16.1-5.9-29.9-17.6-41.7-11.7-11.7-25.6-17.6-41.7-17.6-16.4 0-30.2 5.8-41.9 17.3-11.6 11.6-17.3 25.5-17.3 41.9s5.8 30.2 17.3 41.9c11.6 11.6 25.5 17.3 41.9 17.3s30.2-5.8 41.9-17.3c11.6-11.5 17.4-25.4 17.4-41.8z m78.1 272.6c11.6-11.6 17.3-25.5 17.3-41.9s-5.8-30.2-17.3-41.9S854.3 310 838 310s-30.2 5.8-41.9 17.3c-11.6 11.6-17.3 25.5-17.3 41.9s5.8 30.2 17.3 41.9c11.6 11.6 25.5 17.3 41.9 17.3 16.2 0 30.3-5.8 41.8-17.3z" horiz-adv-x="1024" />
<glyph glyph-name="icontianjiatupian" unicode="&#58901;" d="M986.4068 632.333902l-75.878155 0 0-75.877131c0-20.937868-16.997116-37.936007-37.934984-37.936007-20.945031 0-37.942147 16.999163-37.942147 37.936007l0 75.877131L758.774383 632.333902c-20.942985 0-37.936007 16.999163-37.936007 37.942147 0 20.942985 16.993023 37.934984 37.936007 37.934984l75.877131 0 0 75.878155c0 20.942985 16.997116 37.940101 37.942147 37.940101 20.937868 0 37.934984-16.997116 37.934984-37.940101l0-75.878155 75.878155 0c20.942985 0 37.940101-16.991999 37.940101-37.934984C1024.346901 649.332041 1007.349785 632.333902 986.4068 632.333902L986.4068 632.333902zM758.774383 499.552759c0-31.41243-25.491581-56.909128-56.909128-56.909128-31.413454 0-56.904011 25.497721-56.904011 56.909128s25.490557 56.904011 56.904011 56.904011C733.281779 556.45677 758.774383 530.964166 758.774383 499.552759L758.774383 499.552759zM607.019097 632.333902 75.877131 632.333902l0-528.748453c0.076748 0.265036 83.047438 372.255259 225.244021 372.255259 93.66731 0 188.932-287.689235 248.310366-374.648772 0 0 46.549176 188.480722 126.866433 189.69641 79.44233 1.177825 120.417557-187.301873 120.417557-187.301873l37.936007 0L834.651514 328.824353c0 20.942985 16.997116 37.942147 37.942147 37.942147 20.937868 0 37.934984-16.999163 37.934984-37.942147l0-303.509549c0-41.919738-33.989115-75.877131-75.877131-75.877131L75.877131-50.562327c-41.919738 0-75.877131 33.957393-75.877131 75.877131L0 632.333902c0 41.924855 33.957393 75.877131 75.877131 75.877131l531.141966 0c20.942985 0 37.942147-16.991999 37.942147-37.934984C644.961244 649.332041 627.962082 632.333902 607.019097 632.333902L607.019097 632.333902zM607.019097 632.333902" horiz-adv-x="1040" />
<glyph glyph-name="shanchu" unicode="&#59120;" d="M590.514383 407.959051 952.888054 44.874737C981.253371 16.453832 981.11016-29.804176 952.546629-58.423734 923.783934-87.242895 877.825294-87.196523 849.450322-58.76589L487.076651 304.318424 124.70298-58.76589C96.337663-87.186795 50.170204-87.043365 21.606672-58.423734-7.156023-29.604646-7.109798 16.444104 21.265175 44.874737L383.638845 407.959051 21.265175 771.043365C-7.100143 799.46427-6.956932 845.722278 21.606672 874.341836 50.369368 903.160997 96.328008 903.114625 124.70298 874.683992L487.076651 511.599678 849.450322 874.683992C877.815566 903.104897 923.983025 902.961467 952.546629 874.341836 981.309325 845.522748 981.263026 799.473998 952.888054 771.043365L590.514383 407.959051 590.514383 407.959051Z" horiz-adv-x="1024" />
<glyph glyph-name="chenggong" unicode="&#58982;" d="M1001.305115 620.125859 431.461709 50.281429c-28.221762-28.221762-73.977875-28.221762-102.20066 0L22.661116 356.883409c-28.222785 28.221762-28.222785 73.979922 0 102.20066 28.221762 28.221762 73.977875 28.221762 102.20066 0l255.500115-255.502162 518.743588 518.743588c28.221762 28.221762 73.977875 28.221762 102.199637 0C1029.5279 694.10578 1029.5279 648.34762 1001.305115 620.125859z" horiz-adv-x="1024" />
<glyph glyph-name="caozuochenggong" unicode="&#59384;" d="M376.87958 282.097122 158.344355 461.137845 61.411675 379.974313l377.931538-401.503397C504.790808 152.298917 710.793602 492.277052 962.587302 733.914438l-23.063275 55.614645C665.199171 614.05049 466.434222 393.327436 376.87958 282.097122z" horiz-adv-x="1024" />
<glyph glyph-name="shanchu1" unicode="&#59007;" d="M512 384m-512 0a512 512 0 1 1 1024 0 512 512 0 1 1-1024 0ZM729.6 512H294.4c-7.68 0-12.8 5.12-12.8 12.8v25.6c0 7.68 5.12 12.8 12.8 12.8h115.2v25.6c0 14.08 11.52 25.6 25.6 25.6h153.6c14.08 0 25.6-11.52 25.6-25.6v-25.6h115.2c7.68 0 12.8-5.12 12.8-12.8v-25.6c0-7.68-5.12-12.8-12.8-12.8z m-371.2-38.4h307.2c28.16 0 51.2-23.04 51.2-51.2v-217.6c0-28.16-23.04-51.2-51.2-51.2H358.4c-28.16 0-51.2 23.04-51.2 51.2V422.4c0 28.16 23.04 51.2 51.2 51.2z m192-243.2c0-7.68 5.12-12.8 12.8-12.8s12.8 5.12 12.8 12.8V358.4c0 7.68-5.12 12.8-12.8 12.8s-12.8-5.12-12.8-12.8v-128z m-102.4 0c0-7.68 5.12-12.8 12.8-12.8s12.8 5.12 12.8 12.8V358.4c0 7.68-5.12 12.8-12.8 12.8s-12.8-5.12-12.8-12.8v-128z" horiz-adv-x="1024" />
<glyph glyph-name="jia" unicode="&#58886;" d="M512.17594-127.648121c-29.52585 0-58.347943 6.397801-58.347943 37.395145V331.969885H37.459123c-23.76783 0-37.459123 22.392303-37.459123 51.182406 0 26.614851 10.076536 51.790197 35.187904 51.790198h425.005904V852.111087c0 28.054356 20.888819 43.888913 51.854176 43.888913 28.790103 0 51.182406-12.795602 51.182406-37.395145v-416.49683h430.156133c28.790103 0 30.261598-34.516135 30.261598-58.283965s-7.933273-51.182406-36.723376-51.182406H563.326357v-422.926619c0.735747-24.40761-21.592578-37.363156-51.150417-37.363156z" horiz-adv-x="1024" />
<glyph glyph-name="jiazai" unicode="&#58902;" d="M512.75 512.13c-11.24 0-20.55 8.74-21.25 19.96l-16.26 260.04c-1.35 21.63 15.83 39.92 37.5 39.92 21.68 0 38.86-18.29 37.5-39.92l-16.26-260.04c-0.69-11.22-9.99-19.96-21.23-19.96zM512.75 256.01c11.24 0 20.55-8.74 21.25-19.96l16.26-260.04c1.35-21.63-15.83-39.92-37.5-39.92-21.68 0-38.86 18.29-37.5 39.92l16.26 260.04c0.68 11.22 9.98 19.96 21.23 19.96zM640.19 382.78c0 11.24 8.74 20.55 19.96 21.25l260.04 16.26c21.63 1.35 39.92-15.83 39.92-37.5 0-21.68-18.29-38.86-39.92-37.5l-260.04 16.26c-11.22 0.68-19.96 9.98-19.96 21.23zM605.79 290.89c7.95 7.95 20.71 8.35 29.14 0.91L830.3 119.42c16.25-14.34 17.04-39.42 1.71-54.75-15.33-15.33-40.41-14.54-54.75 1.71L604.88 261.75c-7.44 8.43-7.04 21.19 0.91 29.14zM601.79 474.33c-7.95 7.95-8.35 20.71-0.91 29.14l172.38 195.37c14.34 16.25 39.42 17.04 54.75 1.71 15.33-15.33 14.54-40.41-1.71-54.75L630.93 473.42c-8.43-7.43-21.19-7.03-29.14 0.91zM383.26 382.44c0-11.24-8.74-20.55-19.96-21.25l-260.04-16.26c-21.63-1.35-39.92 15.83-39.92 37.5 0 21.68 18.29 38.86 39.92 37.5l260.04-16.26c11.21-0.68 19.96-9.98 19.96-21.23zM417.66 474.33c-7.95-7.95-20.71-8.35-29.14-0.91L193.15 645.81c-16.25 14.34-17.04 39.42-1.71 54.75 15.33 15.33 40.41 14.54 54.75-1.71l172.38-195.37c7.44-8.44 7.04-21.2-0.91-29.15zM421.66 290.89c7.95-7.95 8.35-20.71 0.91-29.14L250.19 66.38c-14.34-16.25-39.42-17.04-54.75-1.71-15.33 15.33-14.54 40.41 1.71 54.75L392.52 291.8c8.43 7.43 21.19 7.04 29.14-0.91z" horiz-adv-x="1024" />
<glyph glyph-name="jiazai1" unicode="&#59040;" d="M512.1 831.8c-35.4 0-64-28.7-64-64v-128c0-35.4 28.7-64 64-64 35.4 0 64 28.7 64 64v128c0 35.3-28.6 64-64 64zM320.4 567.7l-110.8 64c-30.6 17.7-69.8 7.2-87.4-23.4-17.7-30.6-7.2-69.8 23.4-87.4l110.8-64c30.6-17.7 69.8-7.2 87.4 23.4 17.7 30.6 7.2 69.8-23.4 87.4zM342.4 286.8c-17.7 30.6-56.8 41.1-87.4 23.4l-110.8-64c-30.6-17.7-41.1-56.8-23.4-87.4 17.7-30.6 56.8-41.1 87.4-23.4l110.8 64c30.6 17.7 41.1 56.8 23.4 87.4zM509.2 188.9c-35.4 0-64-28.7-64-64v-128c0-35.4 28.7-64 64-64 35.4 0 64 28.7 64 64v128c0 35.3-28.6 64-64 64zM875.8 243.8l-110.8 64c-30.6 17.7-69.8 7.2-87.4-23.4-17.7-30.6-7.2-69.8 23.4-87.4l110.8-64c30.6-17.7 69.8-7.2 87.4 23.4 17.7 30.6 7.2 69.7-23.4 87.4zM678.9 477.8c17.7-30.6 56.8-41.1 87.4-23.4l110.8 64c30.6 17.7 41.1 56.8 23.4 87.4-17.7 30.6-56.8 41.1-87.4 23.4l-110.8-64c-30.6-17.6-41.1-56.8-23.4-87.4z" horiz-adv-x="1024" />
</font>
</defs></svg>

After

Width:  |  Height:  |  Size: 9.8 KiB

View File

@ -0,0 +1,950 @@
<!--
项目图片上传插件
时间2020.9.24
备注接口的返回值是否符合插件所写的code=0如果不是请复制 upload asyncUpload 查找该方法 在注释的地方修改
-->
<template>
<view class="w-100 imgupload">
<view class="w-100 flex_wrap">
<view
:class="single ? 'single-css' : 'imgs-view'"
v-for="(v, i) in imgArray"
:key="i"
>
<image @click="preview(v, i)" :src="v.url"></image>
<view
v-if="!disabled"
:class="conf.style ? 'del-btn-style-' + conf.style : 'del-btn'"
@click="delImg(i)"
>
<image v-if="conf.delIcon" :src="conf.delIcon"></image>
<text v-if="!conf.delIcon && conf.style == 1" class="icon_upload">
&#xe785;
</text>
<text v-if="!conf.delIcon && conf.style == 2" class="icon_upload">
&#xe785;
</text>
</view>
<view
class="uploading flex_xy_center"
:class="single ? 'single-css' : 'imgs-view'"
v-if="!v.upload && loading && startUpload"
>
<view>
<image v-if="conf.loadIcon" :src="conf.loadIcon"></image>
<text v-if="!conf.loadIcon && conf.style == 1" class="icon_upload">
&#xe6a0;
</text>
<text v-if="!conf.loadIcon && conf.style == 2" class="icon_upload">
&#xe616;
</text>
<view class="upload-txt">{{ conf.loadText || "上传中..." }}</view>
</view>
</view>
<view class="result" v-if="!conf.style && conf.resultTip && v.upload">
<label class="success" v-if="v.result === true">上传成功</label>
<label class="error" v-if="v.result === false">上传失败</label>
</view>
<view
v-if="conf.style == 1 && conf.resultTip && v.upload && !disabled"
class="result-style"
:class="'result-' + (v.result ? 1 : 2)"
>
<view v-if="v.result == true">
<text class="icon_upload">&#xe666;</text>
上传成功
</view>
<view v-if="v.result == false">
<text class="icon_upload">&#xe785;</text>
上传失败
</view>
</view>
</view>
<view
v-if="imgArray.length < imgCount && !disabled"
:style="conf.borderStyle"
class="flex_xy_center"
:class="single ? 'single-add' : 'upload-img-view'"
@click="upPhoto"
>
<text v-if="conf.addStyle == '1'" class="icon_upload">&#xe615;</text>
<text v-if="conf.addStyle == '2'" class="icon_upload add">
&#xe606;
</text>
</view>
</view>
<view v-if="!closeTip && !tipObj.prompt" class="imgupload__tip">
* 最多上传{{ imgCount }}张图片(
<label>{{ imgArray.length }}</label>
/{{ imgCount }})
</view>
<view
class="imgupload__tip"
:style="{ color: tipObj.typeColor }"
v-show="tipObj.prompt || tipObj.must"
>
{{ tipObj.prompt }}
</view>
</view>
</template>
<script>
export default {
name: "imgUpload",
props: {
imgArr: {
//
type: [Array],
},
uploadImgCount: {
//
type: String,
default: "3",
},
imgCount: {
//
type: String,
default: "3",
},
imgSize: {
// M
type: Number,
default: 2,
},
disabled: {
//
type: Boolean,
default: false,
},
formData: {
type: Object,
default: function () {
return {};
},
},
imgType: {
//
type: [Array],
default: function () {
return ["jpeg", "png", "jpg"];
},
},
single: {
//
type: Boolean,
default: false,
},
closeTip: {
type: Boolean,
default: false,
},
loading: {
type: Boolean,
default: true,
},
url: {
//Url
type: String,
},
async: {
type: Boolean,
default: false,
},
header: {
type: Array,
default: function () {
return [];
},
},
previewMany: {
//
type: Boolean,
default: false,
},
pressImg: {
// H5api
type: Number,
default: -1,
},
config: {
type: Object,
default: function () {
return {};
},
},
isAdd: {
typeof: Object,
return: true,
},
},
data() {
return {
sysInfo: {},
imgArray: [],
canUpCount: "",
startUpload: false,
tipObj: {
prompt: "",
typeColor: "#009100",
must: false, //
success: "#009100", //-#009100;
// warning: '#bb9300', // -#bb9300;
error: "#FF0000", // --#FF0000;
warning: "#FF0000",
},
conf: {
delIcon: "", //icon
resultTip: true, //
style: "1", //
loadIcon: "", //
loadText: "", //
borderStyle: "border:2px dotted #dadada",
addStyle: "2", // 1 2
},
headers: {},
curPlatform: "",
currIndex: null,
};
},
created() {
this.getSysInfo();
this.imgArray = this.imgArr || [];
this.changeImgArr(true);
this.canUpCount = this.single ? 1 : Number(this.uploadImgCount);
if (this.url) {
this.tipObj.prompt = "";
} else {
this.tipObj.prompt = "你没有传入上传url,请检查传入参数";
this.tipObj.typeColor = this.tipObj.error;
}
this.changeHeader(this.header);
//
this.conf = Object.assign(this.conf, this.config);
console.log(this.isAdd);
},
watch: {
imgArr(n, o) {
this.imgArray = n || [];
this.changeImgArr(true);
},
imgCount(n, o) {
this.uploadImgCount = n;
this.canUpCount = this.single ? 1 : Number(this.uploadImgCount);
},
url(n, o) {
if (n) {
this.tipObj.prompt = "";
} else {
this.tipObj.prompt = "你没有传入上传url,请检查传入参数";
this.tipObj.typeColor = this.tipObj.error;
}
},
header(n, o) {
this.changeHeader(n);
},
config(n, o) {
this.conf = Object.assign(this.conf, this.config);
},
},
methods: {
upPhoto() {
let that = this;
if (!that.url) {
that.tipObj.prompt = "你没有传入上传url,请检查!";
that.tipObj.typeColor = that.tipObj.error;
return;
}
if (
Number(that.imgCount - that.imgArray.length) <
Number(that.uploadImgCount)
) {
that.canUpCount = Number(that.imgCount - that.imgArray.length);
}
if (!that.tipObj.must) {
that.tipObj.prompt = "";
}
that.tipObj.must = false;
uni.showActionSheet({
itemList: ["拍照上传", "从相册中选择"],
success: function (res) {
if (res.tapIndex == 0) {
uni.chooseImage({
count: Number(that.canUpCount),
sizeType: ["original", "compressed"], //
sourceType: ["camera"], //
success: function (res) {
if (res) {
if (res.tempFiles) {
for (let item of res.tempFiles) {
if (item.size > that.imgSize * 1024 * 1024) {
uni.showToast({
title: `图片不能大于${that.imgSize}M`,
icon: "none",
});
return false;
}
if (item.type) {
let r = that.imgType.some((v) => {
let type = item.type.split("/");
if (type.length) return v === type[1];
});
if (!r) {
uni.showToast({
title: `只允许上传${that.imgType}的类型`,
icon: "none",
});
return false;
}
}
}
}
that.currIndex = that.imgArray.length;
that.imgArray = [...that.imgArray, ...res.tempFilePaths];
that.changeImgArr(false);
if (that.pressImg >= 0) {
//
if (that.checkPlatform()) {
// H5
that.pressImages();
}
} else {
//
that.hasAysnc();
}
}
},
});
} else if (res.tapIndex == 1) {
uni.chooseImage({
count: Number(that.canUpCount),
sizeType: ["original", "compressed"], //
sourceType: ["album"], //
success: function (res) {
if (res) {
if (res.tempFiles) {
for (let item of res.tempFiles) {
if (item.size > that.imgSize * 1024 * 1024) {
uni.showToast({
title: `图片不能大于${that.imgSize}M`,
icon: "none",
});
return false;
}
if (item.type) {
let r = that.imgType.some((v) => {
let type = item.type.split("/");
if (type.length) return v === type[1];
});
if (!r) {
uni.showToast({
title: `只允许上传${that.imgType}的类型`,
icon: "none",
});
return false;
}
}
}
}
that.currIndex = that.imgArray.length;
that.imgArray = [...that.imgArray, ...res.tempFilePaths];
that.changeImgArr(false);
if (that.pressImg >= 0) {
//
if (that.checkPlatform()) {
// H5
that.pressImages();
}
} else {
//
that.hasAysnc();
}
}
},
});
}
},
fail: function (res) {
console.log(res.errMsg);
},
});
},
preview(obj, index) {
if (this.previewMany) {
let urls = [];
urls.push(obj.url);
this.imgArray.map((item) => {
if (obj.id != item.id) {
urls.push(item.url);
}
});
uni.previewImage({
urls: urls,
});
} else {
// ()
uni.previewImage({
urls: [obj.url],
});
}
},
changeImgArr(type) {
for (let index in this.imgArray) {
let item = this.imgArray[index];
if (!item.upload) {
if (item.upload === false) {
this.imgArray[index].url = item.url;
} else {
this.imgArray[index] = {
id: index,
upload: type,
url: item,
result: type,
};
}
}
}
},
pressImages() {
const _this = this;
let success = 0;
let completeNum = 0;
for (let item of _this.imgArray) {
uni.compressImage({
src: item.url,
quality: _this.pressImg,
success: (res) => {
++success;
item.pressUrl = res.tempFilePath;
},
error: (res) => {
console.log(res);
},
complete: (res) => {
++completeNum;
//
if (completeNum === _this.imgArray.length) {
console.log(success);
if (success >= _this.imgArray.length) {
_this.tipObj.prompt = "全部压缩成功!";
_this.tipObj.typeColor = _this.tipObj.success;
} else {
let errorNum = _this.imgArray.length - success;
_this.tipObj.prompt = `${errorNum}个文件压缩失败`;
_this.tipObj.typeColor = _this.tipObj.warning;
}
console.log("res", _this.imgArray);
if (_this.async) {
//
_this.asyncUpload();
}
}
},
});
}
},
asyncUpload() {
const _this = this;
if (_this.imgArray.length) {
let length = _this.imgArray.length;
_this.startUpload = true;
_this.tipObj.prompt = "";
let result = [];
//_this.currIndex;
for (let i = 0; i < length; i++) {
let item = _this.imgArray[i];
let subUrl = _this.pressImg >= 0 ? item.pressUrl : item.url;
if (!item.upload) {
_this.asyncUploadMethod(subUrl, i, (res) => {
if (res) {
result.push(res);
if (_this.single) {
_this.$emit("result", _this.imgArray[0]);
} else {
console.log("resultlist", _this.imgArray);
_this.$emit("result", {
all: _this.imgArray,
new: result,
});
}
}
});
}
}
}
},
asyncUploadMethod(url, i, callback) {
const _this = this;
uni.uploadFile({
url: _this.url,
filePath: url,
name: "upfile",
header: _this.headers,
formData: _this.formData,
success: (uploadFileRes) => {
if (uploadFileRes.statusCode == 200) {
let res = JSON.parse(uploadFileRes.data);
/*注意 如果返回的结果字段不一样,请在这里做修改[res.code]*/
if (res.code === 0 || res.code === "0") {
//
_this.imgArray[i].result = true;
res.code = 0;
_this.imgArray[i].url = res.data.url; //
callback(res.data.url);
} else {
_this.imgArray[i].result = false;
_this.tipObj.prompt = "上传失败,请检查!";
_this.tipObj.typeColor = _this.tipObj.error;
}
} else {
_this.imgArray[i].result = false;
}
},
fail: (e) => {
_this.imgArray[i].result = false;
_this.tipObj.prompt = "上传失败,请检查!";
_this.tipObj.typeColor = _this.tipObj.error;
console.log(e);
},
complete: () => {
_this.imgArray[i].upload = true;
_this.startUpload = false;
_this.$forceUpdate();
},
});
},
delImg(i) {
const _this = this;
uni.showModal({
title: "提示",
content: "是否删除这张照片?",
success: function (res) {
if (res.confirm) {
_this.imgArray.splice(i, 1);
if (_this.async) {
_this.$emit("delImg", i);
}
} else if (res.cancel) {
}
},
});
},
upload(callback) {
const _this = this;
if (!_this.async) {
_this.tipObj.prompt = "";
if (_this.imgArray.length) {
this.startUpload = true;
let successNum = 0;
let urlArr = [];
for (let item of _this.imgArray) {
_this.uploadImg(item, (res) => {
/*注意 如果返回的结果字段不一样,请在这里做修改[res.code]*/
if (res.code == 0) {
successNum++;
urlArr.push(res.url); /*需要线上图片地址[res.fileVo]*/
item.result = true;
} else {
urlArr.push(res);
item.result = false;
}
item.upload = true;
_this.$forceUpdate();
_this.tipObj.prompt =
"正在上传...(成功" + successNum + "张/" + urlArr.length + "张)";
_this.tipObj.typeColor = _this.tipObj.success;
if (urlArr.length == _this.imgArray.length) {
_this.tipObj.prompt = "已全部上传完成!";
_this.tipObj.typeColor = _this.tipObj.success;
if (successNum > 0) {
_this.startUpload = false;
callback(_this.result(urlArr, successNum));
} else {
_this.startUpload = false;
callback(urlArr); //
}
}
});
}
} else {
_this.tipObj.prompt = "请先选择图片后上传!";
_this.tipObj.typeColor = _this.tipObj.warning;
}
} else {
_this.tipObj.prompt = "在异步模式下无法调用upload方法。";
_this.tipObj.typeColor = _this.tipObj.warning;
}
},
result(urlArr, successNum) {
let result = {
result: "success",
code: 0,
urlArray: urlArr,
success: successNum,
};
return result;
},
uploadImg(item, callback) {
const _this = this;
let subUrl = _this.pressImg >= 0 ? item.pressUrl : item.url;
uni.uploadFile({
url: _this.url,
filePath: subUrl,
formData: _this.formData,
header: _this.headers,
name: "upfile",
success: (uploadFileRes) => {
if (uploadFileRes) {
let res = JSON.parse(uploadFileRes.data);
res.resCode = 0;
callback(res);
}
},
fail: (e) => {
callback({
resCode: 500,
msg: "图片上传失败",
localUrl: item,
reason: e,
});
},
});
},
changeHeader(header) {
const _this = this;
if (Array.isArray(header)) {
for (let item of header) {
for (let key in item) {
_this.headers[key] = item[key];
}
}
} else {
_this.tipObj.prompt = "请使用数组格式的Header传参";
_this.tipObj.typeColor = _this.tipObj.error;
}
},
//
hasAysnc() {
const that = this;
if (that.async) {
let startIndex = that.imgArray.length;
//
that.asyncUpload(startIndex);
} else {
that.$emit("result", {
code: 500,
msg: "同步模式下,我不会被调用哦~",
});
}
},
checkPlatform() {
const that = this;
let canUse = true;
//#ifdef H5
that.tipObj.prompt = "该环境不支持图片压缩,图片压缩功能不会生效。";
that.tipObj.must = true;
that.tipObj.typeColor = that.tipObj.warning;
canUse = false;
that.hasAysnc();
//#endif
return canUse;
},
getSysInfo() {
const that = this;
try {
const res = uni.getSystemInfoSync();
that.sysInfo = {
screenWidth: res.screenWidth,
screenHeight: res.screenHeight,
};
} catch (e) {
// error
}
},
},
};
</script>
<style scoped>
@font-face {
font-family: "icon_upload";
/* project id 2170343 */
src: url("./font/font_2170343_nij8dm8i18.eot");
src: url("./font/font_2170343_nij8dm8i18.eot?#iefix")
format("embedded-opentype"),
url("./font/font_2170343_nij8dm8i18.woff2") format("woff2"),
url("./font/font_2170343_nij8dm8i18.woff") format("woff"),
url("./font/font_2170343_nij8dm8i18.ttf") format("truetype"),
url("./font/font_2170343_nij8dm8i18.svg") format("svg");
}
.icon_upload {
font-family: "icon_upload" !important;
font-size: 30rpx;
font-style: normal;
-webkit-font-smoothing: antialiased;
-webkit-text-stroke-width: 0.2px;
-moz-osx-font-smoothing: grayscale;
}
.w-100 {
width: 100%;
}
.flex {
/* 转为弹性盒模型*/
display: flex;
}
.flex_bet {
/* 两端左右*/
display: flex;
justify-content: space-between;
}
.flex_wrap {
/* 转为弹性盒模型并自动换行*/
display: flex;
flex-wrap: wrap;
}
.flex_xy_center {
display: flex;
justify-content: center;
align-items: center;
}
.imgupload image {
height: 100%;
width: 100%;
}
.upload-img-view {
height: 136rpx;
width: 136rpx;
border-radius: 10rpx;
border: 4rpx dotted #f1f1f1;
/* background-color: #F1F1F1; */
}
.single-add {
width: 100%;
height: inherit;
min-height: 200rpx;
border-radius: 10rpx;
border: 4rpx dotted #f1f1f1;
}
.upload-img-view > text,
.single-add > text {
font-size: 70rpx;
color: #949494;
}
.upload-img-view .add,
.single-add .add {
font-size: 55rpx;
}
.upload-txt {
font-size: 24rpx;
color: #ffffff;
}
.imgs-view {
height: 136rpx;
width: 136rpx;
border-radius: 10rpx;
margin-right: 1.8%;
margin-bottom: 16rpx;
border: 1rpx solid #f1f1f1;
box-sizing: border-box;
position: relative;
}
.single-css {
width: 100%;
height: inherit;
min-height: 200rpx;
border-radius: 10rpx;
border: 1rpx solid #f1f1f1;
box-sizing: border-box;
position: relative;
}
.result {
position: absolute;
bottom: 0;
width: 100%;
height: 45rpx;
font-size: 26rpx;
left: 0;
background-color: rgba(0, 0, 0, 0.6);
text-align: center;
line-height: 45rpx;
border-bottom-left-radius: 10rpx;
border-bottom-right-radius: 10rpx;
}
.result > .success {
color: #00b900;
}
.result > .error {
color: #b52e25;
}
.uploading {
position: absolute;
background-color: rgba(0, 0, 0, 0.5);
left: 0;
top: 0;
width: 100%;
height: 100%;
text-align: center;
line-height: 100%;
z-index: 988;
}
.uploading image {
width: 60rpx;
height: 60rpx;
z-index: 989;
animation: rotation 1s linear infinite;
-moz-animation: rotation 1s linear infinite;
-webkit-animation: rotation 1s linear infinite;
-o-animation: rotation 1s linear infinite;
}
.uploading text {
display: inline-block;
font-size: 50rpx;
color: #fffdef;
z-index: 989;
animation: rotation 1s linear infinite;
-moz-animation: rotation 1s linear infinite;
-webkit-animation: rotation 1s linear infinite;
-o-animation: rotation 1s linear infinite;
}
@keyframes rotation {
from {
-webkit-transform: rotate(0deg);
transform: rotate(0deg);
-moz-transform: rotate(0deg);
-o-transform: rotate(0deg);
}
to {
-webkit-transform: rotate(360deg);
transform: rotate(360deg);
-moz-transform: rotate(360deg);
-o-transform: rotate(360deg);
}
}
.imgs-view > image,
.single-css > image {
width: 100%;
height: 100%;
border-radius: 10rpx;
}
.imgupload__tip {
font-size: 24rpx;
color: #ff0000;
margin: 10rpx auto;
}
.imgupload__tip > label {
color: #009100;
}
.del-btn {
position: absolute;
top: 0;
right: 0;
width: 32rpx;
height: 32rpx;
z-index: 988;
}
.del-btn > image {
width: 100%;
height: 100%;
display: flex;
}
.del-btn-style-2 {
position: absolute;
top: 0;
right: 0;
width: 32rpx;
height: 32rpx;
z-index: 988;
}
.del-btn-style-1 {
position: absolute;
top: 0;
right: 0;
width: 44rpx;
height: 44rpx;
z-index: 988;
background: rgba(0, 0, 0, 0.3);
color: #ececec;
border-bottom-left-radius: 30rpx;
display: flex;
justify-content: center;
align-items: center;
font-size: 24rpx;
}
.result-style {
position: absolute;
bottom: 0;
left: 0;
width: 100%;
height: 44rpx;
border-top-right-radius: 50rpx;
display: flex;
justify-content: center;
align-items: center;
transition: all 0.5s ease;
transform: translateX(-100%);
opacity: 0.4;
}
.result-1 {
background: rgba(7, 169, 19, 0.75);
color: white;
transform: translateX(0%);
font-size: 24rpx;
opacity: 1;
}
.result-2 {
background: rgba(239, 0, 5, 0.7);
color: #dadada;
font-size: 24rpx;
transform: translateX(0%);
opacity: 1;
}
</style>

View File

@ -32,9 +32,9 @@
class="uni-navbar-btn-text" class="uni-navbar-btn-text"
v-if="leftText.length" v-if="leftText.length"
> >
<text :style="{ color: themeColor, fontSize: '12px' }">{{ <text :style="{ color: themeColor, fontSize: '12px' }">
leftText {{ leftText }}
}}</text> </text>
</view> </view>
</slot> </slot>
</view> </view>
@ -47,8 +47,9 @@
<text <text
class="uni-nav-bar-text uni-ellipsis-1" class="uni-nav-bar-text uni-ellipsis-1"
:style="{ color: themeColor }" :style="{ color: themeColor }"
>{{ title }}</text
> >
{{ title }}
</text>
</view> </view>
</slot> </slot>
</view> </view>
@ -68,8 +69,9 @@
<text <text
class="uni-nav-bar-right-text" class="uni-nav-bar-right-text"
:style="{ color: themeColor }" :style="{ color: themeColor }"
>{{ rightText }}</text
> >
{{ rightText }}
</text>
</view> </view>
</slot> </slot>
</view> </view>
@ -247,6 +249,7 @@ $nav-height: 44px;
/* #ifndef APP-PLUS */ /* #ifndef APP-PLUS */
font-size: 14px; font-size: 14px;
/* #endif */ /* #endif */
font-weight: bold;
} }
.uni-nav-bar-right-text { .uni-nav-bar-right-text {

View File

@ -70,8 +70,6 @@ export default {
break; break;
} }
console.log("marketId", marketId);
console.log("phoneInfo.brand", phoneInfo.brand);
let params = { let params = {
marketId: 100, marketId: 100,

View File

@ -4,14 +4,11 @@ import store from "./store";
import uView from "@/uni_modules/uview-ui"; import uView from "@/uni_modules/uview-ui";
import "./uni.promisify.adaptor"; import "./uni.promisify.adaptor";
import tui from "./utils/httpRequest"; import tui from "./utils/httpRequest";
import Socket from "./utils/socket.js";
Vue.use(uView); Vue.use(uView);
Vue.config.productionTip = false; Vue.config.productionTip = false;
// Vue.prototype.$utils = Utils
Vue.prototype.tui = tui; Vue.prototype.tui = tui;
Vue.prototype.$Socket = Socket;
App.mpType = "app"; App.mpType = "app";
const app = new Vue({ const app = new Vue({

View File

@ -4,7 +4,7 @@
"package" : "com.xiaofa.shopAdmin", "package" : "com.xiaofa.shopAdmin",
"description" : "", "description" : "",
"versionName" : "1.0.0", "versionName" : "1.0.0",
"versionCode" : 102, "versionCode" : 100,
"transformPx" : false, "transformPx" : false,
/* 5+App */ /* 5+App */
"app-plus" : { "app-plus" : {
@ -17,19 +17,13 @@
"autoclose" : true, "autoclose" : true,
"delay" : 0 "delay" : 0
}, },
"ios" : {
"capabilities" : {
"com.apple.SafariKeychain" : true
}
},
/* */ /* */
"modules" : { "modules" : {
"Maps" : {}, "Maps" : {},
"Camera" : {}, "Camera" : {},
"Record" : {}, "Record" : {},
"VideoPlayer" : {}, "VideoPlayer" : {},
"UIWebview" : {}, "UIWebview" : {}
"Push" : {}
}, },
/* */ /* */
"distribute" : { "distribute" : {
@ -68,25 +62,7 @@
}, },
/* SDK */ /* SDK */
"sdkConfigs" : { "sdkConfigs" : {
"maps" : {}, "maps" : {}
"push" : {
"igexin" : {
"appid" : "rQxaGAKl7t83KlTubAaKC3",
"appkey" : "QSElTn6ttq5nmrIZtFhCT",
"appsecret" : "zbC1MMuzaf7kW91fdhm9v8"
},
"unipush" : {
"version" : "2",
"offline" : false,
"hms" : {},
"oppo" : {},
"vivo" : {},
"mi" : {},
"meizu" : {},
"honor" : {},
"fcm" : {}
}
}
}, },
"icons" : { "icons" : {
"android" : { "android" : {
@ -121,7 +97,7 @@
} }
}, },
"splashscreen" : { "splashscreen" : {
"androidStyle" : "common" "androidStyle" : "default"
} }
} }
}, },

View File

@ -6,7 +6,8 @@
<image <image
class="img" class="img"
:src=" :src="
msgInfo.mine.user_avatar || '../../static/images/user-avatar.jpg' msgInfo.mine.user_avatar ||
'../../static/images/chat/user-avatar.jpg'
" "
/> />
<text>{{ msgInfo.mine.user_nickname }}</text> <text>{{ msgInfo.mine.user_nickname }}</text>
@ -149,7 +150,7 @@ export default {
}, },
onLoad() {}, onLoad() {},
computed: { computed: {
...mapState("user", ["uid", "userInfo", "socket", "imWeidu", "getMsg"]), ...mapState("user", ["uid", "userInfo", "imWeidu", "getMsg"]),
}, },
watch: { watch: {
imWeidu: { imWeidu: {
@ -198,9 +199,9 @@ export default {
this.loading = true; this.loading = true;
let res = await GetImConfig({ type: "json", uid: this.uid }); let res = await GetImConfig({ type: "json", uid: this.uid });
console.log(res);
if (res && res.status == 200) { if (res && res.status == 200) {
this.msgInfo = res.data; this.msgInfo = res.data;
if (res.data.friend.length > 0) { if (res.data.friend.length > 0) {
let _imWeiDu = uni.getStorageSync("imWeiDu"); let _imWeiDu = uni.getStorageSync("imWeiDu");
if (_imWeiDu) { if (_imWeiDu) {
@ -217,6 +218,7 @@ export default {
this.msgList = res.data.friend[0].list; this.msgList = res.data.friend[0].list;
} }
} }
// this.connectSocket(this.userInfo);
} }
this.loading = false; this.loading = false;
}, },
@ -279,11 +281,12 @@ export default {
.IM-status { .IM-status {
display: flex; display: flex;
align-items: center; align-items: center;
gap: 10rpx; gap: 20rpx;
.img { .img {
width: 88rpx; width: 88rpx;
height: 88rpx; height: 88rpx;
border-radius: 10rpx; border-radius: 100%;
margin-right: 20rpx;
} }
} }
@ -384,7 +387,7 @@ export default {
} }
.icon-kefu { .icon-kefu {
// margin-right: 40rpx; margin-right: 40rpx;
} }
.IM-loading { .IM-loading {

View File

@ -144,6 +144,7 @@ import tChatBar from "@/components/t-chat-bar/t-chat-bar";
import tuiBadge from "@/components/tui-badge/tui-badge.vue"; import tuiBadge from "@/components/tui-badge/tui-badge.vue";
import emoji from "../../static/im/emojiData.js"; import emoji from "../../static/im/emojiData.js";
import { mapState } from "vuex"; import { mapState } from "vuex";
import { webSocketManager } from "@/utils/socket.js";
export default { export default {
components: { components: {
tChatBar, tChatBar,
@ -178,7 +179,6 @@ export default {
RECORDER: uni.getRecorderManager(), RECORDER: uni.getRecorderManager(),
playMsgid: "", playMsgid: "",
isPlayVoice: false, isPlayVoice: false,
// socket: {},
chattype: "user", chattype: "user",
isHideKeyBoard: false, isHideKeyBoard: false,
emojiPath: "https://res.wx.qq.com/mpres/htmledition/images/icon/emotion/", emojiPath: "https://res.wx.qq.com/mpres/htmledition/images/icon/emotion/",
@ -326,7 +326,7 @@ export default {
}, },
}, },
computed: { computed: {
...mapState("user", ["uid", "userInfo", "socket", "getMsg"]), ...mapState("user", ["uid", "userInfo", "getMsg"]),
}, },
methods: { methods: {
async setMsgRead(lastid) { 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) { processTimeString(timeStr) {
const parts = timeStr.split(":"); const parts = timeStr.split(":");
@ -800,7 +781,9 @@ export default {
if (res && res.status == 200) { if (res && res.status == 200) {
chat_data.mine.message_id = res.data.message_other_id; 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 lastid = res.data.message_other_id;
let tempmy = this.userInfo.im; let tempmy = this.userInfo.im;
///TOID ///TOID

View File

@ -276,6 +276,7 @@
:placeholder="item.placeholder" :placeholder="item.placeholder"
:readonly="item.isReadonly" :readonly="item.isReadonly"
:maxlength="item.maxLength" :maxlength="item.maxLength"
clearable
/> />
<u-icon <u-icon
v-if="item.type == 'select'" v-if="item.type == 'select'"
@ -366,6 +367,7 @@
v-model="branchSearchText" v-model="branchSearchText"
placeholder="搜索开户银行关键词" placeholder="搜索开户银行关键词"
@change="onBranchBankChange" @change="onBranchBankChange"
clearable
/> />
<view class="branch_list"> <view class="branch_list">
<template v-if="bankList.length"> <template v-if="bankList.length">

View File

@ -29,6 +29,7 @@
v-model="form.searchAddress" v-model="form.searchAddress"
placeholder="搜索地址,更快填写" placeholder="搜索地址,更快填写"
@input="handerSearchAddress" @input="handerSearchAddress"
clearable
/> />
</u-form-item> </u-form-item>
</u-form> </u-form>

View File

@ -35,6 +35,7 @@
class="form-input" class="form-input"
v-model="form.contact_name" v-model="form.contact_name"
placeholder="请输入联系人" placeholder="请输入联系人"
clearable
/> />
</u-form-item> </u-form-item>
<u-form-item <u-form-item
@ -62,6 +63,7 @@
class="form-input" class="form-input"
v-model="form.store_name" v-model="form.store_name"
placeholder="请输入门店名称" placeholder="请输入门店名称"
clearable
/> />
<u-button <u-button
slot="right" slot="right"
@ -97,6 +99,7 @@
v-model="form.store_address" v-model="form.store_address"
@input="handleStoreAddressInput" @input="handleStoreAddressInput"
placeholder="详细地址:如:人民大道205号2楼213" placeholder="详细地址:如:人民大道205号2楼213"
clearable
/> />
</u-form-item> </u-form-item>
<u-form-item label="门脸图" prop="front_facade_image"> <u-form-item label="门脸图" prop="front_facade_image">

View File

@ -66,6 +66,7 @@
class="form-input" class="form-input"
v-model="form.biz_license_company" v-model="form.biz_license_company"
placeholder="请输入公司名称" placeholder="请输入公司名称"
clearable
/> />
</u-form-item> </u-form-item>
<u-form-item label="法人姓名" prop="legal_person_name" required> <u-form-item label="法人姓名" prop="legal_person_name" required>
@ -73,6 +74,7 @@
class="form-input" class="form-input"
v-model="form.legal_person_name" v-model="form.legal_person_name"
placeholder="请输入法人姓名" placeholder="请输入法人姓名"
clearable
/> />
</u-form-item> </u-form-item>
<u-form-item label="注册号" prop="biz_license_number" required> <u-form-item label="注册号" prop="biz_license_number" required>
@ -80,6 +82,7 @@
class="form-input" class="form-input"
v-model="form.biz_license_number" v-model="form.biz_license_number"
placeholder="请输入注册号" placeholder="请输入注册号"
clearable
/> />
</u-form-item> </u-form-item>
<u-form-item label="法人手机号" prop="legal_person_mobile" required> <u-form-item label="法人手机号" prop="legal_person_mobile" required>
@ -88,6 +91,7 @@
class="form-input" class="form-input"
v-model="form.legal_person_mobile" v-model="form.legal_person_mobile"
placeholder="请输入法人手机号" placeholder="请输入法人手机号"
clearable
/> />
</u-form-item> </u-form-item>
<u-form-item label="经营范围" prop="biz_license_content" required> <u-form-item label="经营范围" prop="biz_license_content" required>
@ -96,6 +100,7 @@
class="form-input" class="form-input"
v-model="form.biz_license_content" v-model="form.biz_license_content"
placeholder="请输入经营范围" placeholder="请输入经营范围"
clearable
/> />
</u-form-item> </u-form-item>
<u-form-item <u-form-item

View File

@ -149,10 +149,10 @@
登录 登录
</u-button> </u-button>
</view> </view>
<!-- <view class="agreement-content"> <view class="agreement-content">
登录代表你已经同意 登录代表你已经同意
<text @click="handerSkip()" class="agreement-item">用户协议</text> <text @click="handerSkip()" class="agreement-item">用户协议</text>
</view> --> </view>
</view> </view>
</view> </view>
<u-toast ref="uToast" /> <u-toast ref="uToast" />

View File

@ -1265,7 +1265,6 @@ export default {
this.showOrderLoading = true; this.showOrderLoading = true;
} }
console.log(this.dashboardInfo.store_info.store_id);
this.params = { this.params = {
storeId: this.dashboardInfo.store_info.store_id, storeId: this.dashboardInfo.store_info.store_id,

View File

@ -57,9 +57,10 @@
<view class="btn-content"> <view class="btn-content">
<view class="tool"> <view class="tool">
<view class="right" @click="goLoginPage" <view class="right" @click="goLoginPage">
>已有账号? <text>立即登录</text></view 已有账号?
> <text>立即登录</text>
</view>
</view> </view>
<u-button <u-button
class="btn-register" class="btn-register"
@ -71,11 +72,10 @@
注册 注册
</u-button> </u-button>
</view> </view>
<!-- <view class="agreement-content"> <view class="agreement-content">
注册代表你已经同意<text @click="handerSkip()" class="agreement-item" 注册代表你已经同意
>用户协议</text <text @click="handerSkip()" class="agreement-item">用户协议</text>
> </view>
</view> -->
</view> </view>
</view> </view>
<u-toast ref="uToast" /> <u-toast ref="uToast" />
@ -372,7 +372,7 @@ export default {
.agreement-content { .agreement-content {
position: fixed; position: fixed;
bottom: 10%; bottom: 10%;
width: 90%; width: 83%;
text-align: center; text-align: center;
font-size: 28rpx; font-size: 28rpx;
color: #ccc; color: #ccc;

View File

@ -179,7 +179,7 @@
shape="circle" shape="circle"
@click="handerPageBack" @click="handerPageBack"
> >
确认 退出
</u-button> </u-button>
</view> </view>
</view> </view>

View File

@ -381,6 +381,7 @@
type="number" type="number"
placeholder="请输入商品排序" placeholder="请输入商品排序"
border="none" border="none"
clearable
></u--input> ></u--input>
</u-form-item> </u-form-item>
<u-form-item <u-form-item

View File

@ -57,6 +57,7 @@
disabledColor="#ffffff" disabledColor="#ffffff"
placeholder="请选择商品类型" placeholder="请选择商品类型"
border="none" border="none"
clearable
@click="hideKeyboard()" @click="hideKeyboard()"
></u--input> ></u--input>
<u-icon <u-icon
@ -71,6 +72,7 @@
type="number" type="number"
placeholder="请输入商品排序" placeholder="请输入商品排序"
border="none" border="none"
clearable
></u--input> ></u--input>
</u-form-item> </u-form-item>
<u-form-item <u-form-item
@ -107,6 +109,7 @@
@change="handerLeveInputChange" @change="handerLeveInputChange"
maxlength="8" maxlength="8"
readonly readonly
clearable
@focus="handerInputFocus(index)" @focus="handerInputFocus(index)"
@blur="handerInputBlur(index)" @blur="handerInputBlur(index)"
> >
@ -229,6 +232,7 @@
<u--input <u--input
v-model="form2.type_name" v-model="form2.type_name"
disabled disabled
clearable
disabledColor="#ffffff" disabledColor="#ffffff"
placeholder="请选择商品类型" placeholder="请选择商品类型"
border="none" border="none"
@ -240,6 +244,7 @@
<u--input <u--input
v-model="form2.category_order" v-model="form2.category_order"
type="number" type="number"
clearable
placeholder="请输入商品排序" placeholder="请输入商品排序"
border="none" border="none"
></u--input> ></u--input>

View File

@ -6,7 +6,7 @@
:border="false" :border="false"
:fixed="true" :fixed="true"
:height="'44px'" :height="'44px'"
rightWidth="0" :rightWidth="0"
:leftWidth="30" :leftWidth="30"
backgroundColor="#f5f6fa" backgroundColor="#f5f6fa"
> >
@ -160,11 +160,16 @@
@click="updateProductPutaway(item, index, 1002)" @click="updateProductPutaway(item, index, 1002)"
> >
下架 下架
</view>
<view <u-button
class="commodity-btn-item" class="commodity-btn-item commodity-btn-item-2"
:hairline="true"
:plain="true"
shape="circle"
@click="handerProductEdit(item)"
> >
编辑 编辑
</u-button>
</view> </view>
</view> </view>
</view> </view>
@ -189,32 +194,25 @@
</view> </view>
</view> </view>
<view class="productList-bottom"> <view class="productList-bottom">
<<<<<<< Updated upstream =======
<view class="bottom-item" @click="skipuClassify">分类管理</view>
>>>>>>> Stashed changes
<view class="bottom-item"> <view class="bottom-item">
<u-icon <u-icon class="u-icon" name="grid" size="16" color="#222"></u-icon>
class="u-icon"
name="grid"
size="16"
color="#222"
></u-icon>
<view class="bottom-item-name">分类管理</view> <view class="bottom-item-name">分类管理</view>
</view> </view>
<view class="bottom-item"> <view class="bottom-item">
<u-icon <u-icon class="u-icon" name="list-dot" size="16" color="#222"></u-icon>
class="u-icon"
name="list-dot"
size="16"
color="#222"
></u-icon>
<view class="bottom-item-name" @click="skipuBatch">批量操作</view> <view class="bottom-item-name" @click="skipuBatch">批量操作</view>
</view> </view>
<view class="bottom-item"> <view class="bottom-item">
<u-icon <u-icon class="u-icon" name="bag" size="16" color="#222"></u-icon>
class="u-icon" <view
name="bag" class="bottom-item-name"
size="16" @click="(showRightPopup = true), (isAdd = true)"
color="#222" >
></u-icon> 商品新建
<view class="bottom-item-name">商品新建</view> </view>
</view> </view>
</view> </view>
<u-popup <u-popup
@ -255,10 +253,10 @@
class="input-price" class="input-price"
:placeholder="String(item.item_unit_price)" :placeholder="String(item.item_unit_price)"
border="surround" border="surround"
clearable
v-model="item.item_unit_price_2" v-model="item.item_unit_price_2"
prefixIcon="¥" prefixIcon="¥"
type="number" type="number"
@change="haderPopupPriceInputChange($event, index)"
></u--input> ></u--input>
</view> </view>
<view class="commodity-info-item"> <view class="commodity-info-item">
@ -268,8 +266,8 @@
:placeholder="String(item.item_quantity)" :placeholder="String(item.item_quantity)"
border="surround" border="surround"
type="number" type="number"
clearable
v-model="item.item_quantity_2" v-model="item.item_quantity_2"
@change="haderPopupRepertoryInputChange($event, index)"
></u--input> ></u--input>
</view> </view>
</view> </view>
@ -282,13 +280,27 @@
:hairline="true" :hairline="true"
:plain="true" :plain="true"
shape="circle" shape="circle"
@click="handerSave" @click="updateCommodityPriceAndQuantity"
> >
保存 保存
</u-button> </u-button>
</view> </view>
</view> </view>
</u-popup> </u-popup>
<u-popup
class="right-popup"
zIndex="998"
:overlay="false"
:show="showRightPopup"
mode="right"
>
<addAndEditProduct
@pageBack="showRightPopup = false"
:productItem="productItem"
:isAdd="isAdd"
></addAndEditProduct>
</u-popup>
<u-toast ref="uToast"></u-toast>
</view> </view>
</template> </template>
@ -297,18 +309,22 @@ import {
GetProductCategoryTree, GetProductCategoryTree,
GetProductList, GetProductList,
UpdateProductPutaway, UpdateProductPutaway,
GetCommoditSpecification,
} from "@/api/warehouse/productList"; } from "@/api/warehouse/productList";
import {
GetCommoditSpecification,
UpdateCommodityPriceAndQuantity,
} from "@/api/warehouse/commodity";
import navBar from "@/components/uni-nav-bar/uni-nav-bar"; import navBar from "@/components/uni-nav-bar/uni-nav-bar";
import tuiCollapse from "../manage/components/tui-collapse/tui-collapse.vue"; import tuiCollapse from "../manage/components/tui-collapse/tui-collapse.vue";
import favoriteLoading from "@/components/favorite-loading/favorite-loading.vue"; import favoriteLoading from "@/components/favorite-loading/favorite-loading.vue";
import addAndEditProduct from "./addAndEditProduct.vue";
export default { export default {
name: "productList", name: "productList",
components: { components: {
navBar, navBar,
tuiCollapse, tuiCollapse,
favoriteLoading, favoriteLoading,
addAndEditProduct,
}, },
data() { data() {
return { return {
@ -372,6 +388,10 @@ export default {
time2: null, time2: null,
showBottomPopup: false, showBottomPopup: false,
currSpecificationList: [], currSpecificationList: [],
showRightPopup: false,
productItem: {},
isAdd: true,
selectCommodisItems: [],
}; };
}, },
computed: {}, computed: {},
@ -431,9 +451,61 @@ export default {
}; };
let res = await GetCommoditSpecification(params); let res = await GetCommoditSpecification(params);
if (res && res.status == 200) { 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; this.showBottomPopup = true;
} }
}, },
@ -642,18 +714,49 @@ export default {
url: "../../news/search/search", url: "../../news/search/search",
}); });
}, },
haderPopupPriceInputChange(e, index) { async updateCommodityPriceAndQuantity(item) {
this.currSpecificationList[index].item_unit_price_2 = e; 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() { skipuBatch() {
uni.navigateTo({ uni.navigateTo({
url: "/pages/warehouse/manage/batch", url: "/pages/warehouse/manage/batch",
}); });
}, },
skipuClassify() {
uni.navigateTo({
url: "/pages/warehouse/manage/classifyList",
});
},
handerProductEdit(item) {
this.productItem = item;
this.showRightPopup = true;
this.isAdd = false;
},
}, },
}; };
</script> </script>
@ -772,7 +875,7 @@ page{
.active::before { .active::before {
content: ""; content: "";
position: absolute; position: absolute;
border-left: 4rpx solid #FE411B; border-left: 4rpx solid #fe411b;
height: 30rpx; height: 30rpx;
left: 0; left: 0;
top: 50%; top: 50%;
@ -998,7 +1101,7 @@ page{
.commodity-price { .commodity-price {
font-size: 28rpx; font-size: 28rpx;
color: #FE411B; color: #fe411b;
.currency { .currency {
margin-right: 4px; margin-right: 4px;

View File

@ -47,14 +47,18 @@
custom-prefix="custom-icon-jianhao_fangxing custom-icon" custom-prefix="custom-icon-jianhao_fangxing custom-icon"
size="18" size="18"
color="#FE411B" color="#FE411B"
></u-icon> ></u-icon>
删除
</view> </view>
<view class="btn_item" @click="handerShowEeditPopup(item)"><u-icon <view class="btn_item" @click="handerShowEeditPopup(item)">
<u-icon
class="u-icon-bianji" class="u-icon-bianji"
custom-prefix="custom-icon-icon_519 custom-icon" custom-prefix="custom-icon-icon_519 custom-icon"
size="18" size="18"
color="#FE411B" color="#FE411B"
></u-icon></view> ></u-icon>
编辑
</view>
</view> </view>
</view> </view>
<view <view
@ -84,7 +88,12 @@
shape="circle" shape="circle"
@click="handerAddAndEditPopup(true)" @click="handerAddAndEditPopup(true)"
> >
<u-icon color="#fff" size="20" class="bottom-icon" name="plus-circle"></u-icon> <u-icon
color="#fff"
size="20"
class="bottom-icon"
name="plus-circle"
></u-icon>
新建规格 新建规格
</u-button> </u-button>
</view> </view>
@ -134,6 +143,7 @@
disabledColor="#ffffff" disabledColor="#ffffff"
placeholder="请选择商品分类" placeholder="请选择商品分类"
border="none" border="none"
clearable
@click="hideKeyboard()" @click="hideKeyboard()"
></u--input> ></u--input>
<u-icon slot="right" name="arrow-right"></u-icon> <u-icon slot="right" name="arrow-right"></u-icon>
@ -142,6 +152,7 @@
<u--input <u--input
v-model="form.spec_order" v-model="form.spec_order"
type="number" type="number"
clearable
placeholder="请输入商品排序" placeholder="请输入商品排序"
border="none" border="none"
></u--input> ></u--input>

File diff suppressed because it is too large Load Diff

View File

@ -35,20 +35,22 @@
custom-prefix="custom-icon-jianhao_fangxing custom-icon" custom-prefix="custom-icon-jianhao_fangxing custom-icon"
size="18" size="18"
color="#FE411B" color="#FE411B"
></u-icon>
></u-icon>
</view> </view>
<view class="btn_item" @click="handerAddAndEditPopup(false, item)"> <view
class="btn_item"
@click="handerAddAndEditPopup(false, item)"
>
<u-icon <u-icon
class="u-icon-bianji" class="u-icon-bianji"
custom-prefix="custom-icon-icon_519 custom-icon" custom-prefix="custom-icon-icon_519 custom-icon"
size="18" size="18"
color="#FE411B" color="#FE411B"
></u-icon> ></u-icon>
编辑
</view> </view>
</view> </view>
</view> </view>
</view> </view>
@ -80,7 +82,12 @@
shape="circle" shape="circle"
@click="handerAddAndEditPopup(true)" @click="handerAddAndEditPopup(true)"
> >
<u-icon color="#fff" size="20" class="bottom-icon" name="plus-circle"></u-icon> <u-icon
color="#fff"
size="20"
class="bottom-icon"
name="plus-circle"
></u-icon>
新建商品类型 新建商品类型
</u-button> </u-button>
</view> </view>
@ -209,7 +216,10 @@
v-for="(item, index) in allSpecificationList" v-for="(item, index) in allSpecificationList"
:key="index" :key="index"
> >
<view class="specification-name"><u-icon name="tags" color="#666" size="18"></u-icon>{{ item.name }}</view> <view class="specification-name">
<u-icon name="tags" color="#666" size="18"></u-icon>
分类名称{{ item.name }}
</view>
<u-checkbox-group <u-checkbox-group
class="specification-checkbox-gourp" class="specification-checkbox-gourp"
v-model="item.checkboxList" v-model="item.checkboxList"
@ -696,7 +706,7 @@ export default {
justify-content: space-around; justify-content: space-around;
align-items: center; align-items: center;
padding: 24rpx 0; padding: 24rpx 0;
border-bottom: 1rpx solid rgba(238, 238, 238, .5); border-bottom: 1rpx solid rgba(238, 238, 238, 0.5);
&:last-child { &:last-child {
border-bottom: none; border-bottom: none;
@ -718,7 +728,6 @@ export default {
-webkit-box-orient: vertical; -webkit-box-orient: vertical;
overflow: hidden; overflow: hidden;
text-overflow: ellipsis; /* 超出部分显示省略号 */ text-overflow: ellipsis; /* 超出部分显示省略号 */
} }
.type-catergory-name { .type-catergory-name {

View File

@ -1,7 +1,7 @@
import { GetAuditInfo, GetAuditStatus } from "../../api/audit"; import { GetAuditInfo, GetAuditStatus } from "../../api/audit";
import { GetAccountLogin, GetLogin } from "../../api/login"; import { GetAccountLogin, GetLogin } from "../../api/login";
import { OutLogin } from "../../api/user"; import { OutLogin } from "../../api/user";
import $Socket from "../../utils/socket"; import { webSocketManager } from "@/utils/socket.js";
import Vue from "vue"; import Vue from "vue";
// import $cookies from '../../utils/vue-cookies' // import $cookies from '../../utils/vue-cookies'
@ -72,10 +72,12 @@ const mutations = {
state.imWeidu = {}; state.imWeidu = {};
state.dashboardInfo = {}; state.dashboardInfo = {};
}, },
CONNECT_SOCKET(state, { socket }) { CONNECT_SOCKET(state, { webSocketManager }) {
state.socket = socket; state.socket = webSocketManager;
}, },
GET_IM_MSG(state, { msg }) { GET_IM_MSG(state, { msg }) {
console.log("GET_IM_MSG", msg);
if (!msg.id) return;
state.getMsg = msg; state.getMsg = msg;
var im = {}; var im = {};
let _imWeiDu = uni.getStorageSync("imWeiDu"); let _imWeiDu = uni.getStorageSync("imWeiDu");
@ -121,8 +123,7 @@ const actions = {
// #endif // #endif
params.cid = "ae9c4517a4ae17ea33570839a0f5fdba"; console.log("push_clientid");
params.osType = 1;
const res = await GetAccountLogin(params); const res = await GetAccountLogin(params);
@ -195,6 +196,8 @@ const actions = {
} }
}, },
async LoginOut({ commit }, isTokenExpires) { async LoginOut({ commit }, isTokenExpires) {
webSocketManager.closeAllGlobalConnections();
if (isTokenExpires) { if (isTokenExpires) {
await OutLogin(); await OutLogin();
@ -379,27 +382,22 @@ const actions = {
}, },
connectSocket({ commit }, userInfo) { connectSocket({ commit }, userInfo) {
if (!userInfo) return; if (!userInfo) return;
var socket = new $Socket({
url: userInfo.im.node_site_url, webSocketManager.createGlobalConnection(
maxInterValCount: 5, "ws1",
interValTime: 20000, userInfo.im.node_site_url,
onClose: (res) => { 2000
console.log("sockrt关闭"); );
},
onOpen: (res) => { webSocketManager.getConnection("ws1").onMessage((res) => {
console.log("sockrt连接成功"); // 处理消息逻辑
},
onMsg: (res) => {
console.log("onMsg", res);
if (res) { if (res) {
let msg = JSON.parse(res.data); let msg = res;
console.log("ws1收到的消息:", msg);
commit("GET_IM_MSG", { msg }); commit("GET_IM_MSG", { msg });
} }
},
}); });
socket.connectserver(userInfo.im);
commit("CONNECT_SOCKET", { socket });
}, },
}; };

View File

@ -1,4 +1,3 @@
/*主颜色*/ /*主颜色*/
$base-color: #FE411B; // 蓝色 #4b71ff $base-color: #fe411b; // 蓝色 #4b71ff
$base-btn-bg-color: #fe411b;
$base-btn-bg-color: #FE411B;

View File

@ -1,13 +1,15 @@
<template> <template>
<view class="u-toast"> <view class="u-toast">
<u-overlay <u-overlay :show="isShow" :custom-style="overlayStyle">
:show="isShow"
:custom-style="overlayStyle"
>
<view <view
class="u-toast__content" class="u-toast__content"
:style="[contentStyle]" :style="[contentStyle]"
:class="['u-type-' + tmpConfig.type, (tmpConfig.type === 'loading' || tmpConfig.loading) ? 'u-toast__content--loading' : '']" :class="[
'u-type-' + tmpConfig.type,
tmpConfig.type === 'loading' || tmpConfig.loading
? 'u-toast__content--loading'
: '',
]"
> >
<u-loading-icon <u-loading-icon
v-if="tmpConfig.type === 'loading'" v-if="tmpConfig.type === 'loading'"
@ -31,8 +33,10 @@
<text <text
class="u-toast__content__text" class="u-toast__content__text"
:class="['u-toast__content__text--' + tmpConfig.type]" :class="['u-toast__content__text--' + tmpConfig.type]"
style="max-width: 400rpx;" style="max-width: 400rpx"
>{{ tmpConfig.message }}</text> >
{{ tmpConfig.message }}
</text>
</view> </view>
</u-overlay> </u-overlay>
</view> </view>
@ -62,121 +66,132 @@
* @example <u-toast ref="uToast" /> * @example <u-toast ref="uToast" />
*/ */
export default { export default {
name: 'u-toast', name: "u-toast",
mixins: [uni.$u.mpMixin, uni.$u.mixin], mixins: [uni.$u.mpMixin, uni.$u.mixin],
data() { data() {
return { return {
isShow: false, isShow: false,
timer: null, // timer: null, //
config: { config: {
message: '', // message: "", //
type: '', // primarysuccesserrorwarningblack type: "", // primarysuccesserrorwarningblack
duration: 2000, // duration: 2000, //
icon: true, // icon: true, //
position: 'center', // toast position: "center", // toast
complete: null, // complete: null, //
overlay: false, // 穿 overlay: false, // 穿
loading: false, // loading: false, //
zIndex: 12000,
}, },
tmpConfig: {}, // tmpConfig: {}, //
} };
}, },
computed: { computed: {
iconName() { iconName() {
// nonetypeerror|warning|succes|info // nonetypeerror|warning|succes|info
if(!this.tmpConfig.icon || this.tmpConfig.icon == 'none') { if (!this.tmpConfig.icon || this.tmpConfig.icon == "none") {
return ''; return "";
} }
if (['error', 'warning', 'success', 'primary'].includes(this.tmpConfig.type)) { if (
return uni.$u.type2icon(this.tmpConfig.type) ["error", "warning", "success", "primary"].includes(this.tmpConfig.type)
) {
return uni.$u.type2icon(this.tmpConfig.type);
} else { } else {
return '' return "";
} }
}, },
overlayStyle() { overlayStyle() {
const style = { const style = {
justifyContent: 'center', justifyContent: "center",
alignItems: 'center', alignItems: "center",
display: 'flex' display: "flex",
} zIndex: this.zIndex,
};
// 100% // 100%
style.backgroundColor = 'rgba(0, 0, 0, 0)' style.backgroundColor = "rgba(0, 0, 0, 0)";
return style return style;
}, },
iconStyle() { iconStyle() {
const style = {} const style = {};
// //
style.marginRight = '4px' style.marginRight = "4px";
// #ifdef APP-NVUE // #ifdef APP-NVUE
// iOSAPP1px // iOSAPP1px
if (uni.$u.os() === 'ios') { if (uni.$u.os() === "ios") {
style.marginTop = '-1px' style.marginTop = "-1px";
} }
// #endif // #endif
return style return style;
}, },
loadingIconColor() { loadingIconColor() {
let color = 'rgb(255, 255, 255)' let color = "rgb(255, 255, 255)";
if (['error', 'warning', 'success', 'primary'].includes(this.tmpConfig.type)) { if (
["error", "warning", "success", "primary"].includes(this.tmpConfig.type)
) {
// loading-iconcolor // loading-iconcolor
// rgb // rgb
color = uni.$u.hexToRgb(uni.$u.color[this.tmpConfig.type]) color = uni.$u.hexToRgb(uni.$u.color[this.tmpConfig.type]);
} }
return color return color;
}, },
// //
contentStyle() { contentStyle() {
const windowHeight = uni.$u.sys().windowHeight, style = {} const windowHeight = uni.$u.sys().windowHeight,
let value = 0 style = {};
let value = 0;
// topbottomY // topbottomY
if(this.tmpConfig.position === 'top') { if (this.tmpConfig.position === "top") {
value = - windowHeight * 0.25 value = -windowHeight * 0.25;
} else if(this.tmpConfig.position === 'bottom') { } else if (this.tmpConfig.position === "bottom") {
value = windowHeight * 0.25 value = windowHeight * 0.25;
}
style.transform = `translateY(${value}px)`
return style
} }
style.transform = `translateY(${value}px)`;
return style;
},
}, },
created() { created() {
// toast // toast
['primary', 'success', 'error', 'warning', 'default', 'loading'].map(item => { ["primary", "success", "error", "warning", "default", "loading"].map(
this[item] = message => this.show({ (item) => {
this[item] = (message) =>
this.show({
type: item, type: item,
message message,
}) });
}) }
);
}, },
methods: { methods: {
// toastthis.$refs.xxx.show(options) // toastthis.$refs.xxx.show(options)
show(options) { show(options) {
// this.configu-toast // this.configu-toast
this.tmpConfig = uni.$u.deepMerge(this.config, options) this.tmpConfig = uni.$u.deepMerge(this.config, options);
// //
this.clearTimer() this.clearTimer();
this.isShow = true this.isShow = true;
this.timer = setTimeout(() => { this.timer = setTimeout(() => {
// toast // toast
this.clearTimer() this.clearTimer();
// callback // callback
typeof(this.tmpConfig.complete) === 'function' && this.tmpConfig.complete() typeof this.tmpConfig.complete === "function" &&
}, this.tmpConfig.duration) this.tmpConfig.complete();
}, this.tmpConfig.duration);
}, },
// toastthis.$refs.xxx.hide() // toastthis.$refs.xxx.hide()
hide() { hide() {
this.clearTimer() this.clearTimer();
}, },
clearTimer() { clearTimer() {
this.isShow = false this.isShow = false;
// //
clearTimeout(this.timer) clearTimeout(this.timer);
this.timer = null this.timer = null;
} },
}, },
beforeDestroy() { beforeDestroy() {
this.clearTimer() this.clearTimer();
} },
} };
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
@ -197,7 +212,7 @@
$u-toast-u-type-primary-border-width: 1px !default; $u-toast-u-type-primary-border-width: 1px !default;
$u-toast-u-type-success-color: $u-success !default; $u-toast-u-type-success-color: $u-success !default;
$u-toast-u-type-success-background-color: #dbf1e1 !default; $u-toast-u-type-success-background-color: #dbf1e1 !default;
$u-toast-u-type-success-border-color: #BEF5C8 !default; $u-toast-u-type-success-border-color: #bef5c8 !default;
$u-toast-u-type-success-border-width: 1px !default; $u-toast-u-type-success-border-width: 1px !default;
$u-toast-u-type-error-color: $u-error !default; $u-toast-u-type-error-color: $u-error !default;
$u-toast-u-type-error-background-color: #fef0f0 !default; $u-toast-u-type-error-background-color: #fef0f0 !default;

View File

@ -1,261 +1,189 @@
const noop = function() {}; class WebsocketUtil {
class Socket { constructor(url, time) {
static stopTime = 0; this.is_open_socket = false; // 避免重复连接
static concatCount = 0; this.url = url; // 地址
constructor({ this.data = null;
url = '', // 心跳检测
onOpen = noop, this.timeout = time; // 多少秒执行检测
onMsg = noop, this.heartbeatInterval = null; // 检测服务器端是否还活着
onClose = noop, this.reconnectInterval = null; // 重连之后多久再次重连
onError = noop, this.messageCallbacks = []; // 存储消息回调函数
onReload = noop, this.store = null; // 存储Vuex store引用
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;
}
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 { try {
const res = await this.initChat(SocketTask, SocketTask.extra); return this.connectSocketInit();
reloadStatus = res; } catch (e) {
} catch (e) {} this.is_open_socket = false;
onReload.call(SocketTask, reloadStatus, SocketTask); }
SocketTask.eventPatch.dispatchEvent('onReload', reloadStatus);
resolve(reloadStatus);
})
})
} }
function EventDispatcher() { // 设置store
this.events = events; setStore(store) {
this.store = store;
} }
for (let key in events) {
EventDispatcher.prototype[key] = function(handler) { // 创建WebSocket连接
if (typeof handler != 'function') return; connectSocketInit() {
this.events[key].push(handler) if (this.is_open_socket) return;
}
} this.socketTask = uni.connectSocket({
EventDispatcher.prototype.dispatchEvent = function(type, msg) { url: this.url,
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: () => { success: () => {
resolve(); this.is_open_socket = true;
return this.socketTask;
}, },
fail: err => { });
reject();
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);
}, },
...args fail(err) {
}) console.error("消息发送失败", err);
}) },
});
}
// 关闭连接
close() {
clearInterval(this.heartbeatInterval);
clearInterval(this.reconnectInterval);
this.is_open_socket = false;
if (this.socketTask) {
this.socketTask.close();
} }
} }
export default Socket
// 开启心跳检测
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
);
}
}
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;