diff --git a/README.md b/README.md index 5456194f..c4f6d962 100644 --- a/README.md +++ b/README.md @@ -1,16 +1,12 @@ ## Lilishop B2B2C商城系统 -#### 欢迎交流需求,交流业务,交流技术(基础问题自行解决,其他问题先看文档后提问) - -#### 不用削尖脑袋往老群里加,老群活跃度较低,很多潜水党,新群相对而言活跃一些 :tw-1f606: :tw-1f606: :tw-1f606: :tw-1f606: :tw-1f606: :tw-1f606: #### PS: **演示站点所有环境均部署master分支。如果有演示站点问题,可以反馈,如果演示站点没问题本地运行有问题,需自行处理** -##### 交流 qq 1群 961316482(已满) -##### 交流 qq 2群 875294241(已满) -##### 交流 qq 3群 263785057(已满) -##### 交流 qq 4群 674617534 (已满) -##### 交流 qq 5群 594675235 +- **[在线客服](https://work.weixin.qq.com/kfid/kfc4d8dc24a73c15f44)** +- **微信交流1群(已满)** +- **微信交流2群**: + ![微信群](https://lilishop-wechat.oss-cn-beijing.aliyuncs.com/wechat.jpg) ##### 体验 公众号/小程序/APP 体验,扫描二维码 @@ -19,6 +15,41 @@ [![star](https://gitee.com/beijing_hongye_huicheng/lilishop/badge/star.svg?theme=dark)](https://gitee.com/beijing_hongye_huicheng/lilishop/stargazers)   ![github](https://img.shields.io/github/stars/hongyehuicheng/lilishop.svg?style=social&logo=#181717) +## 2025-10-10日更新 +兼容更高的node版本16 + +这里我用的是node版本 v16.20.2 + +npm版本 8.19.4 + +使用yarn install 然后执行 yarn dev + +yarn 安装/启动 +``` +// 如果没有 yarn 安装yarn +npm install yarn -g + +// 切换源 +yarn config set registry https://registry.npmmirror.com + +// 以buyer项目为例 +cd buyer + +yarn install + +yarn dev +``` + + + + +没有二开过的项目直接拉最新代码即可,二开项目可以跟着提交记录一起同步修改 install出现问题检查的话删除 "package-lock.json" 重新install + +Q&A 为什么不升级更高的node版本? :因为高node版本 OpenSSL 改动 导致旧版本 Webpack 插件会失效 试了好几次如果兼容的话 需要升级Webpack5以及其他的插件 升级内容较多 为了更稳定的还是尽量少动为主 + +**** + + ## 如何在本地环境运行lilishop-ui部署视频 https://www.bilibili.com/video/BV1B28EeJEnP/ @@ -29,8 +60,11 @@ https://www.bilibili.com/video/BV1WD87eoE9F/ ## 开发项目 #### 安装Node.js + 保证`node`版本`14`,推荐 14.17.0 +2025-10-10日拉的代码之后不限制于node版本为14,这里只是以14版本为例子 + 可以使用 `yarn` 或者 `npm` 进行安装 #### yarn 安装/启动 @@ -49,17 +83,6 @@ yarn install yarn dev ``` -#### npm 安装/启动 -``` -npm config set registry https://registry.npmmirror.com - -// 以buyer项目为例 -cd buyer - -npm run install - -npm run dev -``` #### FAQ @@ -223,19 +246,9 @@ PS:手机验证码为 ‘111111’ 4.限制商用,如果需要商业使用请联系我们。QQ3409056806.或者加入qq群联系群主。 - - -### 交流群 - -##### 交流 qq 1群 961316482(已满) -##### 交流 qq 2群 875294241(已满) -##### 交流 qq 3群 263785057(已满) -##### 交流 qq 4群 674617534(已满) -##### 交流 qq 5群 594675235 - ### 附录 有人有自己的学习视频、学习记录文档、希望宣传关联开源项目等均可以私聊仓库所有者。 类似: -清晨敲代码同学的分析: https://blog.csdn.net/vaevaevae233/category_12103567.html \ No newline at end of file +清晨敲代码同学的分析: https://blog.csdn.net/vaevaevae233/category_12103567.html diff --git a/buyer/.npmrc b/buyer/.npmrc new file mode 100644 index 00000000..c0c80ba4 --- /dev/null +++ b/buyer/.npmrc @@ -0,0 +1 @@ +engine-strict=false diff --git a/buyer/.yarnrc b/buyer/.yarnrc new file mode 100644 index 00000000..4f14322d --- /dev/null +++ b/buyer/.yarnrc @@ -0,0 +1 @@ +--ignore-engines true diff --git a/buyer/README.md b/buyer/README.md index 4195bc9a..e69de29b 100644 --- a/buyer/README.md +++ b/buyer/README.md @@ -1,19 +0,0 @@ -# new - -## Project setup -``` -npm install -``` - -### Compiles and hot-reloads for development -``` -npm run serve -``` - -### Compiles and minifies for production -``` -npm run build -``` - -### Customize configuration -See [Configuration Reference](https://cli.vuejs.org/config/). diff --git a/buyer/package.json b/buyer/package.json index b53d6d46..66dd7dba 100644 --- a/buyer/package.json +++ b/buyer/package.json @@ -3,9 +3,12 @@ "version": "1.0.0", "private": true, "scripts": { - "dev": "vue-cli-service serve", "serve": "vue-cli-service serve", - "build": "vue-cli-service build" + "build": "vue-cli-service build", + "dev": "vue-cli-service serve" + }, + "engines": { + "node": ">=14" }, "dependencies": { "@amap/amap-jsapi-loader": "0.0.7", @@ -15,11 +18,10 @@ "less": "^2.7.0", "less-loader": "^5.0.0", "mv-count-down": "^0.1.15", - "node-sass": "^4.14.1", - "postcss-loader": "^7.0.1", + "sass": "^1.63.6", + "postcss-loader": "^4.3.0", "psl": "^1.8.0", "qs": "^6.9.4", - "sass-loader": "^7.3.1", "uuid": "^8.3.2", "view-design": "^4.3.2", "vue": "^2.6.11", @@ -32,7 +34,7 @@ "devDependencies": { "@vue/cli-service": "~4.5.0", "compression-webpack-plugin": "^5.0.0", - "sass-loader": "^7.3.1", + "sass-loader": "^10.4.1", "uglifyjs-webpack-plugin": "^2.2.0", "vue-template-compiler": "^2.6.11" }, @@ -40,5 +42,10 @@ "> 1%", "last 2 versions", "not dead" - ] + ], + "resolutions": { + "minimatch": "^3.1.2", + "node-sass": "npm:sass@^1.63.6", + "@achrinza/node-ipc": "9.2.2" + } } diff --git a/buyer/src/api/login.js b/buyer/src/api/login.js index 5ad6d9a5..e9746924 100644 --- a/buyer/src/api/login.js +++ b/buyer/src/api/login.js @@ -69,6 +69,32 @@ export function loginCallback (uuid) { }); } +export function getThirdAccountBindList () { + return request({ + url: '/buyer/passport/connect/bind/list', + method: Method.GET, + needToken: true + }); +} + +export function bindThirdAccount (data) { + return request({ + url: '/buyer/passport/connect/bind', + method: Method.POST, + needToken: true, + data + }); +} + +export function unbindThirdAccount (data) { + return request({ + url: '/buyer/passport/connect/bind/unbind', + method: Method.POST, + needToken: true, + data + }); +} + /** * 忘记密码 验证手机验证码 */ @@ -109,3 +135,12 @@ export function sCLogin(token,params) { params }); } + +export function getWechatH5QrCode (params) { + return request({ + url: '/buyer/other/wechat/h5/qrcode', + method: Method.GET, + needToken: true, + params + }) +} diff --git a/buyer/src/api/member.js b/buyer/src/api/member.js index eeb7de21..2f1eb240 100644 --- a/buyer/src/api/member.js +++ b/buyer/src/api/member.js @@ -180,6 +180,15 @@ export function receiptList () { }); } +// 发票详情 +export function receiptDetail (id) { + return request({ + url: `/buyer/trade/receipt/${id}`, + method: Method.GET, + needToken: true + }); +} + // 保存发票信息 export function saveReceipt (params) { return request({ @@ -480,6 +489,31 @@ export function memberPointHistory (params) { params }); } + +export function memberGradeCurrent (params) { + return request({ + url: `/buyer/member/memberGrade/current`, + method: Method.GET, + needToken: true, + params + }) +} + +export function memberGradeRules () { + return request({ + url: `/buyer/member/memberGrade/rules`, + method: Method.GET, + needToken: true + }) +} + +export function memberGradeList () { + return request({ + url: `/buyer/member/memberGrade/list`, + method: Method.GET, + needToken: true + }) +} /** * 分页获取会员站内信 * @param {Object} params 请求参数,包括pageNumber、pageSize、status diff --git a/buyer/src/components/Search.vue b/buyer/src/components/Search.vue index 5e9dcfdd..3e7e73bd 100644 --- a/buyer/src/components/Search.vue +++ b/buyer/src/components/Search.vue @@ -173,7 +173,7 @@ export default { border-radius: 18.9px; - /deep/ .ivu-input.ivu-input-large { + ::v-deep .ivu-input.ivu-input-large { border: 1.4px solid $theme_color; box-sizing: border-box; border-radius: 19.6px; @@ -188,7 +188,7 @@ export default { } } - /deep/ .ivu-input-group-append { + ::v-deep .ivu-input-group-append { border-radius: 19.6px !important; cursor: pointer; box-sizing: border-box; diff --git a/buyer/src/components/card/index.vue b/buyer/src/components/card/index.vue index 9dfbc055..9aca6831 100644 --- a/buyer/src/components/card/index.vue +++ b/buyer/src/components/card/index.vue @@ -113,12 +113,12 @@ export default { } } - /deep/ .ivu-card, .ivu-card-head, ._Card { + ::v-deep .ivu-card, .ivu-card-head, ._Card { margin-bottom: 20px; @include white_background_color(); } - /deep/ .ivu-card-head { + ::v-deep .ivu-card-head { position: relative; padding: 0 14px; height: 50px; @@ -140,7 +140,7 @@ export default { cursor: pointer; } - /deep/ .ivu-card-body { + ::v-deep .ivu-card-body { padding: 0 !important; display: none; } diff --git a/buyer/src/components/drawer/Main.vue b/buyer/src/components/drawer/Main.vue index 4b5e3436..2e0b6644 100644 --- a/buyer/src/components/drawer/Main.vue +++ b/buyer/src/components/drawer/Main.vue @@ -147,11 +147,11 @@ export default { justify-content: center; flex-direction: column; } - /deep/.popup .ivu-drawer-body{ + ::v-deep.popup .ivu-drawer-body{ padding: 0!important; background-color: #eee; } - /deep/.popup .ivu-drawer-wrap{ + ::v-deep.popup .ivu-drawer-wrap{ z-index: 3001; } diff --git a/buyer/src/components/goodsDetail/ShowGoodsDetail.vue b/buyer/src/components/goodsDetail/ShowGoodsDetail.vue index 39824e41..1a172247 100644 --- a/buyer/src/components/goodsDetail/ShowGoodsDetail.vue +++ b/buyer/src/components/goodsDetail/ShowGoodsDetail.vue @@ -87,14 +87,12 @@ - diff --git a/buyer/src/pages/home/memberCenter/Distribution.vue b/buyer/src/pages/home/memberCenter/Distribution.vue index c63f8baa..864c603e 100644 --- a/buyer/src/pages/home/memberCenter/Distribution.vue +++ b/buyer/src/pages/home/memberCenter/Distribution.vue @@ -584,7 +584,7 @@ export default { margin-left: 25px; margin-top: 5px } -/deep/ .ivu-alert-message { +::v-deep .ivu-alert-message { p { margin: 4px 0; } diff --git a/buyer/src/pages/home/memberCenter/MemberGrade.vue b/buyer/src/pages/home/memberCenter/MemberGrade.vue new file mode 100644 index 00000000..13c94807 --- /dev/null +++ b/buyer/src/pages/home/memberCenter/MemberGrade.vue @@ -0,0 +1,431 @@ + + + + + diff --git a/buyer/src/pages/home/memberCenter/Profile.vue b/buyer/src/pages/home/memberCenter/Profile.vue index 8c10ec82..0d258ebb 100644 --- a/buyer/src/pages/home/memberCenter/Profile.vue +++ b/buyer/src/pages/home/memberCenter/Profile.vue @@ -54,14 +54,40 @@ export default { }, mounted () { this.formItem = JSON.parse(storage.getItem('userInfo')) + this.formItem.birthday = this.normalizeBirthday(this.formItem.birthday) this.accessToken.accessToken = storage.getItem('accessToken'); }, methods: { + normalizeBirthday (value) { + if (!value) return '' + if (value instanceof Date) return value + if (typeof value === 'number') return new Date(value) + if (typeof value === 'string') { + const m = value.match(/^(\d{4})-(\d{2})-(\d{2})/) + if (m) return new Date(Number(m[1]), Number(m[2]) - 1, Number(m[3])) + const d = new Date(value) + return isNaN(d.getTime()) ? '' : d + } + return '' + }, + formatBirthday (value) { + if (!value) return null + if (typeof value === 'string') { + const m = value.match(/^(\d{4})-(\d{2})-(\d{2})/) + return m ? `${m[1]}-${m[2]}-${m[3]}` : null + } + const d = value instanceof Date ? value : new Date(value) + if (isNaN(d.getTime())) return null + const yyyy = d.getFullYear() + const mm = String(d.getMonth() + 1).padStart(2, '0') + const dd = String(d.getDate()).padStart(2, '0') + return `${yyyy}-${mm}-${dd}` + }, save () { // 保存 this.$refs.form.validate(valid => { if (valid) { let params = { - birthday: this.$options.filters.unixToDate(this.formItem.birthday / 1000, 'yyyy-MM-dd'), + birthday: this.formatBirthday(this.formItem.birthday), face: this.formItem.face, nickName: this.formItem.nickName, sex: this.formItem.sex diff --git a/buyer/src/pages/home/orderCenter/OrderDetail.vue b/buyer/src/pages/home/orderCenter/OrderDetail.vue index cb6c61ec..cafa529c 100644 --- a/buyer/src/pages/home/orderCenter/OrderDetail.vue +++ b/buyer/src/pages/home/orderCenter/OrderDetail.vue @@ -95,12 +95,43 @@

发票信息

- + @@ -151,6 +149,8 @@
diff --git a/manager/src/views/distribution/distributionCash.vue b/manager/src/views/distribution/distributionCash.vue index 83999bbe..81d26996 100644 --- a/manager/src/views/distribution/distributionCash.vue +++ b/manager/src/views/distribution/distributionCash.vue @@ -5,15 +5,15 @@ + style="width: 240px"> + style="width: 240px"> + style="width: 240px"> @@ -22,9 +22,11 @@ + +
- +
@@ -70,7 +72,7 @@ export default { result: 'FAIL_AUDITING', // 是否通过 searchForm: { // 搜索框初始化对象 pageNumber: 1, // 当前页数 - pageSize: 10, // 页面大小 + pageSize: 20, // 页面大小 sort: "createTime", // 默认排序字段 order: "desc", // 默认排序方式 }, @@ -158,50 +160,34 @@ export default { fixed: "right", width: 130, render: (h, params) => { - if(params.row.distributionCashStatus != 'APPLY'){ - return h("div", [ - h( - "Button", - { - props: { - type: "primary", - size: "small", - }, - style: { - marginRight: "5px" - }, - on: { - click: () => { - this.view(params.row); - } + if (params.row.distributionCashStatus != 'APPLY') { + return h("div", { class: "ops" }, [ + h( + "a", + { + on: { + click: () => { + this.view(params.row); } - }, - "查看" - ), - - ]); - }else { - return h("div", [ - h( - "Button", - { - props: { - type: "primary", - size: "small", - }, - style: { - marginRight: "5px" - }, - on: { - click: () => { - this.edit(params.row); - } + } + }, + "查看" + ), + ]); + } else { + return h("div", { class: "ops" }, [ + h( + "a", + { + on: { + click: () => { + this.edit(params.row); } - }, - "审核" - ), - - ]); + } + }, + "审核" + ), + ]); } } } @@ -228,7 +214,7 @@ export default { // 搜索 handleSearch() { this.searchForm.pageNumber = 1; - this.searchForm.pageSize = 10; + this.searchForm.pageSize = 20; this.getDataList(); }, // 获取列表数据 @@ -310,3 +296,15 @@ export default { } }; + diff --git a/manager/src/views/distribution/distributionGoods.vue b/manager/src/views/distribution/distributionGoods.vue index 9fc9a293..0be3e20c 100644 --- a/manager/src/views/distribution/distributionGoods.vue +++ b/manager/src/views/distribution/distributionGoods.vue @@ -4,10 +4,12 @@
- +
+ + @@ -30,7 +32,7 @@ @@ -51,7 +53,7 @@ export default { searchForm: { // 搜索框初始化对象 pageNumber: 1, // 当前页数 - pageSize: 10, // 页面大小 + pageSize: 20, // 页面大小 sort: "createTime", // 默认排序字段 order: "desc", // 默认排序方式 }, @@ -135,14 +137,10 @@ export default { fixed: "right", minWidth: 100, render: (h, params) => { - return h("div", [ + return h("div", { class: "ops" }, [ h( - "Button", + "a", { - props: { - type: "error", - size: "small", - }, on: { click: () => { this.remove(params.row); @@ -178,7 +176,7 @@ export default { // 搜索 handleSearch() { this.searchForm.pageNumber = 1; - this.searchForm.pageSize = 10; + this.searchForm.pageSize = 20; this.getDataList(); }, // 清除选中状态 @@ -254,5 +252,17 @@ export default { }, }; + diff --git a/manager/src/views/distribution/distributionOrder.vue b/manager/src/views/distribution/distributionOrder.vue index 64b007bd..1ac678a8 100644 --- a/manager/src/views/distribution/distributionOrder.vue +++ b/manager/src/views/distribution/distributionOrder.vue @@ -8,7 +8,7 @@ v-model="searchForm.orderSn" placeholder="请输入订单编号" clearable - style="width: 200px" + style="width: 240px" /> @@ -17,21 +17,23 @@ v-model="searchForm.distributionName" placeholder="请输入分销商名称" clearable - style="width: 200px" + style="width: 240px" /> + style="width: 240px"> + + + diff --git a/manager/src/views/goods/goods-info/goodsApply.vue b/manager/src/views/goods/goods-info/goodsApply.vue index 30deb6a4..4e4ef945 100644 --- a/manager/src/views/goods/goods-info/goodsApply.vue +++ b/manager/src/views/goods/goods-info/goodsApply.vue @@ -15,7 +15,7 @@ v-model="searchForm.goodsName" placeholder="请输入商品名称" clearable - style="width: 200px" + style="width: 240px" /> @@ -24,13 +24,15 @@ v-model="searchForm.id" placeholder="请输入商品编号" clearable - style="width: 200px" + style="width: 240px" /> + +
{ return h("div", [ h( - "Button", + "a", { - props: { - type: "success", - size: "small", - }, style: { + color: "#2d8cf0", + cursor: "pointer", + textDecoration: "none", marginRight: "5px", }, on: { @@ -187,13 +188,17 @@ export default { "通过" ), h( - "Button", + "span", + { style: { margin: "0 8px", color: "#dcdee2" } }, + "|" + ), + h( + "a", { - props: { - type: "error", - size: "small", - }, style: { + color: "#2d8cf0", + cursor: "pointer", + textDecoration: "none", marginRight: "5px", }, on: { @@ -205,11 +210,17 @@ export default { "拒绝" ), h( - "Button", + "span", + { style: { margin: "0 8px", color: "#dcdee2" } }, + "|" + ), + h( + "a", { - props: { - type: 'default', - size: "small", + style: { + color: "#2d8cf0", + cursor: "pointer", + textDecoration: "none" }, on: { click: () => { @@ -245,7 +256,7 @@ export default { handleSearch() { // 搜索 this.searchForm.pageNumber = 1; - this.searchForm.pageSize = 10; + this.searchForm.pageSize = 20; this.getDataList(); }, getDataList() { @@ -274,7 +285,11 @@ export default { content: "您确认要审核" + examine + " " + v.goodsName + " ?", loading: true, onOk: () => { - authGoods(v.id, this.goodsAuditForm).then((res) => { + let formData = new FormData(); + formData.append('goodsIds', v.id); + formData.append('authFlag', this.goodsAuditForm.authFlag); + + authGoods(formData).then((res) => { this.$Modal.remove(); if (res.success) { this.$Message.success("审核成功"); diff --git a/manager/src/views/goods/goods-manage/brand.vue b/manager/src/views/goods/goods-manage/brand.vue index 3f17a3db..58d2aa06 100644 --- a/manager/src/views/goods/goods-manage/brand.vue +++ b/manager/src/views/goods/goods-manage/brand.vue @@ -4,18 +4,19 @@ - + + + -
@@ -25,7 +26,14 @@ - +
+ 品牌图标 + +
@@ -33,6 +41,34 @@
+ + + + + + +
+ + +
+
+ + +
+
@@ -43,26 +79,39 @@ import { updateBrand, disableBrand, delBrand, + getCategoryTree, + getBrandCategoryListData, + saveBrandCategory, } from "@/api/goods"; -import uploadPicInput from "@/components/lili/upload-pic-input"; +import ossManage from "@/views/sys/oss-manage/ossManage"; import {regular} from "@/utils"; export default { name: "brand", components: { - uploadPicInput + ossManage }, data() { return { + defaultPic: require("@/assets/default.png"), loading: true, // 表单加载状态 modalType: 0, // 添加或编辑标识 modalVisible: false, // 添加或编辑显示 modalTitle: "", // 添加或编辑标题 + picModelFlag: false, // 图片选择器 + categoryModalVisible: false, + categoryModalTitle: "关联分类", + categoryTreeLoading: false, + categoryTreeData: [], + categoryTreeKey: 0, + categorySubmitLoading: false, + currentBrandId: "", + selectedCategoryIds: [], searchForm: { // 搜索框初始化对象 pageNumber: 1, // 当前页数 - pageSize: 10, // 页面大小 + pageSize: 20, // 页面大小 sort: "create_time", // 默认排序字段 order: "desc", // 默认排序方式 }, @@ -117,11 +166,24 @@ export default { key: "deleteFlag", align: "left", render: (h, params) => { - if (params.row.deleteFlag == 0) { - return h("Tag", {props: {color: "green",},}, "启用"); - } else if (params.row.deleteFlag == 1) { - return h("Tag", {props: {color: "volcano",},}, "禁用"); - } + return h( + "i-switch", + { + props: { + value: params.row.deleteFlag == 0, + size: "large", + }, + on: { + "on-change": (checked) => { + this.handleStatusSwitchChange(params.row, checked); + }, + }, + }, + [ + h("span", { slot: "open" }, "启用"), + h("span", { slot: "close" }, "禁用"), + ] + ); }, filters: [ { @@ -145,60 +207,18 @@ export default { { title: "操作", key: "action", - width: 180, + width: 210, align: "center", fixed: "right", render: (h, params) => { - let enableOrDisable = ""; - if (params.row.deleteFlag == 0) { - enableOrDisable = h( - "Button", - { - props: { - size: "small", - type: "error", - }, - style: { - marginRight: "5px", - }, - on: { - click: () => { - this.disable(params.row); - }, - }, - }, - "禁用" - ); - } else { - enableOrDisable = h( - "Button", - { - props: { - type: "success", - size: "small", - }, - style: { - marginRight: "5px", - }, - on: { - click: () => { - this.enable(params.row); - }, - }, - }, - "启用" - ); - } return h("div", [ h( - "Button", + "a", { - props: { - type: "info", - size: "small", - }, style: { - marginRight: "5px", + color: "#2d8cf0", + cursor: "pointer", + textDecoration: "none", }, on: { click: () => { @@ -208,17 +228,39 @@ export default { }, "编辑" ), - enableOrDisable, - h( - "Button", + "span", + { style: { margin: "0 8px", color: "#dcdee2" } }, + "|" + ), + h( + "a", { - props: { - type: 'default', - size: "small", - }, style: { - marginRight: "5px", + color: "#2d8cf0", + cursor: "pointer", + textDecoration: "none", + }, + on: { + click: () => { + this.openCategoryModal(params.row); + }, + }, + }, + "关联分类" + ), + h( + "span", + { style: { margin: "0 8px", color: "#dcdee2" } }, + "|" + ), + h( + "a", + { + style: { + color: "#2d8cf0", + cursor: "pointer", + textDecoration: "none", }, on: { click: () => { @@ -237,6 +279,100 @@ export default { }; }, methods: { + openLogoPicker() { + this.$refs.ossManage.selectImage = true; + this.picModelFlag = true; + }, + callbackSelected(val) { + this.picModelFlag = false; + this.form.logo = val.url; + }, + buildCategoryTreeNodes(list, selectedSet) { + if (!Array.isArray(list) || list.length === 0) return []; + return list.map((item) => { + const children = this.buildCategoryTreeNodes(item.children || [], selectedSet); + return { + id: item.id, + title: item.name, + expand: true, + checked: selectedSet.has(item.id), + children, + }; + }); + }, + async openCategoryModal(row) { + this.currentBrandId = row.id; + this.categoryModalTitle = "关联分类 - " + (row.name || ""); + this.categoryModalVisible = true; + this.categoryTreeLoading = true; + this.categoryTreeKey += 1; + this.categoryTreeData = []; + this.selectedCategoryIds = []; + try { + const [treeRes, bindRes] = await Promise.all([ + getCategoryTree(), + getBrandCategoryListData(row.id), + ]); + const selectedIds = Array.isArray(bindRes?.result) + ? bindRes.result + .map((x) => (typeof x === "string" ? x : x && x.id)) + .filter(Boolean) + : []; + this.selectedCategoryIds = selectedIds; + const selectedSet = new Set(selectedIds); + this.categoryTreeData = treeRes && treeRes.success + ? this.buildCategoryTreeNodes(treeRes.result || [], selectedSet) + : []; + } finally { + this.categoryTreeLoading = false; + } + }, + onCategoryTreeCheckChange(checkedNodes) { + if (!Array.isArray(checkedNodes)) { + this.selectedCategoryIds = []; + return; + } + this.selectedCategoryIds = checkedNodes + .map((node) => node && node.id) + .filter(Boolean); + }, + submitBrandCategory() { + if (!this.currentBrandId) return; + this.categorySubmitLoading = true; + saveBrandCategory( + this.currentBrandId, + (this.selectedCategoryIds || []).map((id) => String(id)) + ).then((res) => { + this.categorySubmitLoading = false; + if (res && res.success) { + this.$Message.success("操作成功"); + this.categoryModalVisible = false; + return; + } + }).catch(() => { + this.categorySubmitLoading = false; + }); + }, + handleStatusSwitchChange(row, checked) { + const disable = !checked; + this.$Modal.confirm({ + title: disable ? "确认禁用" : "确认启用", + content: "您确认要" + (disable ? "禁用" : "启用") + "品牌 " + row.name + " ?", + loading: true, + onOk: () => { + disableBrand(row.id, { disable }).then((res) => { + this.$Modal.remove(); + if (res.success) { + this.$Message.success("操作成功"); + } + this.getDataList(); + }); + }, + onCancel: () => { + this.$nextTick(() => this.$forceUpdate()); + }, + }); + }, // 删除品牌 async delBrand(id) { let res = await delBrand(id); @@ -263,7 +399,7 @@ export default { // 搜索 handleSearch() { this.searchForm.pageNumber = 1; - this.searchForm.pageSize = 10; + this.searchForm.pageSize = 20; this.getDataList(); }, // 获取数据 @@ -315,15 +451,7 @@ export default { delete this.form.id; this.modalVisible = true; }, - // 刷新 - refresh() { - this.loading = true; - setTimeout(() => { - this.getDataList(); - this.loading = false; - this.$Message.success("刷新成功"); - }, 500); - }, + // 编辑 edit(v) { this.modalType = 1; @@ -340,40 +468,6 @@ export default { this.form = data; this.modalVisible = true; }, - // 启用品牌 - enable(v) { - this.$Modal.confirm({ - title: "确认启用", - content: "您确认要启用品牌 " + v.name + " ?", - loading: true, - onOk: () => { - disableBrand(v.id, {disable: false}).then((res) => { - this.$Modal.remove(); - if (res.success) { - this.$Message.success("操作成功"); - this.getDataList(); - } - }); - }, - }); - }, - // 禁用 - disable(v) { - this.$Modal.confirm({ - title: "确认禁用", - content: "您确认要禁用品牌 " + v.name + " ?", - loading: true, - onOk: () => { - disableBrand(v.id, {disable: true}).then((res) => { - this.$Modal.remove(); - if (res.success) { - this.$Message.success("操作成功"); - this.getDataList(); - } - }); - }, - }); - }, }, mounted() { this.init(); diff --git a/manager/src/views/goods/goods-manage/category.vue b/manager/src/views/goods/goods-manage/category.vue index 58e3eeaf..be2c4157 100644 --- a/manager/src/views/goods/goods-manage/category.vue +++ b/manager/src/views/goods/goods-manage/category.vue @@ -14,55 +14,11 @@ :columns="columns" > @@ -272,6 +233,52 @@ export default { }; }, methods: { + normalizeCategoryTree(list) { + if (!Array.isArray(list) || list.length === 0) return; + list.forEach((item) => { + if (!item || typeof item !== "object") return; + if (item.deleteFlag === 0) item.deleteFlag = false; + else if (item.deleteFlag === 1) item.deleteFlag = true; + else item.deleteFlag = !!item.deleteFlag; + if (Array.isArray(item.children) && item.children.length) { + this.normalizeCategoryTree(item.children); + } + }); + }, + onStatusSwitchChange(row, nextDeleteFlag) { + const previousDeleteFlag = !nextDeleteFlag; + const isClosing = nextDeleteFlag === true; + this.$Modal.confirm({ + title: isClosing ? "确认关闭" : "确认开启", + content: + "您是否要" + + (isClosing ? "关闭" : "开启") + + "当前分类 " + + row.name + + " 及其子分类?", + loading: true, + okText: "是", + cancelText: "否", + onOk: () => { + this.$set(row, "_statusLoading", true); + disableCategory(row.id, { enableOperations: isClosing ? true : 0 }).then( + (res) => { + this.$Modal.remove(); + this.$set(row, "_statusLoading", false); + if (res && res.success) { + this.$Message.success("操作成功"); + this.getAllList(0); + return; + } + row.deleteFlag = previousDeleteFlag; + } + ); + }, + onCancel: () => { + row.deleteFlag = previousDeleteFlag; + }, + }); + }, // 初始化数据 init() { this.getAllList(0); @@ -330,10 +337,6 @@ export default { } }); }, - // 编辑绑定参数 - parameterOperation(v) { - this.$router.push({ name: "parameter", query: { id: v.id } }); - }, // 添加子分类 addChildren(v) { this.modalType = 0; @@ -434,6 +437,7 @@ export default { child._loading = false; child.children = []; }); + this.normalizeCategoryTree(val.children); // 模拟加载 setTimeout(() => { callback(val.children); @@ -442,6 +446,7 @@ export default { }); } else { this.deepCategoryChildren(item.id, this.categoryList); + this.normalizeCategoryTree(this.checkedCategoryChildren); setTimeout(() => { callback(this.checkedCategoryChildren); }, 100); @@ -469,6 +474,7 @@ export default { this.loading = false; if (res.success) { localStorage.setItem("category", JSON.stringify(res.result)); + this.normalizeCategoryTree(res.result); this.categoryList = JSON.parse(JSON.stringify(res.result)); this.tableData = res.result.map((item) => { if(this.recordLevel[0] && item.id === this.recordLevel[0]) { @@ -543,11 +549,30 @@ export default { }; diff --git a/manager/src/views/goods/goods-manage/parameter-edit.vue b/manager/src/views/goods/goods-manage/parameter-edit.vue new file mode 100644 index 00000000..70bb57e6 --- /dev/null +++ b/manager/src/views/goods/goods-manage/parameter-edit.vue @@ -0,0 +1,442 @@ + + + + + diff --git a/manager/src/views/goods/goods-manage/parameter.vue b/manager/src/views/goods/goods-manage/parameter.vue index 3a332d4c..83bb602f 100644 --- a/manager/src/views/goods/goods-manage/parameter.vue +++ b/manager/src/views/goods/goods-manage/parameter.vue @@ -1,385 +1,202 @@ - + diff --git a/manager/src/views/goods/goods-manage/spec.vue b/manager/src/views/goods/goods-manage/spec.vue deleted file mode 100644 index 4baeab38..00000000 --- a/manager/src/views/goods/goods-manage/spec.vue +++ /dev/null @@ -1,334 +0,0 @@ - - - diff --git a/manager/src/views/goods/goods-review/index.vue b/manager/src/views/goods/goods-review/index.vue index 9073fddb..0c7b3fde 100644 --- a/manager/src/views/goods/goods-review/index.vue +++ b/manager/src/views/goods/goods-review/index.vue @@ -4,11 +4,16 @@
- + + + +
+ +