diff --git a/java-mall-app-shop-admin/.hbuilderx/launch.json b/java-mall-app-shop-admin/.hbuilderx/launch.json index 007bebb..131b491 100644 --- a/java-mall-app-shop-admin/.hbuilderx/launch.json +++ b/java-mall-app-shop-admin/.hbuilderx/launch.json @@ -4,24 +4,20 @@ "version" : "0.0", "configurations" : [ { - "app-plus" : - { - "launchtype" : "remote" - }, - "default" : - { - "launchtype" : "local" - }, - "h5" : - { - "launchtype" : "local" - }, - "mp-weixin" : - { - "launchtype" : "local" - }, - "provider" : "aliyun", - "type" : "uniCloud" + "app-plus" : { + "launchtype" : "remote" + }, + "default" : { + "launchtype" : "local" + }, + "h5" : { + "launchtype" : "local" + }, + "mp-weixin" : { + "launchtype" : "local" + }, + "provider" : "aliyun", + "type" : "uniCloud" }, { "playground" : "custom", diff --git a/java-mall-app-shop-admin/api/order.js b/java-mall-app-shop-admin/api/order.js index 0a87857..872b96e 100644 --- a/java-mall-app-shop-admin/api/order.js +++ b/java-mall-app-shop-admin/api/order.js @@ -25,6 +25,95 @@ export function GetOrderList(params) { }); } +/** + * 获取退货订单列表 + * @author Seven + * @data 2025-3-28 + * @param { + * storeId: 1, //店铺Id + * keyword: 'DD-', //搜索订单关键字 + * pageNum: 1, //页码 + * pageSize: 10, //页大小 + * delivery: 1, // 1-同城配送;2-物流配送 + * status: 1, 1-进行中;2-超时的订单;3-退款的订单 + * } + * @returns { } + * @see https://mall.gpxscs.cn/api/admin/shop/shop-order-return/list?pageNum=1&pageSize=20&order_id=&return_id=&startDate=&endDate=&source_lang=zh_CN + */ + +export function GetSalesReturnOrderList(params) { + return http({ + url: "/shop/shop-order-return/list", + method: "get", + params, + baseURL: config.adminApi, + }); +} + +/** + * 获取退货订单详情 + * @author Seven + * @data 2025-3-28 + * @param { + * return_id: FX-20241223-4 退货订单编号 + * } + * @returns { } + * @see https://mall.gpxscs.cn/api/admin/shop/shop-order-return/get?return_id=FX-20241223-4&source_lang=zh_CN + */ + +export function GetSalesReturnOrderDetails(params) { + return http({ + url: "/shop/shop-order-return/get", + method: "get", + params, + baseURL: config.adminApi, + }); +} + +/** + * 退货订单不通过 + * @author Seven + * @data 2025-3-28 + * @param { + * return_store_message: "" , 备注 + * return_id: FX-20241223-4 退货订单编号 + * } + * @returns { } + * @see https://mall.gpxscs.cn/api/admin/shop/shop-order-return/refused?source_lang=zh_CN + */ + +export function GetSalesReturnOrderNoPass(params) { + return http({ + url: "/shop/shop-order-return/refused", + method: "post", + params, + baseURL: config.adminApi, + }); +} + +/** + * 退货订单不通过 + * @author Seven + * @data 2025-3-28 + * @param { + * return_flag: 0 不用退货 1需要退货 + * return_store_message: "" , 备注 + * receiving_address:2 + * return_id: FX-20241223-4 退货订单编号 + * } + * @returns { } + * @see https://mall.gpxscs.cn/api/admin/shop/shop-order-return/review?source_lang=zh_CN + */ + +export function GetSalesReturnOrderPass(params) { + return http({ + url: "/shop/shop-order-return/review", + method: "post", + 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 new file mode 100644 index 0000000..6aafee6 --- /dev/null +++ b/java-mall-app-shop-admin/api/warehouse/productList.js @@ -0,0 +1,72 @@ +import http from "../../utils/http"; +import config from "../../config/config"; + +/** 获取店铺商品分类 + * + * @author Seven + * @data 2025-7-4 + * @returns { } + * @see https://mall.gpxscs.cn/api/admin/shop/shop-base-product-category/tree?source_lang=zh_CN + */ + +export function GetProductCategoryTree() { + return http({ + url: "/shop/shop-base-product-category/tree", + method: "get", + baseURL: config.adminApi, + }); +} + +/** 获取店铺商品列表 + * + * @author Seven + * @data 2025-7-4 + * @param { pageNum pageSize kind_id product_src category_id } + * @returns { } + * @see https://mall.gpxscs.cn/api/admin/shop/shop-product-base/list?pageNum=1&pageSize=20&kind_id=1201,1202,1203&product_src=false&category_id=&source_lang=zh_CN + */ + +export function GetProductList(params) { + return http({ + url: "/shop/shop-product-base/list", + method: "get", + params, + baseURL: config.adminApi, + }); +} + +/** 更新商品上下架 + * + * @author Seven + * @data 2025-7-6 + * @param { pageNum pageSize kind_id product_src category_id } + * @returns { } + * @see https://mall.gpxscs.cn/api/admin/shop/shop-product-base/editState?source_lang=zh_CN + */ + +export function UpdateProductPutaway(params) { + return http({ + url: "/shop/shop-product-base/editState", + method: "post", + params, + baseURL: config.adminApi, + }); +} + +/** 删除商品 + * + * @author Seven + * @data 2025-7-6 + * @param { product_id } + * @returns { } + * @see https://mall.gpxscs.cn/api/admin/shop/shop-product-base/deleteBatch + */ + +export function DelectCommodity(params) { + return http({ + url: "/shop/shop-product-base/deleteBatch", + method: "post", + params, + baseURL: config.adminApi, + }); +} diff --git a/java-mall-app-shop-admin/components/tabbar/tabbar.vue b/java-mall-app-shop-admin/components/tabbar/tabbar.vue index 34a5283..567f497 100644 --- a/java-mall-app-shop-admin/components/tabbar/tabbar.vue +++ b/java-mall-app-shop-admin/components/tabbar/tabbar.vue @@ -25,6 +25,22 @@ color="#000" > + + + + + + {{currentIndex+1}}/{{getLen}} + + + + + + + {{getDesc(currentIndex,imgUrls)}} + + + 删除 + + + + + + + diff --git a/java-mall-app-shop-admin/components/tui-navigation-bar/tui-navigation-bar.vue b/java-mall-app-shop-admin/components/tui-navigation-bar/tui-navigation-bar.vue new file mode 100644 index 0000000..7db07ea --- /dev/null +++ b/java-mall-app-shop-admin/components/tui-navigation-bar/tui-navigation-bar.vue @@ -0,0 +1,258 @@ + + + + + {{ title }} + + + + + + + + \ No newline at end of file diff --git a/java-mall-app-shop-admin/components/tui-upload/tui-upload.vue b/java-mall-app-shop-admin/components/tui-upload/tui-upload.vue new file mode 100644 index 0000000..1b7fadf --- /dev/null +++ b/java-mall-app-shop-admin/components/tui-upload/tui-upload.vue @@ -0,0 +1,613 @@ + + + + + + + + + + {{statusArr[index]==2?'上传中...':'上传失败'}} + 重新上传 + + + + + + + + + + + + + + \ No newline at end of file diff --git a/java-mall-app-shop-admin/pages.json b/java-mall-app-shop-admin/pages.json index 4410740..e43654a 100644 --- a/java-mall-app-shop-admin/pages.json +++ b/java-mall-app-shop-admin/pages.json @@ -1,6 +1,5 @@ { "pages": [ - //pages数组中第一项表示应用启动页,参考:https://uniapp.dcloud.io/collocation/pages { "path": "pages/login/launch", "style": { @@ -91,8 +90,6 @@ "path": "pages/order/order", "style": { "navigationStyle": "custom" - // "onReachBottomDistance": 105, - // "enablePullDownRefresh": true } }, { @@ -197,6 +194,42 @@ "navigationBarTitleText": "网址" } }, + { + "path": "pages/warehouse/warehouse", + "style": { + "navigationStyle": "custom" + } + }, + { + "path": "pages/warehouse/manage/productList", + "style": { + "navigationStyle": "custom" + } + }, + { + "path": "pages/warehouse/manage/brandList", + "style": { + "navigationBarTitleText": "品牌管理" + } + }, + { + "path": "pages/warehouse/manage/photoGallery", + "style": { + "navigationBarTitleText": "商品图库" + } + }, + { + "path": "pages/warehouse/manage/classifyList", + "style": { + "navigationBarTitleText": "分类管理" + } + }, + { + "path": "pages/warehouse/manage/batch", + "style": { + "navigationStyle": "custom" + } + }, { "path": "pages/my/versions", "style": { @@ -232,6 +265,17 @@ }, "text": "工作台" }, + { + "pagePath": "pages/warehouse/warehouse", + "iconfont": { + "text": "\ue606", + "selectedText": "\ue606", + "selectedColor": "#fe4119", + "color": "#000", + "fontSize": "20px" + }, + "text": "经营" + }, { "pagePath": "pages/IM/IM", "iconfont": { diff --git a/java-mall-app-shop-admin/pages/audit/checkAudit.vue b/java-mall-app-shop-admin/pages/audit/checkAudit.vue index 8956c3a..c8839dc 100644 --- a/java-mall-app-shop-admin/pages/audit/checkAudit.vue +++ b/java-mall-app-shop-admin/pages/audit/checkAudit.vue @@ -315,10 +315,9 @@ class="id-radio-group" @change="handelRaddio" > - + - + {{ item.branch_bank_name }} @@ -387,7 +386,7 @@ 数据加载中... - + 11) { - params.mobile = this.userInfo.user_mobile.slice(2); - } else { - params.mobile = this.userInfo.user_mobile; - } + params.mobile = this.userInfo.user_mobile.startsWith("+86") + ? this.userInfo.user_mobile.replace("+86", "") + : this.userInfo.user_mobile; let res = await GetAuditInfo(params); if (res && res.status == 200) { @@ -602,11 +595,11 @@ export default { approval_invalid_col: [], }; - if(this.isPassAudit){ - uni.switchTab({ - url: "/pages/order/order", - }); - return + if (this.isPassAudit) { + uni.switchTab({ + url: "/pages/order/order", + }); + return; } if (!res.data || res.data.approval_status == 4) { @@ -818,7 +811,7 @@ export default { var ocr = await this.getOcrText( imgUrl, fileImg, - orcImgTypeConf.ID_CARD_FRONT + orcImgTypeConf.FR_ID_CARD_FRONT ); this.auditInfo.approval_invalid_col.forEach((item) => { if ( @@ -1058,23 +1051,24 @@ export default { const batchNoRes = await batchNoApi(filePath, file, type); const batchNo = batchNoRes.batchNo; + // 兼容多端的表单数据处理方式 + let formDataStr; + //#ifdef H5 const formData = new FormData(); - let formDataStr = ""; - formData.append("batchNo", batchNo); formData.append("imgType", type); + formDataStr = new URLSearchParams(formData).toString(); + //#endif + + //#ifdef APP-PLUS + formDataStr = `batchNo=${encodeURIComponent( + batchNo + )}&imgType=${encodeURIComponent(type)}`; + //#endif clearTimeout(this.orcTimeout); this.orcTimeout = setTimeout(async () => { - formData.forEach((value, key) => { - if (formDataStr !== "") { - formDataStr += "&"; - } - formDataStr += - encodeURIComponent(key) + "=" + encodeURIComponent(value); - }); - const imgOcrRes = await imgOcrResultApi(formDataStr); clearTimeout(this.orcTimeout); resolve(imgOcrRes?.data); diff --git a/java-mall-app-shop-admin/pages/audit/mapAddress.vue b/java-mall-app-shop-admin/pages/audit/mapAddress.vue index 9bbb22b..cb94598 100644 --- a/java-mall-app-shop-admin/pages/audit/mapAddress.vue +++ b/java-mall-app-shop-admin/pages/audit/mapAddress.vue @@ -166,7 +166,6 @@ export default { this.searchAddressList.forEach((item) => { if (item.name.indexOf(value) >= 0) { - console.log("aa"); item.searchName = item.name.replace( new RegExp(value, "g"), "" + value + "" diff --git a/java-mall-app-shop-admin/pages/audit/shop1.vue b/java-mall-app-shop-admin/pages/audit/shop1.vue index 74a60e0..806bbb8 100644 --- a/java-mall-app-shop-admin/pages/audit/shop1.vue +++ b/java-mall-app-shop-admin/pages/audit/shop1.vue @@ -326,15 +326,9 @@ export default { let userInfo = uni.getStorageSync("userInfo"); let locationItem = uni.getStorageSync("locationItem"); - // userInfo.user_mobile = userInfo.user_mobile.slice(2); - - let isContain = userInfo.user_mobile.indexOf("86"); - - if (isContain != -1 && userInfo.user_mobile.length > 11) { - params.mobile = userInfo.user_mobile.slice(2); - } else { - params.mobile = userInfo.user_mobile; - } + params.mobile = userInfo.user_mobile.startsWith("+86") + ? userInfo.user_mobile.replace("+86", "") + : userInfo.user_mobile; const storeArea = locationItem.administrativeRegion.label[0] + diff --git a/java-mall-app-shop-admin/pages/audit/shop2.vue b/java-mall-app-shop-admin/pages/audit/shop2.vue index 0c0608e..109472c 100644 --- a/java-mall-app-shop-admin/pages/audit/shop2.vue +++ b/java-mall-app-shop-admin/pages/audit/shop2.vue @@ -483,7 +483,7 @@ const orcImgTypeConf = { ID_CARD_FRONT: "ID_CARD_FRONT", // 个人身份证正面 ID_CARD_BEHIND: "ID_CARD_BEHIND", // 个人身份证反面 BUSINESS_LICENCE: "BUSINESS_LICENCE", // 营业执照 - BANK_CARD: "BANK_CARD", + BANK_CARD: "BANK_CARD", // 银行卡 }; export default { @@ -558,7 +558,7 @@ export default { action: "", limitType: ["png", "jpg", "jpeg"], //允许的图片后缀 fileMaxSize: 1 * 1024 * 1024, // 超出1M开启压缩 - maxSize: 20 * 1024 * 1024, //图片最大不能超过20M + maxSize: 10 * 1024 * 1024, //图片最大不能超过10M fileMinSize: 5 * 1024, // 最小为5KB fileList: [], fileList2: [], @@ -723,7 +723,7 @@ export default { uni.navigateBack(); }, overSize(e) { - uni.$u.toast("上传图片大小不能超过20MB!"); + uni.$u.toast("上传图片大小不能超过10MB!"); }, compressImage(url) { return new Promise((reslove, reject) => { @@ -733,6 +733,7 @@ export default { src: tempFilePath, quality: 75, //压缩的程度 success: (res) => { + console.log("压缩成功", res); reslove(res.tempFilePath); //压缩成功返回的路径 }, fail: (error) => { @@ -742,13 +743,13 @@ export default { }); }); }, + async getOcrText(filePath, file, type) { return new Promise(async (resolve, reject) => { this.loading = true; //#ifdef APP-PLUS try { filePath = await this.compressImage(filePath); - console.log("路径", filePath); } catch (error) { console.log(error); } @@ -764,87 +765,94 @@ export default { console.log("OCR上图图片压缩后为:", size); //#endif - - const batchNoRes = await batchNoApi(filePath, file, type); - - if (!batchNoRes) { - this.loading = false; - reject(batchNoRes); - } - - const batchNo = batchNoRes.batchNo; - - const formData = new FormData(); - let formDataStr = ""; - - formData.append("batchNo", batchNo); - formData.append("imgType", type); - - clearTimeout(this.orcTimeout); - - this.orcTimeout = setTimeout(async () => { - formData.forEach((value, key) => { - if (formDataStr !== "") { - formDataStr += "&"; - } - formDataStr += - encodeURIComponent(key) + "=" + encodeURIComponent(value); - }); - - const imgOcrRes = await imgOcrResultApi(formDataStr); - if (imgOcrRes.status == 250) { - switch (type) { - case "FR_ID_CARD_FRONT": - uni.showToast({ - title: "上传身份证正面图片错误,请重新上传", - icon: "error", - duration: 2000, - }); - this.form.legal_person_id_images == ""; - this.fileList3 = []; - break; - case "FR_ID_CARD_BEHIND": - uni.showToast({ - title: "上传身份证反面图片错误,请重新上传", - icon: "error", - duration: 2000, - }); - this.form.legal_person_id_images2 == ""; - this.fileList4 = []; - break; - case "ID_CARD_FRONT": - uni.showToast({ - title: "上传身份证正面图片错误,请重新上传", - icon: "error", - duration: 2000, - }); - this.form2.individual_id_images == ""; - this.fileList5 = []; - break; - case "ID_CARD_BEHIND": - uni.showToast({ - title: "上传身份证反面图片错误,请重新上传", - icon: "error", - duration: 2000, - }); - this.form2.individual_id_images2 == ""; - this.fileList6 = []; - break; - case "BUSINESS_LICENCE": - uni.showToast({ - title: "营业图片上传有误,请重新上传", - icon: "error", - duration: 2000, - }); - this.form.biz_license_image == ""; - this.fileList = []; - break; - } + try { + const batchNoRes = await batchNoApi(filePath, file, type); + console.log("batchNoRes", batchNoRes); + if (!batchNoRes) { + this.loading = false; + reject(batchNoRes); } + + const batchNo = batchNoRes.batchNo; + + // 兼容多端的表单数据处理方式 + let formDataStr; + //#ifdef H5 + const formData = new FormData(); + formData.append("batchNo", batchNo); + formData.append("imgType", type); + formDataStr = new URLSearchParams(formData).toString(); + //#endif + + //#ifdef APP-PLUS + formDataStr = `batchNo=${encodeURIComponent( + batchNo + )}&imgType=${encodeURIComponent(type)}`; + //#endif + clearTimeout(this.orcTimeout); - this.loading = false; - resolve(imgOcrRes?.data); - }, 1000); + + this.orcTimeout = setTimeout(async () => { + const imgOcrRes = await imgOcrResultApi(formDataStr); + console.log("imgOcrRes", imgOcrRes); + if (imgOcrRes.status == 250) { + switch (type) { + case "FR_ID_CARD_FRONT": + uni.showToast({ + title: "上传身份证正面图片错误,请重新上传", + icon: "none", + duration: 2000, + }); + + this.form.legal_person_id_images = ""; + this.fileList3.splice(0, 1); + console.log(this.fileList3); + break; + case "FR_ID_CARD_BEHIND": + uni.showToast({ + title: "上传身份证反面图片错误,请重新上传", + icon: "none", + duration: 2000, + }); + this.form.legal_person_id_images2 = ""; + this.fileList4.splice(0, 1); + break; + case "ID_CARD_FRONT": + uni.showToast({ + title: "上传身份证正面图片错误,请重新上传", + icon: "none", + duration: 2000, + }); + this.form2.individual_id_images = ""; + this.fileList5.splice(0, 1); + break; + case "ID_CARD_BEHIND": + uni.showToast({ + title: "上传身份证反面图片错误,请重新上传", + icon: "none", + duration: 2000, + }); + this.form2.individual_id_images2 = ""; + this.fileList6.splice(0, 1); + break; + case "BUSINESS_LICENCE": + uni.showToast({ + title: "营业图片上传有误,请重新上传", + icon: "none", + duration: 2000, + }); + this.form.biz_license_image = ""; + this.fileList.splice(0, 1); + break; + } + } + clearTimeout(this.orcTimeout); + this.loading = false; + resolve(imgOcrRes?.data); + }, 1000); + } catch (error) { + console.log(error); + } }); }, /**判断文件类型是否正确 */ @@ -942,8 +950,9 @@ export default { var ocr = await this.getOcrText( imgUrl, item, - orcImgTypeConf.ID_CARD_FRONT + orcImgTypeConf.FR_ID_CARD_FRONT ); + this.form.legal_person_name = ocr.name; this.form.legal_person_id_number = ocr.idNumber; this.form.legal_person_id_addr = ocr.address; @@ -1367,5 +1376,15 @@ page { margin-right: 20rpx; width: 240rpx; } + + ::v-deep.u-upload__deletable { + width: 40rpx; + height: 40rpx; + + .uicon-close { + font-size: 28rpx !important; + top: 8rpx !important; + } + } } diff --git a/java-mall-app-shop-admin/pages/audit/shop3.vue b/java-mall-app-shop-admin/pages/audit/shop3.vue index caeb1fd..c6211d5 100644 --- a/java-mall-app-shop-admin/pages/audit/shop3.vue +++ b/java-mall-app-shop-admin/pages/audit/shop3.vue @@ -120,12 +120,12 @@ placeholder="搜索开户银行关键词" @change="onBranchBankChange" /> - + {{ item.branch_bank_name }} @@ -139,7 +139,7 @@ 数据加载中... - + @@ -261,7 +261,7 @@ export default { }, limitType: ["png", "jpg", "jpeg"], //允许的图片后缀 fileMaxSize: 1 * 1024 * 1024, // 超出1M开启压缩 - maxSize: 5 * 1024 * 1024, //图片最大不能超过20M + maxSize: 10 * 1024 * 1024, //图片最大不能超过20M fileMinSize: 5 * 1024, // 最小为5KB showTips: false, }; @@ -288,7 +288,7 @@ export default { uni.navigateBack(); }, overSize(e) { - uni.$u.toast("上传图片大小不能超过20MB!"); + uni.$u.toast("上传图片大小不能超过10MB!"); }, compressImage(url) { return new Promise((reslove, reject) => { @@ -331,24 +331,24 @@ export default { this.bankCardOcrLoaded = true; reject(batchNoRes); } - + // 兼容多端的表单数据处理方式 + let formDataStr; + //#ifdef H5 const formData = new FormData(); - let formDataStr = ""; - formData.append("batchNo", batchNo); formData.append("imgType", type); + formDataStr = new URLSearchParams(formData).toString(); + //#endif + + //#ifdef APP-PLUS + formDataStr = `batchNo=${encodeURIComponent( + batchNo + )}&imgType=${encodeURIComponent(type)}`; + //#endif clearTimeout(this.orcTimeout); this.orcTimeout = setTimeout(async () => { - formData.forEach((value, key) => { - if (formDataStr !== "") { - formDataStr += "&"; - } - formDataStr += - encodeURIComponent(key) + "=" + encodeURIComponent(value); - }); - const imgOcrRes = await imgOcrResultApi(formDataStr); if (imgOcrRes?.status == 200) { diff --git a/java-mall-app-shop-admin/pages/index/index.vue b/java-mall-app-shop-admin/pages/index/index.vue index c6fcfd2..7582cf3 100644 --- a/java-mall-app-shop-admin/pages/index/index.vue +++ b/java-mall-app-shop-admin/pages/index/index.vue @@ -32,13 +32,10 @@ export default { onShow() { if (this.userInfo && Object.keys(this.userInfo).length > 0) { var _userinfo = JSON.parse(JSON.stringify(this.userInfo)); - var mobile = ""; - let isContain = _userinfo.user_mobile.indexOf("86"); - if (isContain != -1 && _userinfo.user_mobile.length > 11) { - mobile = _userinfo.user_mobile.slice(2); - } else { - mobile = _userinfo.user_mobile; - } + let mobile = ""; + mobile = _userinfo.user_mobile.startsWith("+86") + ? _userinfo.user_mobile.replace("+86", "") + : _userinfo.user_mobile; this.checkAccountIsPass({ userInfo: _userinfo, mobile: mobile }); } }, @@ -131,7 +128,7 @@ export default { border: none; } } - + .btn-register { &::after { border: none; diff --git a/java-mall-app-shop-admin/pages/login/login.vue b/java-mall-app-shop-admin/pages/login/login.vue index 814062d..9f595d8 100644 --- a/java-mall-app-shop-admin/pages/login/login.vue +++ b/java-mall-app-shop-admin/pages/login/login.vue @@ -110,10 +110,7 @@ :maxlength="4" > - + - 忘记密码 - 没有店铺? 立即开店 + + 忘记密码 + + + 没有店铺? + 立即开店 + 0) { console.log(this.userInfo); var _userinfo = JSON.parse(JSON.stringify(this.userInfo)); - var mobile = ""; - - let isContain = _userinfo.user_mobile.indexOf("86"); - - if (isContain != -1 && _userinfo.user_mobile.length > 11) { - mobile = _userinfo.user_mobile.slice(2); - } else { - mobile = _userinfo.user_mobile; - } + let mobile = ""; + mobile = _userinfo.user_mobile.startsWith("+86") + ? _userinfo.user_mobile.replace("+86", "") + : _userinfo.user_mobile; this.checkAccountIsPass({ userInfo: _userinfo, mobile: mobile }); diff --git a/java-mall-app-shop-admin/pages/my/shopQRcode/shopQRcode.vue b/java-mall-app-shop-admin/pages/my/shopQRcode/shopQRcode.vue index 4fc56db..7628cb2 100644 --- a/java-mall-app-shop-admin/pages/my/shopQRcode/shopQRcode.vue +++ b/java-mall-app-shop-admin/pages/my/shopQRcode/shopQRcode.vue @@ -4,7 +4,7 @@ @@ -22,7 +22,7 @@ export default { }, onShow() {}, computed: { - ...mapState("account", ["accountInfo"]), + ...mapState("user", ["dashboardInfo"]), }, methods: { save() { @@ -31,7 +31,7 @@ export default { }); //下载图片 uni.downloadFile({ - url: this.accountInfo.store_info.wx_qrcode, + url: this.dashboardInfo.store_info.wx_qrcode, success: (res) => { if (res.statusCode === 200) { //鉴权 diff --git a/java-mall-app-shop-admin/pages/my/storeBusinessStatus/oz-timePicker/oz-timePicker.vue b/java-mall-app-shop-admin/pages/my/storeBusinessStatus/oz-timePicker/oz-timePicker.vue index 4d75607..ffcd45d 100644 --- a/java-mall-app-shop-admin/pages/my/storeBusinessStatus/oz-timePicker/oz-timePicker.vue +++ b/java-mall-app-shop-admin/pages/my/storeBusinessStatus/oz-timePicker/oz-timePicker.vue @@ -3,7 +3,7 @@ - + {{ title }} @@ -48,7 +48,7 @@ {{ item }} @@ -57,7 +57,7 @@ {{ item }} @@ -69,7 +69,7 @@ {{ startTime }} - 至 + 至 {{ endTime }} {{ totalTime }} @@ -85,7 +85,6 @@ 确认 - @@ -169,88 +168,99 @@ export default { }, data() { return { - rangeList: [], - pickerValue: [0, 0, 0, 0], + rangeList: [[], [], [], [], []], // 明确5个子数组 + pickerValue: [0, 0, 0, 0, 0], // 改为5个元素的数组 isScoll: false, // 是否正在滚动 - startTime:"", - endTime:"", - totalTime:"" + startTime: "00:00", + endTime: "00:00", + totalTime: "共0小时0分", + isValidTime: false, }; }, created() { - this.generateRangeLists(); - }, - watch: { - // 监听最大时间限制变化 - maxStartHour() { - this.generateRangeLists(); - }, - maxStartMinute() { - this.generateRangeLists(); - }, - maxEndHour() { - this.generateRangeLists(); - }, - maxEndMinute() { - this.generateRangeLists(); - }, + this.initTimeRanges(); + this.setInitialValue(); }, + methods: { - generateRangeLists() { - const ranges = [[], [], [], []]; + initTimeRanges() { + // 开始小时 (0-23) + this.rangeList[0] = Array.from({ length: 24 }, (_, i) => + i.toString().padStart(2, "0") + ); - // 生成开始小时范围 (0 - maxStartHour) - for (let i = 0; i <= this.maxStartHour; i++) { - ranges[0].push(i >= 10 ? String(i) : `0${i}`); + // 开始分钟 (0-59) + this.rangeList[1] = Array.from({ length: 60 }, (_, i) => + i.toString().padStart(2, "0") + ); + + // 分隔符 + this.rangeList[2] = [this.segmentation]; + + // 结束小时 (0-24) + this.rangeList[3] = Array.from({ length: 25 }, (_, i) => + i.toString().padStart(2, "0") + ); + + // 结束分钟 (初始为00-59) + this.rangeList[4] = Array.from({ length: 60 }, (_, i) => + i.toString().padStart(2, "0") + ); + }, + setInitialValue() { + // 确保value是有效的5元素数组,否则使用默认值 + if (!Array.isArray(this.value) || this.value.length !== 5) { + this.pickerValue = [0, 0, 0, 0, 0]; + return; } - // 生成开始分钟范围 (0 - maxStartMinute) - for (let i = 0; i <= this.maxStartMinute; i++) { - ranges[1].push(i >= 10 ? String(i) : `0${i}`); + // 转换value为pickerValue索引 + this.pickerValue = [ + Math.max(this.rangeList[0].indexOf(this.value[0]), 0), // 开始小时 + Math.max(this.rangeList[1].indexOf(this.value[1]), 0), // 开始分钟 + 0, // 分隔符位置固定为0 + Math.max(this.rangeList[3].indexOf(this.value[3]), 0), // 结束小时 + Math.max(this.rangeList[4].indexOf(this.value[4]), 0), // 结束分钟 + ]; + + // 处理24:00特殊情况 + if (this.value[3] === "24") { + this.pickerValue[4] = 0; + this.rangeList[4] = ["00"]; } - // 生成结束小时范围 (0 - maxEndHour) - for (let i = 0; i <= this.maxEndHour; i++) { - ranges[2].push(i >= 10 ? String(i) : `0${i}`); - } + // 强制更新视图 + this.$nextTick(() => { + this.calculateTimeDifference(); + }); + }, + handle24HourSelection() { + this.pickerValue[4] = 0; // 分钟强制为00 + this.rangeList[4] = ["00"]; // 分钟选项只保留00 + }, - // 生成结束分钟范围 (0 - maxEndMinute) - // 如果结束小时是24,分钟只能是00 - if ( - this.pickerValue && - this.pickerValue[2] === this.rangeList[2]?.length - 1 - ) { - ranges[3] = ["00"]; - } else { - for (let i = 0; i <= this.maxEndMinute; i++) { - ranges[3].push(i >= 10 ? String(i) : `0${i}`); - } + restoreMinuteOptions() { + this.rangeList[4] = Array.from({ length: 60 }, (_, i) => + i.toString().padStart(2, "0") + ); + }, + generateMinutesRange() { + const minutes = []; + for (let i = 0; i <= 59; i++) { + minutes.push(i.toString().padStart(2, "0")); } - this.rangeList = ranges; + return minutes; }, /** * 开启弹窗 */ open() { - this.generateRangeLists(); - - if (Array.isArray(this.value) && this.value.length) { - this.pickerValue = this.value.map((item, index) => { - const i = this.rangeList[index].findIndex( - (child) => Number(child) == Number(this.value[index]) - ); - return i > -1 ? i : 0; - }); - - // If initial end hour is 24, ensure minute is 00 - if (this.pickerValue[2] === this.rangeList[2]?.length - 1) { - this.pickerValue[3] = 0; - this.generateRangeLists(); - } - } else { - this.pickerValue = [0, 0, 0, 0]; - } + this.setInitialValue(); this.$refs.popup.open(); + // 添加延迟确保picker-view正确渲染 + setTimeout(() => { + this.calculateTimeDifference(); + }, 100); }, /** * 关闭弹窗 @@ -264,16 +274,23 @@ export default { * 点击确定 */ onConfirm() { - if (!this.isScoll) { - let data = this.value || ["00", "00", "00", "00"]; - if (this.pickerValue && this.pickerValue.length) { - data = this.pickerValue.map((item, index) => - String(this.rangeList[index][item]) - ); - } - this.$emit("confirm", data); - this.close(); + if (!this.isValidTime) { + uni.showToast({ + title: "开始时间和结束时间至少相差半小时", + icon: "none", + }); + return; } + + const result = [ + this.rangeList[0][this.pickerValue[0]], + this.rangeList[1][this.pickerValue[1]], + this.rangeList[3][this.pickerValue[3]], + this.rangeList[4][this.pickerValue[4]], + ]; + + this.$emit("confirm", result); + this.close(); }, /** * 点击取消 @@ -298,48 +315,84 @@ export default { * @param {Object} e */ bindChange(e) { - const newValue = [...e.detail.value]; - - // 更新 pickerValue + + // 处理24小时选择 + if (newValue[3] === this.rangeList[3].length - 1) { + // 选择24小时 + newValue[4] = 0; // 强制分钟为00 + this.rangeList[4] = ["00"]; + } else if (this.pickerValue[3] === this.rangeList[3].length - 1) { + // 从24小时切换 + this.rangeList[4] = Array.from({ length: 60 }, (_, i) => + i.toString().padStart(2, "0") + ); + } + this.pickerValue = newValue; + this.calculateTimeDifference(); + }, + calculateTimeDifference() { + // 确保获取有效的数值 + const getValidNumber = (val) => (isNaN(val) ? 0 : val); - // 计算 startTime (前两列: 小时和分钟) - const startHour = this.rangeList[0][newValue[0]]; - const startMinute = this.rangeList[1][newValue[1]]; - const startTime = `${startHour}:${startMinute}`; + const startHour = getValidNumber( + parseInt(this.rangeList[0][this.pickerValue[0]]) + ); + const startMinute = getValidNumber( + parseInt(this.rangeList[1][this.pickerValue[1]]) + ); + const endHour = getValidNumber( + parseInt(this.rangeList[3][this.pickerValue[3]]) + ); + let endMinute = getValidNumber( + parseInt(this.rangeList[4][this.pickerValue[4]]) + ); - // 计算 endTime (后两列: 小时和分钟) - const endHour = this.rangeList[3][newValue[3]]; - const endMinute = this.rangeList[4][newValue[4]]; - const endTime = `${endHour}:${endMinute}`; - - // 计算总时长 totalTime - const startDate = new Date(2000, 0, 1, parseInt(startHour), parseInt(startMinute)); - const endDate = new Date(2000, 0, 1, parseInt(endHour), parseInt(endMinute)); - - // 处理跨天情况(如23:00到01:00) - if (endDate < startDate) { - endDate.setDate(endDate.getDate() + 1); + // 处理24:00特殊情况 + if (endHour === 24) { + endMinute = 0; + this.endTime = "24:00"; + } else { + this.endTime = `${endHour.toString().padStart(2, "0")}:${endMinute + .toString() + .padStart(2, "0")}`; } - - const diffMs = endDate - startDate; - const diffHours = Math.floor(diffMs / (1000 * 60 * 60)); - const diffMinutes = Math.floor((diffMs % (1000 * 60 * 60)) / (1000 * 60)); - - const totalTime = `共${diffHours}小时${diffMinutes}分`; - // 更新到data中以便在模板显示 - this.startTime = startTime; - this.endTime = endTime; - this.totalTime = totalTime; + this.startTime = `${startHour.toString().padStart(2, "0")}:${startMinute + .toString() + .padStart(2, "0")}`; - // 检查是否需要限制分钟选择(如选择24:00时分钟只能是00) - if (newValue[3] === this.rangeList[3]?.length - 1) { // 假设24是最后一小时 - newValue[4] = 0; // 设置为00分钟 - this.pickerValue = newValue; - this.generateRangeLists(); + // 计算时间差(分钟) + const startTotal = startHour * 60 + startMinute; + const endTotal = endHour * 60 + endMinute; + let diffMinutes = endTotal - startTotal; + + // 处理跨天情况 + if (diffMinutes < 0) { + diffMinutes += 1440; // 24小时*60分钟 } + + // 验证时间差 + if (diffMinutes === 0) { + this.totalTime = "开始时间需早于结束时间"; + this.isValidTime = false; + } else if (diffMinutes < 30) { + this.totalTime = "时间差需至少30分钟"; + this.isValidTime = false; + } else { + const hours = Math.floor(diffMinutes / 60); + const minutes = diffMinutes % 60; + this.totalTime = `共${hours}小时${minutes}分`; + this.isValidTime = true; + } + }, + pickstart() { + this.isScoll = true; + }, + + pickend() { + this.isScoll = false; }, }, }; @@ -433,15 +486,15 @@ export default { line-height: 80rpx; } -::v-deep .picker-view{ +::v-deep .picker-view { height: 60%; } -.bottom-content{ +.bottom-content { background: #fff; - box-shadow: 0 0 4rpx 4rpx rgba(0, 0, 0, 0.1); + box-shadow: 0 0 28rpx 4rpx rgba(0, 0, 0, 0.1); - .bottom-time{ + .bottom-time { display: flex; justify-content: space-between; padding: 20rpx 28rpx; @@ -449,10 +502,10 @@ export default { font-weight: bold; } - .bottom-btn{ + .bottom-btn { padding: 28rpx 40rpx 80rpx; - .btn-time{ + .btn-time { background: $base-color; color: #fff; @@ -461,8 +514,5 @@ export default { } } } - - } - diff --git a/java-mall-app-shop-admin/pages/my/storeBusinessStatus/updateBusinessTime.vue b/java-mall-app-shop-admin/pages/my/storeBusinessStatus/updateBusinessTime.vue index 75b5de3..abbaec5 100644 --- a/java-mall-app-shop-admin/pages/my/storeBusinessStatus/updateBusinessTime.vue +++ b/java-mall-app-shop-admin/pages/my/storeBusinessStatus/updateBusinessTime.vue @@ -11,16 +11,28 @@ - 23:30 + {{ storeBaseInfo.info.store_opening_hours }} 至 - 23:30 + {{ storeBaseInfo.info.store_close_hours }} + + + 确认修改 + + @@ -31,6 +43,7 @@ import { GetAccountDashboard } from "../../../api/user"; import { UpdateStoreBizState } from "../../../api/store"; import tuiDatetime from "./tui-datetime/tui-datetime.vue"; import ozTimePicker from "./oz-timePicker/oz-timePicker.vue"; +import { GetShopBaseInfo, UpdataShopInfo } from "@/api/shop"; export default { components: { tuiDatetime, @@ -71,6 +84,13 @@ export default { }, showPopup: false, dateTime: "", + storeBaseInfo: { + info: { + store_opening_hours: "", + store_close_hours: "", + }, + }, + timeValue: ["00", "00", "至", "00", "00"], }; }, computed: { @@ -79,9 +99,20 @@ export default { }, }, onShow() { + this.getShopBaseInfo(); this.getAccountDashboard(); }, methods: { + async getShopBaseInfo() { + let res = await GetShopBaseInfo(); + if (res && res.status == 200) { + this.storeBaseInfo = res.data; + const startTime = + this.storeBaseInfo.info.store_opening_hours.split(":"); + const endTime = this.storeBaseInfo.info.store_close_hours.split(":"); + this.timeValue = [...startTime, "至", ...endTime]; + } + }, async getAccountDashboard() { let res = await GetAccountDashboard(); if (res && res.status == 200) { @@ -95,6 +126,26 @@ export default { closeTimePopup() { this.showPopup = false; }, + handerConfirmTiem(e) { + this.storeBaseInfo.info.store_opening_hours = e[0] + ":" + e[1]; + this.storeBaseInfo.info.store_close_hours = e[2] + ":" + e[3]; + }, + async updateStoreBizState() { + var params = { + store_id: this.storeBaseInfo.store_id, + store_opening_hours: this.storeBaseInfo.info.store_opening_hours, + store_close_hours: this.storeBaseInfo.info.store_close_hours, + store_biz_state: this.storeBaseInfo.store_biz_state, + }; + + let res = await UpdateStoreBizState(params); + if (res && res.status == 200) { + uni.showToast({ + title: "修改成功", + icon: "success", + }); + } + }, }, }; @@ -150,6 +201,7 @@ export default { padding: 36rpx 40rpx; border-radius: 24rpx; background: #f5f6fa; + font-weight: 500; } } @@ -166,5 +218,25 @@ export default { } } } + + .business-time-bottm { + position: fixed; + left: 0; + bottom: 0; + width: 90%; + background: #fff; + box-shadow: 0 0 28rpx 4rpx rgba(0, 0, 0, 0.1); + + padding: 28rpx 40rpx 80rpx; + + .btn-time { + background: $base-color; + color: #fff; + border: none; + &::after { + border: none; + } + } + } } diff --git a/java-mall-app-shop-admin/pages/order/order.vue b/java-mall-app-shop-admin/pages/order/order.vue index 53bf170..a9083a6 100644 --- a/java-mall-app-shop-admin/pages/order/order.vue +++ b/java-mall-app-shop-admin/pages/order/order.vue @@ -30,7 +30,7 @@ :width="300" :currentTab="currentTab2" @change="handleTab2" - backgroundColor="#f5f5f5" + backgroundColor="#fff" :height="88" unlined :sliderWidth="150" @@ -42,10 +42,7 @@ sliderBgColor="#fe4119" > - + --> + + + {{ item.label }} + + - + 正在加载... @@ -325,7 +338,7 @@ 暂无交易记录! @@ -416,7 +429,7 @@ {{ item.order_pickup_num_str }} - 备注: + 备注: {{ item.buyer_info.order_message }} @@ -543,11 +556,11 @@ - + {{ item.showRefundOrderInfo ? "收起订单" : "展开订单" }} - + 正在加载... @@ -575,7 +588,7 @@ 暂无交易记录! @@ -590,12 +603,13 @@ animation="spinner15" > @@ -620,10 +634,10 @@ font-weight: bold; " > - 3 + {{ item.orderNum }} - 订单号:{{ item.order_id }} + 退货单号:{{ item.return_id }} @@ -631,11 +645,11 @@ {{ sfFormatStatus(item.order_state_id) }} - + - + + - 张先生 手机尾号3158 + + {{ item.detailsInfo.da_name }}先生 手机尾号{{ + item.detailsInfo.da_mobile.slice(-4) + }} + + - 收货地址:金凤凰商业街18号4楼(桂平发发网络有限公司) + 收货地址:{{ item.detailsInfo.da_address }} - 备注: - 【如遇缺货】:缺货时请与我电话联系 + 退货理由: + {{ item.return_buyer_message }} + + + 退货凭据 + + + - {{ commodityArr.length }} + + {{ item.detailsInfo.items[0].return_item_num }} + 件商品 - + - {{ item.name }} - + {{ group.product_name }} + + X - {{ item.num }} + + {{ group.return_item_num }} + + + + ¥{{ group.return_item_subtotal }} - ¥{{ item.price }} - + - + + - 预计收入 + 实际退款总额 - ¥24.95 + {{ item.return_refund_amount }} + 元 - + - - 拒绝退款 - 同意退款 + + + 拒绝退款 + + + 同意退款 + - - {{ item.showRefundOrderInfo ? "收起订单" : "展开订单" }} - + + {{ item.return_state_name }} + + + {{ item.return_add_time }} + + {{ item.showRefundOrderInfo ? "收起订单" : "展开订单" }} + + - - + + 正在加载... @@ -790,26 +882,101 @@ 暂无交易记录! + + + + + {{ returnOrderType == "pass" ? "退货确认" : "拒绝退款" }} + + + 退货类型: + + + + + {{ item.name }} + + + + + + + + + + 取消 + + + 确认 + + + + @@ -1178,7 +1610,7 @@ export default { @import "@/styles/variables.scss"; .index-container { // overflow: hidden; - background: #f5f5f5; + background: #eeeff3; min-height: 100vh; .shop-info { display: flex; @@ -1207,12 +1639,23 @@ export default { } .tab-content { - margin-bottom: 20rpx; + padding-bottom: 20rpx; background: #fff; } .tab2-content { - background: #f5f5f5; + background: #fff; + } + + .sales-return-img-title { + margin: 20rpx; + font-weight: bold; + } + + .sales-return-img-list { + display: flex; + flex-wrap: wrap; + margin: 40rpx 20rpx; } .search-contetn { @@ -1232,11 +1675,37 @@ export default { } } + .sales-retrun-btn-list { + margin: 38rpx 24rpx 0; + height: 160rpx; + + .sales-retrun-btn-item { + float: left !important; + height: 60rpx; + margin-left: 20rpx; + margin-bottom: 20rpx; + border: none; + + ::after { + border: none; + } + } + + .active { + background: $base-color; + color: #fff; + } + } + .order-info-content { border-radius: 8rpx; .uni-swiper-list { - height: calc(100vh - 310px); + height: calc(100vh - 320px); + } + + .uni-swiper-return-list { + height: calc(100vh - 350px); } .order-msg-tips { @@ -1324,6 +1793,8 @@ export default { border-bottom: 1px solid #f7f7f7; .user-info { + display: flex; + align-items: center; font-size: 26rpx; margin-bottom: 20rpx; } @@ -1494,6 +1965,14 @@ export default { margin-top: 40rpx; font-size: 26rpx; color: #cccccc; + + .time { + color: #333333; + } + } + + .arrow-item-2 { + justify-content: space-between; } } } @@ -1562,9 +2041,6 @@ export default { } } - .btn-down-list { - } - .tui-animation { display: inline-block; transform: rotate(0deg); @@ -1574,5 +2050,80 @@ export default { .tui-animation-show { transform: rotate(180deg); } + + .icon-phone-fill { + margin-left: 10%; + } + + .retrun-state-name { + color: $base-color; + } + + .return-order-popup { + .return-order-popup-content { + width: 600rpx; + min-height: 600rpx; + + .title { + margin: 36rpx; + text-align: center; + font-weight: bold; + font-size: 36rpx; + } + + .radio-content { + display: flex; + justify-content: space-between; + align-items: center; + margin: 60rpx 40rpx 40rpx; + + .radio-type-name { + font-weight: 500; + } + + .radio-list { + flex: 1; + .radio-group { + display: flex; + align-items: center; + justify-content: space-around; + line-height: 40rpx; + + .radio-name { + margin-left: 8rpx; + } + } + } + } + + .popup-textarea { + margin: 28rpx; + .textarea { + border: 1px solid #eeeff3; + } + } + + .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; + } + } + } + } } diff --git a/java-mall-app-shop-admin/pages/warehouse/manage/batch.vue b/java-mall-app-shop-admin/pages/warehouse/manage/batch.vue new file mode 100644 index 0000000..d55bdaf --- /dev/null +++ b/java-mall-app-shop-admin/pages/warehouse/manage/batch.vue @@ -0,0 +1,1988 @@ + + + + + + + + + + + + + + + + + {{ item.label }} + + + + + {{ group.label }} + + + + + + + + + + + + + + + + 已勾选{{ + tabbar[current].children[currTabChildrenIndex].checkboxList + .length + }}个 + + + + + + + + + 已勾选{{ tabbar[current].checkboxList.length }}个 + + + + + + 暂无商品 + + + + + + + + + + + + + {{ item.product_name }} + + + 库存{{ item.itemQuantity }} + + + ¥ + {{ item.product_unit_price }} + + + + + + + + + + + + + + + + {{ item.product_name }} + + + 库存{{ item.itemQuantity }} + + + ¥ + {{ item.product_unit_price }} + + + + + + + + + + 正在加载... + + + + + 没有更多商品了 ~ + + + + + + + + + 共选择{{ selectCommodityList.length }}/100 + + 查看 + + + + + + 上架 + + + 下架 + + + 删除 + + + + + + + 已选商品 + + + 共选择 + {{ selectCommodityList.length }}/100 + 个商品 + + + 清空已选 + + + + + + + + + + + + {{ item.product_name }} + + + 库存{{ item.itemQuantity }} + + + ¥ + {{ item.product_unit_price }} + + + + + + + + + + + + + + 确认清空 + + 已选择 + + {{ this.selectCommodityList.length }} + + 个商品,清空后需要重新勾选 + + + + 取消 + + + 清空 + + + + + + + 确认删除 + + 当前已选择 + + {{ this.selectCommodityList.length }} + + 个商品,删除后不可恢复! + + + + 取消 + + + 删除 + + + + + + + 确认退出 + + 已选择 + + {{ this.selectCommodityList.length }} + + 个商品,现在退出将不保留操作几率 + + + + 取消 + + + 确认 + + + + + + + + + + + + + + diff --git a/java-mall-app-shop-admin/pages/warehouse/manage/batchSearch.vue b/java-mall-app-shop-admin/pages/warehouse/manage/batchSearch.vue new file mode 100644 index 0000000..c8c50de --- /dev/null +++ b/java-mall-app-shop-admin/pages/warehouse/manage/batchSearch.vue @@ -0,0 +1,810 @@ + + + + + + + + + + + + + + + + 暂无商品 + + + + + + + + + + + + + + 库存{{ item.itemQuantity }} + + + ¥ + {{ item.product_unit_price }} + + + + + + + + + + 正在加载... + + + + + 没有更多商品了 ~ + + + + + + + + + + 确定选择 + + + + + 确认退出 + + 您搜索后选择或取消选择商品的操作暂未保存,现在退出将全部失效,确认退出么? + + + + 取消 + + + 确认 + + + + + + + + + + + + diff --git a/java-mall-app-shop-admin/pages/warehouse/manage/brandList.vue b/java-mall-app-shop-admin/pages/warehouse/manage/brandList.vue new file mode 100644 index 0000000..e69de29 diff --git a/java-mall-app-shop-admin/pages/warehouse/manage/classifyList.vue b/java-mall-app-shop-admin/pages/warehouse/manage/classifyList.vue new file mode 100644 index 0000000..e69de29 diff --git a/java-mall-app-shop-admin/pages/warehouse/manage/components/tui-collapse/tui-collapse.vue b/java-mall-app-shop-admin/pages/warehouse/manage/components/tui-collapse/tui-collapse.vue new file mode 100644 index 0000000..0ac934d --- /dev/null +++ b/java-mall-app-shop-admin/pages/warehouse/manage/components/tui-collapse/tui-collapse.vue @@ -0,0 +1,187 @@ + + + + + + + + + + + + + + + + + + + diff --git a/java-mall-app-shop-admin/pages/warehouse/manage/photoGallery.vue b/java-mall-app-shop-admin/pages/warehouse/manage/photoGallery.vue new file mode 100644 index 0000000..e69de29 diff --git a/java-mall-app-shop-admin/pages/warehouse/manage/productList.vue b/java-mall-app-shop-admin/pages/warehouse/manage/productList.vue new file mode 100644 index 0000000..a537b7f --- /dev/null +++ b/java-mall-app-shop-admin/pages/warehouse/manage/productList.vue @@ -0,0 +1,974 @@ + + + + + + + + + + + + + + + + + {{ item.label }} + + + + + {{ group.label }} + + + + + + + + + + + + + 暂无商品 + + + + + + + + + + + {{ item.product_name }} + + + 库存{{ item.itemQuantity }} + + + ¥ + {{ item.product_unit_price }} + + + + + + 价格/库存 + + + 上架 + + + 下架 + + + 编辑 + + + + + + + + + 正在加载... + + + + + 没有更多商品了 ~ + + + + + + + + 分类管理 + + + 批量操作 + + + + 商品新建 + + + + + + + + diff --git a/java-mall-app-shop-admin/pages/warehouse/warehouse.vue b/java-mall-app-shop-admin/pages/warehouse/warehouse.vue new file mode 100644 index 0000000..ed81db4 --- /dev/null +++ b/java-mall-app-shop-admin/pages/warehouse/warehouse.vue @@ -0,0 +1,129 @@ + + + + {{ dashboardInfo.store_info.store_name }} + + + + + + 商品管理 + + + + + + 品牌管理 + + + + + + 分类管理 + + + + + + 商品图库 + + + + + + + + + diff --git a/java-mall-app-shop-admin/static/font/iconfont.css b/java-mall-app-shop-admin/static/font/iconfont.css index 89f7b91..a91cfd8 100644 --- a/java-mall-app-shop-admin/static/font/iconfont.css +++ b/java-mall-app-shop-admin/static/font/iconfont.css @@ -1,8 +1,8 @@ @font-face { font-family: "custom-icon"; /* Project id 4805967 */ - src: url('@/static/font/iconfont.woff2?t=1736404172628') format('woff2'), - url('@/static/font/iconfont.woff?t=1736404172628') format('woff'), - url('@/static/font/iconfont.ttf?t=1736404172628') format('truetype'); + src: url("@/static/font/iconfont.woff2?t=1736404172628") format("woff2"), + url("@/static/font/iconfont.woff?t=1736404172628") format("woff"), + url("@/static/font/iconfont.ttf?t=1736404172628") format("truetype"); } .custom-icon { @@ -21,6 +21,50 @@ -moz-osx-font-smoothing: grayscale; } +.custom-icon-jianhao:before { + content: "\e664"; +} + +.custom-icon-xinjiantuopu:before { + content: "\e83a"; +} + +.custom-icon-piliangcaozuo:before { + content: "\e66a"; +} + +.custom-icon-gongzuotai1:before { + content: "\e660"; +} + +.custom-icon-shangpinguanli:before { + content: "\e666"; +} + +.custom-icon-shangpinpinpai:before { + content: "\e6e6"; +} + +.custom-icon-xiangcetuku:before { + content: "\e63c"; +} + +.custom-icon-fenlei:before { + content: "\fc7d"; +} + +.custom-icon-mianxingtuku:before { + content: "\e60a"; +} + +.custom-icon-icon_shangpindangan_shangpinpinpai:before { + content: "\e60f"; +} + +.custom-icon-yingyezhuangtai:before { + content: "\e605"; +} + .custom-icon-shipin:before { content: "\e629"; } @@ -120,4 +164,3 @@ .custom-icon-password:before { content: "\e61d"; } - diff --git a/java-mall-app-shop-admin/static/font/iconfont.ttf b/java-mall-app-shop-admin/static/font/iconfont.ttf index 8c1d747..a0c4c98 100644 Binary files a/java-mall-app-shop-admin/static/font/iconfont.ttf and b/java-mall-app-shop-admin/static/font/iconfont.ttf differ diff --git a/java-mall-app-shop-admin/static/font/iconfont.woff b/java-mall-app-shop-admin/static/font/iconfont.woff index dc5eed4..84885ba 100644 Binary files a/java-mall-app-shop-admin/static/font/iconfont.woff and b/java-mall-app-shop-admin/static/font/iconfont.woff differ diff --git a/java-mall-app-shop-admin/static/font/iconfont.woff2 b/java-mall-app-shop-admin/static/font/iconfont.woff2 index d9ed4c1..b70e688 100644 Binary files a/java-mall-app-shop-admin/static/font/iconfont.woff2 and b/java-mall-app-shop-admin/static/font/iconfont.woff2 differ diff --git a/java-mall-app-shop-admin/static/no-commodity.png b/java-mall-app-shop-admin/static/no-commodity.png new file mode 100644 index 0000000..64c9d62 Binary files /dev/null and b/java-mall-app-shop-admin/static/no-commodity.png differ diff --git a/java-mall-app-shop-admin/static/warehouse/asdsad.png b/java-mall-app-shop-admin/static/warehouse/asdsad.png new file mode 100644 index 0000000..640ef72 Binary files /dev/null and b/java-mall-app-shop-admin/static/warehouse/asdsad.png differ diff --git a/java-mall-app-shop-admin/static/warehouse/brand-1.png b/java-mall-app-shop-admin/static/warehouse/brand-1.png new file mode 100644 index 0000000..f36a826 Binary files /dev/null and b/java-mall-app-shop-admin/static/warehouse/brand-1.png differ diff --git a/java-mall-app-shop-admin/static/warehouse/brand-2.png b/java-mall-app-shop-admin/static/warehouse/brand-2.png new file mode 100644 index 0000000..355adb5 Binary files /dev/null and b/java-mall-app-shop-admin/static/warehouse/brand-2.png differ diff --git a/java-mall-app-shop-admin/static/warehouse/brand-3.png b/java-mall-app-shop-admin/static/warehouse/brand-3.png new file mode 100644 index 0000000..b8dcc2b Binary files /dev/null and b/java-mall-app-shop-admin/static/warehouse/brand-3.png differ diff --git a/java-mall-app-shop-admin/static/warehouse/classify.png b/java-mall-app-shop-admin/static/warehouse/classify.png new file mode 100644 index 0000000..485885a Binary files /dev/null and b/java-mall-app-shop-admin/static/warehouse/classify.png differ diff --git a/java-mall-app-shop-admin/static/warehouse/photo-gallery-1.png b/java-mall-app-shop-admin/static/warehouse/photo-gallery-1.png new file mode 100644 index 0000000..9885685 Binary files /dev/null and b/java-mall-app-shop-admin/static/warehouse/photo-gallery-1.png differ diff --git a/java-mall-app-shop-admin/static/warehouse/photo-gallery.png b/java-mall-app-shop-admin/static/warehouse/photo-gallery.png new file mode 100644 index 0000000..31bf889 Binary files /dev/null and b/java-mall-app-shop-admin/static/warehouse/photo-gallery.png differ diff --git a/java-mall-app-shop-admin/store/index.js b/java-mall-app-shop-admin/store/index.js index 87ac695..87b8e60 100644 --- a/java-mall-app-shop-admin/store/index.js +++ b/java-mall-app-shop-admin/store/index.js @@ -1,7 +1,6 @@ import Vue from "vue"; import Vuex from "vuex"; import user from "./modules/user"; -import account from "./modules/account"; import order from "./modules/order"; import audit from "./modules/audit"; @@ -10,7 +9,6 @@ Vue.use(Vuex); const store = new Vuex.Store({ modules: { user, - account, order, audit, }, diff --git a/java-mall-app-shop-admin/store/modules/account.js b/java-mall-app-shop-admin/store/modules/account.js deleted file mode 100644 index c29f42d..0000000 --- a/java-mall-app-shop-admin/store/modules/account.js +++ /dev/null @@ -1,44 +0,0 @@ -const defaultState = () => { - return { - accountInfo: uni.getStorageSync('accountDashboard') || { - data: {}, - notice: {}, - order: {}, - product: { - illegal_num: 0, - normal_num: 0, - off_num: 0, - total_num: 0, - verify_passed_off_num: 0, - verify_refused_num: 0, - verify_waiting_num: 0, - }, - return: { - fin_num: 0, - review_num: 0, - total_num: 0, - un_fin_num: 0, - }, - store_info: { - store_id: 1, - wx_qrcode: '', - }, - }, - }; -}; - -const state = defaultState(); - -const getters = {}; - -const mutations = {}; - -const actions = {}; - -export default { - namespaced: true, - state, - getters, - mutations, - actions, -}; diff --git a/java-mall-app-shop-admin/store/modules/user.js b/java-mall-app-shop-admin/store/modules/user.js index b901538..4ce2c6b 100644 --- a/java-mall-app-shop-admin/store/modules/user.js +++ b/java-mall-app-shop-admin/store/modules/user.js @@ -20,6 +20,30 @@ const defaultState = () => { socket: {}, getMsg: {}, imWeidu: {}, + dashboardInfo: uni.getStorageSync("accountDashboard") || { + data: {}, + notice: {}, + order: {}, + product: { + illegal_num: 0, + normal_num: 0, + off_num: 0, + total_num: 0, + verify_passed_off_num: 0, + verify_refused_num: 0, + verify_waiting_num: 0, + }, + return: { + fin_num: 0, + review_num: 0, + total_num: 0, + un_fin_num: 0, + }, + store_info: { + store_id: "", + wx_qrcode: "", + }, + }, }; }; @@ -46,6 +70,7 @@ const mutations = { state.socket = {}; state.getMsg = {}; state.imWeidu = {}; + state.dashboardInfo = {}; }, CONNECT_SOCKET(state, { socket }) { state.socket = socket; @@ -101,13 +126,9 @@ const actions = { if (res && res.status == 200) { let mobile = ""; - let isContain = res.data.user_mobile.indexOf("86"); - - if (isContain != -1 && res.data.user_mobile.length > 11) { - mobile = res.data.user_mobile.slice(2); - } else { - mobile = res.data.user_mobile; - } + mobile = res.data.user_mobile.startsWith("+86") + ? res.data.user_mobile.replace("+86", "") + : res.data.user_mobile; const userInfo = res.data; @@ -148,13 +169,9 @@ const actions = { if (res && res.status == 200) { let mobile = ""; - let isContain = res.data.user_mobile.indexOf("86"); - - if (isContain != -1 && res.data.user_mobile.length > 11) { - mobile = res.data.user_mobile.slice(2); - } else { - mobile = res.data.user_mobile; - } + mobile = res.data.user_mobile.startsWith("+86") + ? res.data.user_mobile.replace("+86", "") + : res.data.user_mobile; const userInfo = res.data; diff --git a/java-mall-app-shop-admin/uni_modules/uview-ui/components/u-tabs/u-tabs.vue b/java-mall-app-shop-admin/uni_modules/uview-ui/components/u-tabs/u-tabs.vue index d2b3b03..0402280 100644 --- a/java-mall-app-shop-admin/uni_modules/uview-ui/components/u-tabs/u-tabs.vue +++ b/java-mall-app-shop-admin/uni_modules/uview-ui/components/u-tabs/u-tabs.vue @@ -167,7 +167,8 @@ .slice(0, this.innerCurrent) .reduce((total, curr) => total + curr.rect.width, 0); // 获取下划线的数值px表示法 - const lineWidth = uni.$u.getPx(this.lineWidth); + const lineWidth = uni.$u.getPx(uni.$u.addUnit(this.lineWidth)); + this.lineOffsetLeft = lineOffsetLeft + (tabItem.rect.width - lineWidth) / 2 // #ifdef APP-NVUE // 第一次移动滑块,无需过渡时间 diff --git a/java-mall-app-shop-admin/utils/exif.js b/java-mall-app-shop-admin/utils/exif.js new file mode 100644 index 0000000..a5e4cbe --- /dev/null +++ b/java-mall-app-shop-admin/utils/exif.js @@ -0,0 +1,1144 @@ +(function () { + var debug = false; + + var root = this; + + var EXIF = function (obj) { + if (obj instanceof EXIF) return obj; + if (!(this instanceof EXIF)) return new EXIF(obj); + this.EXIFwrapped = obj; + }; + + if (typeof exports !== "undefined") { + if (typeof module !== "undefined" && module.exports) { + exports = module.exports = EXIF; + } + exports.EXIF = EXIF; + } else { + root.EXIF = EXIF; + } + + var ExifTags = (EXIF.Tags = { + // version tags + 0x9000: "ExifVersion", // EXIF version + 0xa000: "FlashpixVersion", // Flashpix format version + + // colorspace tags + 0xa001: "ColorSpace", // Color space information tag + + // image configuration + 0xa002: "PixelXDimension", // Valid width of meaningful image + 0xa003: "PixelYDimension", // Valid height of meaningful image + 0x9101: "ComponentsConfiguration", // Information about channels + 0x9102: "CompressedBitsPerPixel", // Compressed bits per pixel + + // user information + 0x927c: "MakerNote", // Any desired information written by the manufacturer + 0x9286: "UserComment", // Comments by user + + // related file + 0xa004: "RelatedSoundFile", // Name of related sound file + + // date and time + 0x9003: "DateTimeOriginal", // Date and time when the original image was generated + 0x9004: "DateTimeDigitized", // Date and time when the image was stored digitally + 0x9290: "SubsecTime", // Fractions of seconds for DateTime + 0x9291: "SubsecTimeOriginal", // Fractions of seconds for DateTimeOriginal + 0x9292: "SubsecTimeDigitized", // Fractions of seconds for DateTimeDigitized + + // picture-taking conditions + 0x829a: "ExposureTime", // Exposure time (in seconds) + 0x829d: "FNumber", // F number + 0x8822: "ExposureProgram", // Exposure program + 0x8824: "SpectralSensitivity", // Spectral sensitivity + 0x8827: "ISOSpeedRatings", // ISO speed rating + 0x8828: "OECF", // Optoelectric conversion factor + 0x9201: "ShutterSpeedValue", // Shutter speed + 0x9202: "ApertureValue", // Lens aperture + 0x9203: "BrightnessValue", // Value of brightness + 0x9204: "ExposureBias", // Exposure bias + 0x9205: "MaxApertureValue", // Smallest F number of lens + 0x9206: "SubjectDistance", // Distance to subject in meters + 0x9207: "MeteringMode", // Metering mode + 0x9208: "LightSource", // Kind of light source + 0x9209: "Flash", // Flash status + 0x9214: "SubjectArea", // Location and area of main subject + 0x920a: "FocalLength", // Focal length of the lens in mm + 0xa20b: "FlashEnergy", // Strobe energy in BCPS + 0xa20c: "SpatialFrequencyResponse", // + 0xa20e: "FocalPlaneXResolution", // Number of pixels in width direction per FocalPlaneResolutionUnit + 0xa20f: "FocalPlaneYResolution", // Number of pixels in height direction per FocalPlaneResolutionUnit + 0xa210: "FocalPlaneResolutionUnit", // Unit for measuring FocalPlaneXResolution and FocalPlaneYResolution + 0xa214: "SubjectLocation", // Location of subject in image + 0xa215: "ExposureIndex", // Exposure index selected on camera + 0xa217: "SensingMethod", // Image sensor type + 0xa300: "FileSource", // Image source (3 == DSC) + 0xa301: "SceneType", // Scene type (1 == directly photographed) + 0xa302: "CFAPattern", // Color filter array geometric pattern + 0xa401: "CustomRendered", // Special processing + 0xa402: "ExposureMode", // Exposure mode + 0xa403: "WhiteBalance", // 1 = auto white balance, 2 = manual + 0xa404: "DigitalZoomRation", // Digital zoom ratio + 0xa405: "FocalLengthIn35mmFilm", // Equivalent foacl length assuming 35mm film camera (in mm) + 0xa406: "SceneCaptureType", // Type of scene + 0xa407: "GainControl", // Degree of overall image gain adjustment + 0xa408: "Contrast", // Direction of contrast processing applied by camera + 0xa409: "Saturation", // Direction of saturation processing applied by camera + 0xa40a: "Sharpness", // Direction of sharpness processing applied by camera + 0xa40b: "DeviceSettingDescription", // + 0xa40c: "SubjectDistanceRange", // Distance to subject + + // other tags + 0xa005: "InteroperabilityIFDPointer", + 0xa420: "ImageUniqueID", // Identifier assigned uniquely to each image + }); + + var TiffTags = (EXIF.TiffTags = { + 0x0100: "ImageWidth", + 0x0101: "ImageHeight", + 0x8769: "ExifIFDPointer", + 0x8825: "GPSInfoIFDPointer", + 0xa005: "InteroperabilityIFDPointer", + 0x0102: "BitsPerSample", + 0x0103: "Compression", + 0x0106: "PhotometricInterpretation", + 0x0112: "Orientation", + 0x0115: "SamplesPerPixel", + 0x011c: "PlanarConfiguration", + 0x0212: "YCbCrSubSampling", + 0x0213: "YCbCrPositioning", + 0x011a: "XResolution", + 0x011b: "YResolution", + 0x0128: "ResolutionUnit", + 0x0111: "StripOffsets", + 0x0116: "RowsPerStrip", + 0x0117: "StripByteCounts", + 0x0201: "JPEGInterchangeFormat", + 0x0202: "JPEGInterchangeFormatLength", + 0x012d: "TransferFunction", + 0x013e: "WhitePoint", + 0x013f: "PrimaryChromaticities", + 0x0211: "YCbCrCoefficients", + 0x0214: "ReferenceBlackWhite", + 0x0132: "DateTime", + 0x010e: "ImageDescription", + 0x010f: "Make", + 0x0110: "Model", + 0x0131: "Software", + 0x013b: "Artist", + 0x8298: "Copyright", + }); + + var GPSTags = (EXIF.GPSTags = { + 0x0000: "GPSVersionID", + 0x0001: "GPSLatitudeRef", + 0x0002: "GPSLatitude", + 0x0003: "GPSLongitudeRef", + 0x0004: "GPSLongitude", + 0x0005: "GPSAltitudeRef", + 0x0006: "GPSAltitude", + 0x0007: "GPSTimeStamp", + 0x0008: "GPSSatellites", + 0x0009: "GPSStatus", + 0x000a: "GPSMeasureMode", + 0x000b: "GPSDOP", + 0x000c: "GPSSpeedRef", + 0x000d: "GPSSpeed", + 0x000e: "GPSTrackRef", + 0x000f: "GPSTrack", + 0x0010: "GPSImgDirectionRef", + 0x0011: "GPSImgDirection", + 0x0012: "GPSMapDatum", + 0x0013: "GPSDestLatitudeRef", + 0x0014: "GPSDestLatitude", + 0x0015: "GPSDestLongitudeRef", + 0x0016: "GPSDestLongitude", + 0x0017: "GPSDestBearingRef", + 0x0018: "GPSDestBearing", + 0x0019: "GPSDestDistanceRef", + 0x001a: "GPSDestDistance", + 0x001b: "GPSProcessingMethod", + 0x001c: "GPSAreaInformation", + 0x001d: "GPSDateStamp", + 0x001e: "GPSDifferential", + }); + + // EXIF 2.3 Spec + var IFD1Tags = (EXIF.IFD1Tags = { + 0x0100: "ImageWidth", + 0x0101: "ImageHeight", + 0x0102: "BitsPerSample", + 0x0103: "Compression", + 0x0106: "PhotometricInterpretation", + 0x0111: "StripOffsets", + 0x0112: "Orientation", + 0x0115: "SamplesPerPixel", + 0x0116: "RowsPerStrip", + 0x0117: "StripByteCounts", + 0x011a: "XResolution", + 0x011b: "YResolution", + 0x011c: "PlanarConfiguration", + 0x0128: "ResolutionUnit", + 0x0201: "JpegIFOffset", // When image format is JPEG, this value show offset to JPEG data stored.(aka "ThumbnailOffset" or "JPEGInterchangeFormat") + 0x0202: "JpegIFByteCount", // When image format is JPEG, this value shows data size of JPEG image (aka "ThumbnailLength" or "JPEGInterchangeFormatLength") + 0x0211: "YCbCrCoefficients", + 0x0212: "YCbCrSubSampling", + 0x0213: "YCbCrPositioning", + 0x0214: "ReferenceBlackWhite", + }); + + var StringValues = (EXIF.StringValues = { + ExposureProgram: { + 0: "Not defined", + 1: "Manual", + 2: "Normal program", + 3: "Aperture priority", + 4: "Shutter priority", + 5: "Creative program", + 6: "Action program", + 7: "Portrait mode", + 8: "Landscape mode", + }, + MeteringMode: { + 0: "Unknown", + 1: "Average", + 2: "CenterWeightedAverage", + 3: "Spot", + 4: "MultiSpot", + 5: "Pattern", + 6: "Partial", + 255: "Other", + }, + LightSource: { + 0: "Unknown", + 1: "Daylight", + 2: "Fluorescent", + 3: "Tungsten (incandescent light)", + 4: "Flash", + 9: "Fine weather", + 10: "Cloudy weather", + 11: "Shade", + 12: "Daylight fluorescent (D 5700 - 7100K)", + 13: "Day white fluorescent (N 4600 - 5400K)", + 14: "Cool white fluorescent (W 3900 - 4500K)", + 15: "White fluorescent (WW 3200 - 3700K)", + 17: "Standard light A", + 18: "Standard light B", + 19: "Standard light C", + 20: "D55", + 21: "D65", + 22: "D75", + 23: "D50", + 24: "ISO studio tungsten", + 255: "Other", + }, + Flash: { + 0x0000: "Flash did not fire", + 0x0001: "Flash fired", + 0x0005: "Strobe return light not detected", + 0x0007: "Strobe return light detected", + 0x0009: "Flash fired, compulsory flash mode", + 0x000d: "Flash fired, compulsory flash mode, return light not detected", + 0x000f: "Flash fired, compulsory flash mode, return light detected", + 0x0010: "Flash did not fire, compulsory flash mode", + 0x0018: "Flash did not fire, auto mode", + 0x0019: "Flash fired, auto mode", + 0x001d: "Flash fired, auto mode, return light not detected", + 0x001f: "Flash fired, auto mode, return light detected", + 0x0020: "No flash function", + 0x0041: "Flash fired, red-eye reduction mode", + 0x0045: "Flash fired, red-eye reduction mode, return light not detected", + 0x0047: "Flash fired, red-eye reduction mode, return light detected", + 0x0049: "Flash fired, compulsory flash mode, red-eye reduction mode", + 0x004d: + "Flash fired, compulsory flash mode, red-eye reduction mode, return light not detected", + 0x004f: + "Flash fired, compulsory flash mode, red-eye reduction mode, return light detected", + 0x0059: "Flash fired, auto mode, red-eye reduction mode", + 0x005d: + "Flash fired, auto mode, return light not detected, red-eye reduction mode", + 0x005f: + "Flash fired, auto mode, return light detected, red-eye reduction mode", + }, + SensingMethod: { + 1: "Not defined", + 2: "One-chip color area sensor", + 3: "Two-chip color area sensor", + 4: "Three-chip color area sensor", + 5: "Color sequential area sensor", + 7: "Trilinear sensor", + 8: "Color sequential linear sensor", + }, + SceneCaptureType: { + 0: "Standard", + 1: "Landscape", + 2: "Portrait", + 3: "Night scene", + }, + SceneType: { + 1: "Directly photographed", + }, + CustomRendered: { + 0: "Normal process", + 1: "Custom process", + }, + WhiteBalance: { + 0: "Auto white balance", + 1: "Manual white balance", + }, + GainControl: { + 0: "None", + 1: "Low gain up", + 2: "High gain up", + 3: "Low gain down", + 4: "High gain down", + }, + Contrast: { + 0: "Normal", + 1: "Soft", + 2: "Hard", + }, + Saturation: { + 0: "Normal", + 1: "Low saturation", + 2: "High saturation", + }, + Sharpness: { + 0: "Normal", + 1: "Soft", + 2: "Hard", + }, + SubjectDistanceRange: { + 0: "Unknown", + 1: "Macro", + 2: "Close view", + 3: "Distant view", + }, + FileSource: { + 3: "DSC", + }, + + Components: { + 0: "", + 1: "Y", + 2: "Cb", + 3: "Cr", + 4: "R", + 5: "G", + 6: "B", + }, + }); + + function addEvent(element, event, handler) { + if (element.addEventListener) { + element.addEventListener(event, handler, false); + } else if (element.attachEvent) { + element.attachEvent("on" + event, handler); + } + } + + function imageHasData(img) { + return !!img.exifdata; + } + + function base64ToArrayBuffer(base64, contentType) { + contentType = + contentType || base64.match(/^data\:([^\;]+)\;base64,/im)[1] || ""; // e.g. 'data:image/jpeg;base64,...' => 'image/jpeg' + base64 = base64.replace(/^data\:([^\;]+)\;base64,/gim, ""); + var binary = atob(base64); + var len = binary.length; + var buffer = new ArrayBuffer(len); + var view = new Uint8Array(buffer); + for (var i = 0; i < len; i++) { + view[i] = binary.charCodeAt(i); + } + return buffer; + } + + function objectURLToBlob(url, callback) { + var http = new XMLHttpRequest(); + http.open("GET", url, true); + http.responseType = "blob"; + http.onload = function (e) { + if (this.status == 200 || this.status === 0) { + callback(this.response); + } + }; + http.send(); + } + + function getImageData(img, callback) { + function handleBinaryFile(binFile) { + var data = findEXIFinJPEG(binFile); + img.exifdata = data || {}; + var iptcdata = findIPTCinJPEG(binFile); + img.iptcdata = iptcdata || {}; + if (EXIF.isXmpEnabled) { + var xmpdata = findXMPinJPEG(binFile); + img.xmpdata = xmpdata || {}; + } + if (callback) { + callback.call(img); + } + } + + if (img.src) { + if (/^data\:/i.test(img.src)) { + // Data URI + var arrayBuffer = base64ToArrayBuffer(img.src); + handleBinaryFile(arrayBuffer); + } else if (/^blob\:/i.test(img.src)) { + // Object URL + var fileReader = new FileReader(); + fileReader.onload = function (e) { + handleBinaryFile(e.target.result); + }; + objectURLToBlob(img.src, function (blob) { + fileReader.readAsArrayBuffer(blob); + }); + } else { + var http = new XMLHttpRequest(); + http.onload = function () { + if (this.status == 200 || this.status === 0) { + handleBinaryFile(http.response); + } else { + throw "Could not load image"; + } + http = null; + }; + http.open("GET", img.src, true); + http.responseType = "arraybuffer"; + http.send(null); + } + } else if ( + self.FileReader && + (img instanceof self.Blob || img instanceof self.File) + ) { + var fileReader = new FileReader(); + fileReader.onload = function (e) { + if (debug) + console.log("Got file of length " + e.target.result.byteLength); + handleBinaryFile(e.target.result); + }; + + fileReader.readAsArrayBuffer(img); + } + } + + function findEXIFinJPEG(file) { + var dataView = new DataView(file); + + if (debug) console.log("Got file of length " + file.byteLength); + if (dataView.getUint8(0) != 0xff || dataView.getUint8(1) != 0xd8) { + if (debug) console.log("Not a valid JPEG"); + return false; // not a valid jpeg + } + + var offset = 2, + length = file.byteLength, + marker; + + while (offset < length) { + if (dataView.getUint8(offset) != 0xff) { + if (debug) + console.log( + "Not a valid marker at offset " + + offset + + ", found: " + + dataView.getUint8(offset) + ); + return false; // not a valid marker, something is wrong + } + + marker = dataView.getUint8(offset + 1); + if (debug) console.log(marker); + + // we could implement handling for other markers here, + // but we're only looking for 0xFFE1 for EXIF data + + if (marker == 225) { + if (debug) console.log("Found 0xFFE1 marker"); + + return readEXIFData( + dataView, + offset + 4, + dataView.getUint16(offset + 2) - 2 + ); + + // offset += 2 + file.getShortAt(offset+2, true); + } else { + offset += 2 + dataView.getUint16(offset + 2); + } + } + } + + function findIPTCinJPEG(file) { + var dataView = new DataView(file); + + if (debug) console.log("Got file of length " + file.byteLength); + if (dataView.getUint8(0) != 0xff || dataView.getUint8(1) != 0xd8) { + if (debug) console.log("Not a valid JPEG"); + return false; // not a valid jpeg + } + + var offset = 2, + length = file.byteLength; + + var isFieldSegmentStart = function (dataView, offset) { + return ( + dataView.getUint8(offset) === 0x38 && + dataView.getUint8(offset + 1) === 0x42 && + dataView.getUint8(offset + 2) === 0x49 && + dataView.getUint8(offset + 3) === 0x4d && + dataView.getUint8(offset + 4) === 0x04 && + dataView.getUint8(offset + 5) === 0x04 + ); + }; + + while (offset < length) { + if (isFieldSegmentStart(dataView, offset)) { + // Get the length of the name header (which is padded to an even number of bytes) + var nameHeaderLength = dataView.getUint8(offset + 7); + if (nameHeaderLength % 2 !== 0) nameHeaderLength += 1; + // Check for pre photoshop 6 format + if (nameHeaderLength === 0) { + // Always 4 + nameHeaderLength = 4; + } + + var startOffset = offset + 8 + nameHeaderLength; + var sectionLength = dataView.getUint16(offset + 6 + nameHeaderLength); + + return readIPTCData(file, startOffset, sectionLength); + + break; + } + + // Not the marker, continue searching + offset++; + } + } + var IptcFieldMap = { + 0x78: "caption", + 0x6e: "credit", + 0x19: "keywords", + 0x37: "dateCreated", + 0x50: "byline", + 0x55: "bylineTitle", + 0x7a: "captionWriter", + 0x69: "headline", + 0x74: "copyright", + 0x0f: "category", + }; + function readIPTCData(file, startOffset, sectionLength) { + var dataView = new DataView(file); + var data = {}; + var fieldValue, fieldName, dataSize, segmentType, segmentSize; + var segmentStartPos = startOffset; + while (segmentStartPos < startOffset + sectionLength) { + if ( + dataView.getUint8(segmentStartPos) === 0x1c && + dataView.getUint8(segmentStartPos + 1) === 0x02 + ) { + segmentType = dataView.getUint8(segmentStartPos + 2); + if (segmentType in IptcFieldMap) { + dataSize = dataView.getInt16(segmentStartPos + 3); + segmentSize = dataSize + 5; + fieldName = IptcFieldMap[segmentType]; + fieldValue = getStringFromDB(dataView, segmentStartPos + 5, dataSize); + // Check if we already stored a value with this name + if (data.hasOwnProperty(fieldName)) { + // Value already stored with this name, create multivalue field + if (data[fieldName] instanceof Array) { + data[fieldName].push(fieldValue); + } else { + data[fieldName] = [data[fieldName], fieldValue]; + } + } else { + data[fieldName] = fieldValue; + } + } + } + segmentStartPos++; + } + return data; + } + + function readTags(file, tiffStart, dirStart, strings, bigEnd) { + var entries = file.getUint16(dirStart, !bigEnd), + tags = {}, + entryOffset, + tag, + i; + + for (i = 0; i < entries; i++) { + entryOffset = dirStart + i * 12 + 2; + tag = strings[file.getUint16(entryOffset, !bigEnd)]; + if (!tag && debug) + console.log("Unknown tag: " + file.getUint16(entryOffset, !bigEnd)); + tags[tag] = readTagValue(file, entryOffset, tiffStart, dirStart, bigEnd); + } + return tags; + } + + function readTagValue(file, entryOffset, tiffStart, dirStart, bigEnd) { + var type = file.getUint16(entryOffset + 2, !bigEnd), + numValues = file.getUint32(entryOffset + 4, !bigEnd), + valueOffset = file.getUint32(entryOffset + 8, !bigEnd) + tiffStart, + offset, + vals, + val, + n, + numerator, + denominator; + + switch (type) { + case 1: // byte, 8-bit unsigned int + case 7: // undefined, 8-bit byte, value depending on field + if (numValues == 1) { + return file.getUint8(entryOffset + 8, !bigEnd); + } else { + offset = numValues > 4 ? valueOffset : entryOffset + 8; + vals = []; + for (n = 0; n < numValues; n++) { + vals[n] = file.getUint8(offset + n); + } + return vals; + } + + case 2: // ascii, 8-bit byte + offset = numValues > 4 ? valueOffset : entryOffset + 8; + return getStringFromDB(file, offset, numValues - 1); + + case 3: // short, 16 bit int + if (numValues == 1) { + return file.getUint16(entryOffset + 8, !bigEnd); + } else { + offset = numValues > 2 ? valueOffset : entryOffset + 8; + vals = []; + for (n = 0; n < numValues; n++) { + vals[n] = file.getUint16(offset + 2 * n, !bigEnd); + } + return vals; + } + + case 4: // long, 32 bit int + if (numValues == 1) { + return file.getUint32(entryOffset + 8, !bigEnd); + } else { + vals = []; + for (n = 0; n < numValues; n++) { + vals[n] = file.getUint32(valueOffset + 4 * n, !bigEnd); + } + return vals; + } + + case 5: // rational = two long values, first is numerator, second is denominator + if (numValues == 1) { + numerator = file.getUint32(valueOffset, !bigEnd); + denominator = file.getUint32(valueOffset + 4, !bigEnd); + val = new Number(numerator / denominator); + val.numerator = numerator; + val.denominator = denominator; + return val; + } else { + vals = []; + for (n = 0; n < numValues; n++) { + numerator = file.getUint32(valueOffset + 8 * n, !bigEnd); + denominator = file.getUint32(valueOffset + 4 + 8 * n, !bigEnd); + vals[n] = new Number(numerator / denominator); + vals[n].numerator = numerator; + vals[n].denominator = denominator; + } + return vals; + } + + case 9: // slong, 32 bit signed int + if (numValues == 1) { + return file.getInt32(entryOffset + 8, !bigEnd); + } else { + vals = []; + for (n = 0; n < numValues; n++) { + vals[n] = file.getInt32(valueOffset + 4 * n, !bigEnd); + } + return vals; + } + + case 10: // signed rational, two slongs, first is numerator, second is denominator + if (numValues == 1) { + return ( + file.getInt32(valueOffset, !bigEnd) / + file.getInt32(valueOffset + 4, !bigEnd) + ); + } else { + vals = []; + for (n = 0; n < numValues; n++) { + vals[n] = + file.getInt32(valueOffset + 8 * n, !bigEnd) / + file.getInt32(valueOffset + 4 + 8 * n, !bigEnd); + } + return vals; + } + } + } + + /** + * Given an IFD (Image File Directory) start offset + * returns an offset to next IFD or 0 if it's the last IFD. + */ + function getNextIFDOffset(dataView, dirStart, bigEnd) { + //the first 2bytes means the number of directory entries contains in this IFD + var entries = dataView.getUint16(dirStart, !bigEnd); + + // After last directory entry, there is a 4bytes of data, + // it means an offset to next IFD. + // If its value is '0x00000000', it means this is the last IFD and there is no linked IFD. + + return dataView.getUint32(dirStart + 2 + entries * 12, !bigEnd); // each entry is 12 bytes long + } + + function readThumbnailImage(dataView, tiffStart, firstIFDOffset, bigEnd) { + // get the IFD1 offset + var IFD1OffsetPointer = getNextIFDOffset( + dataView, + tiffStart + firstIFDOffset, + bigEnd + ); + + if (!IFD1OffsetPointer) { + // console.log('******** IFD1Offset is empty, image thumb not found ********'); + return {}; + } else if (IFD1OffsetPointer > dataView.byteLength) { + // this should not happen + // console.log('******** IFD1Offset is outside the bounds of the DataView ********'); + return {}; + } + // console.log('******* thumbnail IFD offset (IFD1) is: %s', IFD1OffsetPointer); + + var thumbTags = readTags( + dataView, + tiffStart, + tiffStart + IFD1OffsetPointer, + IFD1Tags, + bigEnd + ); + + // EXIF 2.3 specification for JPEG format thumbnail + + // If the value of Compression(0x0103) Tag in IFD1 is '6', thumbnail image format is JPEG. + // Most of Exif image uses JPEG format for thumbnail. In that case, you can get offset of thumbnail + // by JpegIFOffset(0x0201) Tag in IFD1, size of thumbnail by JpegIFByteCount(0x0202) Tag. + // Data format is ordinary JPEG format, starts from 0xFFD8 and ends by 0xFFD9. It seems that + // JPEG format and 160x120pixels of size are recommended thumbnail format for Exif2.1 or later. + + if (thumbTags["Compression"]) { + // console.log('Thumbnail image found!'); + + switch (thumbTags["Compression"]) { + case 6: + // console.log('Thumbnail image format is JPEG'); + if (thumbTags.JpegIFOffset && thumbTags.JpegIFByteCount) { + // extract the thumbnail + var tOffset = tiffStart + thumbTags.JpegIFOffset; + var tLength = thumbTags.JpegIFByteCount; + thumbTags["blob"] = new Blob( + [new Uint8Array(dataView.buffer, tOffset, tLength)], + { + type: "image/jpeg", + } + ); + } + break; + + case 1: + console.log( + "Thumbnail image format is TIFF, which is not implemented." + ); + break; + default: + console.log( + "Unknown thumbnail image format '%s'", + thumbTags["Compression"] + ); + } + } else if (thumbTags["PhotometricInterpretation"] == 2) { + console.log("Thumbnail image format is RGB, which is not implemented."); + } + return thumbTags; + } + + function getStringFromDB(buffer, start, length) { + var outstr = ""; + for (var n = start; n < start + length; n++) { + outstr += String.fromCharCode(buffer.getUint8(n)); + } + return outstr; + } + + function readEXIFData(file, start) { + if (getStringFromDB(file, start, 4) != "Exif") { + if (debug) + console.log("Not valid EXIF data! " + getStringFromDB(file, start, 4)); + return false; + } + + var bigEnd, + tags, + tag, + exifData, + gpsData, + tiffOffset = start + 6; + + // test for TIFF validity and endianness + if (file.getUint16(tiffOffset) == 0x4949) { + bigEnd = false; + } else if (file.getUint16(tiffOffset) == 0x4d4d) { + bigEnd = true; + } else { + if (debug) console.log("Not valid TIFF data! (no 0x4949 or 0x4D4D)"); + return false; + } + + if (file.getUint16(tiffOffset + 2, !bigEnd) != 0x002a) { + if (debug) console.log("Not valid TIFF data! (no 0x002A)"); + return false; + } + + var firstIFDOffset = file.getUint32(tiffOffset + 4, !bigEnd); + + if (firstIFDOffset < 0x00000008) { + if (debug) + console.log( + "Not valid TIFF data! (First offset less than 8)", + file.getUint32(tiffOffset + 4, !bigEnd) + ); + return false; + } + + tags = readTags( + file, + tiffOffset, + tiffOffset + firstIFDOffset, + TiffTags, + bigEnd + ); + + if (tags.ExifIFDPointer) { + exifData = readTags( + file, + tiffOffset, + tiffOffset + tags.ExifIFDPointer, + ExifTags, + bigEnd + ); + for (tag in exifData) { + switch (tag) { + case "LightSource": + case "Flash": + case "MeteringMode": + case "ExposureProgram": + case "SensingMethod": + case "SceneCaptureType": + case "SceneType": + case "CustomRendered": + case "WhiteBalance": + case "GainControl": + case "Contrast": + case "Saturation": + case "Sharpness": + case "SubjectDistanceRange": + case "FileSource": + exifData[tag] = StringValues[tag][exifData[tag]]; + break; + + case "ExifVersion": + case "FlashpixVersion": + exifData[tag] = String.fromCharCode( + exifData[tag][0], + exifData[tag][1], + exifData[tag][2], + exifData[tag][3] + ); + break; + + case "ComponentsConfiguration": + exifData[tag] = + StringValues.Components[exifData[tag][0]] + + StringValues.Components[exifData[tag][1]] + + StringValues.Components[exifData[tag][2]] + + StringValues.Components[exifData[tag][3]]; + break; + } + tags[tag] = exifData[tag]; + } + } + + if (tags.GPSInfoIFDPointer) { + gpsData = readTags( + file, + tiffOffset, + tiffOffset + tags.GPSInfoIFDPointer, + GPSTags, + bigEnd + ); + for (tag in gpsData) { + switch (tag) { + case "GPSVersionID": + gpsData[tag] = + gpsData[tag][0] + + "." + + gpsData[tag][1] + + "." + + gpsData[tag][2] + + "." + + gpsData[tag][3]; + break; + } + tags[tag] = gpsData[tag]; + } + } + + // extract thumbnail + tags["thumbnail"] = readThumbnailImage( + file, + tiffOffset, + firstIFDOffset, + bigEnd + ); + + return tags; + } + + function findXMPinJPEG(file) { + if (!("DOMParser" in self)) { + // console.warn('XML parsing not supported without DOMParser'); + return; + } + var dataView = new DataView(file); + + if (debug) console.log("Got file of length " + file.byteLength); + if (dataView.getUint8(0) != 0xff || dataView.getUint8(1) != 0xd8) { + if (debug) console.log("Not a valid JPEG"); + return false; // not a valid jpeg + } + + var offset = 2, + length = file.byteLength, + dom = new DOMParser(); + + while (offset < length - 4) { + if (getStringFromDB(dataView, offset, 4) == "http") { + var startOffset = offset - 1; + var sectionLength = dataView.getUint16(offset - 2) - 1; + var xmpString = getStringFromDB(dataView, startOffset, sectionLength); + var xmpEndIndex = xmpString.indexOf("xmpmeta>") + 8; + xmpString = xmpString.substring( + xmpString.indexOf(" 0) { + json["@attributes"] = {}; + for (var j = 0; j < xml.attributes.length; j++) { + var attribute = xml.attributes.item(j); + json["@attributes"][attribute.nodeName] = attribute.nodeValue; + } + } + } else if (xml.nodeType == 3) { + // text node + return xml.nodeValue; + } + + // deal with children + if (xml.hasChildNodes()) { + for (var i = 0; i < xml.childNodes.length; i++) { + var child = xml.childNodes.item(i); + var nodeName = child.nodeName; + if (json[nodeName] == null) { + json[nodeName] = xml2json(child); + } else { + if (json[nodeName].push == null) { + var old = json[nodeName]; + json[nodeName] = []; + json[nodeName].push(old); + } + json[nodeName].push(xml2json(child)); + } + } + } + + return json; + } + + function xml2Object(xml) { + try { + var obj = {}; + if (xml.children.length > 0) { + for (var i = 0; i < xml.children.length; i++) { + var item = xml.children.item(i); + var attributes = item.attributes; + for (var idx in attributes) { + var itemAtt = attributes[idx]; + var dataKey = itemAtt.nodeName; + var dataValue = itemAtt.nodeValue; + + if (dataKey !== undefined) { + obj[dataKey] = dataValue; + } + } + var nodeName = item.nodeName; + + if (typeof obj[nodeName] == "undefined") { + obj[nodeName] = xml2json(item); + } else { + if (typeof obj[nodeName].push == "undefined") { + var old = obj[nodeName]; + + obj[nodeName] = []; + obj[nodeName].push(old); + } + obj[nodeName].push(xml2json(item)); + } + } + } else { + obj = xml.textContent; + } + return obj; + } catch (e) { + console.log(e.message); + } + } + + EXIF.enableXmp = function () { + EXIF.isXmpEnabled = true; + }; + + EXIF.disableXmp = function () { + EXIF.isXmpEnabled = false; + }; + + EXIF.getData = function (img, callback) { + console.log("EXIF", img); + // if ( + // ((self.Image && img instanceof self.Image) || + // (self.HTMLImageElement && img instanceof self.HTMLImageElement)) && + // !img.complete + // ) + // return false; + + if (!imageHasData(img)) { + getImageData(img, callback); + } else { + if (callback) { + callback.call(img); + } + } + return true; + }; + + EXIF.getTag = function (img, tag) { + if (!imageHasData(img)) return; + return img.exifdata[tag]; + }; + + EXIF.getIptcTag = function (img, tag) { + if (!imageHasData(img)) return; + return img.iptcdata[tag]; + }; + + EXIF.getAllTags = function (img) { + if (!imageHasData(img)) return {}; + var a, + data = img.exifdata, + tags = {}; + for (a in data) { + if (data.hasOwnProperty(a)) { + tags[a] = data[a]; + } + } + return tags; + }; + + EXIF.getAllIptcTags = function (img) { + if (!imageHasData(img)) return {}; + var a, + data = img.iptcdata, + tags = {}; + for (a in data) { + if (data.hasOwnProperty(a)) { + tags[a] = data[a]; + } + } + return tags; + }; + + EXIF.pretty = function (img) { + if (!imageHasData(img)) return ""; + var a, + data = img.exifdata, + strPretty = ""; + for (a in data) { + if (data.hasOwnProperty(a)) { + if (typeof data[a] == "object") { + if (data[a] instanceof Number) { + strPretty += + a + + " : " + + data[a] + + " [" + + data[a].numerator + + "/" + + data[a].denominator + + "]\r\n"; + } else { + strPretty += a + " : [" + data[a].length + " values]\r\n"; + } + } else { + strPretty += a + " : " + data[a] + "\r\n"; + } + } + } + return strPretty; + }; + + EXIF.readFromBinaryFile = function (file) { + return findEXIFinJPEG(file); + }; + + if (typeof define === "function" && define.amd) { + define("exif-js", [], function () { + return EXIF; + }); + } +}).call(this); diff --git a/java-mall-app-shop-admin/utils/tupian.js b/java-mall-app-shop-admin/utils/tupian.js new file mode 100644 index 0000000..4b06b03 --- /dev/null +++ b/java-mall-app-shop-admin/utils/tupian.js @@ -0,0 +1,262 @@ +/** + * imageUtil.js + *解决图片旋转的问题 + * **/ + +import EXIF from "./exif.js"; + +async function compressImage(path) { + let imageInfo = await getImageInfo(path); + let systemInfo = await getSystemInfo(); + return new Promise(function (resolve, reject) { + // #ifdef APP-PLUS || APP-NVUE + appCompressImage(path, imageInfo) + .then((res) => { + resolve(res); + }) + .catch((e) => { + reject(e); + }); + // #endif + + // #ifdef H5 + let orientation = 1; + let img = document.createElement("img"); + img.src = path; + img.onload = function () { + EXIF.getData(img, function () { + orientation = EXIF.getTag(this, "Orientation"); + canvasImg(path, orientation, imageInfo, systemInfo) + .then((res) => { + debugger; + resolve(res); + }) + .catch((e) => { + reject(e); + }); + }); + }; + img.onerror = function () { + reject(path); + }; + // #endif + }); +} + +// app处理旋转图片 +function appCompressImage(src, imageInfo) { + return new Promise(function (resolve, reject) { + let orientation = imageInfo.orientation; + let rotate = 0; + let quality = 80; + if (plus.os.name == "iOS") { + rotate = 0; + quality = 25; + } else { + switch (orientation) { + case "up": //exif:1 不旋转 + rotate = 0; + break; + case "down": //exif:3 旋转180度 + rotate = 180; + break; + case "right": //exif:6 旋转90度 + rotate = 90; + break; + case "left": //exif:8 旋转270度 + rotate = 270; + break; + default: + rotate = 0; + break; + } + } + + plus.zip.compressImage( + { + src: src, + dst: + "_doc/uniapp_temp" + "/compressed/" + Math.round(new Date()) + ".png", + format: "png", + quality: quality, + width: "auto", + height: "auto", + rotate: rotate, + }, + function (event) { + resolve(event.target); + }, + function (error) { + reject(src); + } + ); + }); +} + +// 画图片 +function canvasImg(path, or, imageInfo, systemInfo) { + return new Promise(function (resolve, reject) { + let canvasId = "uploadCanvas"; + const ctx = uni.createCanvasContext(canvasId); + let scale = imageInfo.width / imageInfo.height; + + // 图片参数 start + let maxdestWidth = 1100; // 2000; + let destWidth = imageInfo.width; + let destHeight = imageInfo.height; + + let destCompressWidth = imageInfo.width; + let destCompressHeight = imageInfo.height; + + // 压缩图片 最大不超过5M 1200 + // 当宽大于高的时候 + if (imageInfo.width > imageInfo.height) { + if (imageInfo.width > maxdestWidth) { + destCompressWidth = maxdestWidth; + destCompressHeight = Math.floor(destCompressWidth / scale); + } else { + destCompressWidth = (imageInfo.width * 8) / 10; + destCompressHeight = Math.floor(destCompressWidth / scale); + } + } + // 当高大于宽 + else { + if (imageInfo.height > maxdestWidth) { + destCompressHeight = maxdestWidth; + destCompressWidth = Math.floor(destCompressHeight * scale); + } else { + destCompressHeight = imageInfo.height * 0.8; + destCompressWidth = Math.floor(destCompressHeight * scale); + } + } + + destWidth = destCompressHeight; + destHeight = destCompressWidth; + // 图片参数 end + + // 画布参数 start + let maxWidth = 300; + let canvasW = imageInfo.width; + let canvasH = imageInfo.height; + + let width = imageInfo.width; + let height = imageInfo.height; + + // canvas画布不能超过最大宽 + if (canvasW > maxWidth) { + canvasW = maxWidth; + canvasH = Math.floor(canvasW / scale); + } + + width = canvasW; + height = canvasH; + // 画布参数 end + + // console.log('--or---', or) + //单独处理苹果最新版本 + if ( + systemInfo.model == "iPhone" && + systemInfo.system.indexOf("13.4.1") > -1 + ) { + ctx.drawImage(path, 0, 0, canvasW, canvasH); + destWidth = destCompressWidth; + destHeight = destCompressHeight; + } else { + if (or == 6) { + //逆时针旋转了90 + ctx.translate(width, 0); + ctx.rotate(Math.PI / 2); + ctx.drawImage(path, 0, 0, canvasH, canvasW); + } else if (or == 3) { + //逆时针旋转了180 + ctx.translate(width, height); + ctx.rotate(Math.PI); + ctx.drawImage(path, 0, 0, canvasH, canvasW); + } else if (or == 8) { + //顺时针旋转90 + ctx.translate(0, height); + ctx.rotate(-Math.PI / 2); + ctx.drawImage(path, 0, 0, canvasH, canvasW); + } else { + ctx.drawImage(path, 0, 0, canvasW, canvasH); + // return resolve(path); + + destWidth = destCompressWidth; + destHeight = destCompressHeight; + } + } + // console.log('图片原始长宽', imageInfo, maxWidth, canvasW, canvasH, width, height, destWidth, destHeight); + + ctx.draw( + true, + setTimeout(() => { + uni.canvasToTempFilePath({ + x: 0, + y: 0, + width: width, //画布宽度 + height: height, + destWidth: destWidth, + destHeight: destHeight, + fileType: "png", + canvasId: canvasId, + success: (res) => { + resolve(res.tempFilePath); + }, + fail: (err) => { + resolve(path); + }, + }); + }, 200) + ); + }); +} + +// 获取图片信息 +function getImageInfo(path) { + return new Promise(function (resolve, reject) { + // #ifdef APP-PLUS + plus.io.getImageInfo({ + src: path, + success: function (image) { + // console.log('orientation=' + image.orientation); + resolve(image); + }, + fail: function (err) { + console.log("getImageInfoErr: " + JSON.stringify(err)); + reject(err); + }, + }); + // #endif + + // #ifdef H5 || MP-WEIXIN + uni.getImageInfo({ + src: path, + success: function (image) { + // console.log('orientation=' + image.orientation); + resolve(image); + }, + fail: function (err) { + console.log("getImageInfoErr: " + JSON.stringify(err)); + reject(err); + }, + }); + // #endif + }); +} + +// 获取系统信息 +function getSystemInfo(path) { + return new Promise(function (resolve, reject) { + uni.getSystemInfo({ + success(res) { + resolve(res); + }, + fail(err) { + console.log("getSystemInfoErr: " + JSON.stringify(err)); + reject(err); + }, + }); + }); +} + +export default compressImage;