diff --git a/pages.json b/pages.json index f39db70..95137fd 100644 --- a/pages.json +++ b/pages.json @@ -120,10 +120,49 @@ "navigationBarTitleText": "提现" }, "meta": { - "auth": false + "auth": true + } + }, + { + "path": "point/buy", + "style": { + "navigationBarTitleText": "购买积分" + }, + "meta": { + "auth": true + } + }, { + "path": "point/share", + "style": { + "navigationBarTitleText": "分发积分" + }, + "meta": { + "auth": true + } + }, { + "path": "point/loglist", + "style": { + "navigationBarTitleText": "历史积分" + }, + "meta": { + "auth": true } } ] + }, + { + "root": "pages/product", + "pages": [ + { + "path": "manageGoods", + "style": { + "navigationBarTitleText": "商品管理" + }, + "meta": { + "auth": false + } + } + ] } ], "tabBar": { diff --git a/pages/index/my.vue b/pages/index/my.vue index c483869..c73055a 100644 --- a/pages/index/my.vue +++ b/pages/index/my.vue @@ -1,43 +1,43 @@ diff --git a/pages/index/product.vue b/pages/index/product.vue index 7ab5aa7..d9422aa 100644 --- a/pages/index/product.vue +++ b/pages/index/product.vue @@ -1,34 +1,21 @@ + + diff --git a/pages/order/list.vue b/pages/order/list.vue index d34f7ce..1ae6a2a 100644 --- a/pages/order/list.vue +++ b/pages/order/list.vue @@ -1,117 +1,77 @@ diff --git a/pages/product/manageGoods.vue b/pages/product/manageGoods.vue new file mode 100644 index 0000000..b4252b5 --- /dev/null +++ b/pages/product/manageGoods.vue @@ -0,0 +1,245 @@ + + + + + + diff --git a/pages/user/point/buy.vue b/pages/user/point/buy.vue new file mode 100644 index 0000000..c3fc60a --- /dev/null +++ b/pages/user/point/buy.vue @@ -0,0 +1,167 @@ + + + + + \ No newline at end of file diff --git a/pages/user/point/loglist.vue b/pages/user/point/loglist.vue new file mode 100644 index 0000000..8fdb320 --- /dev/null +++ b/pages/user/point/loglist.vue @@ -0,0 +1,105 @@ + + + + + \ No newline at end of file diff --git a/pages/user/point/share.vue b/pages/user/point/share.vue new file mode 100644 index 0000000..e395ba4 --- /dev/null +++ b/pages/user/point/share.vue @@ -0,0 +1,124 @@ + + + + + \ No newline at end of file diff --git a/pages/user/wallet/withdraw.vue b/pages/user/wallet/withdraw.vue index 3681cf7..096ac5a 100644 --- a/pages/user/wallet/withdraw.vue +++ b/pages/user/wallet/withdraw.vue @@ -1,19 +1,26 @@ @@ -37,4 +49,75 @@ const state = ref({ last: 1000, canUse: 10000 }) - \ No newline at end of file + + + \ No newline at end of file diff --git a/peach/api/common/file.js b/peach/api/common/file.js new file mode 100644 index 0000000..cf93524 --- /dev/null +++ b/peach/api/common/file.js @@ -0,0 +1,53 @@ +import { baseUrl, apiPath } from "@/peach/config"; + +const FileApi = { + // 上传文件 + uploadFile: (file) => { + const token = uni.getStorageSync("token"); + uni.showLoading({ + title: "上传中", + }); + return new Promise((resolve, reject) => { + uni.uploadFile({ + url: baseUrl + apiPath + "/infra/file/upload", + filePath: file, + name: "file", + header: { + // Accept: 'text/json', + Accept: "*/*", + "tenant-id": "1", + // Authorization: 'Bearer test247', + }, + success: (uploadFileRes) => { + let result = JSON.parse(uploadFileRes.data); + console.log(result); + if (result.error === 1) { + uni.showToast({ + icon: "none", + title: result.msg, + }); + } else { + uni.showToast({ + icon: "none", + title: "上传成功", + }); + return resolve(result); + } + }, + fail: (error) => { + console.log("上传失败:", error); + uni.showToast({ + title: "上传失败", + icon: "none", + }); + return resolve(false); + }, + complete: () => { + uni.hideLoading(); + }, + }); + }); + }, +}; + +export default FileApi; diff --git a/peach/api/member/point.js b/peach/api/member/point.js new file mode 100644 index 0000000..a4f62c3 --- /dev/null +++ b/peach/api/member/point.js @@ -0,0 +1,14 @@ +import request from "@/peach/request"; + +const PointApi = { + // 派发积分 + sendPoint: (data) => { + return request({ + url: "/particulars/point/send-member", + method: "POST", + data, + }); + }, +}; + +export default PointApi; diff --git a/peach/api/trade/goods.js b/peach/api/trade/goods.js new file mode 100644 index 0000000..4de984b --- /dev/null +++ b/peach/api/trade/goods.js @@ -0,0 +1,30 @@ +import request from "@/peach/request"; + +const GoodsApi = { + // 商品详情 + getProduct: (data) => { + return request({ + url: "/trade/order/page", + method: "GET", + params: data, + }); + }, + // 添加商品 + addProduct: (data) => { + return request({ + url: "/trade/order/page", + method: "POST", + data, + }); + }, + // 修改商品 + editProduct: (data) => { + return request({ + url: "/trade/order/page", + method: "POST", + data, + }); + }, +}; + +export default GoodsApi; diff --git a/peach/api/trade/order.js b/peach/api/trade/order.js new file mode 100644 index 0000000..75692c7 --- /dev/null +++ b/peach/api/trade/order.js @@ -0,0 +1,14 @@ +import request from "@/peach/request"; + +const OrderUtil = { + // 获取订单列表 + getOrderPage: (data) => { + return request({ + url: "/trade/order/page", + method: "GET", + params: data, + }); + }, +}; + +export default OrderUtil; diff --git a/peach/components/p-uploader/choose-and-upload-file.js b/peach/components/p-uploader/choose-and-upload-file.js new file mode 100644 index 0000000..ca6c1ae --- /dev/null +++ b/peach/components/p-uploader/choose-and-upload-file.js @@ -0,0 +1,227 @@ +"use strict"; +import FileApi from "@/peach/api/common/file"; + +const ERR_MSG_OK = "chooseAndUploadFile:ok"; +const ERR_MSG_FAIL = "chooseAndUploadFile:fail"; + +function chooseImage(opts) { + const { + count, + sizeType = ["original", "compressed"], + sourceType = ["album", "camera"], + extension, + } = opts; + return new Promise((resolve, reject) => { + uni.chooseImage({ + count, + sizeType, + sourceType, + extension, + success(res) { + resolve(normalizeChooseAndUploadFileRes(res, "image")); + }, + fail(res) { + reject({ + errMsg: res.errMsg.replace("chooseImage:fail", ERR_MSG_FAIL), + }); + }, + }); + }); +} + +function chooseVideo(opts) { + const { + camera, + compressed, + maxDuration, + sourceType = ["album", "camera"], + extension, + } = opts; + return new Promise((resolve, reject) => { + uni.chooseVideo({ + camera, + compressed, + maxDuration, + sourceType, + extension, + success(res) { + const { tempFilePath, duration, size, height, width } = res; + resolve( + normalizeChooseAndUploadFileRes( + { + errMsg: "chooseVideo:ok", + tempFilePaths: [tempFilePath], + tempFiles: [ + { + name: (res.tempFile && res.tempFile.name) || "", + path: tempFilePath, + size, + type: (res.tempFile && res.tempFile.type) || "", + width, + height, + duration, + fileType: "video", + cloudPath: "", + }, + ], + }, + "video" + ) + ); + }, + fail(res) { + reject({ + errMsg: res.errMsg.replace("chooseVideo:fail", ERR_MSG_FAIL), + }); + }, + }); + }); +} + +function chooseAll(opts) { + const { count, extension } = opts; + return new Promise((resolve, reject) => { + let chooseFile = uni.chooseFile; + if ( + typeof wx !== "undefined" && + typeof wx.chooseMessageFile === "function" + ) { + chooseFile = wx.chooseMessageFile; + } + if (typeof chooseFile !== "function") { + return reject({ + errMsg: + ERR_MSG_FAIL + " 请指定 type 类型,该平台仅支持选择 image 或 video。", + }); + } + chooseFile({ + type: "all", + count, + extension, + success(res) { + resolve(normalizeChooseAndUploadFileRes(res)); + }, + fail(res) { + reject({ + errMsg: res.errMsg.replace("chooseFile:fail", ERR_MSG_FAIL), + }); + }, + }); + }); +} + +function normalizeChooseAndUploadFileRes(res, fileType) { + res.tempFiles.forEach((item, index) => { + if (!item.name) { + item.name = item.path.substring(item.path.lastIndexOf("/") + 1); + } + if (fileType) { + item.fileType = fileType; + } + item.cloudPath = + Date.now() + + "_" + + index + + item.name.substring(item.name.lastIndexOf(".")); + }); + if (!res.tempFilePaths) { + res.tempFilePaths = res.tempFiles.map((file) => file.path); + } + return res; +} + +function uploadCloudFiles(files, max = 5, onUploadProgress) { + files = JSON.parse(JSON.stringify(files)); + const len = files.length; + let count = 0; + let self = this; + return new Promise((resolve) => { + while (count < max) { + next(); + } + + function next() { + let cur = count++; + if (cur >= len) { + !files.find((item) => !item.url && !item.errMsg) && resolve(files); + return; + } + const fileItem = files[cur]; + const index = self.files.findIndex((v) => v.uuid === fileItem.uuid); + fileItem.url = ""; + delete fileItem.errMsg; + + uniCloud + .uploadFile({ + filePath: fileItem.path, + cloudPath: fileItem.cloudPath, + fileType: fileItem.fileType, + onUploadProgress: (res) => { + res.index = index; + onUploadProgress && onUploadProgress(res); + }, + }) + .then((res) => { + fileItem.url = res.fileID; + fileItem.index = index; + if (cur < len) { + next(); + } + }) + .catch((res) => { + fileItem.errMsg = res.errMsg || res.message; + fileItem.index = index; + if (cur < len) { + next(); + } + }); + } + }); +} + +function uploadFiles(choosePromise, { onChooseFile, onUploadProgress }) { + return choosePromise + .then((res) => { + if (onChooseFile) { + const customChooseRes = onChooseFile(res); + if (typeof customChooseRes !== "undefined") { + return Promise.resolve(customChooseRes).then((chooseRes) => + typeof chooseRes === "undefined" ? res : chooseRes + ); + } + } + return res; + }) + .then((res) => { + if (res === false) { + return { + errMsg: ERR_MSG_OK, + tempFilePaths: [], + tempFiles: [], + }; + } + return res; + }) + .then(async (files) => { + for (let file of files.tempFiles) { + const { data } = await FileApi.uploadFile(file.path); + file.url = data; + } + return files; + }); +} + +function chooseAndUploadFile( + opts = { + type: "all", + } +) { + if (opts.type === "image") { + return uploadFiles(chooseImage(opts), opts); + } else if (opts.type === "video") { + return uploadFiles(chooseVideo(opts), opts); + } + return uploadFiles(chooseAll(opts), opts); +} + +export { chooseAndUploadFile, uploadCloudFiles }; diff --git a/peach/components/p-uploader/p-uploader.vue b/peach/components/p-uploader/p-uploader.vue new file mode 100644 index 0000000..0030201 --- /dev/null +++ b/peach/components/p-uploader/p-uploader.vue @@ -0,0 +1,666 @@ + + + + + + diff --git a/peach/components/p-uploader/upload-file.vue b/peach/components/p-uploader/upload-file.vue new file mode 100644 index 0000000..abe56e9 --- /dev/null +++ b/peach/components/p-uploader/upload-file.vue @@ -0,0 +1,318 @@ + + + + + diff --git a/peach/components/p-uploader/upload-image.vue b/peach/components/p-uploader/upload-image.vue new file mode 100644 index 0000000..0ed1590 --- /dev/null +++ b/peach/components/p-uploader/upload-image.vue @@ -0,0 +1,302 @@ + + + + + diff --git a/peach/components/p-uploader/utils.js b/peach/components/p-uploader/utils.js new file mode 100644 index 0000000..7b40d21 --- /dev/null +++ b/peach/components/p-uploader/utils.js @@ -0,0 +1,110 @@ +/** + * 获取文件名和后缀 + * @param {String} name + */ +export const get_file_ext = (name) => { + const last_len = name.lastIndexOf("."); + const len = name.length; + return { + name: name.substring(0, last_len), + ext: name.substring(last_len + 1, len), + }; +}; + +/** + * 获取扩展名 + * @param {Array} fileExtname + */ +export const get_extname = (fileExtname) => { + if (!Array.isArray(fileExtname)) { + let extname = fileExtname.replace(/(\[|\])/g, ""); + return extname.split(","); + } else { + return fileExtname; + } + return []; +}; + +/** + * 获取文件和检测是否可选 + */ +export const get_files_and_is_max = (res, _extname) => { + let filePaths = []; + let files = []; + if (!_extname || _extname.length === 0) { + return { + filePaths, + files, + }; + } + res.tempFiles.forEach((v) => { + let fileFullName = get_file_ext(v.name); + const extname = fileFullName.ext.toLowerCase(); + if (_extname.indexOf(extname) !== -1) { + files.push(v); + filePaths.push(v.path); + } + }); + if (files.length !== res.tempFiles.length) { + uni.showToast({ + title: `当前选择了${res.tempFiles.length}个文件 ,${ + res.tempFiles.length - files.length + } 个文件格式不正确`, + icon: "none", + duration: 5000, + }); + } + + return { + filePaths, + files, + }; +}; + +/** + * 获取图片信息 + * @param {Object} filepath + */ +export const get_file_info = (filepath) => { + return new Promise((resolve, reject) => { + uni.getImageInfo({ + src: filepath, + success(res) { + resolve(res); + }, + fail(err) { + reject(err); + }, + }); + }); +}; +/** + * 获取封装数据 + */ +export const get_file_data = async (files, type = "image") => { + // 最终需要上传数据库的数据 + let fileFullName = get_file_ext(files.name); + const extname = fileFullName.ext.toLowerCase(); + let filedata = { + name: files.name, + uuid: files.uuid, + extname: extname || "", + cloudPath: files.cloudPath, + fileType: files.fileType, + url: files.path || files.path, + size: files.size, //单位是字节 + image: {}, + path: files.path, + video: {}, + }; + if (type === "image") { + const imageinfo = await get_file_info(files.path); + delete filedata.video; + filedata.image.width = imageinfo.width; + filedata.image.height = imageinfo.height; + filedata.image.location = imageinfo.path; + } else { + delete filedata.image; + } + return filedata; +}; diff --git a/peach/scss/_tools.scss b/peach/scss/_tools.scss index a1702e5..7699ea0 100644 --- a/peach/scss/_tools.scss +++ b/peach/scss/_tools.scss @@ -104,7 +104,7 @@ margin padding: 内外边距 ==================== */ -@for $i from 0 through 100 { +@for $i from 0 through 200 { // 只要双数和能被5除尽的数 @if $i % 2==0 or $i % 5==0 { // 得出:u-margin-30或者u-m-30 diff --git a/static/upload-camera.png b/static/upload-camera.png new file mode 100644 index 0000000..e304e25 Binary files /dev/null and b/static/upload-camera.png differ diff --git a/uni_modules/uni-forms/components/uni-forms-item/uni-forms-item.vue b/uni_modules/uni-forms/components/uni-forms-item/uni-forms-item.vue index 59b0528..b295967 100644 --- a/uni_modules/uni-forms/components/uni-forms-item/uni-forms-item.vue +++ b/uni_modules/uni-forms/components/uni-forms-item/uni-forms-item.vue @@ -1,627 +1,628 @@